UNPKG

parquetjs-lite

Version:

fully asynchronous, pure JavaScript implementation of the Parquet file format

919 lines (805 loc) 26 kB
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ var log = require('./log'); var Int64 = require('node-int64'); var Thrift = require('./thrift'); var Type = Thrift.Type; module.exports = TCompactProtocol; var POW_8 = Math.pow(2, 8); var POW_24 = Math.pow(2, 24); var POW_32 = Math.pow(2, 32); var POW_40 = Math.pow(2, 40); var POW_48 = Math.pow(2, 48); var POW_52 = Math.pow(2, 52); var POW_1022 = Math.pow(2, 1022); /** * Constructor Function for the Compact Protocol. * @constructor * @param {object} [trans] - The underlying transport to read/write. * @classdesc The Apache Thrift Protocol layer performs serialization * of base types, the compact protocol serializes data in binary * form with minimal space used for scalar values. */ function TCompactProtocol(trans) { this.trans = trans; this.lastField_ = []; this.lastFieldId_ = 0; this.string_limit_ = 0; this.string_buf_ = null; this.string_buf_size_ = 0; this.container_limit_ = 0; this.booleanField_ = { name: null, hasBoolValue: false }; this.boolValue_ = { hasBoolValue: false, boolValue: false }; }; // // Compact Protocol Constants // /** * Compact Protocol ID number. * @readonly * @const {number} PROTOCOL_ID */ TCompactProtocol.PROTOCOL_ID = -126; //1000 0010 /** * Compact Protocol version number. * @readonly * @const {number} VERSION_N */ TCompactProtocol.VERSION_N = 1; /** * Compact Protocol version mask for combining protocol version and message type in one byte. * @readonly * @const {number} VERSION_MASK */ TCompactProtocol.VERSION_MASK = 0x1f; //0001 1111 /** * Compact Protocol message type mask for combining protocol version and message type in one byte. * @readonly * @const {number} TYPE_MASK */ TCompactProtocol.TYPE_MASK = -32; //1110 0000 /** * Compact Protocol message type bits for ensuring message type bit size. * @readonly * @const {number} TYPE_BITS */ TCompactProtocol.TYPE_BITS = 7; //0000 0111 /** * Compact Protocol message type shift amount for combining protocol version and message type in one byte. * @readonly * @const {number} TYPE_SHIFT_AMOUNT */ TCompactProtocol.TYPE_SHIFT_AMOUNT = 5; /** * Compact Protocol type IDs used to keep type data within one nibble. * @readonly * @property {number} CT_STOP - End of a set of fields. * @property {number} CT_BOOLEAN_TRUE - Flag for Boolean field with true value (packed field and value). * @property {number} CT_BOOLEAN_FALSE - Flag for Boolean field with false value (packed field and value). * @property {number} CT_BYTE - Signed 8 bit integer. * @property {number} CT_I16 - Signed 16 bit integer. * @property {number} CT_I32 - Signed 32 bit integer. * @property {number} CT_I64 - Signed 64 bit integer (2^53 max in JavaScript). * @property {number} CT_DOUBLE - 64 bit IEEE 854 floating point. * @property {number} CT_BINARY - Array of bytes (used for strings also). * @property {number} CT_LIST - A collection type (unordered). * @property {number} CT_SET - A collection type (unordered and without repeated values). * @property {number} CT_MAP - A collection type (map/associative-array/dictionary). * @property {number} CT_STRUCT - A multifield type. */ TCompactProtocol.Types = { CT_STOP: 0x00, CT_BOOLEAN_TRUE: 0x01, CT_BOOLEAN_FALSE: 0x02, CT_BYTE: 0x03, CT_I16: 0x04, CT_I32: 0x05, CT_I64: 0x06, CT_DOUBLE: 0x07, CT_BINARY: 0x08, CT_LIST: 0x09, CT_SET: 0x0A, CT_MAP: 0x0B, CT_STRUCT: 0x0C }; /** * Array mapping Compact type IDs to standard Thrift type IDs. * @readonly */ TCompactProtocol.TTypeToCType = [ TCompactProtocol.Types.CT_STOP, // T_STOP 0, // unused TCompactProtocol.Types.CT_BOOLEAN_TRUE, // T_BOOL TCompactProtocol.Types.CT_BYTE, // T_BYTE TCompactProtocol.Types.CT_DOUBLE, // T_DOUBLE 0, // unused TCompactProtocol.Types.CT_I16, // T_I16 0, // unused TCompactProtocol.Types.CT_I32, // T_I32 0, // unused TCompactProtocol.Types.CT_I64, // T_I64 TCompactProtocol.Types.CT_BINARY, // T_STRING TCompactProtocol.Types.CT_STRUCT, // T_STRUCT TCompactProtocol.Types.CT_MAP, // T_MAP TCompactProtocol.Types.CT_SET, // T_SET TCompactProtocol.Types.CT_LIST, // T_LIST ]; // // Compact Protocol Utilities // /** * Returns the underlying transport layer. * @return {object} The underlying transport layer. */TCompactProtocol.prototype.getTransport = function() { return this.trans; }; /** * Lookup a Compact Protocol Type value for a given Thrift Type value. * N.B. Used only internally. * @param {number} ttype - Thrift type value * @returns {number} Compact protocol type value */ TCompactProtocol.prototype.getCompactType = function(ttype) { return TCompactProtocol.TTypeToCType[ttype]; }; /** * Lookup a Thrift Type value for a given Compact Protocol Type value. * N.B. Used only internally. * @param {number} type - Compact Protocol type value * @returns {number} Thrift Type value */ TCompactProtocol.prototype.getTType = function(type) { switch (type) { case Type.STOP: return Type.STOP; case TCompactProtocol.Types.CT_BOOLEAN_FALSE: case TCompactProtocol.Types.CT_BOOLEAN_TRUE: return Type.BOOL; case TCompactProtocol.Types.CT_BYTE: return Type.BYTE; case TCompactProtocol.Types.CT_I16: return Type.I16; case TCompactProtocol.Types.CT_I32: return Type.I32; case TCompactProtocol.Types.CT_I64: return Type.I64; case TCompactProtocol.Types.CT_DOUBLE: return Type.DOUBLE; case TCompactProtocol.Types.CT_BINARY: return Type.STRING; case TCompactProtocol.Types.CT_LIST: return Type.LIST; case TCompactProtocol.Types.CT_SET: return Type.SET; case TCompactProtocol.Types.CT_MAP: return Type.MAP; case TCompactProtocol.Types.CT_STRUCT: return Type.STRUCT; default: throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.INVALID_DATA, "Unknown type: " + type); } return Type.STOP; }; // // Compact Protocol write operations // /** * Send any buffered bytes to the end point. */ TCompactProtocol.prototype.flush = function() { return this.trans.flush(); }; /** * Writes an RPC message header * @param {string} name - The method name for the message. * @param {number} type - The type of message (CALL, REPLY, EXCEPTION, ONEWAY). * @param {number} seqid - The call sequence number (if any). */ TCompactProtocol.prototype.writeMessageBegin = function(name, type, seqid) { this.writeByte(TCompactProtocol.PROTOCOL_ID); this.writeByte((TCompactProtocol.VERSION_N & TCompactProtocol.VERSION_MASK) | ((type << TCompactProtocol.TYPE_SHIFT_AMOUNT) & TCompactProtocol.TYPE_MASK)); this.writeVarint32(seqid); this.writeString(name); // Record client seqid to find callback again if (this._seqid) { // TODO better logging log warning log.warning('SeqId already set', { 'name': name }); } else { this._seqid = seqid; this.trans.setCurrSeqId(seqid); } }; TCompactProtocol.prototype.writeMessageEnd = function() { }; TCompactProtocol.prototype.writeStructBegin = function(name) { this.lastField_.push(this.lastFieldId_); this.lastFieldId_ = 0; }; TCompactProtocol.prototype.writeStructEnd = function() { this.lastFieldId_ = this.lastField_.pop(); }; /** * Writes a struct field header * @param {string} name - The field name (not written with the compact protocol). * @param {number} type - The field data type (a normal Thrift field Type). * @param {number} id - The IDL field Id. */ TCompactProtocol.prototype.writeFieldBegin = function(name, type, id) { if (type != Type.BOOL) { return this.writeFieldBeginInternal(name, type, id, -1); } this.booleanField_.name = name; this.booleanField_.fieldType = type; this.booleanField_.fieldId = id; }; TCompactProtocol.prototype.writeFieldEnd = function() { }; TCompactProtocol.prototype.writeFieldStop = function() { this.writeByte(TCompactProtocol.Types.CT_STOP); }; /** * Writes a map collection header * @param {number} keyType - The Thrift type of the map keys. * @param {number} valType - The Thrift type of the map values. * @param {number} size - The number of k/v pairs in the map. */ TCompactProtocol.prototype.writeMapBegin = function(keyType, valType, size) { if (size === 0) { this.writeByte(0); } else { this.writeVarint32(size); this.writeByte(this.getCompactType(keyType) << 4 | this.getCompactType(valType)); } }; TCompactProtocol.prototype.writeMapEnd = function() { }; /** * Writes a list collection header * @param {number} elemType - The Thrift type of the list elements. * @param {number} size - The number of elements in the list. */ TCompactProtocol.prototype.writeListBegin = function(elemType, size) { this.writeCollectionBegin(elemType, size); }; TCompactProtocol.prototype.writeListEnd = function() { }; /** * Writes a set collection header * @param {number} elemType - The Thrift type of the set elements. * @param {number} size - The number of elements in the set. */ TCompactProtocol.prototype.writeSetBegin = function(elemType, size) { this.writeCollectionBegin(elemType, size); }; TCompactProtocol.prototype.writeSetEnd = function() { }; TCompactProtocol.prototype.writeBool = function(value) { if (this.booleanField_.name !== null) { // we haven't written the field header yet this.writeFieldBeginInternal(this.booleanField_.name, this.booleanField_.fieldType, this.booleanField_.fieldId, (value ? TCompactProtocol.Types.CT_BOOLEAN_TRUE : TCompactProtocol.Types.CT_BOOLEAN_FALSE)); this.booleanField_.name = null; } else { // we're not part of a field, so just write the value this.writeByte((value ? TCompactProtocol.Types.CT_BOOLEAN_TRUE : TCompactProtocol.Types.CT_BOOLEAN_FALSE)); } }; TCompactProtocol.prototype.writeByte = function(b) { this.trans.write(new Buffer([b])); }; TCompactProtocol.prototype.writeI16 = function(i16) { this.writeVarint32(this.i32ToZigzag(i16)); }; TCompactProtocol.prototype.writeI32 = function(i32) { this.writeVarint32(this.i32ToZigzag(i32)); }; TCompactProtocol.prototype.writeI64 = function(i64) { this.writeVarint64(this.i64ToZigzag(i64)); }; // Little-endian, unlike TBinaryProtocol TCompactProtocol.prototype.writeDouble = function(v) { var buff = new Buffer(8); var m, e, c; buff[7] = (v < 0 ? 0x80 : 0x00); v = Math.abs(v); if (v !== v) { // NaN, use QNaN IEEE format m = 2251799813685248; e = 2047; } else if (v === Infinity) { m = 0; e = 2047; } else { e = Math.floor(Math.log(v) / Math.LN2); c = Math.pow(2, -e); if (v * c < 1) { e--; c *= 2; } if (e + 1023 >= 2047) { // Overflow m = 0; e = 2047; } else if (e + 1023 >= 1) { // Normalized - term order matters, as Math.pow(2, 52-e) and v*Math.pow(2, 52) can overflow m = (v*c-1) * POW_52; e += 1023; } else { // Denormalized - also catches the '0' case, somewhat by chance m = (v * POW_1022) * POW_52; e = 0; } } buff[6] = (e << 4) & 0xf0; buff[7] |= (e >> 4) & 0x7f; buff[0] = m & 0xff; m = Math.floor(m / POW_8); buff[1] = m & 0xff; m = Math.floor(m / POW_8); buff[2] = m & 0xff; m = Math.floor(m / POW_8); buff[3] = m & 0xff; m >>= 8; buff[4] = m & 0xff; m >>= 8; buff[5] = m & 0xff; m >>= 8; buff[6] |= m & 0x0f; this.trans.write(buff); }; TCompactProtocol.prototype.writeStringOrBinary = function(name, encoding, arg) { if (typeof arg === 'string') { this.writeVarint32(Buffer.byteLength(arg, encoding)) ; this.trans.write(new Buffer(arg, encoding)); } else if (arg instanceof Buffer || Object.prototype.toString.call(arg) == '[object Uint8Array]') { // Buffers in Node.js under Browserify may extend UInt8Array instead of // defining a new object. We detect them here so we can write them // correctly this.writeVarint32(arg.length); this.trans.write(arg); } else { throw new Error(name + ' called without a string/Buffer argument: ' + arg); } }; TCompactProtocol.prototype.writeString = function(arg) { this.writeStringOrBinary('writeString', 'utf8', arg); }; TCompactProtocol.prototype.writeBinary = function(arg) { this.writeStringOrBinary('writeBinary', 'binary', arg); }; // // Compact Protocol internal write methods // TCompactProtocol.prototype.writeFieldBeginInternal = function(name, fieldType, fieldId, typeOverride) { //If there's a type override, use that. var typeToWrite = (typeOverride == -1 ? this.getCompactType(fieldType) : typeOverride); //Check if we can delta encode the field id if (fieldId > this.lastFieldId_ && fieldId - this.lastFieldId_ <= 15) { //Include the type delta with the field ID this.writeByte((fieldId - this.lastFieldId_) << 4 | typeToWrite); } else { //Write separate type and ID values this.writeByte(typeToWrite); this.writeI16(fieldId); } this.lastFieldId_ = fieldId; }; TCompactProtocol.prototype.writeCollectionBegin = function(elemType, size) { if (size <= 14) { //Combine size and type in one byte if possible this.writeByte(size << 4 | this.getCompactType(elemType)); } else { this.writeByte(0xf0 | this.getCompactType(elemType)); this.writeVarint32(size); } }; /** * Write an i32 as a varint. Results in 1-5 bytes on the wire. */ TCompactProtocol.prototype.writeVarint32 = function(n) { var buf = new Buffer(5); var wsize = 0; while (true) { if ((n & ~0x7F) === 0) { buf[wsize++] = n; break; } else { buf[wsize++] = ((n & 0x7F) | 0x80); n = n >>> 7; } } var wbuf = new Buffer(wsize); buf.copy(wbuf,0,0,wsize); this.trans.write(wbuf); }; /** * Write an i64 as a varint. Results in 1-10 bytes on the wire. * N.B. node-int64 is always big endian */ TCompactProtocol.prototype.writeVarint64 = function(n) { if (typeof n === "number"){ n = new Int64(n); } if (! (n instanceof Int64)) { throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.INVALID_DATA, "Expected Int64 or Number, found: " + n); } var buf = new Buffer(10); var wsize = 0; var hi = n.buffer.readUInt32BE(0, true); var lo = n.buffer.readUInt32BE(4, true); var mask = 0; while (true) { if (((lo & ~0x7F) === 0) && (hi === 0)) { buf[wsize++] = lo; break; } else { buf[wsize++] = ((lo & 0x7F) | 0x80); mask = hi << 25; lo = lo >>> 7; hi = hi >>> 7; lo = lo | mask; } } var wbuf = new Buffer(wsize); buf.copy(wbuf,0,0,wsize); this.trans.write(wbuf); }; /** * Convert l into a zigzag long. This allows negative numbers to be * represented compactly as a varint. */ TCompactProtocol.prototype.i64ToZigzag = function(l) { if (typeof l === 'string') { l = new Int64(parseInt(l, 10)); } else if (typeof l === 'number') { l = new Int64(l); } if (! (l instanceof Int64)) { throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.INVALID_DATA, "Expected Int64 or Number, found: " + l); } var hi = l.buffer.readUInt32BE(0, true); var lo = l.buffer.readUInt32BE(4, true); var sign = hi >>> 31; hi = ((hi << 1) | (lo >>> 31)) ^ ((!!sign) ? 0xFFFFFFFF : 0); lo = (lo << 1) ^ ((!!sign) ? 0xFFFFFFFF : 0); return new Int64(hi, lo); }; /** * Convert n into a zigzag int. This allows negative numbers to be * represented compactly as a varint. */ TCompactProtocol.prototype.i32ToZigzag = function(n) { return (n << 1) ^ ((n & 0x80000000) ? 0xFFFFFFFF : 0); }; // // Compact Protocol read operations // TCompactProtocol.prototype.readMessageBegin = function() { //Read protocol ID var protocolId = this.trans.readByte(); if (protocolId != TCompactProtocol.PROTOCOL_ID) { throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.BAD_VERSION, "Bad protocol identifier " + protocolId); } //Read Version and Type var versionAndType = this.trans.readByte(); var version = (versionAndType & TCompactProtocol.VERSION_MASK); if (version != TCompactProtocol.VERSION_N) { throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.BAD_VERSION, "Bad protocol version " + version); } var type = ((versionAndType >> TCompactProtocol.TYPE_SHIFT_AMOUNT) & TCompactProtocol.TYPE_BITS); //Read SeqId var seqid = this.readVarint32(); //Read name var name = this.readString(); return {fname: name, mtype: type, rseqid: seqid}; }; TCompactProtocol.prototype.readMessageEnd = function() { }; TCompactProtocol.prototype.readStructBegin = function() { this.lastField_.push(this.lastFieldId_); this.lastFieldId_ = 0; return {fname: ''}; }; TCompactProtocol.prototype.readStructEnd = function() { this.lastFieldId_ = this.lastField_.pop(); }; TCompactProtocol.prototype.readFieldBegin = function() { var fieldId = 0; var b = this.trans.readByte(b); var type = (b & 0x0f); if (type == TCompactProtocol.Types.CT_STOP) { return {fname: null, ftype: Thrift.Type.STOP, fid: 0}; } //Mask off the 4 MSB of the type header to check for field id delta. var modifier = ((b & 0x000000f0) >>> 4); if (modifier === 0) { //If not a delta read the field id. fieldId = this.readI16(); } else { //Recover the field id from the delta fieldId = (this.lastFieldId_ + modifier); } var fieldType = this.getTType(type); //Boolean are encoded with the type if (type == TCompactProtocol.Types.CT_BOOLEAN_TRUE || type == TCompactProtocol.Types.CT_BOOLEAN_FALSE) { this.boolValue_.hasBoolValue = true; this.boolValue_.boolValue = (type == TCompactProtocol.Types.CT_BOOLEAN_TRUE ? true : false); } //Save the new field for the next delta computation. this.lastFieldId_ = fieldId; return {fname: null, ftype: fieldType, fid: fieldId}; }; TCompactProtocol.prototype.readFieldEnd = function() { }; TCompactProtocol.prototype.readMapBegin = function() { var msize = this.readVarint32(); if (msize < 0) { throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.NEGATIVE_SIZE, "Negative map size"); } var kvType = 0; if (msize !== 0) { kvType = this.trans.readByte(); } var keyType = this.getTType((kvType & 0xf0) >>> 4); var valType = this.getTType(kvType & 0xf); return {ktype: keyType, vtype: valType, size: msize}; }; TCompactProtocol.prototype.readMapEnd = function() { }; TCompactProtocol.prototype.readListBegin = function() { var size_and_type = this.trans.readByte(); var lsize = (size_and_type >>> 4) & 0x0000000f; if (lsize == 15) { lsize = this.readVarint32(); } if (lsize < 0) { throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.NEGATIVE_SIZE, "Negative list size"); } var elemType = this.getTType(size_and_type & 0x0000000f); return {etype: elemType, size: lsize}; }; TCompactProtocol.prototype.readListEnd = function() { }; TCompactProtocol.prototype.readSetBegin = function() { return this.readListBegin(); }; TCompactProtocol.prototype.readSetEnd = function() { }; TCompactProtocol.prototype.readBool = function() { var value = false; var rsize = 0; if (this.boolValue_.hasBoolValue === true) { value = this.boolValue_.boolValue; this.boolValue_.hasBoolValue = false; } else { var res = this.trans.readByte(); rsize = res.rsize; value = (res.value == TCompactProtocol.Types.CT_BOOLEAN_TRUE); } return value; }; TCompactProtocol.prototype.readByte = function() { return this.trans.readByte(); }; TCompactProtocol.prototype.readI16 = function() { return this.readI32(); }; TCompactProtocol.prototype.readI32 = function() { return this.zigzagToI32(this.readVarint32()); }; TCompactProtocol.prototype.readI64 = function() { return this.zigzagToI64(this.readVarint64()); }; // Little-endian, unlike TBinaryProtocol TCompactProtocol.prototype.readDouble = function() { var buff = this.trans.read(8); var off = 0; var signed = buff[off + 7] & 0x80; var e = (buff[off+6] & 0xF0) >> 4; e += (buff[off+7] & 0x7F) << 4; var m = buff[off]; m += buff[off+1] << 8; m += buff[off+2] << 16; m += buff[off+3] * POW_24; m += buff[off+4] * POW_32; m += buff[off+5] * POW_40; m += (buff[off+6] & 0x0F) * POW_48; switch (e) { case 0: e = -1022; break; case 2047: return m ? NaN : (signed ? -Infinity : Infinity); default: m += POW_52; e -= 1023; } if (signed) { m *= -1; } return m * Math.pow(2, e - 52); }; TCompactProtocol.prototype.readBinary = function() { var size = this.readVarint32(); if (size === 0) { return new Buffer(0); } if (size < 0) { throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.NEGATIVE_SIZE, "Negative binary size"); } return this.trans.read(size); }; TCompactProtocol.prototype.readString = function() { var size = this.readVarint32(); // Catch empty string case if (size === 0) { return ""; } // Catch error cases if (size < 0) { throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.NEGATIVE_SIZE, "Negative string size"); } return this.trans.readString(size); }; // // Compact Protocol internal read operations // /** * Read an i32 from the wire as a varint. The MSB of each byte is set * if there is another byte to follow. This can read up to 5 bytes. */ TCompactProtocol.prototype.readVarint32 = function() { return this.readVarint64().toNumber(); }; /** * Read an i64 from the wire as a proper varint. The MSB of each byte is set * if there is another byte to follow. This can read up to 10 bytes. */ TCompactProtocol.prototype.readVarint64 = function() { var rsize = 0; var lo = 0; var hi = 0; var shift = 0; while (true) { var b = this.trans.readByte(); rsize ++; if (shift <= 25) { lo = lo | ((b & 0x7f) << shift); } else if (25 < shift && shift < 32) { lo = lo | ((b & 0x7f) << shift); hi = hi | ((b & 0x7f) >>> (32-shift)); } else { hi = hi | ((b & 0x7f) << (shift-32)); } shift += 7; if (!(b & 0x80)) { break; } if (rsize >= 10) { throw new Thrift.TProtocolException(Thrift.TProtocolExceptionType.INVALID_DATA, "Variable-length int over 10 bytes."); } } return new Int64(hi, lo); }; /** * Convert from zigzag int to int. */ TCompactProtocol.prototype.zigzagToI32 = function(n) { return (n >>> 1) ^ (-1 * (n & 1)); }; /** * Convert from zigzag long to long. */ TCompactProtocol.prototype.zigzagToI64 = function(n) { var hi = n.buffer.readUInt32BE(0, true); var lo = n.buffer.readUInt32BE(4, true); var neg = new Int64(hi & 0, lo & 1); neg._2scomp(); var hi_neg = neg.buffer.readUInt32BE(0, true); var lo_neg = neg.buffer.readUInt32BE(4, true); var hi_lo = (hi << 31); hi = (hi >>> 1) ^ (hi_neg); lo = ((lo >>> 1) | hi_lo) ^ (lo_neg); return new Int64(hi, lo); }; TCompactProtocol.prototype.skip = function(type) { switch (type) { case Type.STOP: return; case Type.BOOL: this.readBool(); break; case Type.BYTE: this.readByte(); break; case Type.I16: this.readI16(); break; case Type.I32: this.readI32(); break; case Type.I64: this.readI64(); break; case Type.DOUBLE: this.readDouble(); break; case Type.STRING: this.readString(); break; case Type.STRUCT: this.readStructBegin(); while (true) { var r = this.readFieldBegin(); if (r.ftype === Type.STOP) { break; } this.skip(r.ftype); this.readFieldEnd(); } this.readStructEnd(); break; case Type.MAP: var mapBegin = this.readMapBegin(); for (var i = 0; i < mapBegin.size; ++i) { this.skip(mapBegin.ktype); this.skip(mapBegin.vtype); } this.readMapEnd(); break; case Type.SET: var setBegin = this.readSetBegin(); for (var i2 = 0; i2 < setBegin.size; ++i2) { this.skip(setBegin.etype); } this.readSetEnd(); break; case Type.LIST: var listBegin = this.readListBegin(); for (var i3 = 0; i3 < listBegin.size; ++i3) { this.skip(listBegin.etype); } this.readListEnd(); break; default: throw new Error("Invalid type: " + type); } };