protobufjs 3.6.0 → 3.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/bin/proto2js +16 -4
  2. package/bower.json +1 -1
  3. package/dist/ProtoBuf.js +645 -441
  4. package/dist/ProtoBuf.min.js +96 -96
  5. package/dist/ProtoBuf.min.js.gz +0 -0
  6. package/dist/ProtoBuf.min.map +2 -2
  7. package/dist/ProtoBuf.noparse.js +520 -357
  8. package/dist/ProtoBuf.noparse.min.js +68 -66
  9. package/dist/ProtoBuf.noparse.min.js.gz +0 -0
  10. package/dist/ProtoBuf.noparse.min.map +3 -3
  11. package/docs/ProtoBuf.Builder.Message.html +673 -135
  12. package/docs/ProtoBuf.Builder.Service.html +58 -19
  13. package/docs/ProtoBuf.Builder.html +374 -46
  14. package/docs/ProtoBuf.DotProto.Parser.html +58 -19
  15. package/docs/ProtoBuf.DotProto.Tokenizer.html +104 -19
  16. package/docs/ProtoBuf.DotProto.html +16 -10
  17. package/docs/ProtoBuf.Reflect.Enum.Value.html +207 -33
  18. package/docs/ProtoBuf.Reflect.Enum.html +318 -56
  19. package/docs/ProtoBuf.Reflect.Extension.html +53 -13
  20. package/docs/ProtoBuf.Reflect.Message.ExtensionField.html +450 -68
  21. package/docs/ProtoBuf.Reflect.Message.Field.html +454 -51
  22. package/docs/ProtoBuf.Reflect.Message.OneOf.html +1044 -0
  23. package/docs/ProtoBuf.Reflect.Message.html +378 -64
  24. package/docs/ProtoBuf.Reflect.Namespace.html +333 -51
  25. package/docs/ProtoBuf.Reflect.Service.Method.html +228 -35
  26. package/docs/ProtoBuf.Reflect.Service.RPCMethod.html +262 -41
  27. package/docs/ProtoBuf.Reflect.Service.html +318 -56
  28. package/docs/ProtoBuf.Reflect.T.html +210 -25
  29. package/docs/ProtoBuf.Reflect.html +17 -11
  30. package/docs/ProtoBuf.Util.html +59 -13
  31. package/docs/ProtoBuf.html +235 -67
  32. package/docs/ProtoBuf.js.html +648 -443
  33. package/docs/index.html +4 -2
  34. package/docs/styles/jsdoc-default.css +2 -2
  35. package/examples/protoify/.npmignore +2 -0
  36. package/examples/protoify/README.md +28 -0
  37. package/examples/protoify/index.js +147 -0
  38. package/examples/protoify/json.js +123 -0
  39. package/examples/protoify/json.json +123 -0
  40. package/examples/protoify/json.proto +30 -0
  41. package/examples/protoify/package.json +15 -0
  42. package/examples/protoify/test.js +56 -0
  43. package/examples/websocket/README.md +1 -0
  44. package/examples/websocket/package.json +1 -1
  45. package/externs/ProtoBuf.js +922 -922
  46. package/package.json +3 -3
  47. package/scripts/build.js +58 -58
  48. package/src/ProtoBuf/Builder/Message.js +107 -77
  49. package/src/ProtoBuf/Builder/Service.js +8 -5
  50. package/src/ProtoBuf/Builder.js +71 -37
  51. package/src/ProtoBuf/DotProto/Parser.js +108 -72
  52. package/src/ProtoBuf/DotProto/Tokenizer.js +17 -11
  53. package/src/ProtoBuf/Lang.js +1 -1
  54. package/src/ProtoBuf/Reflect/Enum/Value.js +3 -2
  55. package/src/ProtoBuf/Reflect/Enum.js +9 -5
  56. package/src/ProtoBuf/Reflect/Extension.js +4 -3
  57. package/src/ProtoBuf/Reflect/Message/ExtensionField.js +4 -3
  58. package/src/ProtoBuf/Reflect/Message/Field.js +45 -26
  59. package/src/ProtoBuf/Reflect/Message/OneOf.js +19 -0
  60. package/src/ProtoBuf/Reflect/Message.js +36 -19
  61. package/src/ProtoBuf/Reflect/Namespace.js +19 -15
  62. package/src/ProtoBuf/Reflect/Service/Method.js +9 -5
  63. package/src/ProtoBuf/Reflect/Service/RPCMethod.js +3 -2
  64. package/src/ProtoBuf/Reflect/Service.js +9 -5
  65. package/src/ProtoBuf/Reflect/T.js +20 -6
  66. package/src/ProtoBuf/Reflect.js +9 -0
  67. package/src/ProtoBuf/Util.js +132 -132
  68. package/src/ProtoBuf.js +15 -17
  69. package/src/google/protobuf/descriptor.json +33 -13
  70. package/tests/bench.txt +373 -373
  71. package/tests/complex.json +8 -4
  72. package/tests/custom-options.json +169 -169
  73. package/tests/extend.json +71 -71
  74. package/tests/nodeunit-browser/nodeunit.css +70 -70
  75. package/tests/nodeunit-browser/nodeunit.js +2108 -2108
  76. package/tests/oneof.proto +6 -0
  77. package/tests/options.json +32 -32
  78. package/tests/options.proto +2 -0
  79. package/tests/proto2js/Bar.json +46 -46
  80. package/tests/suite.js +83 -12
  81. package/.idea/.name +0 -1
  82. package/.idea/ProtoBuf.iml +0 -9
  83. package/.idea/dictionaries/Daniel.xml +0 -7
  84. package/.idea/encodings.xml +0 -5
  85. package/.idea/misc.xml +0 -5
  86. package/.idea/modules.xml +0 -9
  87. package/.idea/scopes/scope_settings.xml +0 -5
  88. package/.idea/vcs.xml +0 -7
  89. package/.idea/workspace.xml +0 -551
  90. package/NOTICE +0 -2
  91. package/sandbox/issue146/MyOptions.proto +0 -28
  92. package/sandbox/issue146/Sample.proto +0 -21
  93. package/sandbox/issue146/main.js +0 -3
  94. package/sandbox/issue147/enum.proto +0 -8
  95. package/sandbox/issue147/main.js +0 -3
  96. package/sandbox/issue42/innerextend.proto +0 -18
  97. package/sandbox/issue42/main.js +0 -8
  98. package/sandbox/issue42/outerextend.proto +0 -17
  99. package/v8.log +0 -3828
@@ -6,7 +6,7 @@
6
6
  /**
7
7
  * Constructs a new Parser.
8
8
  * @exports ProtoBuf.DotProto.Parser
9
- * @class proto parser
9
+ * @class prototype parser
10
10
  * @param {string} proto Protocol source
11
11
  * @constructor
12
12
  */
@@ -20,13 +20,19 @@ var Parser = function(proto) {
20
20
  this.tn = new Tokenizer(proto);
21
21
  };
22
22
 
23
+ /**
24
+ * @alias ProtoBuf.DotProto.Parser.prototype
25
+ * @inner
26
+ */
27
+ var ParserPrototype = Parser.prototype;
28
+
23
29
  /**
24
30
  * Runs the parser.
25
31
  * @return {{package: string|null, messages: Array.<object>, enums: Array.<object>, imports: Array.<string>, options: object<string,*>}}
26
32
  * @throws {Error} If the source cannot be parsed
27
33
  * @expose
28
34
  */
29
- Parser.prototype.parse = function() {
35
+ ParserPrototype.parse = function() {
30
36
  var topLevel = {
31
37
  "name": "[ROOT]", // temporary
32
38
  "package": null,
@@ -41,12 +47,12 @@ Parser.prototype.parse = function() {
41
47
  switch (token) {
42
48
  case 'package':
43
49
  if (!head || topLevel["package"] !== null)
44
- throw Error("Illegal package at line "+this.tn.line);
50
+ throw Error("Unexpected package at line "+this.tn.line);
45
51
  topLevel["package"] = this._parsePackage(token);
46
52
  break;
47
53
  case 'import':
48
54
  if (!head)
49
- throw Error("Illegal import at line "+this.tn.line);
55
+ throw Error("Unexpected import at line "+this.tn.line);
50
56
  topLevel.imports.push(this._parseImport(token));
51
57
  break;
52
58
  case 'message':
@@ -59,7 +65,7 @@ Parser.prototype.parse = function() {
59
65
  break;
60
66
  case 'option':
61
67
  if (!head)
62
- throw Error("Illegal option at line "+this.tn.line);
68
+ throw Error("Unexpected option at line "+this.tn.line);
63
69
  this._parseOption(topLevel, token);
64
70
  break;
65
71
  case 'service':
@@ -72,7 +78,7 @@ Parser.prototype.parse = function() {
72
78
  this._parseIgnoredStatement(topLevel, token);
73
79
  break;
74
80
  default:
75
- throw Error("Illegal token at line "+this.tn.line+": "+token);
81
+ throw Error("Unexpected token at line "+this.tn.line+": "+token);
76
82
  }
77
83
  }
78
84
  delete topLevel["name"];
@@ -86,7 +92,7 @@ Parser.prototype.parse = function() {
86
92
  * @throws {Error} If the number value is invalid
87
93
  * @private
88
94
  */
89
- Parser.prototype._parseNumber = function(val) {
95
+ ParserPrototype._parseNumber = function(val) {
90
96
  var sign = 1;
91
97
  if (val.charAt(0) == '-')
92
98
  sign = -1,
@@ -104,18 +110,17 @@ Parser.prototype._parseNumber = function(val) {
104
110
 
105
111
  /**
106
112
  * Parses a (possibly multiline) string.
107
- * @param {string} context Context description
108
113
  * @returns {string}
109
114
  * @private
110
115
  */
111
- Parser.prototype._parseString = function(context) {
116
+ ParserPrototype._parseString = function() {
112
117
  var value = "", token;
113
118
  do {
114
119
  token = this.tn.next(); // Known to be = this.tn.stringEndsWith
115
120
  value += this.tn.next();
116
121
  token = this.tn.next();
117
122
  if (token !== this.tn.stringEndsWith)
118
- throw Error("Illegal end of string in "+context+" at line "+this.tn.line+": "+token+" ('"+this.tn.stringEndsWith+"' expected)");
123
+ throw Error("Illegal end of string at line "+this.tn.line+": "+token);
119
124
  token = this.tn.peek();
120
125
  } while (token === Lang.STRINGOPEN || token === Lang.STRINGOPEN_SQ);
121
126
  return value;
@@ -129,7 +134,7 @@ Parser.prototype._parseString = function(context) {
129
134
  * @throws {Error} If the ID value is invalid
130
135
  * @private
131
136
  */
132
- Parser.prototype._parseId = function(val, neg) {
137
+ ParserPrototype._parseId = function(val, neg) {
133
138
  var id = -1;
134
139
  var sign = 1;
135
140
  if (val.charAt(0) == '-')
@@ -142,10 +147,10 @@ Parser.prototype._parseId = function(val, neg) {
142
147
  else if (Lang.NUMBER_OCT.test(val))
143
148
  id = parseInt(val.substring(1), 8);
144
149
  else
145
- throw Error("Illegal ID at line "+this.tn.line+": "+(sign < 0 ? '-' : '')+val);
150
+ throw Error("Illegal id at line "+this.tn.line+": "+(sign < 0 ? '-' : '')+val);
146
151
  id = (sign*id)|0; // Force to 32bit
147
152
  if (!neg && id < 0)
148
- throw Error("Illegal ID at line "+this.tn.line+": "+(sign < 0 ? '-' : '')+val);
153
+ throw Error("Illegal id at line "+this.tn.line+": "+(sign < 0 ? '-' : '')+val);
149
154
  return id;
150
155
  };
151
156
 
@@ -156,14 +161,14 @@ Parser.prototype._parseId = function(val, neg) {
156
161
  * @throws {Error} If the package definition cannot be parsed
157
162
  * @private
158
163
  */
159
- Parser.prototype._parsePackage = function(token) {
164
+ ParserPrototype._parsePackage = function(token) {
160
165
  token = this.tn.next();
161
166
  if (!Lang.TYPEREF.test(token))
162
- throw Error("Illegal package at line "+this.tn.line+": "+token);
167
+ throw Error("Illegal package name at line "+this.tn.line+": "+token);
163
168
  var pkg = token;
164
169
  token = this.tn.next();
165
170
  if (token != Lang.END)
166
- throw Error("Illegal end of package at line "+this.tn.line+": "+token+" ('"+Lang.END+"' expected)");
171
+ throw Error("Illegal end of package at line "+this.tn.line+": "+token);
167
172
  return pkg;
168
173
  };
169
174
 
@@ -174,17 +179,17 @@ Parser.prototype._parsePackage = function(token) {
174
179
  * @throws {Error} If the import definition cannot be parsed
175
180
  * @private
176
181
  */
177
- Parser.prototype._parseImport = function(token) {
182
+ ParserPrototype._parseImport = function(token) {
178
183
  token = this.tn.peek();
179
184
  if (token === "public")
180
185
  this.tn.next(),
181
186
  token = this.tn.peek();
182
187
  if (token !== Lang.STRINGOPEN && token !== Lang.STRINGOPEN_SQ)
183
- throw Error("Illegal import at line "+this.tn.line+": "+token+" ('"+Lang.STRINGOPEN+"' or '"+Lang.STRINGOPEN_SQ+"' expected)");
184
- var imported = this._parseString("root");
188
+ throw Error("Illegal start of import at line "+this.tn.line+": "+token);
189
+ var imported = this._parseString();
185
190
  token = this.tn.next();
186
191
  if (token !== Lang.END)
187
- throw Error("Illegal import at line "+this.tn.line+": "+token+" ('"+Lang.END+"' expected)");
192
+ throw Error("Illegal end of import at line "+this.tn.line+": "+token);
188
193
  return imported;
189
194
  };
190
195
 
@@ -195,7 +200,7 @@ Parser.prototype._parseImport = function(token) {
195
200
  * @throws {Error} If the option cannot be parsed
196
201
  * @private
197
202
  */
198
- Parser.prototype._parseOption = function(parent, token) {
203
+ ParserPrototype._parseOption = function(parent, token) {
199
204
  token = this.tn.next();
200
205
  var custom = false;
201
206
  if (token == Lang.COPTOPEN)
@@ -204,12 +209,12 @@ Parser.prototype._parseOption = function(parent, token) {
204
209
  if (!Lang.TYPEREF.test(token))
205
210
  // we can allow options of the form google.protobuf.* since they will just get ignored anyways
206
211
  if (!/google\.protobuf\./.test(token))
207
- throw Error("Illegal option in message "+parent.name+" at line "+this.tn.line+": "+token);
212
+ throw Error("Illegal option name in message "+parent.name+" at line "+this.tn.line+": "+token);
208
213
  var name = token;
209
214
  token = this.tn.next();
210
215
  if (custom) { // (my_method_option).foo, (my_method_option), some_method_option, (foo.my_option).bar
211
216
  if (token !== Lang.COPTCLOSE)
212
- throw Error("Illegal option in message "+parent.name+", option "+name+" at line "+this.tn.line+": "+token+" ('"+Lang.COPTCLOSE+"' expected)");
217
+ throw Error("Illegal end in message "+parent.name+", option "+name+" at line "+this.tn.line+": "+token);
213
218
  name = '('+name+')';
214
219
  token = this.tn.next();
215
220
  if (Lang.FQTYPEREF.test(token))
@@ -217,11 +222,11 @@ Parser.prototype._parseOption = function(parent, token) {
217
222
  token = this.tn.next();
218
223
  }
219
224
  if (token !== Lang.EQUAL)
220
- throw Error("Illegal option operator in message "+parent.name+", option "+name+" at line "+this.tn.line+": "+token+" ('"+Lang.EQUAL+"' expected)");
225
+ throw Error("Illegal operator in message "+parent.name+", option "+name+" at line "+this.tn.line+": "+token);
221
226
  var value;
222
227
  token = this.tn.peek();
223
228
  if (token === Lang.STRINGOPEN || token === Lang.STRINGOPEN_SQ)
224
- value = this._parseString("message "+parent.name+", option "+name);
229
+ value = this._parseString();
225
230
  else {
226
231
  this.tn.next();
227
232
  if (Lang.NUMBER.test(token))
@@ -235,7 +240,7 @@ Parser.prototype._parseOption = function(parent, token) {
235
240
  }
236
241
  token = this.tn.next();
237
242
  if (token !== Lang.END)
238
- throw Error("Illegal end of option in message "+parent.name+", option "+name+" at line "+this.tn.line+": "+token+" ('"+Lang.END+"' expected)");
243
+ throw Error("Illegal end of option in message "+parent.name+", option "+name+" at line "+this.tn.line+": "+token);
239
244
  parent["options"][name] = value;
240
245
  };
241
246
 
@@ -246,12 +251,12 @@ Parser.prototype._parseOption = function(parent, token) {
246
251
  * @throws {Error} If the directive cannot be parsed
247
252
  * @private
248
253
  */
249
- Parser.prototype._parseIgnoredStatement = function(parent, keyword) {
254
+ ParserPrototype._parseIgnoredStatement = function(parent, keyword) {
250
255
  var token;
251
256
  do {
252
257
  token = this.tn.next();
253
258
  if (token === null)
254
- throw Error("Unexpected EOF in "+parent.name+", "+keyword+" (ignored) at line "+this.tn.line);
259
+ throw Error("Unexpected EOF in "+parent.name+", "+keyword+" at line "+this.tn.line);
255
260
  if (token === Lang.END)
256
261
  break;
257
262
  } while (true);
@@ -264,7 +269,7 @@ Parser.prototype._parseIgnoredStatement = function(parent, keyword) {
264
269
  * @throws {Error} If the service cannot be parsed
265
270
  * @private
266
271
  */
267
- Parser.prototype._parseService = function(parent, token) {
272
+ ParserPrototype._parseService = function(parent, token) {
268
273
  token = this.tn.next();
269
274
  if (!Lang.NAME.test(token))
270
275
  throw Error("Illegal service name at line "+this.tn.line+": "+token);
@@ -276,7 +281,7 @@ Parser.prototype._parseService = function(parent, token) {
276
281
  };
277
282
  token = this.tn.next();
278
283
  if (token !== Lang.OPEN)
279
- throw Error("Illegal OPEN after service "+name+" at line "+this.tn.line+": "+token+" ('"+Lang.OPEN+"' expected)");
284
+ throw Error("Illegal start of service "+name+" at line "+this.tn.line+": "+token);
280
285
  do {
281
286
  token = this.tn.next();
282
287
  if (token === "option")
@@ -284,7 +289,7 @@ Parser.prototype._parseService = function(parent, token) {
284
289
  else if (token === 'rpc')
285
290
  this._parseServiceRPC(svc, token);
286
291
  else if (token !== Lang.CLOSE)
287
- throw Error("Illegal type for service "+name+" at line "+this.tn.line+": "+token);
292
+ throw Error("Illegal type of service "+name+" at line "+this.tn.line+": "+token);
288
293
  } while (token !== Lang.CLOSE);
289
294
  parent["services"].push(svc);
290
295
  };
@@ -295,11 +300,11 @@ Parser.prototype._parseService = function(parent, token) {
295
300
  * @param {string} token Initial token
296
301
  * @private
297
302
  */
298
- Parser.prototype._parseServiceRPC = function(svc, token) {
303
+ ParserPrototype._parseServiceRPC = function(svc, token) {
299
304
  var type = token;
300
305
  token = this.tn.next();
301
306
  if (!Lang.NAME.test(token))
302
- throw Error("Illegal RPC method name in service "+svc["name"]+" at line "+this.tn.line+": "+token);
307
+ throw Error("Illegal method name in service "+svc["name"]+" at line "+this.tn.line+": "+token);
303
308
  var name = token;
304
309
  var method = {
305
310
  "request": null,
@@ -308,25 +313,25 @@ Parser.prototype._parseServiceRPC = function(svc, token) {
308
313
  };
309
314
  token = this.tn.next();
310
315
  if (token !== Lang.COPTOPEN)
311
- throw Error("Illegal start of request type in RPC service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token+" ('"+Lang.COPTOPEN+"' expected)");
316
+ throw Error("Illegal start of request type in service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token);
312
317
  token = this.tn.next();
313
318
  if (!Lang.TYPEREF.test(token))
314
- throw Error("Illegal request type in RPC service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token);
319
+ throw Error("Illegal request type in service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token);
315
320
  method["request"] = token;
316
321
  token = this.tn.next();
317
322
  if (token != Lang.COPTCLOSE)
318
- throw Error("Illegal end of request type in RPC service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token+" ('"+Lang.COPTCLOSE+"' expected)");
323
+ throw Error("Illegal end of request type in service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token);
319
324
  token = this.tn.next();
320
325
  if (token.toLowerCase() !== "returns")
321
- throw Error("Illegal request/response delimiter in RPC service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token+" ('returns' expected)");
326
+ throw Error("Illegal delimiter in service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token);
322
327
  token = this.tn.next();
323
328
  if (token != Lang.COPTOPEN)
324
- throw Error("Illegal start of response type in RPC service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token+" ('"+Lang.COPTOPEN+"' expected)");
329
+ throw Error("Illegal start of response type in service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token);
325
330
  token = this.tn.next();
326
331
  method["response"] = token;
327
332
  token = this.tn.next();
328
333
  if (token !== Lang.COPTCLOSE)
329
- throw Error("Illegal end of response type in RPC service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token+" ('"+Lang.COPTCLOSE+"' expected)");
334
+ throw Error("Illegal end of response type in service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token);
330
335
  token = this.tn.next();
331
336
  if (token === Lang.OPEN) {
332
337
  do {
@@ -334,12 +339,12 @@ Parser.prototype._parseServiceRPC = function(svc, token) {
334
339
  if (token === 'option')
335
340
  this._parseOption(method, token); // <- will fail for the custom-options example
336
341
  else if (token !== Lang.CLOSE)
337
- throw Error("Illegal start of option in RPC service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token+" ('option' expected)");
342
+ throw Error("Illegal start of option inservice "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token);
338
343
  } while (token !== Lang.CLOSE);
339
344
  if (this.tn.peek() === Lang.END)
340
345
  this.tn.next();
341
346
  } else if (token !== Lang.END)
342
- throw Error("Illegal method delimiter in RPC service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token+" ('"+Lang.END+"' or '"+Lang.OPEN+"' expected)");
347
+ throw Error("Illegal delimiter in service "+svc["name"]+"#"+name+" at line "+this.tn.line+": "+token);
343
348
  if (typeof svc[type] === 'undefined')
344
349
  svc[type] = {};
345
350
  svc[type][name] = method;
@@ -354,7 +359,7 @@ Parser.prototype._parseServiceRPC = function(svc, token) {
354
359
  * @throws {Error} If the message cannot be parsed
355
360
  * @private
356
361
  */
357
- Parser.prototype._parseMessage = function(parent, fld, token) {
362
+ ParserPrototype._parseMessage = function(parent, fld, token) {
358
363
  /** @dict */
359
364
  var msg = {}; // Note: At some point we might want to exclude the parser, so we need a dict.
360
365
  var isGroup = token === "group";
@@ -365,7 +370,7 @@ Parser.prototype._parseMessage = function(parent, fld, token) {
365
370
  if (isGroup) {
366
371
  token = this.tn.next();
367
372
  if (token !== Lang.EQUAL)
368
- throw Error("Illegal id assignment after group "+msg.name+" at line "+this.tn.line+": "+token+" ('"+Lang.EQUAL+"' expected)");
373
+ throw Error("Illegal id assignment after group "+msg.name+" at line "+this.tn.line+": "+token);
369
374
  token = this.tn.next();
370
375
  try {
371
376
  fld["id"] = this._parseId(token);
@@ -378,12 +383,13 @@ Parser.prototype._parseMessage = function(parent, fld, token) {
378
383
  msg["enums"] = [];
379
384
  msg["messages"] = [];
380
385
  msg["options"] = {};
386
+ msg["oneofs"] = {};
381
387
  token = this.tn.next();
382
388
  if (token === Lang.OPTOPEN && fld)
383
389
  this._parseFieldOptions(msg, fld, token),
384
390
  token = this.tn.next();
385
391
  if (token !== Lang.OPEN)
386
- throw Error("Illegal OPEN after "+(isGroup ? "group" : "message")+" "+msg.name+" at line "+this.tn.line+": "+token+" ('"+Lang.OPEN+"' expected)");
392
+ throw Error("Illegal start of "+(isGroup ? "group" : "message")+" "+msg.name+" at line "+this.tn.line+": "+token);
387
393
  // msg["extensions"] = undefined
388
394
  do {
389
395
  token = this.tn.next();
@@ -394,6 +400,8 @@ Parser.prototype._parseMessage = function(parent, fld, token) {
394
400
  break;
395
401
  } else if (Lang.RULE.test(token))
396
402
  this._parseMessageField(msg, token);
403
+ else if (token === "oneof")
404
+ this._parseMessageOneOf(msg, token);
397
405
  else if (token === "enum")
398
406
  this._parseEnum(msg, token);
399
407
  else if (token === "message")
@@ -405,7 +413,7 @@ Parser.prototype._parseMessage = function(parent, fld, token) {
405
413
  else if (token === "extend")
406
414
  this._parseExtend(msg, token);
407
415
  else
408
- throw Error("Illegal token in message "+msg.name+" at line "+this.tn.line+": "+token+" (type or '"+Lang.CLOSE+"' expected)");
416
+ throw Error("Illegal token in message "+msg.name+" at line "+this.tn.line+": "+token);
409
417
  } while (true);
410
418
  parent["messages"].push(msg);
411
419
  return msg;
@@ -415,10 +423,11 @@ Parser.prototype._parseMessage = function(parent, fld, token) {
415
423
  * Parses a message field.
416
424
  * @param {Object} msg Message definition
417
425
  * @param {string} token Initial token
426
+ * @returns {!Object} Field descriptor
418
427
  * @throws {Error} If the message field cannot be parsed
419
428
  * @private
420
429
  */
421
- Parser.prototype._parseMessageField = function(msg, token) {
430
+ ParserPrototype._parseMessageField = function(msg, token) {
422
431
  /** @dict */
423
432
  var fld = {}, grp = null;
424
433
  fld["rule"] = token;
@@ -447,21 +456,48 @@ Parser.prototype._parseMessageField = function(msg, token) {
447
456
  fld["name"] = token;
448
457
  token = this.tn.next();
449
458
  if (token !== Lang.EQUAL)
450
- throw Error("Illegal field id assignment in message "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token+" ('"+Lang.EQUAL+"' expected)");
459
+ throw Error("Illegal token in field "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token);
451
460
  token = this.tn.next();
452
461
  try {
453
462
  fld["id"] = this._parseId(token);
454
463
  } catch (e) {
455
- throw Error("Illegal field id value in message "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token);
464
+ throw Error("Illegal field id in message "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token);
456
465
  }
457
466
  token = this.tn.next();
458
467
  if (token === Lang.OPTOPEN)
459
468
  this._parseFieldOptions(msg, fld, token),
460
469
  token = this.tn.next();
461
470
  if (token !== Lang.END)
462
- throw Error("Illegal field delimiter in message "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token+" ('"+Lang.END+"' expected)");
471
+ throw Error("Illegal delimiter in message "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token);
463
472
  }
464
473
  msg["fields"].push(fld);
474
+ return fld;
475
+ };
476
+
477
+ /**
478
+ * Parses a message oneof.
479
+ * @param {Object} msg Message definition
480
+ * @param {string} token Initial token
481
+ * @throws {Error} If the message oneof cannot be parsed
482
+ * @private
483
+ */
484
+ ParserPrototype._parseMessageOneOf = function(msg, token) {
485
+ token = this.tn.next();
486
+ if (!Lang.NAME.test(token))
487
+ throw Error("Illegal oneof name in message "+msg.name+" at line "+this.tn.line+": "+token);
488
+ var name = token,
489
+ fld;
490
+ var fields = [];
491
+ token = this.tn.next();
492
+ if (token !== Lang.OPEN)
493
+ throw Error("Illegal start of oneof "+name+" at line "+this.tn.line+": "+token);
494
+ while (this.tn.peek() !== Lang.CLOSE) {
495
+ fld = this._parseMessageField(msg, "optional");
496
+ fld["oneof"] = name;
497
+ fields.push(fld["id"]);
498
+ }
499
+ this.tn.next();
500
+ msg["oneofs"][name] = fields;
465
501
  };
466
502
 
467
503
  /**
@@ -472,7 +508,7 @@ Parser.prototype._parseMessageField = function(msg, token) {
472
508
  * @throws {Error} If the message field options cannot be parsed
473
509
  * @private
474
510
  */
475
- Parser.prototype._parseFieldOptions = function(msg, fld, token) {
511
+ ParserPrototype._parseFieldOptions = function(msg, fld, token) {
476
512
  var first = true;
477
513
  do {
478
514
  token = this.tn.next();
@@ -480,7 +516,7 @@ Parser.prototype._parseFieldOptions = function(msg, fld, token) {
480
516
  break;
481
517
  else if (token === Lang.OPTEND) {
482
518
  if (first)
483
- throw Error("Illegal start of message field options in message "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token);
519
+ throw Error("Illegal start of options in message "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token);
484
520
  token = this.tn.next();
485
521
  }
486
522
  this._parseFieldOption(msg, fld, token);
@@ -496,18 +532,18 @@ Parser.prototype._parseFieldOptions = function(msg, fld, token) {
496
532
  * @throws {Error} If the mesage field option cannot be parsed
497
533
  * @private
498
534
  */
499
- Parser.prototype._parseFieldOption = function(msg, fld, token) {
535
+ ParserPrototype._parseFieldOption = function(msg, fld, token) {
500
536
  var custom = false;
501
537
  if (token === Lang.COPTOPEN)
502
538
  token = this.tn.next(),
503
539
  custom = true;
504
540
  if (!Lang.TYPEREF.test(token))
505
- throw Error("Illegal field option in message "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token);
541
+ throw Error("Illegal field option in "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token);
506
542
  var name = token;
507
543
  token = this.tn.next();
508
544
  if (custom) {
509
545
  if (token !== Lang.COPTCLOSE)
510
- throw Error("Illegal custom field option name delimiter in message "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token+" (')' expected)");
546
+ throw Error("Illegal delimiter in "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token);
511
547
  name = '('+name+')';
512
548
  token = this.tn.next();
513
549
  if (Lang.FQTYPEREF.test(token))
@@ -515,11 +551,11 @@ Parser.prototype._parseFieldOption = function(msg, fld, token) {
515
551
  token = this.tn.next();
516
552
  }
517
553
  if (token !== Lang.EQUAL)
518
- throw Error("Illegal field option operation in message "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token+" ('=' expected)");
554
+ throw Error("Illegal token in "+msg.name+"#"+fld.name+" at line "+this.tn.line+": "+token);
519
555
  var value;
520
556
  token = this.tn.peek();
521
557
  if (token === Lang.STRINGOPEN || token === Lang.STRINGOPEN_SQ) {
522
- value = this._parseString("message "+msg.name+"#"+fld.name);
558
+ value = this._parseString();
523
559
  } else if (Lang.NUMBER.test(token, true))
524
560
  value = this._parseNumber(this.tn.next(), true);
525
561
  else if (Lang.BOOL.test(token))
@@ -527,7 +563,7 @@ Parser.prototype._parseFieldOption = function(msg, fld, token) {
527
563
  else if (Lang.TYPEREF.test(token))
528
564
  value = this.tn.next(); // TODO: Resolve?
529
565
  else
530
- throw Error("Illegal field option value in message "+msg.name+"#"+fld.name+", option "+name+" at line "+this.tn.line+": "+token);
566
+ throw Error("Illegal value in message "+msg.name+"#"+fld.name+", option "+name+" at line "+this.tn.line+": "+token);
531
567
  fld["options"][name] = value;
532
568
  };
533
569
 
@@ -538,7 +574,7 @@ Parser.prototype._parseFieldOption = function(msg, fld, token) {
538
574
  * @throws {Error} If the enum cannot be parsed
539
575
  * @private
540
576
  */
541
- Parser.prototype._parseEnum = function(msg, token) {
577
+ ParserPrototype._parseEnum = function(msg, token) {
542
578
  /** @dict */
543
579
  var enm = {};
544
580
  token = this.tn.next();
@@ -547,7 +583,7 @@ Parser.prototype._parseEnum = function(msg, token) {
547
583
  enm["name"] = token;
548
584
  token = this.tn.next();
549
585
  if (token !== Lang.OPEN)
550
- throw Error("Illegal OPEN after enum "+enm.name+" at line "+this.tn.line+": "+token);
586
+ throw Error("Illegal start of enum "+enm.name+" at line "+this.tn.line+": "+token);
551
587
  enm["values"] = [];
552
588
  enm["options"] = {};
553
589
  do {
@@ -562,7 +598,7 @@ Parser.prototype._parseEnum = function(msg, token) {
562
598
  this._parseOption(enm, token);
563
599
  else {
564
600
  if (!Lang.NAME.test(token))
565
- throw Error("Illegal enum value name in enum "+enm.name+" at line "+this.tn.line+": "+token);
601
+ throw Error("Illegal name in enum "+enm.name+" at line "+this.tn.line+": "+token);
566
602
  this._parseEnumValue(enm, token);
567
603
  }
568
604
  } while (true);
@@ -576,18 +612,18 @@ Parser.prototype._parseEnum = function(msg, token) {
576
612
  * @throws {Error} If the enum value cannot be parsed
577
613
  * @private
578
614
  */
579
- Parser.prototype._parseEnumValue = function(enm, token) {
615
+ ParserPrototype._parseEnumValue = function(enm, token) {
580
616
  /** @dict */
581
617
  var val = {};
582
618
  val["name"] = token;
583
619
  token = this.tn.next();
584
620
  if (token !== Lang.EQUAL)
585
- throw Error("Illegal enum value operator in enum "+enm.name+" at line "+this.tn.line+": "+token+" ('"+Lang.EQUAL+"' expected)");
621
+ throw Error("Illegal token in enum "+enm.name+" at line "+this.tn.line+": "+token);
586
622
  token = this.tn.next();
587
623
  try {
588
624
  val["id"] = this._parseId(token, true);
589
625
  } catch (e) {
590
- throw Error("Illegal enum value id in enum "+enm.name+" at line "+this.tn.line+": "+token);
626
+ throw Error("Illegal id in enum "+enm.name+" at line "+this.tn.line+": "+token);
591
627
  }
592
628
  enm["values"].push(val);
593
629
  token = this.tn.next();
@@ -597,7 +633,7 @@ Parser.prototype._parseEnumValue = function(enm, token) {
597
633
  token = this.tn.next();
598
634
  }
599
635
  if (token !== Lang.END)
600
- throw Error("Illegal enum value delimiter in enum "+enm.name+" at line "+this.tn.line+": "+token+" ('"+Lang.END+"' expected)");
636
+ throw Error("Illegal delimiter in enum "+enm.name+" at line "+this.tn.line+": "+token);
601
637
  };
602
638
 
603
639
  /**
@@ -607,7 +643,7 @@ Parser.prototype._parseEnumValue = function(enm, token) {
607
643
  * @throws {Error} If the extensions statement cannot be parsed
608
644
  * @private
609
645
  */
610
- Parser.prototype._parseExtensions = function(msg, token) {
646
+ ParserPrototype._parseExtensions = function(msg, token) {
611
647
  /** @type {Array.<number>} */
612
648
  var range = [];
613
649
  token = this.tn.next();
@@ -619,7 +655,7 @@ Parser.prototype._parseExtensions = function(msg, token) {
619
655
  range.push(this._parseNumber(token));
620
656
  token = this.tn.next();
621
657
  if (token !== 'to')
622
- throw Error("Illegal extensions delimiter in message "+msg.name+" at line "+this.tn.line+" ('to' expected)");
658
+ throw Error("Illegal extensions delimiter in message "+msg.name+" at line "+this.tn.line+": "+token);
623
659
  token = this.tn.next();
624
660
  if (token === "min")
625
661
  range.push(ProtoBuf.ID_MIN);
@@ -629,7 +665,7 @@ Parser.prototype._parseExtensions = function(msg, token) {
629
665
  range.push(this._parseNumber(token));
630
666
  token = this.tn.next();
631
667
  if (token !== Lang.END)
632
- throw Error("Illegal extension delimiter in message "+msg.name+" at line "+this.tn.line+": "+token+" ('"+Lang.END+"' expected)");
668
+ throw Error("Illegal extensions delimiter in message "+msg.name+" at line "+this.tn.line+": "+token);
633
669
  return range;
634
670
  };
635
671
 
@@ -640,17 +676,17 @@ Parser.prototype._parseExtensions = function(msg, token) {
640
676
  * @throws {Error} If the extend block cannot be parsed
641
677
  * @private
642
678
  */
643
- Parser.prototype._parseExtend = function(parent, token) {
679
+ ParserPrototype._parseExtend = function(parent, token) {
644
680
  token = this.tn.next();
645
681
  if (!Lang.TYPEREF.test(token))
646
- throw Error("Illegal extended message name at line "+this.tn.line+": "+token);
682
+ throw Error("Illegal message name at line "+this.tn.line+": "+token);
647
683
  /** @dict */
648
684
  var ext = {};
649
685
  ext["ref"] = token;
650
686
  ext["fields"] = [];
651
687
  token = this.tn.next();
652
688
  if (token !== Lang.OPEN)
653
- throw Error("Illegal OPEN in extend "+ext.name+" at line "+this.tn.line+": "+token+" ('"+Lang.OPEN+"' expected)");
689
+ throw Error("Illegal start of extend "+ext.name+" at line "+this.tn.line+": "+token);
654
690
  do {
655
691
  token = this.tn.next();
656
692
  if (token === Lang.CLOSE) {
@@ -661,7 +697,7 @@ Parser.prototype._parseExtend = function(parent, token) {
661
697
  } else if (Lang.RULE.test(token))
662
698
  this._parseMessageField(ext, token);
663
699
  else
664
- throw Error("Illegal token in extend "+ext.name+" at line "+this.tn.line+": "+token+" (rule or '"+Lang.CLOSE+"' expected)");
700
+ throw Error("Illegal token in extend "+ext.name+" at line "+this.tn.line+": "+token);
665
701
  } while (true);
666
702
  parent["messages"].push(ext);
667
703
  return ext;
@@ -671,6 +707,6 @@ Parser.prototype._parseExtend = function(parent, token) {
671
707
  * Returns a string representation of this object.
672
708
  * @returns {string} String representation as of "Parser"
673
709
  */
674
- Parser.prototype.toString = function() {
710
+ ParserPrototype.toString = function() {
675
711
  return "Parser";
676
712
  };