6aafd2ab818415bbec1e75593914e06a7a27b685
[motion2.git] / legacy-libs / protobufjs / ext / descriptor / index.js
1 "use strict";
2 var $protobuf = require("../..");
3 module.exports = exports = $protobuf.descriptor = $protobuf.Root.fromJSON(require("../../google/protobuf/descriptor.json")).lookup(".google.protobuf");
4
5 var Namespace = $protobuf.Namespace,
6     Root      = $protobuf.Root,
7     Enum      = $protobuf.Enum,
8     Type      = $protobuf.Type,
9     Field     = $protobuf.Field,
10     MapField  = $protobuf.MapField,
11     OneOf     = $protobuf.OneOf,
12     Service   = $protobuf.Service,
13     Method    = $protobuf.Method;
14
15 // --- Root ---
16
17 /**
18  * Properties of a FileDescriptorSet message.
19  * @interface IFileDescriptorSet
20  * @property {IFileDescriptorProto[]} file Files
21  */
22
23 /**
24  * Properties of a FileDescriptorProto message.
25  * @interface IFileDescriptorProto
26  * @property {string} [name] File name
27  * @property {string} [package] Package
28  * @property {*} [dependency] Not supported
29  * @property {*} [publicDependency] Not supported
30  * @property {*} [weakDependency] Not supported
31  * @property {IDescriptorProto[]} [messageType] Nested message types
32  * @property {IEnumDescriptorProto[]} [enumType] Nested enums
33  * @property {IServiceDescriptorProto[]} [service] Nested services
34  * @property {IFieldDescriptorProto[]} [extension] Nested extension fields
35  * @property {IFileOptions} [options] Options
36  * @property {*} [sourceCodeInfo] Not supported
37  * @property {string} [syntax="proto2"] Syntax
38  */
39
40 /**
41  * Properties of a FileOptions message.
42  * @interface IFileOptions
43  * @property {string} [javaPackage]
44  * @property {string} [javaOuterClassname]
45  * @property {boolean} [javaMultipleFiles]
46  * @property {boolean} [javaGenerateEqualsAndHash]
47  * @property {boolean} [javaStringCheckUtf8]
48  * @property {IFileOptionsOptimizeMode} [optimizeFor=1]
49  * @property {string} [goPackage]
50  * @property {boolean} [ccGenericServices]
51  * @property {boolean} [javaGenericServices]
52  * @property {boolean} [pyGenericServices]
53  * @property {boolean} [deprecated]
54  * @property {boolean} [ccEnableArenas]
55  * @property {string} [objcClassPrefix]
56  * @property {string} [csharpNamespace]
57  */
58
59 /**
60  * Values of he FileOptions.OptimizeMode enum.
61  * @typedef IFileOptionsOptimizeMode
62  * @type {number}
63  * @property {number} SPEED=1
64  * @property {number} CODE_SIZE=2
65  * @property {number} LITE_RUNTIME=3
66  */
67
68 /**
69  * Creates a root from a descriptor set.
70  * @param {IFileDescriptorSet|Reader|Uint8Array} descriptor Descriptor
71  * @returns {Root} Root instance
72  */
73 Root.fromDescriptor = function fromDescriptor(descriptor) {
74
75     // Decode the descriptor message if specified as a buffer:
76     if (typeof descriptor.length === "number")
77         descriptor = exports.FileDescriptorSet.decode(descriptor);
78
79     var root = new Root();
80
81     if (descriptor.file) {
82         var fileDescriptor,
83             filePackage;
84         for (var j = 0, i; j < descriptor.file.length; ++j) {
85             filePackage = root;
86             if ((fileDescriptor = descriptor.file[j])["package"] && fileDescriptor["package"].length)
87                 filePackage = root.define(fileDescriptor["package"]);
88             if (fileDescriptor.name && fileDescriptor.name.length)
89                 root.files.push(filePackage.filename = fileDescriptor.name);
90             if (fileDescriptor.messageType)
91                 for (i = 0; i < fileDescriptor.messageType.length; ++i)
92                     filePackage.add(Type.fromDescriptor(fileDescriptor.messageType[i], fileDescriptor.syntax));
93             if (fileDescriptor.enumType)
94                 for (i = 0; i < fileDescriptor.enumType.length; ++i)
95                     filePackage.add(Enum.fromDescriptor(fileDescriptor.enumType[i]));
96             if (fileDescriptor.extension)
97                 for (i = 0; i < fileDescriptor.extension.length; ++i)
98                     filePackage.add(Field.fromDescriptor(fileDescriptor.extension[i]));
99             if (fileDescriptor.service)
100                 for (i = 0; i < fileDescriptor.service.length; ++i)
101                     filePackage.add(Service.fromDescriptor(fileDescriptor.service[i]));
102             var opts = fromDescriptorOptions(fileDescriptor.options, exports.FileOptions);
103             if (opts) {
104                 var ks = Object.keys(opts);
105                 for (i = 0; i < ks.length; ++i)
106                     filePackage.setOption(ks[i], opts[ks[i]]);
107             }
108         }
109     }
110
111     return root;
112 };
113
114 /**
115  * Converts a root to a descriptor set.
116  * @returns {Message<IFileDescriptorSet>} Descriptor
117  * @param {string} [syntax="proto2"] Syntax
118  */
119 Root.prototype.toDescriptor = function toDescriptor(syntax) {
120     var set = exports.FileDescriptorSet.create();
121     Root_toDescriptorRecursive(this, set.file, syntax);
122     return set;
123 };
124
125 // Traverses a namespace and assembles the descriptor set
126 function Root_toDescriptorRecursive(ns, files, syntax) {
127
128     // Create a new file
129     var file = exports.FileDescriptorProto.create({ name: ns.filename || (ns.fullName.substring(1).replace(/\./g, "_") || "root") + ".proto" });
130     if (syntax)
131         file.syntax = syntax;
132     if (!(ns instanceof Root))
133         file["package"] = ns.fullName.substring(1);
134
135     // Add nested types
136     for (var i = 0, nested; i < ns.nestedArray.length; ++i)
137         if ((nested = ns._nestedArray[i]) instanceof Type)
138             file.messageType.push(nested.toDescriptor(syntax));
139         else if (nested instanceof Enum)
140             file.enumType.push(nested.toDescriptor());
141         else if (nested instanceof Field)
142             file.extension.push(nested.toDescriptor(syntax));
143         else if (nested instanceof Service)
144             file.service.push(nested.toDescriptor());
145         else if (nested instanceof /* plain */ Namespace)
146             Root_toDescriptorRecursive(nested, files, syntax); // requires new file
147
148     // Keep package-level options
149     file.options = toDescriptorOptions(ns.options, exports.FileOptions);
150
151     // And keep the file only if there is at least one nested object
152     if (file.messageType.length + file.enumType.length + file.extension.length + file.service.length)
153         files.push(file);
154 }
155
156 // --- Type ---
157
158 /**
159  * Properties of a DescriptorProto message.
160  * @interface IDescriptorProto
161  * @property {string} [name] Message type name
162  * @property {IFieldDescriptorProto[]} [field] Fields
163  * @property {IFieldDescriptorProto[]} [extension] Extension fields
164  * @property {IDescriptorProto[]} [nestedType] Nested message types
165  * @property {IEnumDescriptorProto[]} [enumType] Nested enums
166  * @property {IDescriptorProtoExtensionRange[]} [extensionRange] Extension ranges
167  * @property {IOneofDescriptorProto[]} [oneofDecl] Oneofs
168  * @property {IMessageOptions} [options] Not supported
169  * @property {IDescriptorProtoReservedRange[]} [reservedRange] Reserved ranges
170  * @property {string[]} [reservedName] Reserved names
171  */
172
173 /**
174  * Properties of a MessageOptions message.
175  * @interface IMessageOptions
176  * @property {boolean} [mapEntry=false] Whether this message is a map entry
177  */
178
179 /**
180  * Properties of an ExtensionRange message.
181  * @interface IDescriptorProtoExtensionRange
182  * @property {number} [start] Start field id
183  * @property {number} [end] End field id
184  */
185
186 /**
187  * Properties of a ReservedRange message.
188  * @interface IDescriptorProtoReservedRange
189  * @property {number} [start] Start field id
190  * @property {number} [end] End field id
191  */
192
193 var unnamedMessageIndex = 0;
194
195 /**
196  * Creates a type from a descriptor.
197  * @param {IDescriptorProto|Reader|Uint8Array} descriptor Descriptor
198  * @param {string} [syntax="proto2"] Syntax
199  * @returns {Type} Type instance
200  */
201 Type.fromDescriptor = function fromDescriptor(descriptor, syntax) {
202
203     // Decode the descriptor message if specified as a buffer:
204     if (typeof descriptor.length === "number")
205         descriptor = exports.DescriptorProto.decode(descriptor);
206
207     // Create the message type
208     var type = new Type(descriptor.name.length ? descriptor.name : "Type" + unnamedMessageIndex++, fromDescriptorOptions(descriptor.options, exports.MessageOptions)),
209         i;
210
211     /* Oneofs */ if (descriptor.oneofDecl)
212         for (i = 0; i < descriptor.oneofDecl.length; ++i)
213             type.add(OneOf.fromDescriptor(descriptor.oneofDecl[i]));
214     /* Fields */ if (descriptor.field)
215         for (i = 0; i < descriptor.field.length; ++i) {
216             var field = Field.fromDescriptor(descriptor.field[i], syntax);
217             type.add(field);
218             if (descriptor.field[i].hasOwnProperty("oneofIndex")) // eslint-disable-line no-prototype-builtins
219                 type.oneofsArray[descriptor.field[i].oneofIndex].add(field);
220         }
221     /* Extension fields */ if (descriptor.extension)
222         for (i = 0; i < descriptor.extension.length; ++i)
223             type.add(Field.fromDescriptor(descriptor.extension[i], syntax));
224     /* Nested types */ if (descriptor.nestedType)
225         for (i = 0; i < descriptor.nestedType.length; ++i) {
226             type.add(Type.fromDescriptor(descriptor.nestedType[i], syntax));
227             if (descriptor.nestedType[i].options && descriptor.nestedType[i].options.mapEntry)
228                 type.setOption("map_entry", true);
229         }
230     /* Nested enums */ if (descriptor.enumType)
231         for (i = 0; i < descriptor.enumType.length; ++i)
232             type.add(Enum.fromDescriptor(descriptor.enumType[i]));
233     /* Extension ranges */ if (descriptor.extensionRange && descriptor.extensionRange.length) {
234         type.extensions = [];
235         for (i = 0; i < descriptor.extensionRange.length; ++i)
236             type.extensions.push([ descriptor.extensionRange[i].start, descriptor.extensionRange[i].end ]);
237     }
238     /* Reserved... */ if (descriptor.reservedRange && descriptor.reservedRange.length || descriptor.reservedName && descriptor.reservedName.length) {
239         type.reserved = [];
240         /* Ranges */ if (descriptor.reservedRange)
241             for (i = 0; i < descriptor.reservedRange.length; ++i)
242                 type.reserved.push([ descriptor.reservedRange[i].start, descriptor.reservedRange[i].end ]);
243         /* Names */ if (descriptor.reservedName)
244             for (i = 0; i < descriptor.reservedName.length; ++i)
245                 type.reserved.push(descriptor.reservedName[i]);
246     }
247
248     return type;
249 };
250
251 /**
252  * Converts a type to a descriptor.
253  * @returns {Message<IDescriptorProto>} Descriptor
254  * @param {string} [syntax="proto2"] Syntax
255  */
256 Type.prototype.toDescriptor = function toDescriptor(syntax) {
257     var descriptor = exports.DescriptorProto.create({ name: this.name }),
258         i;
259
260     /* Fields */ for (i = 0; i < this.fieldsArray.length; ++i) {
261         var fieldDescriptor;
262         descriptor.field.push(fieldDescriptor = this._fieldsArray[i].toDescriptor(syntax));
263         if (this._fieldsArray[i] instanceof MapField) { // map fields are repeated FieldNameEntry
264             var keyType = toDescriptorType(this._fieldsArray[i].keyType, this._fieldsArray[i].resolvedKeyType),
265                 valueType = toDescriptorType(this._fieldsArray[i].type, this._fieldsArray[i].resolvedType),
266                 valueTypeName = valueType === /* type */ 11 || valueType === /* enum */ 14
267                     ? this._fieldsArray[i].resolvedType && shortname(this.parent, this._fieldsArray[i].resolvedType) || this._fieldsArray[i].type
268                     : undefined;
269             descriptor.nestedType.push(exports.DescriptorProto.create({
270                 name: fieldDescriptor.typeName,
271                 field: [
272                     exports.FieldDescriptorProto.create({ name: "key", number: 1, label: 1, type: keyType }), // can't reference a type or enum
273                     exports.FieldDescriptorProto.create({ name: "value", number: 2, label: 1, type: valueType, typeName: valueTypeName })
274                 ],
275                 options: exports.MessageOptions.create({ mapEntry: true })
276             }));
277         }
278     }
279     /* Oneofs */ for (i = 0; i < this.oneofsArray.length; ++i)
280         descriptor.oneofDecl.push(this._oneofsArray[i].toDescriptor());
281     /* Nested... */ for (i = 0; i < this.nestedArray.length; ++i) {
282         /* Extension fields */ if (this._nestedArray[i] instanceof Field)
283             descriptor.field.push(this._nestedArray[i].toDescriptor(syntax));
284         /* Types */ else if (this._nestedArray[i] instanceof Type)
285             descriptor.nestedType.push(this._nestedArray[i].toDescriptor(syntax));
286         /* Enums */ else if (this._nestedArray[i] instanceof Enum)
287             descriptor.enumType.push(this._nestedArray[i].toDescriptor());
288         // plain nested namespaces become packages instead in Root#toDescriptor
289     }
290     /* Extension ranges */ if (this.extensions)
291         for (i = 0; i < this.extensions.length; ++i)
292             descriptor.extensionRange.push(exports.DescriptorProto.ExtensionRange.create({ start: this.extensions[i][0], end: this.extensions[i][1] }));
293     /* Reserved... */ if (this.reserved)
294         for (i = 0; i < this.reserved.length; ++i)
295             /* Names */ if (typeof this.reserved[i] === "string")
296                 descriptor.reservedName.push(this.reserved[i]);
297             /* Ranges */ else
298                 descriptor.reservedRange.push(exports.DescriptorProto.ReservedRange.create({ start: this.reserved[i][0], end: this.reserved[i][1] }));
299
300     descriptor.options = toDescriptorOptions(this.options, exports.MessageOptions);
301
302     return descriptor;
303 };
304
305 // --- Field ---
306
307 /**
308  * Properties of a FieldDescriptorProto message.
309  * @interface IFieldDescriptorProto
310  * @property {string} [name] Field name
311  * @property {number} [number] Field id
312  * @property {IFieldDescriptorProtoLabel} [label] Field rule
313  * @property {IFieldDescriptorProtoType} [type] Field basic type
314  * @property {string} [typeName] Field type name
315  * @property {string} [extendee] Extended type name
316  * @property {string} [defaultValue] Literal default value
317  * @property {number} [oneofIndex] Oneof index if part of a oneof
318  * @property {*} [jsonName] Not supported
319  * @property {IFieldOptions} [options] Field options
320  */
321
322 /**
323  * Values of the FieldDescriptorProto.Label enum.
324  * @typedef IFieldDescriptorProtoLabel
325  * @type {number}
326  * @property {number} LABEL_OPTIONAL=1
327  * @property {number} LABEL_REQUIRED=2
328  * @property {number} LABEL_REPEATED=3
329  */
330
331 /**
332  * Values of the FieldDescriptorProto.Type enum.
333  * @typedef IFieldDescriptorProtoType
334  * @type {number}
335  * @property {number} TYPE_DOUBLE=1
336  * @property {number} TYPE_FLOAT=2
337  * @property {number} TYPE_INT64=3
338  * @property {number} TYPE_UINT64=4
339  * @property {number} TYPE_INT32=5
340  * @property {number} TYPE_FIXED64=6
341  * @property {number} TYPE_FIXED32=7
342  * @property {number} TYPE_BOOL=8
343  * @property {number} TYPE_STRING=9
344  * @property {number} TYPE_GROUP=10
345  * @property {number} TYPE_MESSAGE=11
346  * @property {number} TYPE_BYTES=12
347  * @property {number} TYPE_UINT32=13
348  * @property {number} TYPE_ENUM=14
349  * @property {number} TYPE_SFIXED32=15
350  * @property {number} TYPE_SFIXED64=16
351  * @property {number} TYPE_SINT32=17
352  * @property {number} TYPE_SINT64=18
353  */
354
355 /**
356  * Properties of a FieldOptions message.
357  * @interface IFieldOptions
358  * @property {boolean} [packed] Whether packed or not (defaults to `false` for proto2 and `true` for proto3)
359  * @property {IFieldOptionsJSType} [jstype] JavaScript value type (not used by protobuf.js)
360  */
361
362 /**
363  * Values of the FieldOptions.JSType enum.
364  * @typedef IFieldOptionsJSType
365  * @type {number}
366  * @property {number} JS_NORMAL=0
367  * @property {number} JS_STRING=1
368  * @property {number} JS_NUMBER=2
369  */
370
371 // copied here from parse.js
372 var numberRe = /^(?![eE])[0-9]*(?:\.[0-9]*)?(?:[eE][+-]?[0-9]+)?$/;
373
374 /**
375  * Creates a field from a descriptor.
376  * @param {IFieldDescriptorProto|Reader|Uint8Array} descriptor Descriptor
377  * @param {string} [syntax="proto2"] Syntax
378  * @returns {Field} Field instance
379  */
380 Field.fromDescriptor = function fromDescriptor(descriptor, syntax) {
381
382     // Decode the descriptor message if specified as a buffer:
383     if (typeof descriptor.length === "number")
384         descriptor = exports.DescriptorProto.decode(descriptor);
385
386     if (typeof descriptor.number !== "number")
387         throw Error("missing field id");
388
389     // Rewire field type
390     var fieldType;
391     if (descriptor.typeName && descriptor.typeName.length)
392         fieldType = descriptor.typeName;
393     else
394         fieldType = fromDescriptorType(descriptor.type);
395
396     // Rewire field rule
397     var fieldRule;
398     switch (descriptor.label) {
399         // 0 is reserved for errors
400         case 1: fieldRule = undefined; break;
401         case 2: fieldRule = "required"; break;
402         case 3: fieldRule = "repeated"; break;
403         default: throw Error("illegal label: " + descriptor.label);
404     }
405
406         var extendee = descriptor.extendee;
407         if (descriptor.extendee !== undefined) {
408                 extendee = extendee.length ? extendee : undefined;
409         }
410     var field = new Field(
411         descriptor.name.length ? descriptor.name : "field" + descriptor.number,
412         descriptor.number,
413         fieldType,
414         fieldRule,
415         extendee
416     );
417
418     field.options = fromDescriptorOptions(descriptor.options, exports.FieldOptions);
419
420     if (descriptor.defaultValue && descriptor.defaultValue.length) {
421         var defaultValue = descriptor.defaultValue;
422         switch (defaultValue) {
423             case "true": case "TRUE":
424                 defaultValue = true;
425                 break;
426             case "false": case "FALSE":
427                 defaultValue = false;
428                 break;
429             default:
430                 var match = numberRe.exec(defaultValue);
431                 if (match)
432                     defaultValue = parseInt(defaultValue); // eslint-disable-line radix
433                 break;
434         }
435         field.setOption("default", defaultValue);
436     }
437
438     if (packableDescriptorType(descriptor.type)) {
439         if (syntax === "proto3") { // defaults to packed=true (internal preset is packed=true)
440             if (descriptor.options && !descriptor.options.packed)
441                 field.setOption("packed", false);
442         } else if (!(descriptor.options && descriptor.options.packed)) // defaults to packed=false
443             field.setOption("packed", false);
444     }
445
446     return field;
447 };
448
449 /**
450  * Converts a field to a descriptor.
451  * @returns {Message<IFieldDescriptorProto>} Descriptor
452  * @param {string} [syntax="proto2"] Syntax
453  */
454 Field.prototype.toDescriptor = function toDescriptor(syntax) {
455     var descriptor = exports.FieldDescriptorProto.create({ name: this.name, number: this.id });
456
457     if (this.map) {
458
459         descriptor.type = 11; // message
460         descriptor.typeName = $protobuf.util.ucFirst(this.name); // fieldName -> FieldNameEntry (built in Type#toDescriptor)
461         descriptor.label = 3; // repeated
462
463     } else {
464
465         // Rewire field type
466         switch (descriptor.type = toDescriptorType(this.type, this.resolve().resolvedType)) {
467             case 10: // group
468             case 11: // type
469             case 14: // enum
470                 descriptor.typeName = this.resolvedType ? shortname(this.parent, this.resolvedType) : this.type;
471                 break;
472         }
473
474         // Rewire field rule
475         switch (this.rule) {
476             case "repeated": descriptor.label = 3; break;
477             case "required": descriptor.label = 2; break;
478             default: descriptor.label = 1; break;
479         }
480
481     }
482
483     // Handle extension field
484     descriptor.extendee = this.extensionField ? this.extensionField.parent.fullName : this.extend;
485
486     // Handle part of oneof
487     if (this.partOf)
488         if ((descriptor.oneofIndex = this.parent.oneofsArray.indexOf(this.partOf)) < 0)
489             throw Error("missing oneof");
490
491     if (this.options) {
492         descriptor.options = toDescriptorOptions(this.options, exports.FieldOptions);
493         if (this.options["default"] != null)
494             descriptor.defaultValue = String(this.options["default"]);
495     }
496
497     if (syntax === "proto3") { // defaults to packed=true
498         if (!this.packed)
499             (descriptor.options || (descriptor.options = exports.FieldOptions.create())).packed = false;
500     } else if (this.packed) // defaults to packed=false
501         (descriptor.options || (descriptor.options = exports.FieldOptions.create())).packed = true;
502
503     return descriptor;
504 };
505
506 // --- Enum ---
507
508 /**
509  * Properties of an EnumDescriptorProto message.
510  * @interface IEnumDescriptorProto
511  * @property {string} [name] Enum name
512  * @property {IEnumValueDescriptorProto[]} [value] Enum values
513  * @property {IEnumOptions} [options] Enum options
514  */
515
516 /**
517  * Properties of an EnumValueDescriptorProto message.
518  * @interface IEnumValueDescriptorProto
519  * @property {string} [name] Name
520  * @property {number} [number] Value
521  * @property {*} [options] Not supported
522  */
523
524 /**
525  * Properties of an EnumOptions message.
526  * @interface IEnumOptions
527  * @property {boolean} [allowAlias] Whether aliases are allowed
528  * @property {boolean} [deprecated]
529  */
530
531 var unnamedEnumIndex = 0;
532
533 /**
534  * Creates an enum from a descriptor.
535  * @param {IEnumDescriptorProto|Reader|Uint8Array} descriptor Descriptor
536  * @returns {Enum} Enum instance
537  */
538 Enum.fromDescriptor = function fromDescriptor(descriptor) {
539
540     // Decode the descriptor message if specified as a buffer:
541     if (typeof descriptor.length === "number")
542         descriptor = exports.EnumDescriptorProto.decode(descriptor);
543
544     // Construct values object
545     var values = {};
546     if (descriptor.value)
547         for (var i = 0; i < descriptor.value.length; ++i) {
548             var name  = descriptor.value[i].name,
549                 value = descriptor.value[i].number || 0;
550             values[name && name.length ? name : "NAME" + value] = value;
551         }
552
553     return new Enum(
554         descriptor.name && descriptor.name.length ? descriptor.name : "Enum" + unnamedEnumIndex++,
555         values,
556         fromDescriptorOptions(descriptor.options, exports.EnumOptions)
557     );
558 };
559
560 /**
561  * Converts an enum to a descriptor.
562  * @returns {Message<IEnumDescriptorProto>} Descriptor
563  */
564 Enum.prototype.toDescriptor = function toDescriptor() {
565
566     // Values
567     var values = [];
568     for (var i = 0, ks = Object.keys(this.values); i < ks.length; ++i)
569         values.push(exports.EnumValueDescriptorProto.create({ name: ks[i], number: this.values[ks[i]] }));
570
571     return exports.EnumDescriptorProto.create({
572         name: this.name,
573         value: values,
574         options: toDescriptorOptions(this.options, exports.EnumOptions)
575     });
576 };
577
578 // --- OneOf ---
579
580 /**
581  * Properties of a OneofDescriptorProto message.
582  * @interface IOneofDescriptorProto
583  * @property {string} [name] Oneof name
584  * @property {*} [options] Not supported
585  */
586
587 var unnamedOneofIndex = 0;
588
589 /**
590  * Creates a oneof from a descriptor.
591  * @param {IOneofDescriptorProto|Reader|Uint8Array} descriptor Descriptor
592  * @returns {OneOf} OneOf instance
593  */
594 OneOf.fromDescriptor = function fromDescriptor(descriptor) {
595
596     // Decode the descriptor message if specified as a buffer:
597     if (typeof descriptor.length === "number")
598         descriptor = exports.OneofDescriptorProto.decode(descriptor);
599
600     return new OneOf(
601         // unnamedOneOfIndex is global, not per type, because we have no ref to a type here
602         descriptor.name && descriptor.name.length ? descriptor.name : "oneof" + unnamedOneofIndex++
603         // fromDescriptorOptions(descriptor.options, exports.OneofOptions) - only uninterpreted_option
604     );
605 };
606
607 /**
608  * Converts a oneof to a descriptor.
609  * @returns {Message<IOneofDescriptorProto>} Descriptor
610  */
611 OneOf.prototype.toDescriptor = function toDescriptor() {
612     return exports.OneofDescriptorProto.create({
613         name: this.name
614         // options: toDescriptorOptions(this.options, exports.OneofOptions) - only uninterpreted_option
615     });
616 };
617
618 // --- Service ---
619
620 /**
621  * Properties of a ServiceDescriptorProto message.
622  * @interface IServiceDescriptorProto
623  * @property {string} [name] Service name
624  * @property {IMethodDescriptorProto[]} [method] Methods
625  * @property {IServiceOptions} [options] Options
626  */
627
628 /**
629  * Properties of a ServiceOptions message.
630  * @interface IServiceOptions
631  * @property {boolean} [deprecated]
632  */
633
634 var unnamedServiceIndex = 0;
635
636 /**
637  * Creates a service from a descriptor.
638  * @param {IServiceDescriptorProto|Reader|Uint8Array} descriptor Descriptor
639  * @returns {Service} Service instance
640  */
641 Service.fromDescriptor = function fromDescriptor(descriptor) {
642
643     // Decode the descriptor message if specified as a buffer:
644     if (typeof descriptor.length === "number")
645         descriptor = exports.ServiceDescriptorProto.decode(descriptor);
646
647     var service = new Service(descriptor.name && descriptor.name.length ? descriptor.name : "Service" + unnamedServiceIndex++, fromDescriptorOptions(descriptor.options, exports.ServiceOptions));
648     if (descriptor.method)
649         for (var i = 0; i < descriptor.method.length; ++i)
650             service.add(Method.fromDescriptor(descriptor.method[i]));
651
652     return service;
653 };
654
655 /**
656  * Converts a service to a descriptor.
657  * @returns {Message<IServiceDescriptorProto>} Descriptor
658  */
659 Service.prototype.toDescriptor = function toDescriptor() {
660
661     // Methods
662     var methods = [];
663     for (var i = 0; i < this.methodsArray.length; ++i)
664         methods.push(this._methodsArray[i].toDescriptor());
665
666     return exports.ServiceDescriptorProto.create({
667         name: this.name,
668         method: methods,
669         options: toDescriptorOptions(this.options, exports.ServiceOptions)
670     });
671 };
672
673 // --- Method ---
674
675 /**
676  * Properties of a MethodDescriptorProto message.
677  * @interface IMethodDescriptorProto
678  * @property {string} [name] Method name
679  * @property {string} [inputType] Request type name
680  * @property {string} [outputType] Response type name
681  * @property {IMethodOptions} [options] Not supported
682  * @property {boolean} [clientStreaming=false] Whether requests are streamed
683  * @property {boolean} [serverStreaming=false] Whether responses are streamed
684  */
685
686 /**
687  * Properties of a MethodOptions message.
688  * @interface IMethodOptions
689  * @property {boolean} [deprecated]
690  */
691
692 var unnamedMethodIndex = 0;
693
694 /**
695  * Creates a method from a descriptor.
696  * @param {IMethodDescriptorProto|Reader|Uint8Array} descriptor Descriptor
697  * @returns {Method} Reflected method instance
698  */
699 Method.fromDescriptor = function fromDescriptor(descriptor) {
700
701     // Decode the descriptor message if specified as a buffer:
702     if (typeof descriptor.length === "number")
703         descriptor = exports.MethodDescriptorProto.decode(descriptor);
704
705     return new Method(
706         // unnamedMethodIndex is global, not per service, because we have no ref to a service here
707         descriptor.name && descriptor.name.length ? descriptor.name : "Method" + unnamedMethodIndex++,
708         "rpc",
709         descriptor.inputType,
710         descriptor.outputType,
711         Boolean(descriptor.clientStreaming),
712         Boolean(descriptor.serverStreaming),
713         fromDescriptorOptions(descriptor.options, exports.MethodOptions)
714     );
715 };
716
717 /**
718  * Converts a method to a descriptor.
719  * @returns {Message<IMethodDescriptorProto>} Descriptor
720  */
721 Method.prototype.toDescriptor = function toDescriptor() {
722     return exports.MethodDescriptorProto.create({
723         name: this.name,
724         inputType: this.resolvedRequestType ? this.resolvedRequestType.fullName : this.requestType,
725         outputType: this.resolvedResponseType ? this.resolvedResponseType.fullName : this.responseType,
726         clientStreaming: this.requestStream,
727         serverStreaming: this.responseStream,
728         options: toDescriptorOptions(this.options, exports.MethodOptions)
729     });
730 };
731
732 // --- utility ---
733
734 // Converts a descriptor type to a protobuf.js basic type
735 function fromDescriptorType(type) {
736     switch (type) {
737         // 0 is reserved for errors
738         case 1: return "double";
739         case 2: return "float";
740         case 3: return "int64";
741         case 4: return "uint64";
742         case 5: return "int32";
743         case 6: return "fixed64";
744         case 7: return "fixed32";
745         case 8: return "bool";
746         case 9: return "string";
747         case 12: return "bytes";
748         case 13: return "uint32";
749         case 15: return "sfixed32";
750         case 16: return "sfixed64";
751         case 17: return "sint32";
752         case 18: return "sint64";
753     }
754     throw Error("illegal type: " + type);
755 }
756
757 // Tests if a descriptor type is packable
758 function packableDescriptorType(type) {
759     switch (type) {
760         case 1: // double
761         case 2: // float
762         case 3: // int64
763         case 4: // uint64
764         case 5: // int32
765         case 6: // fixed64
766         case 7: // fixed32
767         case 8: // bool
768         case 13: // uint32
769         case 14: // enum (!)
770         case 15: // sfixed32
771         case 16: // sfixed64
772         case 17: // sint32
773         case 18: // sint64
774             return true;
775     }
776     return false;
777 }
778
779 // Converts a protobuf.js basic type to a descriptor type
780 function toDescriptorType(type, resolvedType) {
781     switch (type) {
782         // 0 is reserved for errors
783         case "double": return 1;
784         case "float": return 2;
785         case "int64": return 3;
786         case "uint64": return 4;
787         case "int32": return 5;
788         case "fixed64": return 6;
789         case "fixed32": return 7;
790         case "bool": return 8;
791         case "string": return 9;
792         case "bytes": return 12;
793         case "uint32": return 13;
794         case "sfixed32": return 15;
795         case "sfixed64": return 16;
796         case "sint32": return 17;
797         case "sint64": return 18;
798     }
799     if (resolvedType instanceof Enum)
800         return 14;
801     if (resolvedType instanceof Type)
802         return resolvedType.group ? 10 : 11;
803     throw Error("illegal type: " + type);
804 }
805
806 // Converts descriptor options to an options object
807 function fromDescriptorOptions(options, type) {
808     if (!options)
809         return undefined;
810     var out = [];
811     for (var i = 0, field, key, val; i < type.fieldsArray.length; ++i)
812         if ((key = (field = type._fieldsArray[i]).name) !== "uninterpretedOption")
813             if (options.hasOwnProperty(key)) { // eslint-disable-line no-prototype-builtins
814                 val = options[key];
815                 if (field.resolvedType instanceof Enum && typeof val === "number" && field.resolvedType.valuesById[val] !== undefined)
816                     val = field.resolvedType.valuesById[val];
817                 out.push(underScore(key), val);
818             }
819     return out.length ? $protobuf.util.toObject(out) : undefined;
820 }
821
822 // Converts an options object to descriptor options
823 function toDescriptorOptions(options, type) {
824     if (!options)
825         return undefined;
826     var out = [];
827     for (var i = 0, ks = Object.keys(options), key, val; i < ks.length; ++i) {
828         val = options[key = ks[i]];
829         if (key === "default")
830             continue;
831         var field = type.fields[key];
832         if (!field && !(field = type.fields[key = $protobuf.util.camelCase(key)]))
833             continue;
834         out.push(key, val);
835     }
836     return out.length ? type.fromObject($protobuf.util.toObject(out)) : undefined;
837 }
838
839 // Calculates the shortest relative path from `from` to `to`.
840 function shortname(from, to) {
841     var fromPath = from.fullName.split("."),
842         toPath = to.fullName.split("."),
843         i = 0,
844         j = 0,
845         k = toPath.length - 1;
846     if (!(from instanceof Root) && to instanceof Namespace)
847         while (i < fromPath.length && j < k && fromPath[i] === toPath[j]) {
848             var other = to.lookup(fromPath[i++], true);
849             if (other !== null && other !== to)
850                 break;
851             ++j;
852         }
853     else
854         for (; i < fromPath.length && j < k && fromPath[i] === toPath[j]; ++i, ++j);
855     return toPath.slice(j).join(".");
856 }
857
858 // copied here from cli/targets/proto.js
859 function underScore(str) {
860     return str.substring(0,1)
861          + str.substring(1)
862                .replace(/([A-Z])(?=[a-z]|$)/g, function($0, $1) { return "_" + $1.toLowerCase(); });
863 }
864
865 // --- exports ---
866
867 /**
868  * Reflected file descriptor set.
869  * @name FileDescriptorSet
870  * @type {Type}
871  * @const
872  * @tstype $protobuf.Type
873  */
874
875 /**
876  * Reflected file descriptor proto.
877  * @name FileDescriptorProto
878  * @type {Type}
879  * @const
880  * @tstype $protobuf.Type
881  */
882
883 /**
884  * Reflected descriptor proto.
885  * @name DescriptorProto
886  * @type {Type}
887  * @property {Type} ExtensionRange
888  * @property {Type} ReservedRange
889  * @const
890  * @tstype $protobuf.Type & {
891  *     ExtensionRange: $protobuf.Type,
892  *     ReservedRange: $protobuf.Type
893  * }
894  */
895
896 /**
897  * Reflected field descriptor proto.
898  * @name FieldDescriptorProto
899  * @type {Type}
900  * @property {Enum} Label
901  * @property {Enum} Type
902  * @const
903  * @tstype $protobuf.Type & {
904  *     Label: $protobuf.Enum,
905  *     Type: $protobuf.Enum
906  * }
907  */
908
909 /**
910  * Reflected oneof descriptor proto.
911  * @name OneofDescriptorProto
912  * @type {Type}
913  * @const
914  * @tstype $protobuf.Type
915  */
916
917 /**
918  * Reflected enum descriptor proto.
919  * @name EnumDescriptorProto
920  * @type {Type}
921  * @const
922  * @tstype $protobuf.Type
923  */
924
925 /**
926  * Reflected service descriptor proto.
927  * @name ServiceDescriptorProto
928  * @type {Type}
929  * @const
930  * @tstype $protobuf.Type
931  */
932
933 /**
934  * Reflected enum value descriptor proto.
935  * @name EnumValueDescriptorProto
936  * @type {Type}
937  * @const
938  * @tstype $protobuf.Type
939  */
940
941 /**
942  * Reflected method descriptor proto.
943  * @name MethodDescriptorProto
944  * @type {Type}
945  * @const
946  * @tstype $protobuf.Type
947  */
948
949 /**
950  * Reflected file options.
951  * @name FileOptions
952  * @type {Type}
953  * @property {Enum} OptimizeMode
954  * @const
955  * @tstype $protobuf.Type & {
956  *     OptimizeMode: $protobuf.Enum
957  * }
958  */
959
960 /**
961  * Reflected message options.
962  * @name MessageOptions
963  * @type {Type}
964  * @const
965  * @tstype $protobuf.Type
966  */
967
968 /**
969  * Reflected field options.
970  * @name FieldOptions
971  * @type {Type}
972  * @property {Enum} CType
973  * @property {Enum} JSType
974  * @const
975  * @tstype $protobuf.Type & {
976  *     CType: $protobuf.Enum,
977  *     JSType: $protobuf.Enum
978  * }
979  */
980
981 /**
982  * Reflected oneof options.
983  * @name OneofOptions
984  * @type {Type}
985  * @const
986  * @tstype $protobuf.Type
987  */
988
989 /**
990  * Reflected enum options.
991  * @name EnumOptions
992  * @type {Type}
993  * @const
994  * @tstype $protobuf.Type
995  */
996
997 /**
998  * Reflected enum value options.
999  * @name EnumValueOptions
1000  * @type {Type}
1001  * @const
1002  * @tstype $protobuf.Type
1003  */
1004
1005 /**
1006  * Reflected service options.
1007  * @name ServiceOptions
1008  * @type {Type}
1009  * @const
1010  * @tstype $protobuf.Type
1011  */
1012
1013 /**
1014  * Reflected method options.
1015  * @name MethodOptions
1016  * @type {Type}
1017  * @const
1018  * @tstype $protobuf.Type
1019  */
1020
1021 /**
1022  * Reflected uninterpretet option.
1023  * @name UninterpretedOption
1024  * @type {Type}
1025  * @property {Type} NamePart
1026  * @const
1027  * @tstype $protobuf.Type & {
1028  *     NamePart: $protobuf.Type
1029  * }
1030  */
1031
1032 /**
1033  * Reflected source code info.
1034  * @name SourceCodeInfo
1035  * @type {Type}
1036  * @property {Type} Location
1037  * @const
1038  * @tstype $protobuf.Type & {
1039  *     Location: $protobuf.Type
1040  * }
1041  */
1042
1043 /**
1044  * Reflected generated code info.
1045  * @name GeneratedCodeInfo
1046  * @type {Type}
1047  * @property {Type} Annotation
1048  * @const
1049  * @tstype $protobuf.Type & {
1050  *     Annotation: $protobuf.Type
1051  * }
1052  */