Skip to content

Commit 2d8ce6e

Browse files
committed
Other: ext/descriptor passes descriptor.proto test with no differences, see #757
1 parent 0589ace commit 2d8ce6e

File tree

4 files changed

+147
-110
lines changed

4 files changed

+147
-110
lines changed

examples/js-decorators.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// the README example.
33

44
/*eslint-disable strict, no-console*/
5-
var protobuf = require("..");
5+
var protobuf = require("../light");
66

77
var Type = protobuf.Type,
88
Field = protobuf.Field,
@@ -38,4 +38,5 @@ var message = new AwesomeMessage({ awesomeField: "hello" });
3838
var buffer = AwesomeMessage.encode(message).finish();
3939
var decoded = AwesomeMessage.decode(buffer);
4040

41-
console.log(decoded, "internal name: " + AwesomeMessage.$type.name);
41+
console.log(decoded);
42+
console.log("internal name: " + AwesomeMessage.$type.name);

ext/descriptor/index.js

Lines changed: 132 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,20 @@ Root.fromDescriptor = function fromDescriptor(descriptor) {
7979
return root;
8080
};
8181

82+
/**
83+
* Converts a root to a descriptor set.
84+
* @returns {Message<FileDescriptorSetProperties>} Descriptor
85+
* @param {string} [syntax="proto2"] Syntax
86+
* @see Part of the {@link descriptor} extension (ext/descriptor)
87+
*/
88+
Root.prototype.toDescriptor = function toDescriptor(syntax) {
89+
var set = exports.FileDescriptorSet.create();
90+
Root_toDescriptorRecursive(this, set.file, syntax);
91+
return set;
92+
};
93+
8294
// Traverses a namespace and assembles the descriptor set
83-
function traverseNamespace(ns, files, syntax) {
95+
function Root_toDescriptorRecursive(ns, files, syntax) {
8496

8597
// Create a new file
8698
var file = exports.FileDescriptorProto.create({ name: ns.filename || (ns.fullName.substring(1).replace(/\./g, "_") || "root") + ".proto" });
@@ -100,25 +112,13 @@ function traverseNamespace(ns, files, syntax) {
100112
else if (nested instanceof Service)
101113
file.service.push(nested.toDescriptor());
102114
else if (nested instanceof /* plain */ Namespace)
103-
traverseNamespace(nested, files, syntax); // requires new file
115+
Root_toDescriptorRecursive(nested, files, syntax); // requires new file
104116

105117
// And keep the file only if there is at least one nested object
106118
if (file.messageType.length + file.enumType.length + file.extension.length + file.service.length)
107119
files.push(file);
108120
}
109121

110-
/**
111-
* Converts a root to a descriptor set.
112-
* @returns {Message<FileDescriptorSetProperties>} Descriptor
113-
* @param {string} [syntax="proto2"] Syntax
114-
* @see Part of the {@link descriptor} extension (ext/descriptor)
115-
*/
116-
Root.prototype.toDescriptor = function toDescriptor(syntax) {
117-
var set = exports.FileDescriptorSet.create();
118-
traverseNamespace(this, set.file, syntax);
119-
return set;
120-
};
121-
122122
// --- Type ---
123123

124124
/**
@@ -183,15 +183,19 @@ Type.fromDescriptor = function fromDescriptor(descriptor, syntax) {
183183
var type = new Type(descriptor.name.length ? descriptor.name : "Type" + unnamedMessageIndex++),
184184
i;
185185

186+
/* Oneofs */ if (descriptor.oneofDecl)
187+
for (i = 0; i < descriptor.oneofDecl.length; ++i)
188+
type.add(OneOf.fromDescriptor(descriptor.oneofDecl[i]));
186189
/* Fields */ if (descriptor.field)
187-
for (i = 0; i < descriptor.field.length; ++i)
188-
type.add(Field.fromDescriptor(descriptor.field[i], syntax));
190+
for (i = 0; i < descriptor.field.length; ++i) {
191+
var field = Field.fromDescriptor(descriptor.field[i], syntax);
192+
type.add(field);
193+
if (descriptor.field[i].hasOwnProperty("oneofIndex")) // eslint-disable-line no-prototype-builtins
194+
type.oneofsArray[descriptor.field[i].oneofIndex].add(field);
195+
}
189196
/* Extension fields */ if (descriptor.extension)
190197
for (i = 0; i < descriptor.extension.length; ++i)
191198
type.add(Field.fromDescriptor(descriptor.extension[i], syntax));
192-
/* Oneofs */ if (descriptor.oneofDecl)
193-
for (i = 0; i < descriptor.oneofDecl.length; ++i)
194-
type.add(OneOf.fromDescriptor(descriptor.oneofDecl[i]));
195199
/* Nested types */ if (descriptor.nestedType)
196200
for (i = 0; i < descriptor.nestedType.length; ++i) {
197201
type.add(Type.fromDescriptor(descriptor.nestedType[i], syntax));
@@ -230,15 +234,16 @@ Type.prototype.toDescriptor = function toDescriptor(syntax) {
230234
i;
231235

232236
/* Fields */ for (i = 0; i < this.fieldsArray.length; ++i) {
233-
descriptor.field.push(this._fieldsArray[i].toDescriptor(syntax));
237+
var fieldDescriptor;
238+
descriptor.field.push(fieldDescriptor = this._fieldsArray[i].toDescriptor(syntax));
234239
if (this._fieldsArray[i] instanceof MapField) { // map fields are repeated FieldNameEntry
235240
var keyType = toDescriptorType(this._fieldsArray[i].keyType, this._fieldsArray[i].resolvedKeyType),
236241
valueType = toDescriptorType(this._fieldsArray[i].type, this._fieldsArray[i].resolvedType),
237242
valueTypeName = valueType === /* type */ 11 || valueType === /* enum */ 14
238-
? this._fieldsArray[i].resolvedType && this._fieldsArray[i].resolvedType.fullName || this._fieldsArray[i].type
243+
? this._fieldsArray[i].resolvedType && shortname(this.parent, this._fieldsArray[i].resolvedType) || this._fieldsArray[i].type
239244
: undefined;
240245
descriptor.nestedType.push(exports.DescriptorProto.create({
241-
name: descriptor.field[descriptor.field.length - 1].typeName,
246+
name: fieldDescriptor.typeName,
242247
field: [
243248
exports.FieldDescriptorProto.create({ name: "key", number: 1, label: 1, type: keyType }), // can't reference a type or enum
244249
exports.FieldDescriptorProto.create({ name: "value", number: 2, label: 1, type: valueType, typeName: valueTypeName })
@@ -247,11 +252,11 @@ Type.prototype.toDescriptor = function toDescriptor(syntax) {
247252
}));
248253
}
249254
}
255+
/* Oneofs */ for (i = 0; i < this.oneofsArray.length; ++i)
256+
descriptor.oneofDecl.push(this._oneofsArray[i].toDescriptor());
250257
/* Nested... */ for (i = 0; i < this.nestedArray.length; ++i) {
251258
/* Extension fields */ if (this._nestedArray[i] instanceof Field)
252259
descriptor.field.push(this._nestedArray[i].toDescriptor(syntax));
253-
/* Oneofs */ else if (this._nestedArray[i] instanceof OneOf)
254-
descriptor.oneofDecl.push(this._nestedArray[i].toDescriptor());
255260
/* Types */ else if (this._nestedArray[i] instanceof Type)
256261
descriptor.nestedType.push(this._nestedArray[i].toDescriptor(syntax));
257262
/* Enums */ else if (this._nestedArray[i] instanceof Enum)
@@ -286,7 +291,7 @@ Type.prototype.toDescriptor = function toDescriptor(syntax) {
286291
* @property {FieldDescriptorProto_Type} [type] Field basic type
287292
* @property {string} [typeName] Field type name
288293
* @property {string} [extendee] Extended type name
289-
* @property {*} [defaultValue] Not supported
294+
* @property {string} [defaultValue] Literal default value
290295
* @property {number} [oneofIndex] Oneof index if part of a oneof
291296
* @property {*} [jsonName] Not supported
292297
* @property {FieldOptionsProperties} [options] Field options
@@ -346,51 +351,6 @@ Type.prototype.toDescriptor = function toDescriptor(syntax) {
346351
* @property {number} JS_NUMBER=2
347352
*/
348353

349-
// Converts a descriptor type to a protobuf.js basic type
350-
function fromDescriptorType(type) {
351-
switch (type) {
352-
// 0 is reserved for errors
353-
case 1: return "double";
354-
case 2: return "float";
355-
case 3: return "int64";
356-
case 4: return "uint64";
357-
case 5: return "int32";
358-
case 6: return "fixed64";
359-
case 7: return "fixed32";
360-
case 8: return "bool";
361-
case 9: return "string";
362-
case 12: return "bytes";
363-
case 13: return "uint32";
364-
case 15: return "sfixed32";
365-
case 16: return "sfixed64";
366-
case 17: return "sint32";
367-
case 18: return "sint64";
368-
}
369-
throw Error("illegal type: " + type);
370-
}
371-
372-
// Tests if a descriptor type is packable
373-
function packableDescriptorType(type) {
374-
switch (type) {
375-
case 1: // double
376-
case 2: // float
377-
case 3: // int64
378-
case 4: // uint64
379-
case 5: // int32
380-
case 6: // fixed64
381-
case 7: // fixed32
382-
case 8: // bool
383-
case 13: // uint32
384-
case 14: // enum (!)
385-
case 15: // sfixed32
386-
case 16: // sfixed64
387-
case 17: // sint32
388-
case 18: // sint64
389-
return true;
390-
}
391-
return false;
392-
}
393-
394354
/**
395355
* Creates a field from a descriptor.
396356
* @param {FieldDescriptorProtoProperties|Reader|Uint8Array} descriptor Descriptor
@@ -434,6 +394,8 @@ Field.fromDescriptor = function fromDescriptor(descriptor, syntax) {
434394

435395
if (descriptor.options)
436396
field.options = fromDescriptorOptions(descriptor.options, exports.FieldOptions);
397+
if (descriptor.defaultValue && descriptor.defaultValue.length)
398+
field.setOption("default", descriptor.defaultValue);
437399

438400
if (packableDescriptorType(descriptor.type)) {
439401
if (syntax === "proto3") { // defaults to packed=true (internal preset is packed=true)
@@ -446,33 +408,6 @@ Field.fromDescriptor = function fromDescriptor(descriptor, syntax) {
446408
return field;
447409
};
448410

449-
// Converts a protobuf.js basic type to a descriptor type
450-
function toDescriptorType(type, resolvedType) {
451-
switch (type) {
452-
// 0 is reserved for errors
453-
case "double": return 1;
454-
case "float": return 2;
455-
case "int64": return 3;
456-
case "uint64": return 4;
457-
case "int32": return 5;
458-
case "fixed64": return 6;
459-
case "fixed32": return 7;
460-
case "bool": return 8;
461-
case "string": return 9;
462-
case "bytes": return 12;
463-
case "uint32": return 13;
464-
case "sfixed32": return 15;
465-
case "sfixed64": return 16;
466-
case "sint32": return 17;
467-
case "sint64": return 18;
468-
}
469-
if (resolvedType instanceof Enum)
470-
return 14;
471-
if (resolvedType instanceof Type)
472-
return resolvedType.group ? 10 : 11;
473-
throw Error("illegal type: " + type);
474-
}
475-
476411
/**
477412
* Converts a field to a descriptor.
478413
* @returns {Message<FieldDescriptorProtoProperties>} Descriptor
@@ -495,7 +430,7 @@ Field.prototype.toDescriptor = function toDescriptor(syntax) {
495430
case 10: // group
496431
case 11: // type
497432
case 14: // enum
498-
descriptor.typeName = this.resolvedType ? this.resolvedType.fullName : this.type; // TODO: shorten
433+
descriptor.typeName = this.resolvedType ? shortname(this.parent, this.resolvedType) : this.type;
499434
break;
500435
}
501436

@@ -516,8 +451,11 @@ Field.prototype.toDescriptor = function toDescriptor(syntax) {
516451
if ((descriptor.oneofIndex = this.parent.oneofsArray.indexOf(this.partOf)) < 0)
517452
throw Error("missing oneof");
518453

519-
if (this.options)
454+
if (this.options) {
520455
descriptor.options = toDescriptorOptions(this.options, exports.FieldOptions);
456+
if (this.options["default"] != null)
457+
descriptor.defaultValue = String(this.options["default"]);
458+
}
521459

522460
if (syntax === "proto3") { // defaults to packed=true
523461
if (!this.packed)
@@ -757,6 +695,79 @@ Method.prototype.toDescriptor = function toDescriptor() {
757695

758696
// --- utility ---
759697

698+
// Converts a descriptor type to a protobuf.js basic type
699+
function fromDescriptorType(type) {
700+
switch (type) {
701+
// 0 is reserved for errors
702+
case 1: return "double";
703+
case 2: return "float";
704+
case 3: return "int64";
705+
case 4: return "uint64";
706+
case 5: return "int32";
707+
case 6: return "fixed64";
708+
case 7: return "fixed32";
709+
case 8: return "bool";
710+
case 9: return "string";
711+
case 12: return "bytes";
712+
case 13: return "uint32";
713+
case 15: return "sfixed32";
714+
case 16: return "sfixed64";
715+
case 17: return "sint32";
716+
case 18: return "sint64";
717+
}
718+
throw Error("illegal type: " + type);
719+
}
720+
721+
// Tests if a descriptor type is packable
722+
function packableDescriptorType(type) {
723+
switch (type) {
724+
case 1: // double
725+
case 2: // float
726+
case 3: // int64
727+
case 4: // uint64
728+
case 5: // int32
729+
case 6: // fixed64
730+
case 7: // fixed32
731+
case 8: // bool
732+
case 13: // uint32
733+
case 14: // enum (!)
734+
case 15: // sfixed32
735+
case 16: // sfixed64
736+
case 17: // sint32
737+
case 18: // sint64
738+
return true;
739+
}
740+
return false;
741+
}
742+
743+
// Converts a protobuf.js basic type to a descriptor type
744+
function toDescriptorType(type, resolvedType) {
745+
switch (type) {
746+
// 0 is reserved for errors
747+
case "double": return 1;
748+
case "float": return 2;
749+
case "int64": return 3;
750+
case "uint64": return 4;
751+
case "int32": return 5;
752+
case "fixed64": return 6;
753+
case "fixed32": return 7;
754+
case "bool": return 8;
755+
case "string": return 9;
756+
case "bytes": return 12;
757+
case "uint32": return 13;
758+
case "sfixed32": return 15;
759+
case "sfixed64": return 16;
760+
case "sint32": return 17;
761+
case "sint64": return 18;
762+
}
763+
if (resolvedType instanceof Enum)
764+
return 14;
765+
if (resolvedType instanceof Type)
766+
return resolvedType.group ? 10 : 11;
767+
throw Error("illegal type: " + type);
768+
}
769+
770+
// Converts descriptor options to an options object
760771
function fromDescriptorOptions(options, type) {
761772
var out = [];
762773
for (var i = 0, key; i < type.fieldsArray.length; ++i)
@@ -766,13 +777,34 @@ function fromDescriptorOptions(options, type) {
766777
return out.length ? $protobuf.util.toObject(out) : undefined;
767778
}
768779

780+
// Converts an options object to descriptor options
769781
function toDescriptorOptions(options, type) {
770782
var out = [];
771783
for (var i = 0, key; i < type.fieldsArray.length; ++i)
772-
out.push(key = type._fieldsArray[i].name, options[key]);
784+
if ((key = type._fieldsArray[i].name) !== "default")
785+
out.push(key, options[key]);
773786
return out.length ? type.fromObject($protobuf.util.toObject(out)) : undefined;
774787
}
775788

789+
// Calculates the shortest relative path from `from` to `to`.
790+
function shortname(from, to) {
791+
var fromPath = from.fullName.split("."),
792+
toPath = to.fullName.split("."),
793+
i = 0,
794+
j = 0,
795+
k = toPath.length - 1;
796+
if (!(from instanceof Root) && to instanceof Namespace)
797+
while (i < fromPath.length && j < k && fromPath[i] === toPath[j]) {
798+
var other = to.lookup(fromPath[i++], true);
799+
if (other !== null && other !== to)
800+
break;
801+
++j;
802+
}
803+
else
804+
for (; i < fromPath.length && j < k && fromPath[i] === toPath[j]; ++i, ++j);
805+
return toPath.slice(j).join(".");
806+
}
807+
776808
// --- exports ---
777809

778810
/**

ext/descriptor/test.js

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,13 @@ var root2 = protobuf.Root.fromDescriptor(buf, "proto2").resolveAll();
4040

4141
// console.log("\nDecoded proto", JSON.stringify(root2, null, 2));
4242

43-
require("deep-diff").diff(root.toJSON(), root2.toJSON()).forEach(function(diff) {
44-
console.log(diff.kind + " @ " + diff.path.join("."));
45-
console.log("lhs:", diff.lhs);
46-
console.log("rhs:", diff.rhs);
47-
console.log();
48-
});
43+
var diff = require("deep-diff").diff(root.toJSON(), root2.toJSON());
44+
if (diff)
45+
diff.forEach(function(diff) {
46+
console.log(diff.kind + " @ " + diff.path.join("."));
47+
console.log("lhs:", diff.lhs);
48+
console.log("rhs:", diff.rhs);
49+
console.log();
50+
});
51+
else
52+
console.log("no differences");

0 commit comments

Comments
 (0)