]> git.proxmox.com Git - ceph.git/blob - ceph/src/jaegertracing/thrift/lib/nodejs/lib/thrift/json_protocol.js
buildsys: switch source download to quincy
[ceph.git] / ceph / src / jaegertracing / thrift / lib / nodejs / lib / thrift / json_protocol.js
1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20 var Int64 = require('node-int64');
21 var Thrift = require('./thrift');
22 var Type = Thrift.Type;
23 var util = require("util");
24
25 var Int64Util = require('./int64_util');
26 var json_parse = require('./json_parse');
27
28 var InputBufferUnderrunError = require('./input_buffer_underrun_error');
29
30 module.exports = TJSONProtocol;
31
32 /**
33 * Initializes a Thrift JSON protocol instance.
34 * @constructor
35 * @param {Thrift.Transport} trans - The transport to serialize to/from.
36 * @classdesc Apache Thrift Protocols perform serialization which enables cross
37 * language RPC. The Protocol type is the JavaScript browser implementation
38 * of the Apache Thrift TJSONProtocol.
39 * @example
40 * var protocol = new Thrift.Protocol(transport);
41 */
42 function TJSONProtocol(trans) {
43 this.tstack = [];
44 this.tpos = [];
45 this.trans = trans;
46 };
47
48 /**
49 * Thrift IDL type Id to string mapping.
50 * @readonly
51 * @see {@link Thrift.Type}
52 */
53 TJSONProtocol.Type = {};
54 TJSONProtocol.Type[Type.BOOL] = '"tf"';
55 TJSONProtocol.Type[Type.BYTE] = '"i8"';
56 TJSONProtocol.Type[Type.I16] = '"i16"';
57 TJSONProtocol.Type[Type.I32] = '"i32"';
58 TJSONProtocol.Type[Type.I64] = '"i64"';
59 TJSONProtocol.Type[Type.DOUBLE] = '"dbl"';
60 TJSONProtocol.Type[Type.STRUCT] = '"rec"';
61 TJSONProtocol.Type[Type.STRING] = '"str"';
62 TJSONProtocol.Type[Type.MAP] = '"map"';
63 TJSONProtocol.Type[Type.LIST] = '"lst"';
64 TJSONProtocol.Type[Type.SET] = '"set"';
65
66 /**
67 * Thrift IDL type string to Id mapping.
68 * @readonly
69 * @see {@link Thrift.Type}
70 */
71 TJSONProtocol.RType = {};
72 TJSONProtocol.RType.tf = Type.BOOL;
73 TJSONProtocol.RType.i8 = Type.BYTE;
74 TJSONProtocol.RType.i16 = Type.I16;
75 TJSONProtocol.RType.i32 = Type.I32;
76 TJSONProtocol.RType.i64 = Type.I64;
77 TJSONProtocol.RType.dbl = Type.DOUBLE;
78 TJSONProtocol.RType.rec = Type.STRUCT;
79 TJSONProtocol.RType.str = Type.STRING;
80 TJSONProtocol.RType.map = Type.MAP;
81 TJSONProtocol.RType.lst = Type.LIST;
82 TJSONProtocol.RType.set = Type.SET;
83
84 /**
85 * The TJSONProtocol version number.
86 * @readonly
87 * @const {number} Version
88 * @memberof Thrift.Protocol
89 */
90 TJSONProtocol.Version = 1;
91
92 TJSONProtocol.prototype.flush = function() {
93 this.writeToTransportIfStackIsFlushable();
94 return this.trans.flush();
95 };
96
97 TJSONProtocol.prototype.writeToTransportIfStackIsFlushable = function() {
98 if (this.tstack.length === 1) {
99 this.trans.write(this.tstack.pop());
100 }
101 };
102
103 /**
104 * Serializes the beginning of a Thrift RPC message.
105 * @param {string} name - The service method to call.
106 * @param {Thrift.MessageType} messageType - The type of method call.
107 * @param {number} seqid - The sequence number of this call (always 0 in Apache Thrift).
108 */
109 TJSONProtocol.prototype.writeMessageBegin = function(name, messageType, seqid) {
110 this.tstack.push([TJSONProtocol.Version, '"' + name + '"', messageType, seqid]);
111 };
112
113 /**
114 * Serializes the end of a Thrift RPC message.
115 */
116 TJSONProtocol.prototype.writeMessageEnd = function() {
117 var obj = this.tstack.pop();
118
119 this.wobj = this.tstack.pop();
120 this.wobj.push(obj);
121
122 this.wbuf = '[' + this.wobj.join(',') + ']';
123
124 // we assume there is nothing more to come so we write
125 this.trans.write(this.wbuf);
126 };
127
128 /**
129 * Serializes the beginning of a struct.
130 * @param {string} name - The name of the struct.
131 */
132 TJSONProtocol.prototype.writeStructBegin = function(name) {
133 this.tpos.push(this.tstack.length);
134 this.tstack.push({});
135 };
136
137 /**
138 * Serializes the end of a struct.
139 */
140 TJSONProtocol.prototype.writeStructEnd = function() {
141 var p = this.tpos.pop();
142 var struct = this.tstack[p];
143 var str = '{';
144 var first = true;
145 for (var key in struct) {
146 if (first) {
147 first = false;
148 } else {
149 str += ',';
150 }
151
152 str += key + ':' + struct[key];
153 }
154
155 str += '}';
156 this.tstack[p] = str;
157
158 this.writeToTransportIfStackIsFlushable();
159 };
160
161 /**
162 * Serializes the beginning of a struct field.
163 * @param {string} name - The name of the field.
164 * @param {Thrift.Protocol.Type} fieldType - The data type of the field.
165 * @param {number} fieldId - The field's unique identifier.
166 */
167 TJSONProtocol.prototype.writeFieldBegin = function(name, fieldType, fieldId) {
168 this.tpos.push(this.tstack.length);
169 this.tstack.push({ 'fieldId': '"' +
170 fieldId + '"', 'fieldType': TJSONProtocol.Type[fieldType]
171 });
172 };
173
174 /**
175 * Serializes the end of a field.
176 */
177 TJSONProtocol.prototype.writeFieldEnd = function() {
178 var value = this.tstack.pop();
179 var fieldInfo = this.tstack.pop();
180
181 if (':' + value === ":[object Object]") {
182 this.tstack[this.tstack.length - 1][fieldInfo.fieldId] = '{' +
183 fieldInfo.fieldType + ':' + JSON.stringify(value) + '}';
184 } else {
185 this.tstack[this.tstack.length - 1][fieldInfo.fieldId] = '{' +
186 fieldInfo.fieldType + ':' + value + '}';
187 }
188 this.tpos.pop();
189
190 this.writeToTransportIfStackIsFlushable();
191 };
192
193 /**
194 * Serializes the end of the set of fields for a struct.
195 */
196 TJSONProtocol.prototype.writeFieldStop = function() {
197 };
198
199 /**
200 * Serializes the beginning of a map collection.
201 * @param {Thrift.Type} keyType - The data type of the key.
202 * @param {Thrift.Type} valType - The data type of the value.
203 * @param {number} [size] - The number of elements in the map (ignored).
204 */
205 TJSONProtocol.prototype.writeMapBegin = function(keyType, valType, size) {
206 //size is invalid, we'll set it on end.
207 this.tpos.push(this.tstack.length);
208 this.tstack.push([TJSONProtocol.Type[keyType], TJSONProtocol.Type[valType], 0]);
209 };
210
211 /**
212 * Serializes the end of a map.
213 */
214 TJSONProtocol.prototype.writeMapEnd = function() {
215 var p = this.tpos.pop();
216
217 if (p == this.tstack.length) {
218 return;
219 }
220
221 if ((this.tstack.length - p - 1) % 2 !== 0) {
222 this.tstack.push('');
223 }
224
225 var size = (this.tstack.length - p - 1) / 2;
226
227 this.tstack[p][this.tstack[p].length - 1] = size;
228
229 var map = '}';
230 var first = true;
231 while (this.tstack.length > p + 1) {
232 var v = this.tstack.pop();
233 var k = this.tstack.pop();
234 if (first) {
235 first = false;
236 } else {
237 map = ',' + map;
238 }
239
240 if (! isNaN(k)) { k = '"' + k + '"'; } //json "keys" need to be strings
241 map = k + ':' + v + map;
242 }
243 map = '{' + map;
244
245 this.tstack[p].push(map);
246 this.tstack[p] = '[' + this.tstack[p].join(',') + ']';
247
248 this.writeToTransportIfStackIsFlushable();
249 };
250
251 /**
252 * Serializes the beginning of a list collection.
253 * @param {Thrift.Type} elemType - The data type of the elements.
254 * @param {number} size - The number of elements in the list.
255 */
256 TJSONProtocol.prototype.writeListBegin = function(elemType, size) {
257 this.tpos.push(this.tstack.length);
258 this.tstack.push([TJSONProtocol.Type[elemType], size]);
259 };
260
261 /**
262 * Serializes the end of a list.
263 */
264 TJSONProtocol.prototype.writeListEnd = function() {
265 var p = this.tpos.pop();
266
267 while (this.tstack.length > p + 1) {
268 var tmpVal = this.tstack[p + 1];
269 this.tstack.splice(p + 1, 1);
270 this.tstack[p].push(tmpVal);
271 }
272
273 this.tstack[p] = '[' + this.tstack[p].join(',') + ']';
274
275 this.writeToTransportIfStackIsFlushable();
276 };
277
278 /**
279 * Serializes the beginning of a set collection.
280 * @param {Thrift.Type} elemType - The data type of the elements.
281 * @param {number} size - The number of elements in the list.
282 */
283 TJSONProtocol.prototype.writeSetBegin = function(elemType, size) {
284 this.tpos.push(this.tstack.length);
285 this.tstack.push([TJSONProtocol.Type[elemType], size]);
286 };
287
288 /**
289 * Serializes the end of a set.
290 */
291 TJSONProtocol.prototype.writeSetEnd = function() {
292 var p = this.tpos.pop();
293
294 while (this.tstack.length > p + 1) {
295 var tmpVal = this.tstack[p + 1];
296 this.tstack.splice(p + 1, 1);
297 this.tstack[p].push(tmpVal);
298 }
299
300 this.tstack[p] = '[' + this.tstack[p].join(',') + ']';
301
302 this.writeToTransportIfStackIsFlushable();
303 };
304
305 /** Serializes a boolean */
306 TJSONProtocol.prototype.writeBool = function(bool) {
307 this.tstack.push(bool ? 1 : 0);
308 };
309
310 /** Serializes a number */
311 TJSONProtocol.prototype.writeByte = function(byte) {
312 this.tstack.push(byte);
313 };
314
315 /** Serializes a number */
316 TJSONProtocol.prototype.writeI16 = function(i16) {
317 this.tstack.push(i16);
318 };
319
320 /** Serializes a number */
321 TJSONProtocol.prototype.writeI32 = function(i32) {
322 this.tstack.push(i32);
323 };
324
325 /** Serializes a number */
326 TJSONProtocol.prototype.writeI64 = function(i64) {
327 if (i64 instanceof Int64) {
328 this.tstack.push(Int64Util.toDecimalString(i64));
329 } else {
330 this.tstack.push(i64);
331 }
332 };
333
334 /** Serializes a number */
335 TJSONProtocol.prototype.writeDouble = function(dub) {
336 this.tstack.push(dub);
337 };
338
339 /** Serializes a string */
340 TJSONProtocol.prototype.writeString = function(arg) {
341 // We do not encode uri components for wire transfer:
342 if (arg === null) {
343 this.tstack.push(null);
344 } else {
345 if (typeof arg === 'string') {
346 var str = arg;
347 } else if (arg instanceof Buffer) {
348 var str = arg.toString('utf8');
349 } else {
350 throw new Error('writeString called without a string/Buffer argument: ' + arg);
351 }
352
353 // concat may be slower than building a byte buffer
354 var escapedString = '';
355 for (var i = 0; i < str.length; i++) {
356 var ch = str.charAt(i); // a single double quote: "
357 if (ch === '\"') {
358 escapedString += '\\\"'; // write out as: \"
359 } else if (ch === '\\') { // a single backslash: \
360 escapedString += '\\\\'; // write out as: \\
361 /* Currently escaped forward slashes break TJSONProtocol.
362 * As it stands, we can simply pass forward slashes into
363 * our strings across the wire without being escaped.
364 * I think this is the protocol's bug, not thrift.js
365 * } else if(ch === '/') { // a single forward slash: /
366 * escapedString += '\\/'; // write out as \/
367 * }
368 */
369 } else if (ch === '\b') { // a single backspace: invisible
370 escapedString += '\\b'; // write out as: \b"
371 } else if (ch === '\f') { // a single formfeed: invisible
372 escapedString += '\\f'; // write out as: \f"
373 } else if (ch === '\n') { // a single newline: invisible
374 escapedString += '\\n'; // write out as: \n"
375 } else if (ch === '\r') { // a single return: invisible
376 escapedString += '\\r'; // write out as: \r"
377 } else if (ch === '\t') { // a single tab: invisible
378 escapedString += '\\t'; // write out as: \t"
379 } else {
380 escapedString += ch; // Else it need not be escaped
381 }
382 }
383 this.tstack.push('"' + escapedString + '"');
384 }
385 };
386
387 /** Serializes a string */
388 TJSONProtocol.prototype.writeBinary = function(arg) {
389 if (typeof arg === 'string') {
390 var buf = new Buffer(arg, 'binary');
391 } else if (arg instanceof Buffer ||
392 Object.prototype.toString.call(arg) == '[object Uint8Array]') {
393 var buf = arg;
394 } else {
395 throw new Error('writeBinary called without a string/Buffer argument: ' + arg);
396 }
397 this.tstack.push('"' + buf.toString('base64') + '"');
398 };
399
400 /**
401 * @class
402 * @name AnonReadMessageBeginReturn
403 * @property {string} fname - The name of the service method.
404 * @property {Thrift.MessageType} mtype - The type of message call.
405 * @property {number} rseqid - The sequence number of the message (0 in Thrift RPC).
406 */
407 /**
408 * Deserializes the beginning of a message.
409 * @returns {AnonReadMessageBeginReturn}
410 */
411 TJSONProtocol.prototype.readMessageBegin = function() {
412 this.rstack = [];
413 this.rpos = [];
414
415 //Borrow the inbound transport buffer and ensure data is present/consistent
416 var transBuf = this.trans.borrow();
417 if (transBuf.readIndex >= transBuf.writeIndex) {
418 throw new InputBufferUnderrunError();
419 }
420 var cursor = transBuf.readIndex;
421
422 if (transBuf.buf[cursor] !== 0x5B) { //[
423 throw new Error("Malformed JSON input, no opening bracket");
424 }
425
426 //Parse a single message (there may be several in the buffer)
427 // TODO: Handle characters using multiple code units
428 cursor++;
429 var openBracketCount = 1;
430 var inString = false;
431 for (; cursor < transBuf.writeIndex; cursor++) {
432 var chr = transBuf.buf[cursor];
433 //we use hexa charcode here because data[i] returns an int and not a char
434 if (inString) {
435 if (chr === 0x22) { //"
436 inString = false;
437 } else if (chr === 0x5C) { //\
438 //escaped character, skip
439 cursor += 1;
440 }
441 } else {
442 if (chr === 0x5B) { //[
443 openBracketCount += 1;
444 } else if (chr === 0x5D) { //]
445 openBracketCount -= 1;
446 if (openBracketCount === 0) {
447 //end of json message detected
448 break;
449 }
450 } else if (chr === 0x22) { //"
451 inString = true;
452 }
453 }
454 }
455
456 if (openBracketCount !== 0) {
457 // Missing closing bracket. Can be buffer underrun.
458 throw new InputBufferUnderrunError();
459 }
460
461 //Reconstitute the JSON object and conume the necessary bytes
462 this.robj = json_parse(transBuf.buf.slice(transBuf.readIndex, cursor+1).toString());
463 this.trans.consume(cursor + 1 - transBuf.readIndex);
464
465 //Verify the protocol version
466 var version = this.robj.shift();
467 if (version != TJSONProtocol.Version) {
468 throw new Error('Wrong thrift protocol version: ' + version);
469 }
470
471 //Objectify the thrift message {name/type/sequence-number} for return
472 // and then save the JSON object in rstack
473 var r = {};
474 r.fname = this.robj.shift();
475 r.mtype = this.robj.shift();
476 r.rseqid = this.robj.shift();
477 this.rstack.push(this.robj.shift());
478 return r;
479 };
480
481 /** Deserializes the end of a message. */
482 TJSONProtocol.prototype.readMessageEnd = function() {
483 };
484
485 /**
486 * Deserializes the beginning of a struct.
487 * @param {string} [name] - The name of the struct (ignored)
488 * @returns {object} - An object with an empty string fname property
489 */
490 TJSONProtocol.prototype.readStructBegin = function() {
491 var r = {};
492 r.fname = '';
493
494 //incase this is an array of structs
495 if (this.rstack[this.rstack.length - 1] instanceof Array) {
496 this.rstack.push(this.rstack[this.rstack.length - 1].shift());
497 }
498
499 return r;
500 };
501
502 /** Deserializes the end of a struct. */
503 TJSONProtocol.prototype.readStructEnd = function() {
504 this.rstack.pop();
505 };
506
507 /**
508 * @class
509 * @name AnonReadFieldBeginReturn
510 * @property {string} fname - The name of the field (always '').
511 * @property {Thrift.Type} ftype - The data type of the field.
512 * @property {number} fid - The unique identifier of the field.
513 */
514 /**
515 * Deserializes the beginning of a field.
516 * @returns {AnonReadFieldBeginReturn}
517 */
518 TJSONProtocol.prototype.readFieldBegin = function() {
519 var r = {};
520
521 var fid = -1;
522 var ftype = Type.STOP;
523
524 //get a fieldId
525 for (var f in (this.rstack[this.rstack.length - 1])) {
526 if (f === null) {
527 continue;
528 }
529
530 fid = parseInt(f, 10);
531 this.rpos.push(this.rstack.length);
532
533 var field = this.rstack[this.rstack.length - 1][fid];
534
535 //remove so we don't see it again
536 delete this.rstack[this.rstack.length - 1][fid];
537
538 this.rstack.push(field);
539
540 break;
541 }
542
543 if (fid != -1) {
544 //should only be 1 of these but this is the only
545 //way to match a key
546 for (var i in (this.rstack[this.rstack.length - 1])) {
547 if (TJSONProtocol.RType[i] === null) {
548 continue;
549 }
550
551 ftype = TJSONProtocol.RType[i];
552 this.rstack[this.rstack.length - 1] = this.rstack[this.rstack.length - 1][i];
553 }
554 }
555
556 r.fname = '';
557 r.ftype = ftype;
558 r.fid = fid;
559
560 return r;
561 };
562
563 /** Deserializes the end of a field. */
564 TJSONProtocol.prototype.readFieldEnd = function() {
565 var pos = this.rpos.pop();
566
567 //get back to the right place in the stack
568 while (this.rstack.length > pos) {
569 this.rstack.pop();
570 }
571 };
572
573 /**
574 * @class
575 * @name AnonReadMapBeginReturn
576 * @property {Thrift.Type} ktype - The data type of the key.
577 * @property {Thrift.Type} vtype - The data type of the value.
578 * @property {number} size - The number of elements in the map.
579 */
580 /**
581 * Deserializes the beginning of a map.
582 * @returns {AnonReadMapBeginReturn}
583 */
584 TJSONProtocol.prototype.readMapBegin = function() {
585 var map = this.rstack.pop();
586 var first = map.shift();
587 if (first instanceof Array) {
588 this.rstack.push(map);
589 map = first;
590 first = map.shift();
591 }
592
593 var r = {};
594 r.ktype = TJSONProtocol.RType[first];
595 r.vtype = TJSONProtocol.RType[map.shift()];
596 r.size = map.shift();
597
598
599 this.rpos.push(this.rstack.length);
600 this.rstack.push(map.shift());
601
602 return r;
603 };
604
605 /** Deserializes the end of a map. */
606 TJSONProtocol.prototype.readMapEnd = function() {
607 this.readFieldEnd();
608 };
609
610 /**
611 * @class
612 * @name AnonReadColBeginReturn
613 * @property {Thrift.Type} etype - The data type of the element.
614 * @property {number} size - The number of elements in the collection.
615 */
616 /**
617 * Deserializes the beginning of a list.
618 * @returns {AnonReadColBeginReturn}
619 */
620 TJSONProtocol.prototype.readListBegin = function() {
621 var list = this.rstack[this.rstack.length - 1];
622
623 var r = {};
624 r.etype = TJSONProtocol.RType[list.shift()];
625 r.size = list.shift();
626
627 this.rpos.push(this.rstack.length);
628 this.rstack.push(list.shift());
629
630 return r;
631 };
632
633 /** Deserializes the end of a list. */
634 TJSONProtocol.prototype.readListEnd = function() {
635 var pos = this.rpos.pop() - 2;
636 var st = this.rstack;
637 st.pop();
638 if (st instanceof Array && st.length > pos && st[pos].length > 0) {
639 st.push(st[pos].shift());
640 }
641 };
642
643 /**
644 * Deserializes the beginning of a set.
645 * @returns {AnonReadColBeginReturn}
646 */
647 TJSONProtocol.prototype.readSetBegin = function() {
648 return this.readListBegin();
649 };
650
651 /** Deserializes the end of a set. */
652 TJSONProtocol.prototype.readSetEnd = function() {
653 return this.readListEnd();
654 };
655
656 TJSONProtocol.prototype.readBool = function() {
657 return this.readValue() == '1';
658 };
659
660 TJSONProtocol.prototype.readByte = function() {
661 return this.readI32();
662 };
663
664 TJSONProtocol.prototype.readI16 = function() {
665 return this.readI32();
666 };
667
668 TJSONProtocol.prototype.readI32 = function(f) {
669 return +this.readValue();
670 }
671
672 /** Returns the next value found in the protocol buffer */
673 TJSONProtocol.prototype.readValue = function(f) {
674 if (f === undefined) {
675 f = this.rstack[this.rstack.length - 1];
676 }
677
678 var r = {};
679
680 if (f instanceof Array) {
681 if (f.length === 0) {
682 r.value = undefined;
683 } else {
684 r.value = f.shift();
685 }
686 } else if (!(f instanceof Int64) && f instanceof Object) {
687 for (var i in f) {
688 if (i === null) {
689 continue;
690 }
691 this.rstack.push(f[i]);
692 delete f[i];
693
694 r.value = i;
695 break;
696 }
697 } else {
698 r.value = f;
699 this.rstack.pop();
700 }
701
702 return r.value;
703 };
704
705 TJSONProtocol.prototype.readI64 = function() {
706 var n = this.readValue()
707 if (typeof n === 'string') {
708 // Assuming no one is sending in 1.11111e+33 format
709 return Int64Util.fromDecimalString(n);
710 } else {
711 return new Int64(n);
712 }
713 };
714
715 TJSONProtocol.prototype.readDouble = function() {
716 return this.readI32();
717 };
718
719 TJSONProtocol.prototype.readBinary = function() {
720 return new Buffer(this.readValue(), 'base64');
721 };
722
723 TJSONProtocol.prototype.readString = function() {
724 return this.readValue();
725 };
726
727 /**
728 * Returns the underlying transport.
729 * @readonly
730 * @returns {Thrift.Transport} The underlying transport.
731 */
732 TJSONProtocol.prototype.getTransport = function() {
733 return this.trans;
734 };
735
736 /**
737 * Method to arbitrarily skip over data
738 */
739 TJSONProtocol.prototype.skip = function(type) {
740 switch (type) {
741 case Type.BOOL:
742 this.readBool();
743 break;
744 case Type.BYTE:
745 this.readByte();
746 break;
747 case Type.I16:
748 this.readI16();
749 break;
750 case Type.I32:
751 this.readI32();
752 break;
753 case Type.I64:
754 this.readI64();
755 break;
756 case Type.DOUBLE:
757 this.readDouble();
758 break;
759 case Type.STRING:
760 this.readString();
761 break;
762 case Type.STRUCT:
763 this.readStructBegin();
764 while (true) {
765 var r = this.readFieldBegin();
766 if (r.ftype === Type.STOP) {
767 break;
768 }
769 this.skip(r.ftype);
770 this.readFieldEnd();
771 }
772 this.readStructEnd();
773 break;
774 case Type.MAP:
775 var mapBegin = this.readMapBegin();
776 for (var i = 0; i < mapBegin.size; ++i) {
777 this.skip(mapBegin.ktype);
778 this.skip(mapBegin.vtype);
779 }
780 this.readMapEnd();
781 break;
782 case Type.SET:
783 var setBegin = this.readSetBegin();
784 for (var i2 = 0; i2 < setBegin.size; ++i2) {
785 this.skip(setBegin.etype);
786 }
787 this.readSetEnd();
788 break;
789 case Type.LIST:
790 var listBegin = this.readListBegin();
791 for (var i3 = 0; i3 < listBegin.size; ++i3) {
792 this.skip(listBegin.etype);
793 }
794 this.readListEnd();
795 break;
796 default:
797 throw new Error("Invalid type: " + type);
798 }
799 };