protobufjs 8.1.6-experimental → 8.2.0
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.
- package/README.md +219 -565
- package/dist/light/protobuf.js +1986 -1483
- package/dist/light/protobuf.js.map +1 -1
- package/dist/light/protobuf.min.js +3 -3
- package/dist/light/protobuf.min.js.map +1 -1
- package/dist/minimal/protobuf.js +1122 -861
- package/dist/minimal/protobuf.js.map +1 -1
- package/dist/minimal/protobuf.min.js +3 -3
- package/dist/minimal/protobuf.min.js.map +1 -1
- package/dist/protobuf.js +2089 -1513
- package/dist/protobuf.js.map +1 -1
- package/dist/protobuf.min.js +3 -3
- package/dist/protobuf.min.js.map +1 -1
- package/ext/README.md +81 -0
- package/ext/descriptor/README.md +3 -70
- package/ext/descriptor/index.d.ts +1 -191
- package/ext/descriptor/index.js +1 -1161
- package/ext/descriptor.d.ts +309 -0
- package/ext/descriptor.js +1236 -0
- package/ext/textformat.d.ts +30 -0
- package/ext/textformat.js +1249 -0
- package/google/protobuf/compiler/plugin.json +126 -0
- package/google/protobuf/compiler/plugin.proto +47 -0
- package/google/protobuf/descriptor.json +2 -2
- package/google/protobuf/descriptor.proto +2 -1
- package/index.d.ts +590 -476
- package/package.json +23 -38
- package/src/converter.js +60 -24
- package/src/decoder.js +122 -49
- package/src/encoder.js +10 -2
- package/src/enum.js +4 -1
- package/src/field.js +10 -7
- package/src/mapfield.js +1 -0
- package/src/message.js +7 -6
- package/src/method.js +4 -3
- package/src/namespace.js +23 -12
- package/src/object.js +24 -19
- package/src/oneof.js +2 -0
- package/src/parse.js +114 -46
- package/src/reader.js +145 -30
- package/src/reader_buffer.js +24 -3
- package/src/root.js +7 -4
- package/src/service.js +12 -6
- package/src/tokenize.js +6 -1
- package/src/type.js +48 -25
- package/src/types.js +1 -1
- package/src/util/aspromise.d.ts +13 -0
- package/src/util/aspromise.js +52 -0
- package/src/util/base64.d.ts +32 -0
- package/src/util/base64.js +146 -0
- package/src/util/codegen.d.ts +31 -0
- package/src/util/codegen.js +113 -0
- package/src/util/eventemitter.d.ts +45 -0
- package/src/util/eventemitter.js +84 -0
- package/src/util/fetch.d.ts +56 -0
- package/src/util/fetch.js +112 -0
- package/src/util/float.d.ts +83 -0
- package/src/util/float.js +335 -0
- package/src/util/fs.js +11 -0
- package/src/util/inquire.d.ts +10 -0
- package/src/util/inquire.js +38 -0
- package/src/util/minimal.js +67 -12
- package/src/util/path.d.ts +22 -0
- package/src/util/path.js +72 -0
- package/src/util/patterns.js +8 -0
- package/src/util/pool.d.ts +32 -0
- package/src/util/pool.js +48 -0
- package/src/util/utf8.d.ts +24 -0
- package/src/util/utf8.js +104 -0
- package/src/util.js +30 -13
- package/src/verifier.js +7 -4
- package/src/wrappers.js +4 -3
- package/src/writer.js +27 -4
- package/src/writer_buffer.js +12 -0
- package/tsconfig.json +2 -2
- package/ext/descriptor/test.js +0 -54
|
@@ -0,0 +1,1249 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var protobuf = require("../light");
|
|
3
|
+
|
|
4
|
+
var Type = protobuf.Type,
|
|
5
|
+
Enum = protobuf.Enum,
|
|
6
|
+
Field = protobuf.Field,
|
|
7
|
+
Reader = protobuf.Reader,
|
|
8
|
+
types = protobuf.types,
|
|
9
|
+
util = protobuf.util;
|
|
10
|
+
|
|
11
|
+
var textformat = protobuf.textformat = module.exports = {};
|
|
12
|
+
|
|
13
|
+
var recursionLimit;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Maximum recursion depth for text format parsing and formatting. Defaults to util.recursionLimit.
|
|
17
|
+
* @type {number}
|
|
18
|
+
*/
|
|
19
|
+
Object.defineProperty(textformat, "recursionLimit", {
|
|
20
|
+
get: function get() {
|
|
21
|
+
return recursionLimit === undefined ? util.recursionLimit : recursionLimit;
|
|
22
|
+
},
|
|
23
|
+
set: function set(value) {
|
|
24
|
+
recursionLimit = value == null ? undefined : value;
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Maximum recursion depth for formatting length-delimited unknown fields.
|
|
30
|
+
* @type {number}
|
|
31
|
+
*/
|
|
32
|
+
textformat.unknownRecursionLimit = 10;
|
|
33
|
+
|
|
34
|
+
var punct = {
|
|
35
|
+
"{": true,
|
|
36
|
+
"}": true,
|
|
37
|
+
"<": true,
|
|
38
|
+
">": true,
|
|
39
|
+
":": true,
|
|
40
|
+
"[": true,
|
|
41
|
+
"]": true,
|
|
42
|
+
",": true,
|
|
43
|
+
";": true,
|
|
44
|
+
"-": true
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
var identRe = /^[A-Za-z_][A-Za-z0-9_]*$/,
|
|
48
|
+
numberStartRe = /[0-9]/,
|
|
49
|
+
wordCharRe = /[A-Za-z0-9_]/,
|
|
50
|
+
hexRe = /^[0-9A-Fa-f]$/,
|
|
51
|
+
octRe = /^[0-7]$/,
|
|
52
|
+
floatRe = /^(?:[0-9]+\.[0-9]*(?:[eE][+-]?[0-9]+)?[fF]?|\.[0-9]+(?:[eE][+-]?[0-9]+)?[fF]?|[0-9]+[eE][+-]?[0-9]+[fF]?|[0-9]+[fF])/,
|
|
53
|
+
hexIntRe = /^0[xX][0-9A-Fa-f]+/,
|
|
54
|
+
octIntRe = /^0[0-7]+/,
|
|
55
|
+
decIntRe = /^(?:0|[1-9][0-9]*)/;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Parses protobuf text format using the specified reflected message type.
|
|
59
|
+
* @param {Type} type Reflected message type
|
|
60
|
+
* @param {string} text Text format input
|
|
61
|
+
* @returns {Message<{}>} Message instance
|
|
62
|
+
*/
|
|
63
|
+
function parseText(type, text) {
|
|
64
|
+
if (!(type instanceof Type))
|
|
65
|
+
throw TypeError("type must be a Type");
|
|
66
|
+
type.root.resolveAll();
|
|
67
|
+
var parser = new Parser(String(text));
|
|
68
|
+
var object = parser.parseMessage(type, null, 0);
|
|
69
|
+
parser.expectEnd();
|
|
70
|
+
var err = verifyTextMessage(type, object),
|
|
71
|
+
message;
|
|
72
|
+
if (err)
|
|
73
|
+
throw Error(err);
|
|
74
|
+
message = type.create(object);
|
|
75
|
+
return message;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Formats a message as protobuf text format using the specified reflected type.
|
|
80
|
+
* @param {Type} type Reflected message type
|
|
81
|
+
* @param {Message<{}>|Object.<string,*>} message Message instance or plain object
|
|
82
|
+
* @param {Object} [options] Text format options
|
|
83
|
+
* @param {boolean} [options.unknowns=false] Includes and formats unknown fields
|
|
84
|
+
* @returns {string} Text format output
|
|
85
|
+
*/
|
|
86
|
+
function formatText(type, message, options) {
|
|
87
|
+
if (!(type instanceof Type))
|
|
88
|
+
throw TypeError("type must be a Type");
|
|
89
|
+
type.root.resolveAll();
|
|
90
|
+
var lines = [];
|
|
91
|
+
writeMessage(type, message, lines, 0, options || {}, 0, textformat.recursionLimit);
|
|
92
|
+
return lines.join("\n");
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Parses this type from protobuf text format.
|
|
97
|
+
* @param {string} text Text format input
|
|
98
|
+
* @returns {Message<{}>} Message instance
|
|
99
|
+
*/
|
|
100
|
+
Type.prototype.fromText = function fromText(text) {
|
|
101
|
+
return parseText(this, text);
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Formats a message of this type as protobuf text format.
|
|
106
|
+
* @param {Message<{}>|Object.<string,*>} message Message instance or plain object
|
|
107
|
+
* @param {Object} [options] Text format options
|
|
108
|
+
* @returns {string} Text format output
|
|
109
|
+
*/
|
|
110
|
+
Type.prototype.toText = function toText(message, options) {
|
|
111
|
+
return formatText(this, message, options);
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
function Tokenizer(source) {
|
|
115
|
+
this.source = source;
|
|
116
|
+
this.pos = 0;
|
|
117
|
+
this.len = source.length;
|
|
118
|
+
this.line = 1;
|
|
119
|
+
this.stack = [];
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
Tokenizer.prototype.error = function error(message) {
|
|
123
|
+
return Error(message + " (line " + this.line + ")");
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
Tokenizer.prototype.peek = function peek() {
|
|
127
|
+
var token = this.next();
|
|
128
|
+
this.push(token);
|
|
129
|
+
return token;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
Tokenizer.prototype.push = function push(token) {
|
|
133
|
+
if (token)
|
|
134
|
+
this.stack.unshift(token);
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
Tokenizer.prototype.next = function next() {
|
|
138
|
+
if (this.stack.length)
|
|
139
|
+
return this.stack.shift();
|
|
140
|
+
this.skipSpace();
|
|
141
|
+
if (this.pos >= this.len)
|
|
142
|
+
return null;
|
|
143
|
+
|
|
144
|
+
var ch = this.source.charAt(this.pos);
|
|
145
|
+
if (ch === "\"" || ch === "'")
|
|
146
|
+
return this.readString(ch);
|
|
147
|
+
if (ch === "." && numberStartRe.test(this.source.charAt(this.pos + 1)) || numberStartRe.test(ch))
|
|
148
|
+
return this.readNumber();
|
|
149
|
+
if (punct[ch]) {
|
|
150
|
+
++this.pos;
|
|
151
|
+
return { type: "punct", value: ch, raw: ch, line: this.line };
|
|
152
|
+
}
|
|
153
|
+
return this.readWord();
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
Tokenizer.prototype.expect = function expect(value) {
|
|
157
|
+
var token = this.next();
|
|
158
|
+
if (!token || token.value !== value)
|
|
159
|
+
throw this.error("expected '" + value + "'");
|
|
160
|
+
return token;
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
Tokenizer.prototype.skip = function skip(value) {
|
|
164
|
+
var token = this.next();
|
|
165
|
+
if (token && token.value === value)
|
|
166
|
+
return true;
|
|
167
|
+
this.push(token);
|
|
168
|
+
return false;
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
Tokenizer.prototype.skipSpace = function skipSpace() {
|
|
172
|
+
var ch;
|
|
173
|
+
while (this.pos < this.len) {
|
|
174
|
+
ch = this.source.charAt(this.pos);
|
|
175
|
+
if (ch === "#") {
|
|
176
|
+
while (this.pos < this.len && this.source.charAt(this.pos) !== "\n")
|
|
177
|
+
++this.pos;
|
|
178
|
+
} else if (ch === " " || ch === "\t" || ch === "\v" || ch === "\f" || ch === "\r") {
|
|
179
|
+
++this.pos;
|
|
180
|
+
} else if (ch === "\n") {
|
|
181
|
+
++this.pos;
|
|
182
|
+
++this.line;
|
|
183
|
+
} else
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
Tokenizer.prototype.readWord = function readWord() {
|
|
189
|
+
var start = this.pos,
|
|
190
|
+
ch;
|
|
191
|
+
while (this.pos < this.len) {
|
|
192
|
+
ch = this.source.charAt(this.pos);
|
|
193
|
+
if (ch === "#" || ch === "\"" || ch === "'" || punct[ch] || /\s/.test(ch))
|
|
194
|
+
break;
|
|
195
|
+
++this.pos;
|
|
196
|
+
}
|
|
197
|
+
if (start === this.pos)
|
|
198
|
+
throw this.error("illegal character '" + this.source.charAt(this.pos) + "'");
|
|
199
|
+
var raw = this.source.substring(start, this.pos);
|
|
200
|
+
return { type: "word", value: raw, raw: raw, line: this.line };
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
Tokenizer.prototype.readNumber = function readNumber() {
|
|
204
|
+
var rest = this.source.substring(this.pos),
|
|
205
|
+
matches = [
|
|
206
|
+
floatRe.exec(rest),
|
|
207
|
+
hexIntRe.exec(rest),
|
|
208
|
+
octIntRe.exec(rest),
|
|
209
|
+
decIntRe.exec(rest)
|
|
210
|
+
],
|
|
211
|
+
raw = null;
|
|
212
|
+
for (var i = 0; i < matches.length; ++i)
|
|
213
|
+
if (matches[i] && (!raw || matches[i][0].length > raw.length))
|
|
214
|
+
raw = matches[i][0];
|
|
215
|
+
if (!raw)
|
|
216
|
+
throw this.error("illegal number");
|
|
217
|
+
this.pos += raw.length;
|
|
218
|
+
if (this.pos < this.len && wordCharRe.test(this.source.charAt(this.pos)))
|
|
219
|
+
throw this.error("illegal number '" + raw + this.source.charAt(this.pos) + "'");
|
|
220
|
+
return { type: "number", value: raw, raw: raw, line: this.line };
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
Tokenizer.prototype.readString = function readString(quote) {
|
|
224
|
+
var bytes = [],
|
|
225
|
+
ch,
|
|
226
|
+
code;
|
|
227
|
+
++this.pos;
|
|
228
|
+
while (this.pos < this.len) {
|
|
229
|
+
ch = this.source.charAt(this.pos++);
|
|
230
|
+
if (ch === quote)
|
|
231
|
+
return { type: "string", value: bytes, raw: quote, line: this.line };
|
|
232
|
+
if (ch === "\n")
|
|
233
|
+
throw this.error("illegal string");
|
|
234
|
+
if (ch !== "\\") {
|
|
235
|
+
code = ch.charCodeAt(0);
|
|
236
|
+
if ((code & 0xFC00) === 0xD800 && this.pos < this.len) {
|
|
237
|
+
var next = this.source.charCodeAt(this.pos);
|
|
238
|
+
if ((next & 0xFC00) === 0xDC00) {
|
|
239
|
+
++this.pos;
|
|
240
|
+
code = 0x10000 + ((code & 0x03FF) << 10) + (next & 0x03FF);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
pushUtf8(bytes, code);
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
246
|
+
if (this.pos >= this.len)
|
|
247
|
+
throw this.error("illegal string escape");
|
|
248
|
+
ch = this.source.charAt(this.pos++);
|
|
249
|
+
switch (ch) {
|
|
250
|
+
case "a": bytes.push(7); break;
|
|
251
|
+
case "b": bytes.push(8); break;
|
|
252
|
+
case "f": bytes.push(12); break;
|
|
253
|
+
case "n": bytes.push(10); break;
|
|
254
|
+
case "r": bytes.push(13); break;
|
|
255
|
+
case "t": bytes.push(9); break;
|
|
256
|
+
case "v": bytes.push(11); break;
|
|
257
|
+
case "?": bytes.push(63); break;
|
|
258
|
+
case "\\": bytes.push(92); break;
|
|
259
|
+
case "'": bytes.push(39); break;
|
|
260
|
+
case "\"": bytes.push(34); break;
|
|
261
|
+
case "x":
|
|
262
|
+
case "X":
|
|
263
|
+
bytes.push(this.readHexEscape());
|
|
264
|
+
break;
|
|
265
|
+
case "u":
|
|
266
|
+
pushUtf8(bytes, this.readCodePoint(4));
|
|
267
|
+
break;
|
|
268
|
+
case "U":
|
|
269
|
+
pushUtf8(bytes, this.readCodePoint(8));
|
|
270
|
+
break;
|
|
271
|
+
default:
|
|
272
|
+
if (octRe.test(ch)) {
|
|
273
|
+
bytes.push(this.readOctEscape(ch));
|
|
274
|
+
break;
|
|
275
|
+
}
|
|
276
|
+
throw this.error("illegal string escape '\\" + ch + "'");
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
throw this.error("unterminated string");
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
Tokenizer.prototype.readHexEscape = function readHexEscape() {
|
|
283
|
+
var value = 0,
|
|
284
|
+
count = 0,
|
|
285
|
+
ch;
|
|
286
|
+
while (count < 2 && this.pos < this.len && hexRe.test(ch = this.source.charAt(this.pos))) {
|
|
287
|
+
value = value * 16 + parseInt(ch, 16);
|
|
288
|
+
++this.pos;
|
|
289
|
+
++count;
|
|
290
|
+
}
|
|
291
|
+
if (!count)
|
|
292
|
+
throw this.error("illegal hex escape");
|
|
293
|
+
return value;
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
Tokenizer.prototype.readOctEscape = function readOctEscape(first) {
|
|
297
|
+
var value = parseInt(first, 8),
|
|
298
|
+
count = 1,
|
|
299
|
+
ch;
|
|
300
|
+
while (count < 3 && this.pos < this.len && octRe.test(ch = this.source.charAt(this.pos))) {
|
|
301
|
+
value = value * 8 + parseInt(ch, 8);
|
|
302
|
+
++this.pos;
|
|
303
|
+
++count;
|
|
304
|
+
}
|
|
305
|
+
return value & 255;
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
Tokenizer.prototype.readCodePoint = function readCodePoint(size) {
|
|
309
|
+
var raw = this.source.substring(this.pos, this.pos + size);
|
|
310
|
+
if (raw.length !== size || !/^[0-9A-Fa-f]+$/.test(raw))
|
|
311
|
+
throw this.error("illegal unicode escape");
|
|
312
|
+
this.pos += size;
|
|
313
|
+
var code = parseInt(raw, 16);
|
|
314
|
+
if (code > 0x10FFFF || code >= 0xD800 && code <= 0xDFFF)
|
|
315
|
+
throw this.error("illegal unicode escape");
|
|
316
|
+
return code;
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
function Parser(source) {
|
|
320
|
+
this.tn = new Tokenizer(source);
|
|
321
|
+
this.recursionLimit = textformat.recursionLimit;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
Parser.prototype.error = function error(message) {
|
|
325
|
+
throw this.tn.error(message);
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
Parser.prototype.expectEnd = function expectEnd() {
|
|
329
|
+
var token = this.tn.next();
|
|
330
|
+
if (token)
|
|
331
|
+
this.error("unexpected token '" + token.value + "'");
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
Parser.prototype.checkRecursion = function checkRecursion(depth) {
|
|
335
|
+
if (depth > this.recursionLimit)
|
|
336
|
+
this.error("max depth exceeded");
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
Parser.prototype.parseMessage = function parseMessage(type, end, depth) {
|
|
340
|
+
this.checkRecursion(depth);
|
|
341
|
+
var object = {},
|
|
342
|
+
seen = {};
|
|
343
|
+
for (;;) {
|
|
344
|
+
var token = this.tn.peek();
|
|
345
|
+
if (!token) {
|
|
346
|
+
if (end)
|
|
347
|
+
this.error("expected '" + end + "'");
|
|
348
|
+
return object;
|
|
349
|
+
}
|
|
350
|
+
if (end && token.value === end) {
|
|
351
|
+
this.tn.next();
|
|
352
|
+
return object;
|
|
353
|
+
}
|
|
354
|
+
if (isSeparator(token))
|
|
355
|
+
this.error("unexpected separator");
|
|
356
|
+
this.parseField(type, object, seen, depth);
|
|
357
|
+
token = this.tn.peek();
|
|
358
|
+
if (token && isSeparator(token)) {
|
|
359
|
+
this.tn.next();
|
|
360
|
+
token = this.tn.peek();
|
|
361
|
+
if (token && isSeparator(token))
|
|
362
|
+
this.error("unexpected separator");
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
};
|
|
366
|
+
|
|
367
|
+
Parser.prototype.parseField = function parseField(type, object, seen, depth) {
|
|
368
|
+
var info = this.readFieldName(type);
|
|
369
|
+
if (info.any) {
|
|
370
|
+
this.parseAny(type, info.name, object, seen, depth);
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
if (!info.field) {
|
|
374
|
+
this.skipReservedValue(depth);
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
var field = info.field.resolve();
|
|
379
|
+
if (field.map) {
|
|
380
|
+
this.parseMessageFieldDelimiter();
|
|
381
|
+
this.parseMapField(field, object, depth);
|
|
382
|
+
} else if (field.resolvedType instanceof Type) {
|
|
383
|
+
this.parseMessageFieldDelimiter();
|
|
384
|
+
if (this.tn.skip("[")) {
|
|
385
|
+
if (!field.repeated)
|
|
386
|
+
this.error(field.fullName + ": list value specified for singular field");
|
|
387
|
+
if (!this.tn.skip("]")) {
|
|
388
|
+
do {
|
|
389
|
+
addField(object, seen, field, this.parseMessageValue(field.resolvedType, depth));
|
|
390
|
+
} while (this.tn.skip(","));
|
|
391
|
+
this.tn.expect("]");
|
|
392
|
+
}
|
|
393
|
+
} else
|
|
394
|
+
addField(object, seen, field, this.parseMessageValue(field.resolvedType, depth));
|
|
395
|
+
} else {
|
|
396
|
+
this.tn.expect(":");
|
|
397
|
+
if (this.tn.skip("[")) {
|
|
398
|
+
if (!field.repeated)
|
|
399
|
+
this.error(field.fullName + ": list value specified for singular field");
|
|
400
|
+
if (!this.tn.skip("]")) {
|
|
401
|
+
do {
|
|
402
|
+
addField(object, seen, field, this.parseScalar(field));
|
|
403
|
+
} while (this.tn.skip(","));
|
|
404
|
+
this.tn.expect("]");
|
|
405
|
+
}
|
|
406
|
+
} else
|
|
407
|
+
addField(object, seen, field, this.parseScalar(field));
|
|
408
|
+
}
|
|
409
|
+
};
|
|
410
|
+
|
|
411
|
+
Parser.prototype.readFieldName = function readFieldName(type) {
|
|
412
|
+
var token = this.tn.next();
|
|
413
|
+
if (!token)
|
|
414
|
+
this.error("expected field name");
|
|
415
|
+
if (token.value === "[") {
|
|
416
|
+
var bracketName = this.readBracketName();
|
|
417
|
+
if (type.fullName === ".google.protobuf.Any" && bracketName.indexOf("/") >= 0)
|
|
418
|
+
return { any: true, name: bracketName };
|
|
419
|
+
return { field: lookupExtension(type, bracketName), name: bracketName };
|
|
420
|
+
}
|
|
421
|
+
if (token.type !== "word" || !identRe.test(token.value))
|
|
422
|
+
this.error("illegal field name '" + token.value + "'");
|
|
423
|
+
|
|
424
|
+
var field = lookupField(type, token.value);
|
|
425
|
+
if (!field) {
|
|
426
|
+
if (type.isReservedName(token.value))
|
|
427
|
+
return { name: token.value };
|
|
428
|
+
this.error(type.fullName + ": unknown field '" + token.value + "'");
|
|
429
|
+
}
|
|
430
|
+
return { field: field, name: token.value };
|
|
431
|
+
};
|
|
432
|
+
|
|
433
|
+
Parser.prototype.readBracketName = function readBracketName() {
|
|
434
|
+
var parts = [],
|
|
435
|
+
token;
|
|
436
|
+
while (token = this.tn.next()) {
|
|
437
|
+
if (token.value === "]")
|
|
438
|
+
return parts.join("");
|
|
439
|
+
parts.push(token.raw || token.value);
|
|
440
|
+
}
|
|
441
|
+
this.error("unterminated bracketed field name");
|
|
442
|
+
return null;
|
|
443
|
+
};
|
|
444
|
+
|
|
445
|
+
Parser.prototype.parseAny = function parseAny(type, typeUrl, object, seen, depth) {
|
|
446
|
+
this.parseMessageFieldDelimiter();
|
|
447
|
+
validateTypeUrl(typeUrl);
|
|
448
|
+
var typeName = typeUrl.substring(typeUrl.lastIndexOf("/") + 1),
|
|
449
|
+
embeddedType = type.root.lookupType(typeName.charAt(0) === "." ? typeName : "." + typeName),
|
|
450
|
+
embedded = this.parseMessageValue(embeddedType, depth),
|
|
451
|
+
typeUrlField = lookupField(type, "type_url") || lookupField(type, "typeUrl"),
|
|
452
|
+
valueField = lookupField(type, "value");
|
|
453
|
+
addField(object, seen, typeUrlField, typeUrl);
|
|
454
|
+
addField(object, seen, valueField, embeddedType.encode(embedded).finish());
|
|
455
|
+
};
|
|
456
|
+
|
|
457
|
+
Parser.prototype.parseMapField = function parseMapField(field, object, depth) {
|
|
458
|
+
if (!object[field.name])
|
|
459
|
+
object[field.name] = {};
|
|
460
|
+
if (this.tn.skip("[")) {
|
|
461
|
+
if (!this.tn.skip("]")) {
|
|
462
|
+
do {
|
|
463
|
+
addMapEntry(field, object[field.name], this.parseMapEntry(field, depth + 1));
|
|
464
|
+
} while (this.tn.skip(","));
|
|
465
|
+
this.tn.expect("]");
|
|
466
|
+
}
|
|
467
|
+
} else
|
|
468
|
+
addMapEntry(field, object[field.name], this.parseMapEntry(field, depth + 1));
|
|
469
|
+
};
|
|
470
|
+
|
|
471
|
+
Parser.prototype.parseMessageFieldDelimiter = function parseMessageFieldDelimiter() {
|
|
472
|
+
this.tn.skip(":");
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
Parser.prototype.parseMapEntry = function parseMapEntry(field, depth) {
|
|
476
|
+
this.checkRecursion(depth);
|
|
477
|
+
var end;
|
|
478
|
+
if (this.tn.skip("{"))
|
|
479
|
+
end = "}";
|
|
480
|
+
else if (this.tn.skip("<"))
|
|
481
|
+
end = ">";
|
|
482
|
+
else
|
|
483
|
+
this.error("expected map entry");
|
|
484
|
+
|
|
485
|
+
var entry = {},
|
|
486
|
+
token,
|
|
487
|
+
valueField = mapValueField(field),
|
|
488
|
+
keyField = mapKeyField(field);
|
|
489
|
+
for (;;) {
|
|
490
|
+
token = this.tn.peek();
|
|
491
|
+
if (!token)
|
|
492
|
+
this.error("expected '" + end + "'");
|
|
493
|
+
if (token.value === end) {
|
|
494
|
+
this.tn.next();
|
|
495
|
+
return entry;
|
|
496
|
+
}
|
|
497
|
+
if (isSeparator(token))
|
|
498
|
+
this.error("unexpected separator");
|
|
499
|
+
token = this.tn.next();
|
|
500
|
+
if (token.type !== "word")
|
|
501
|
+
this.error("expected map field name");
|
|
502
|
+
if (token.value === "key") {
|
|
503
|
+
this.tn.expect(":");
|
|
504
|
+
entry.key = this.parseScalar(keyField);
|
|
505
|
+
} else if (token.value === "value") {
|
|
506
|
+
if (valueField.resolvedType instanceof Type) {
|
|
507
|
+
this.parseMessageFieldDelimiter();
|
|
508
|
+
entry.value = this.parseMessageValue(valueField.resolvedType, depth);
|
|
509
|
+
} else {
|
|
510
|
+
this.tn.expect(":");
|
|
511
|
+
entry.value = this.parseScalar(valueField);
|
|
512
|
+
}
|
|
513
|
+
} else
|
|
514
|
+
this.error("unknown map field '" + token.value + "'");
|
|
515
|
+
token = this.tn.peek();
|
|
516
|
+
if (token && isSeparator(token)) {
|
|
517
|
+
this.tn.next();
|
|
518
|
+
token = this.tn.peek();
|
|
519
|
+
if (token && isSeparator(token))
|
|
520
|
+
this.error("unexpected separator");
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
};
|
|
524
|
+
|
|
525
|
+
Parser.prototype.parseMessageValue = function parseMessageValue(type, depth) {
|
|
526
|
+
var end;
|
|
527
|
+
if (this.tn.skip("{"))
|
|
528
|
+
end = "}";
|
|
529
|
+
else if (this.tn.skip("<"))
|
|
530
|
+
end = ">";
|
|
531
|
+
else
|
|
532
|
+
this.error("expected message value");
|
|
533
|
+
return this.parseMessage(type, end, depth + 1);
|
|
534
|
+
};
|
|
535
|
+
|
|
536
|
+
Parser.prototype.parseScalar = function parseScalar(field) {
|
|
537
|
+
if (field.type === "string" || field.type === "bytes") {
|
|
538
|
+
var bytes = this.readStringBytes();
|
|
539
|
+
return field.type === "bytes" ? util.newBuffer(bytes) : utf8Read(bytes, true);
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
var sign = 1;
|
|
543
|
+
if (this.tn.skip("-"))
|
|
544
|
+
sign = -1;
|
|
545
|
+
|
|
546
|
+
var token = this.tn.next();
|
|
547
|
+
if (!token)
|
|
548
|
+
this.error("expected value");
|
|
549
|
+
|
|
550
|
+
if (field.resolvedType instanceof Enum)
|
|
551
|
+
return parseEnum(field, token, sign);
|
|
552
|
+
|
|
553
|
+
switch (field.type) {
|
|
554
|
+
case "double":
|
|
555
|
+
case "float":
|
|
556
|
+
return parseFloatValue(token, sign);
|
|
557
|
+
case "bool":
|
|
558
|
+
return parseBool(token, sign);
|
|
559
|
+
case "int32":
|
|
560
|
+
case "sint32":
|
|
561
|
+
case "sfixed32":
|
|
562
|
+
return parseInteger(token, sign, false, 32);
|
|
563
|
+
case "uint32":
|
|
564
|
+
case "fixed32":
|
|
565
|
+
return parseInteger(token, sign, true, 32);
|
|
566
|
+
case "int64":
|
|
567
|
+
case "sint64":
|
|
568
|
+
case "sfixed64":
|
|
569
|
+
return parseInteger(token, sign, false, 64);
|
|
570
|
+
case "uint64":
|
|
571
|
+
case "fixed64":
|
|
572
|
+
return parseInteger(token, sign, true, 64);
|
|
573
|
+
default:
|
|
574
|
+
this.error(field.fullName + ": unsupported scalar type");
|
|
575
|
+
}
|
|
576
|
+
return undefined;
|
|
577
|
+
};
|
|
578
|
+
|
|
579
|
+
Parser.prototype.readStringBytes = function readStringBytes() {
|
|
580
|
+
var token = this.tn.next(),
|
|
581
|
+
bytes = [];
|
|
582
|
+
if (!token || token.type !== "string")
|
|
583
|
+
this.error("expected string");
|
|
584
|
+
Array.prototype.push.apply(bytes, token.value);
|
|
585
|
+
while ((token = this.tn.peek()) && token.type === "string") {
|
|
586
|
+
token = this.tn.next();
|
|
587
|
+
Array.prototype.push.apply(bytes, token.value);
|
|
588
|
+
}
|
|
589
|
+
return bytes;
|
|
590
|
+
};
|
|
591
|
+
|
|
592
|
+
Parser.prototype.skipReservedValue = function skipReservedValue(depth) {
|
|
593
|
+
this.tn.skip(":");
|
|
594
|
+
var token = this.tn.peek();
|
|
595
|
+
if (!token)
|
|
596
|
+
return;
|
|
597
|
+
if (token.value === "{") {
|
|
598
|
+
this.skipBalanced("{", "}", depth);
|
|
599
|
+
} else if (token.value === "<") {
|
|
600
|
+
this.skipBalanced("<", ">", depth);
|
|
601
|
+
} else if (token.value === "[") {
|
|
602
|
+
this.skipBalanced("[", "]", depth);
|
|
603
|
+
} else if (token.type === "string") {
|
|
604
|
+
this.readStringBytes();
|
|
605
|
+
} else {
|
|
606
|
+
if (token.value === "-")
|
|
607
|
+
this.tn.next();
|
|
608
|
+
this.tn.next();
|
|
609
|
+
}
|
|
610
|
+
};
|
|
611
|
+
|
|
612
|
+
Parser.prototype.skipBalanced = function skipBalanced(open, close, depth) {
|
|
613
|
+
var balance = 0,
|
|
614
|
+
token;
|
|
615
|
+
do {
|
|
616
|
+
token = this.tn.next();
|
|
617
|
+
if (!token)
|
|
618
|
+
this.error("expected '" + close + "'");
|
|
619
|
+
if (token.value === open) {
|
|
620
|
+
if (depth + ++balance > this.recursionLimit)
|
|
621
|
+
this.error("max depth exceeded");
|
|
622
|
+
}
|
|
623
|
+
else if (token.value === close)
|
|
624
|
+
--balance;
|
|
625
|
+
} while (balance);
|
|
626
|
+
};
|
|
627
|
+
|
|
628
|
+
function addField(object, seen, field, value) {
|
|
629
|
+
if (field.repeated) {
|
|
630
|
+
(object[field.name] || (object[field.name] = [])).push(value);
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
633
|
+
if (Object.prototype.hasOwnProperty.call(seen, field.name))
|
|
634
|
+
throw Error(field.fullName + ": multiple values");
|
|
635
|
+
if (field.partOf) {
|
|
636
|
+
var oneofName = "$oneof:" + field.partOf.name;
|
|
637
|
+
if (seen[oneofName])
|
|
638
|
+
throw Error(field.partOf.name + ": multiple values");
|
|
639
|
+
seen[oneofName] = true;
|
|
640
|
+
}
|
|
641
|
+
seen[field.name] = true;
|
|
642
|
+
object[field.name] = value;
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
function addMapEntry(field, map, entry) {
|
|
646
|
+
var keyField = mapKeyField(field),
|
|
647
|
+
valueField = mapValueField(field),
|
|
648
|
+
key = Object.prototype.hasOwnProperty.call(entry, "key")
|
|
649
|
+
? entry.key
|
|
650
|
+
: defaultScalarValue(keyField),
|
|
651
|
+
value = Object.prototype.hasOwnProperty.call(entry, "value")
|
|
652
|
+
? entry.value
|
|
653
|
+
: defaultMapValue(valueField);
|
|
654
|
+
map[mapKey(keyField, key)] = value;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
function defaultMapValue(field) {
|
|
658
|
+
if (field.resolvedType instanceof Type)
|
|
659
|
+
return field.resolvedType.create();
|
|
660
|
+
if (field.resolvedType instanceof Enum)
|
|
661
|
+
return field.typeDefault;
|
|
662
|
+
return defaultScalarValue(field);
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
function defaultScalarValue(field) {
|
|
666
|
+
if (field.type === "string")
|
|
667
|
+
return "";
|
|
668
|
+
if (field.type === "bytes")
|
|
669
|
+
return util.newBuffer([]);
|
|
670
|
+
if (field.type === "bool")
|
|
671
|
+
return false;
|
|
672
|
+
return field.defaultValue;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
function mapKeyField(field) {
|
|
676
|
+
return {
|
|
677
|
+
name: "key",
|
|
678
|
+
fullName: field.fullName + ".key",
|
|
679
|
+
type: field.keyType,
|
|
680
|
+
resolvedType: null,
|
|
681
|
+
defaultValue: field.keyType === "bool" ? false : field.keyType === "string" ? "" : 0
|
|
682
|
+
};
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
function mapValueField(field) {
|
|
686
|
+
return {
|
|
687
|
+
name: "value",
|
|
688
|
+
fullName: field.fullName + ".value",
|
|
689
|
+
type: field.type,
|
|
690
|
+
resolvedType: field.resolvedType,
|
|
691
|
+
defaultValue: field.resolvedType instanceof Enum ? field.resolvedType.values[Object.keys(field.resolvedType.values)[0]] : field.typeDefault
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
function mapKey(field, value) {
|
|
696
|
+
if (types.long[field.type] !== undefined)
|
|
697
|
+
return String(value);
|
|
698
|
+
if (field.type === "bool")
|
|
699
|
+
return value ? "true" : "false";
|
|
700
|
+
return String(value);
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
function lookupField(type, name) {
|
|
704
|
+
var fields = type.fieldsArray;
|
|
705
|
+
for (var i = 0; i < fields.length; ++i) {
|
|
706
|
+
var field = fields[i].resolve();
|
|
707
|
+
if (field.name === name || underScore(field.name) === name)
|
|
708
|
+
return field;
|
|
709
|
+
if (field.delimited && field.resolvedType instanceof Type) {
|
|
710
|
+
var groupName = field.resolvedType.name,
|
|
711
|
+
lowerName = name.toLowerCase(),
|
|
712
|
+
compactName = compact(name);
|
|
713
|
+
if (groupName === name || underScore(groupName) === name
|
|
714
|
+
|| field.name.toLowerCase() === lowerName
|
|
715
|
+
|| groupName.toLowerCase() === lowerName
|
|
716
|
+
|| compact(field.name) === compactName
|
|
717
|
+
|| compact(groupName) === compactName)
|
|
718
|
+
return field;
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
return null;
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
function lookupExtension(type, name) {
|
|
725
|
+
var fullName = name.charAt(0) === "." ? name : "." + name,
|
|
726
|
+
camelName = camelCaseLastPath(fullName),
|
|
727
|
+
field = type.get(fullName) || type.root.lookup(fullName, Field)
|
|
728
|
+
|| type.get(camelName) || type.root.lookup(camelName, Field);
|
|
729
|
+
if (!field)
|
|
730
|
+
field = lookupExtensionField(type, fullName);
|
|
731
|
+
if (field && field.extend !== undefined && field.extensionField)
|
|
732
|
+
field = field.extensionField;
|
|
733
|
+
if (!field || field.parent !== type)
|
|
734
|
+
throw Error(type.fullName + ": unknown extension '" + name + "'");
|
|
735
|
+
return field;
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
function camelCaseLastPath(name) {
|
|
739
|
+
var dot = name.lastIndexOf(".");
|
|
740
|
+
return name.substring(0, dot + 1) + util.camelCase(name.substring(dot + 1));
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
function parseEnum(field, token, sign) {
|
|
744
|
+
if (sign < 0) {
|
|
745
|
+
if (token.type !== "number")
|
|
746
|
+
throw Error(field.fullName + ": enum value expected");
|
|
747
|
+
return checkEnumValue(field, parseInteger(token, sign, false, 32));
|
|
748
|
+
}
|
|
749
|
+
if (token.type === "word") {
|
|
750
|
+
var value = field.resolvedType.values[token.value];
|
|
751
|
+
if (value === undefined)
|
|
752
|
+
throw Error(field.fullName + ": enum value expected");
|
|
753
|
+
return value;
|
|
754
|
+
}
|
|
755
|
+
return checkEnumValue(field, parseInteger(token, sign, false, 32));
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
function parseBool(token, sign) {
|
|
759
|
+
if (sign < 0)
|
|
760
|
+
throw Error("bool value expected");
|
|
761
|
+
if (token.type === "word") {
|
|
762
|
+
switch (token.value) {
|
|
763
|
+
case "true":
|
|
764
|
+
case "True":
|
|
765
|
+
case "t":
|
|
766
|
+
return true;
|
|
767
|
+
case "false":
|
|
768
|
+
case "False":
|
|
769
|
+
case "f":
|
|
770
|
+
return false;
|
|
771
|
+
}
|
|
772
|
+
} else if (token.type === "number") {
|
|
773
|
+
var value = parseInteger(token, 1, true, 32);
|
|
774
|
+
if (value === 0)
|
|
775
|
+
return false;
|
|
776
|
+
if (value === 1)
|
|
777
|
+
return true;
|
|
778
|
+
}
|
|
779
|
+
throw Error("bool value expected");
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
function parseFloatValue(token, sign) {
|
|
783
|
+
if (token.type === "word") {
|
|
784
|
+
switch (token.value.toLowerCase()) {
|
|
785
|
+
case "inf":
|
|
786
|
+
case "infinity":
|
|
787
|
+
return sign * Infinity;
|
|
788
|
+
case "nan":
|
|
789
|
+
return NaN;
|
|
790
|
+
}
|
|
791
|
+
throw Error("float value expected");
|
|
792
|
+
}
|
|
793
|
+
if (token.type !== "number")
|
|
794
|
+
throw Error("float value expected");
|
|
795
|
+
var raw = token.value;
|
|
796
|
+
if (/^0[xX]/.test(raw) || /^0[0-7]/.test(raw) && raw.length > 1)
|
|
797
|
+
throw Error("float value expected");
|
|
798
|
+
if (/[fF]$/.test(raw))
|
|
799
|
+
raw = raw.substring(0, raw.length - 1);
|
|
800
|
+
return sign * Number(raw);
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
function parseInteger(token, sign, unsigned, bits) {
|
|
804
|
+
if (token.type !== "number")
|
|
805
|
+
throw Error("integer value expected");
|
|
806
|
+
if (sign < 0 && unsigned)
|
|
807
|
+
throw Error("unsigned integer value expected");
|
|
808
|
+
|
|
809
|
+
var raw = token.value,
|
|
810
|
+
radix = 10,
|
|
811
|
+
digits = raw;
|
|
812
|
+
if (/^0[xX]/.test(raw)) {
|
|
813
|
+
radix = 16;
|
|
814
|
+
digits = raw.substring(2);
|
|
815
|
+
} else if (/^0[0-7]/.test(raw) && raw.length > 1) {
|
|
816
|
+
radix = 8;
|
|
817
|
+
digits = raw.substring(1);
|
|
818
|
+
} else if (!/^(?:0|[1-9][0-9]*)$/.test(raw))
|
|
819
|
+
throw Error("integer value expected");
|
|
820
|
+
|
|
821
|
+
if (typeof util.global.BigInt === "function")
|
|
822
|
+
return parseIntegerBigInt(digits, radix, sign, unsigned, bits);
|
|
823
|
+
|
|
824
|
+
var value = parseInt(digits, radix) * sign;
|
|
825
|
+
if (bits === 64 && util.Long)
|
|
826
|
+
return util.Long.fromString(String(value), unsigned);
|
|
827
|
+
return value;
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
function parseIntegerBigInt(digits, radix, sign, unsigned, bits) {
|
|
831
|
+
var value,
|
|
832
|
+
BigInt = util.global.BigInt;
|
|
833
|
+
if (radix === 16)
|
|
834
|
+
value = BigInt("0x" + digits);
|
|
835
|
+
else if (radix === 8)
|
|
836
|
+
value = BigInt("0o" + digits);
|
|
837
|
+
else
|
|
838
|
+
value = BigInt(digits);
|
|
839
|
+
if (sign < 0)
|
|
840
|
+
value = -value;
|
|
841
|
+
|
|
842
|
+
var min,
|
|
843
|
+
max;
|
|
844
|
+
if (bits === 32) {
|
|
845
|
+
min = unsigned ? BigInt(0) : -BigInt(2147483648);
|
|
846
|
+
max = unsigned ? BigInt(4294967295) : BigInt(2147483647);
|
|
847
|
+
} else {
|
|
848
|
+
min = unsigned ? BigInt(0) : -BigInt("9223372036854775808");
|
|
849
|
+
max = unsigned ? BigInt("18446744073709551615") : BigInt("9223372036854775807");
|
|
850
|
+
}
|
|
851
|
+
if (value < min || value > max)
|
|
852
|
+
throw Error((unsigned ? "unsigned " : "") + "integer value out of range");
|
|
853
|
+
if (bits === 64 && util.Long)
|
|
854
|
+
return util.Long.fromString(value.toString(), unsigned, 10);
|
|
855
|
+
return Number(value);
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
function checkRecursion(depth, recursionLimit) {
|
|
859
|
+
if (depth > recursionLimit)
|
|
860
|
+
throw Error("max depth exceeded");
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
function writeMessage(type, message, lines, indent, options, depth, recursionLimit) {
|
|
864
|
+
checkRecursion(depth, recursionLimit);
|
|
865
|
+
var fields = type.fieldsArray.slice().sort(util.compareFieldsById);
|
|
866
|
+
for (var i = 0; i < fields.length; ++i) {
|
|
867
|
+
var field = fields[i].resolve(),
|
|
868
|
+
value = message[field.name];
|
|
869
|
+
if (value == null || !Object.prototype.hasOwnProperty.call(message, field.name))
|
|
870
|
+
continue;
|
|
871
|
+
if (field.map)
|
|
872
|
+
writeMapField(field, value, lines, indent, options, depth, recursionLimit);
|
|
873
|
+
else if (field.repeated)
|
|
874
|
+
for (var j = 0; j < value.length; ++j)
|
|
875
|
+
writeField(field, value[j], lines, indent, options, depth, recursionLimit);
|
|
876
|
+
else
|
|
877
|
+
writeField(field, value, lines, indent, options, depth, recursionLimit);
|
|
878
|
+
}
|
|
879
|
+
if (options.unknowns && message.$unknowns != null && Object.prototype.hasOwnProperty.call(message, "$unknowns"))
|
|
880
|
+
writeUnknowns(message.$unknowns, lines, indent);
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
function writeMapField(field, map, lines, indent, options, depth, recursionLimit) {
|
|
884
|
+
var keys = Object.keys(map).sort(),
|
|
885
|
+
keyField = mapKeyField(field),
|
|
886
|
+
valueField = mapValueField(field),
|
|
887
|
+
name = formatFieldName(field),
|
|
888
|
+
sp = spaces(indent);
|
|
889
|
+
for (var i = 0; i < keys.length; ++i) {
|
|
890
|
+
checkRecursion(depth + 1, recursionLimit);
|
|
891
|
+
var key = keyField.long ? util.longFromKey(keys[i], keyField.type === "uint64" || keyField.type === "fixed64") : keys[i];
|
|
892
|
+
if (keyField.type === "bool")
|
|
893
|
+
key = util.boolFromKey(keys[i]);
|
|
894
|
+
lines.push(sp + name + " {");
|
|
895
|
+
lines.push(spaces(indent + 2) + "key: " + formatScalar(keyField, key));
|
|
896
|
+
if (valueField.resolvedType instanceof Type) {
|
|
897
|
+
lines.push(spaces(indent + 2) + "value {");
|
|
898
|
+
writeMessage(valueField.resolvedType, map[keys[i]], lines, indent + 4, options, depth + 2, recursionLimit);
|
|
899
|
+
lines.push(spaces(indent + 2) + "}");
|
|
900
|
+
} else
|
|
901
|
+
lines.push(spaces(indent + 2) + "value: " + formatScalar(valueField, map[keys[i]]));
|
|
902
|
+
lines.push(sp + "}");
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
function writeField(field, value, lines, indent, options, depth, recursionLimit) {
|
|
907
|
+
var name = formatFieldName(field),
|
|
908
|
+
sp = spaces(indent);
|
|
909
|
+
if (field.resolvedType instanceof Type) {
|
|
910
|
+
lines.push(sp + name + " {");
|
|
911
|
+
writeMessage(field.resolvedType, value, lines, indent + 2, options, depth + 1, recursionLimit);
|
|
912
|
+
lines.push(sp + "}");
|
|
913
|
+
} else
|
|
914
|
+
lines.push(sp + name + ": " + formatScalar(field, value));
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
function writeUnknowns(unknowns, lines, indent) {
|
|
918
|
+
for (var i = 0; i < unknowns.length; ++i) {
|
|
919
|
+
var reader = Reader.create(unknowns[i]);
|
|
920
|
+
writeUnknownFieldSet(reader, lines, indent, undefined, textformat.unknownRecursionLimit);
|
|
921
|
+
if (reader.pos !== reader.len)
|
|
922
|
+
throw Error("invalid unknown field data");
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
function writeUnknownFieldSet(reader, lines, indent, endGroup, recursionBudget) {
|
|
927
|
+
if (recursionBudget < 0)
|
|
928
|
+
throw Error("max depth exceeded");
|
|
929
|
+
while (reader.pos < reader.len) {
|
|
930
|
+
var tag = reader.tag(),
|
|
931
|
+
fieldNumber = tag >>> 3,
|
|
932
|
+
wireType = tag & 7;
|
|
933
|
+
if (!fieldNumber)
|
|
934
|
+
throw Error("illegal tag: field number 0");
|
|
935
|
+
if (wireType === 4) {
|
|
936
|
+
if (fieldNumber !== endGroup)
|
|
937
|
+
throw Error("invalid end group tag");
|
|
938
|
+
return;
|
|
939
|
+
}
|
|
940
|
+
writeUnknownField(reader, fieldNumber, wireType, lines, indent, recursionBudget);
|
|
941
|
+
}
|
|
942
|
+
if (endGroup !== undefined)
|
|
943
|
+
throw Error("missing end group tag");
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
function writeUnknownField(reader, fieldNumber, wireType, lines, indent, recursionBudget) {
|
|
947
|
+
var sp = spaces(indent),
|
|
948
|
+
lo;
|
|
949
|
+
switch (wireType) {
|
|
950
|
+
case 0:
|
|
951
|
+
lines.push(sp + fieldNumber + ": " + readUnknownVarint(reader));
|
|
952
|
+
break;
|
|
953
|
+
case 1:
|
|
954
|
+
lo = reader.fixed32();
|
|
955
|
+
lines.push(sp + fieldNumber + ": 0x" + hexPad(reader.fixed32(), 8) + hexPad(lo, 8));
|
|
956
|
+
break;
|
|
957
|
+
case 2:
|
|
958
|
+
writeUnknownLengthDelimited(reader, fieldNumber, lines, indent, recursionBudget);
|
|
959
|
+
break;
|
|
960
|
+
case 3:
|
|
961
|
+
lines.push(sp + fieldNumber + " {");
|
|
962
|
+
writeUnknownFieldSet(reader, lines, indent + 2, fieldNumber, recursionBudget - 1);
|
|
963
|
+
lines.push(sp + "}");
|
|
964
|
+
break;
|
|
965
|
+
case 5:
|
|
966
|
+
lines.push(sp + fieldNumber + ": 0x" + hexPad(reader.fixed32(), 8));
|
|
967
|
+
break;
|
|
968
|
+
default:
|
|
969
|
+
throw Error("invalid wire type " + wireType);
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
function writeUnknownLengthDelimited(reader, fieldNumber, lines, indent, recursionBudget) {
|
|
974
|
+
var value = reader.bytes(),
|
|
975
|
+
nested = value.length && recursionBudget > 0
|
|
976
|
+
? tryFormatUnknownMessage(value, indent + 2, recursionBudget - 1)
|
|
977
|
+
: null,
|
|
978
|
+
sp = spaces(indent);
|
|
979
|
+
if (nested) {
|
|
980
|
+
lines.push(sp + fieldNumber + " {");
|
|
981
|
+
for (var i = 0; i < nested.length; ++i)
|
|
982
|
+
lines.push(nested[i]);
|
|
983
|
+
lines.push(sp + "}");
|
|
984
|
+
} else
|
|
985
|
+
lines.push(sp + fieldNumber + ": " + quoteBytes(value));
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
function tryFormatUnknownMessage(bytes, indent, recursionBudget) {
|
|
989
|
+
var reader = Reader.create(bytes),
|
|
990
|
+
lines = [];
|
|
991
|
+
try {
|
|
992
|
+
writeUnknownFieldSet(reader, lines, indent, undefined, recursionBudget);
|
|
993
|
+
return reader.pos === reader.len ? lines : null;
|
|
994
|
+
} catch (e) {
|
|
995
|
+
return null;
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
function readUnknownVarint(reader) {
|
|
1000
|
+
var BigInt = util.global.BigInt;
|
|
1001
|
+
if (typeof BigInt !== "function")
|
|
1002
|
+
return String(reader.uint64());
|
|
1003
|
+
|
|
1004
|
+
var value = BigInt(0),
|
|
1005
|
+
shift = BigInt(0),
|
|
1006
|
+
b;
|
|
1007
|
+
for (var i = 0; i < 10; ++i) {
|
|
1008
|
+
if (reader.pos >= reader.len)
|
|
1009
|
+
throw Error("invalid varint encoding");
|
|
1010
|
+
b = reader.buf[reader.pos++];
|
|
1011
|
+
value += BigInt(b & 127) << shift;
|
|
1012
|
+
if (b < 128)
|
|
1013
|
+
return value.toString();
|
|
1014
|
+
shift += BigInt(7);
|
|
1015
|
+
}
|
|
1016
|
+
throw Error("invalid varint encoding");
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
function hexPad(value, length) {
|
|
1020
|
+
var str = value.toString(16);
|
|
1021
|
+
while (str.length < length)
|
|
1022
|
+
str = "0" + str;
|
|
1023
|
+
return str;
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
function formatFieldName(field) {
|
|
1027
|
+
if (field.declaringField || field.name.charAt(0) === ".")
|
|
1028
|
+
return "[" + formatExtensionName(field) + "]";
|
|
1029
|
+
if (field.delimited && field.resolvedType instanceof Type && compact(field.name) === compact(field.resolvedType.name))
|
|
1030
|
+
return field.resolvedType.name;
|
|
1031
|
+
return underScore(field.name);
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
function formatExtensionName(field) {
|
|
1035
|
+
var name = field.name.replace(/^\./, ""),
|
|
1036
|
+
dot = name.lastIndexOf("."),
|
|
1037
|
+
path = name.substring(0, dot + 1),
|
|
1038
|
+
last = name.substring(dot + 1);
|
|
1039
|
+
if (field.delimited && field.resolvedType instanceof Type && field.resolvedType.group)
|
|
1040
|
+
last = last.toLowerCase();
|
|
1041
|
+
else
|
|
1042
|
+
last = underScore(last);
|
|
1043
|
+
return path + last;
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
function formatScalar(field, value) {
|
|
1047
|
+
if (field.resolvedType instanceof Enum) {
|
|
1048
|
+
var name = field.resolvedType.valuesById[value];
|
|
1049
|
+
return name === undefined ? String(value) : name;
|
|
1050
|
+
}
|
|
1051
|
+
switch (field.type) {
|
|
1052
|
+
case "string":
|
|
1053
|
+
return quoteBytes(utf8Bytes(String(value)));
|
|
1054
|
+
case "bytes":
|
|
1055
|
+
return quoteBytes(bytesValue(value));
|
|
1056
|
+
case "bool":
|
|
1057
|
+
return value ? "true" : "false";
|
|
1058
|
+
case "double":
|
|
1059
|
+
case "float":
|
|
1060
|
+
if (isNaN(value))
|
|
1061
|
+
return "nan";
|
|
1062
|
+
if (value === 0 && 1 / value === -Infinity)
|
|
1063
|
+
return "-0";
|
|
1064
|
+
if (value === Infinity)
|
|
1065
|
+
return "inf";
|
|
1066
|
+
if (value === -Infinity)
|
|
1067
|
+
return "-inf";
|
|
1068
|
+
return String(value);
|
|
1069
|
+
default:
|
|
1070
|
+
return String(value);
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
function bytesValue(value) {
|
|
1075
|
+
if (typeof value === "string") {
|
|
1076
|
+
var length = util.base64.length(value),
|
|
1077
|
+
buffer = util.newBuffer(length);
|
|
1078
|
+
util.base64.decode(value, buffer, 0);
|
|
1079
|
+
return buffer;
|
|
1080
|
+
}
|
|
1081
|
+
return value;
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
function quoteBytes(bytes) {
|
|
1085
|
+
var out = "\"",
|
|
1086
|
+
oct;
|
|
1087
|
+
for (var i = 0; i < bytes.length; ++i) {
|
|
1088
|
+
var b = bytes[i];
|
|
1089
|
+
switch (b) {
|
|
1090
|
+
case 9: out += "\\t"; break;
|
|
1091
|
+
case 10: out += "\\n"; break;
|
|
1092
|
+
case 13: out += "\\r"; break;
|
|
1093
|
+
case 34: out += "\\\""; break;
|
|
1094
|
+
case 92: out += "\\\\"; break;
|
|
1095
|
+
default:
|
|
1096
|
+
if (b >= 32 && b <= 126)
|
|
1097
|
+
out += String.fromCharCode(b);
|
|
1098
|
+
else {
|
|
1099
|
+
oct = b.toString(8);
|
|
1100
|
+
out += "\\" + (oct.length < 2 ? "00" : oct.length < 3 ? "0" : "") + oct;
|
|
1101
|
+
}
|
|
1102
|
+
break;
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
return out + "\"";
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
function spaces(indent) {
|
|
1109
|
+
var str = "";
|
|
1110
|
+
while (str.length < indent)
|
|
1111
|
+
str += " ";
|
|
1112
|
+
return str;
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
function utf8Read(bytes, strict) {
|
|
1116
|
+
if (strict && !validUtf8(bytes))
|
|
1117
|
+
throw Error("invalid UTF-8 string");
|
|
1118
|
+
var buffer = util.newBuffer(bytes);
|
|
1119
|
+
return util.utf8.read(buffer, 0, buffer.length);
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
function validUtf8(bytes) {
|
|
1123
|
+
for (var i = 0, b; i < bytes.length;) {
|
|
1124
|
+
b = bytes[i++];
|
|
1125
|
+
if (b <= 0x7F)
|
|
1126
|
+
continue;
|
|
1127
|
+
if (b >= 0xC2 && b <= 0xDF) {
|
|
1128
|
+
if ((b = bytes[i++]) < 0x80 || b > 0xBF)
|
|
1129
|
+
return false;
|
|
1130
|
+
} else if (b === 0xE0) {
|
|
1131
|
+
if ((b = bytes[i++]) < 0xA0 || b > 0xBF || (b = bytes[i++]) < 0x80 || b > 0xBF)
|
|
1132
|
+
return false;
|
|
1133
|
+
} else if (b >= 0xE1 && b <= 0xEC || b >= 0xEE && b <= 0xEF) {
|
|
1134
|
+
if ((b = bytes[i++]) < 0x80 || b > 0xBF || (b = bytes[i++]) < 0x80 || b > 0xBF)
|
|
1135
|
+
return false;
|
|
1136
|
+
} else if (b === 0xED) {
|
|
1137
|
+
if ((b = bytes[i++]) < 0x80 || b > 0x9F || (b = bytes[i++]) < 0x80 || b > 0xBF)
|
|
1138
|
+
return false;
|
|
1139
|
+
} else if (b === 0xF0) {
|
|
1140
|
+
if ((b = bytes[i++]) < 0x90 || b > 0xBF || (b = bytes[i++]) < 0x80 || b > 0xBF || (b = bytes[i++]) < 0x80 || b > 0xBF)
|
|
1141
|
+
return false;
|
|
1142
|
+
} else if (b >= 0xF1 && b <= 0xF3) {
|
|
1143
|
+
if ((b = bytes[i++]) < 0x80 || b > 0xBF || (b = bytes[i++]) < 0x80 || b > 0xBF || (b = bytes[i++]) < 0x80 || b > 0xBF)
|
|
1144
|
+
return false;
|
|
1145
|
+
} else if (b === 0xF4) {
|
|
1146
|
+
if ((b = bytes[i++]) < 0x80 || b > 0x8F || (b = bytes[i++]) < 0x80 || b > 0xBF || (b = bytes[i++]) < 0x80 || b > 0xBF)
|
|
1147
|
+
return false;
|
|
1148
|
+
} else
|
|
1149
|
+
return false;
|
|
1150
|
+
}
|
|
1151
|
+
return true;
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
function utf8Bytes(str) {
|
|
1155
|
+
var buffer = util.newBuffer(util.utf8.length(str));
|
|
1156
|
+
util.utf8.write(str, buffer, 0);
|
|
1157
|
+
return buffer;
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
function pushUtf8(bytes, code) {
|
|
1161
|
+
if (code < 0x80) {
|
|
1162
|
+
bytes.push(code);
|
|
1163
|
+
} else if (code < 0x800) {
|
|
1164
|
+
bytes.push(code >> 6 | 192, code & 63 | 128);
|
|
1165
|
+
} else if (code < 0x10000) {
|
|
1166
|
+
bytes.push(code >> 12 | 224, code >> 6 & 63 | 128, code & 63 | 128);
|
|
1167
|
+
} else {
|
|
1168
|
+
bytes.push(code >> 18 | 240, code >> 12 & 63 | 128, code >> 6 & 63 | 128, code & 63 | 128);
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
function verifyTextMessage(type, message) {
|
|
1173
|
+
var fields = type.fieldsArray;
|
|
1174
|
+
for (var i = 0; i < fields.length; ++i) {
|
|
1175
|
+
var field = fields[i].resolve(),
|
|
1176
|
+
value = message[field.name];
|
|
1177
|
+
if (value == null || !Object.prototype.hasOwnProperty.call(message, field.name)) {
|
|
1178
|
+
if (field.required)
|
|
1179
|
+
return field.fullName + ": missing required field";
|
|
1180
|
+
continue;
|
|
1181
|
+
}
|
|
1182
|
+
if (field.map) {
|
|
1183
|
+
if (field.resolvedType instanceof Type)
|
|
1184
|
+
for (var key in value)
|
|
1185
|
+
if (Object.prototype.hasOwnProperty.call(value, key)) {
|
|
1186
|
+
var mapErr = verifyTextMessage(field.resolvedType, value[key]);
|
|
1187
|
+
if (mapErr)
|
|
1188
|
+
return mapErr;
|
|
1189
|
+
}
|
|
1190
|
+
} else if (field.repeated) {
|
|
1191
|
+
if (field.resolvedType instanceof Type)
|
|
1192
|
+
for (var j = 0; j < value.length; ++j) {
|
|
1193
|
+
var repeatedErr = verifyTextMessage(field.resolvedType, value[j]);
|
|
1194
|
+
if (repeatedErr)
|
|
1195
|
+
return repeatedErr;
|
|
1196
|
+
}
|
|
1197
|
+
} else if (field.resolvedType instanceof Type) {
|
|
1198
|
+
var err = verifyTextMessage(field.resolvedType, value);
|
|
1199
|
+
if (err)
|
|
1200
|
+
return err;
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
return null;
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
function isSeparator(token) {
|
|
1207
|
+
return token.value === "," || token.value === ";";
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
function validateTypeUrl(typeUrl) {
|
|
1211
|
+
for (var i = 0; i < typeUrl.length; ++i)
|
|
1212
|
+
if (typeUrl.charAt(i) === "%") {
|
|
1213
|
+
if (i + 2 >= typeUrl.length || !hexRe.test(typeUrl.charAt(i + 1)) || !hexRe.test(typeUrl.charAt(i + 2)))
|
|
1214
|
+
throw Error("invalid Any type URL");
|
|
1215
|
+
i += 2;
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
function lookupExtensionField(type, fullName) {
|
|
1220
|
+
var fields = type.fieldsArray;
|
|
1221
|
+
for (var i = 0; i < fields.length; ++i) {
|
|
1222
|
+
var field = fields[i].resolve();
|
|
1223
|
+
if (field.name.charAt(0) === "." && "." + formatExtensionName(field) === fullName)
|
|
1224
|
+
return field;
|
|
1225
|
+
}
|
|
1226
|
+
return null;
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
function checkEnumValue(field, value) {
|
|
1230
|
+
if (isClosedEnum(field) && field.resolvedType.valuesById[value] === undefined)
|
|
1231
|
+
throw Error(field.fullName + ": enum value expected");
|
|
1232
|
+
return value;
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
function isClosedEnum(field) {
|
|
1236
|
+
return field.resolvedType
|
|
1237
|
+
&& field.resolvedType._features
|
|
1238
|
+
&& field.resolvedType._features.enum_type === "CLOSED";
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
function compact(str) {
|
|
1242
|
+
return str.replace(/_/g, "").toLowerCase();
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
function underScore(str) {
|
|
1246
|
+
return str.substring(0, 1)
|
|
1247
|
+
+ str.substring(1)
|
|
1248
|
+
.replace(/([A-Z])(?=[a-z]|$)/g, function($0, $1) { return "_" + $1.toLowerCase(); });
|
|
1249
|
+
}
|