UNPKG

bytebuffer

Version:

The swiss army knife for binary data in JavaScript.

222 lines (211 loc) 11.7 kB
//? if (VARINT64) { // types/varints/varint64 if (Long) { /** * Maximum number of bytes required to store a 64bit base 128 variable-length integer. * @type {number} * @const * @expose */ ByteBuffer.MAX_VARINT64_BYTES = 10; /** * Calculates the actual number of bytes required to store a 64bit base 128 variable-length integer. * @param {number|!Long} value Value to encode * @returns {number} Number of bytes required. Capped to {@link ByteBuffer.MAX_VARINT64_BYTES} * @expose */ ByteBuffer.calculateVarint64 = function(value) { //? LONG('value'); // ref: src/google/protobuf/io/coded_stream.cc var part0 = value.toInt() >>> 0, part1 = value.shiftRightUnsigned(28).toInt() >>> 0, part2 = value.shiftRightUnsigned(56).toInt() >>> 0; if (part2 == 0) { if (part1 == 0) { if (part0 < 1 << 14) return part0 < 1 << 7 ? 1 : 2; else return part0 < 1 << 21 ? 3 : 4; } else { if (part1 < 1 << 14) return part1 < 1 << 7 ? 5 : 6; else return part1 < 1 << 21 ? 7 : 8; } } else return part2 < 1 << 7 ? 9 : 10; }; /** * Zigzag encodes a signed 64bit integer so that it can be effectively used with varint encoding. * @param {number|!Long} value Signed long * @returns {!Long} Unsigned zigzag encoded long * @expose */ ByteBuffer.zigZagEncode64 = function(value) { //? LONG('value', false); // ref: src/google/protobuf/wire_format_lite.h return value.shiftLeft(1).xor(value.shiftRight(63)).toUnsigned(); }; /** * Decodes a zigzag encoded signed 64bit integer. * @param {!Long|number} value Unsigned zigzag encoded long or JavaScript number * @returns {!Long} Signed long * @expose */ ByteBuffer.zigZagDecode64 = function(value) { //? LONG('value', false); // ref: src/google/protobuf/wire_format_lite.h return value.shiftRightUnsigned(1).xor(value.and(Long.ONE).toSigned().negate()).toSigned(); }; /** * Writes a 64bit base 128 variable-length integer. * @param {number|Long} value Value to write * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes * written if omitted. * @returns {!ByteBuffer|number} `this` if offset is omitted, else the actual number of bytes written. * @expose */ ByteBufferPrototype.writeVarint64 = function(value, offset) { //? RELATIVE(); if (!this.noAssert) { //? ASSERT_LONG('value'); //? ASSERT_OFFSET(); } //? LONG('value', false); var size = ByteBuffer.calculateVarint64(value), part0 = value.toInt() >>> 0, part1 = value.shiftRightUnsigned(28).toInt() >>> 0, part2 = value.shiftRightUnsigned(56).toInt() >>> 0; //? ENSURE_CAPACITY('size'); switch (size) { //? if (NODE) { case 10: this.buffer[offset+9] = (part2 >>> 7) & 0x01; case 9 : this.buffer[offset+8] = size !== 9 ? (part2 ) | 0x80 : (part2 ) & 0x7F; case 8 : this.buffer[offset+7] = size !== 8 ? (part1 >>> 21) | 0x80 : (part1 >>> 21) & 0x7F; case 7 : this.buffer[offset+6] = size !== 7 ? (part1 >>> 14) | 0x80 : (part1 >>> 14) & 0x7F; case 6 : this.buffer[offset+5] = size !== 6 ? (part1 >>> 7) | 0x80 : (part1 >>> 7) & 0x7F; case 5 : this.buffer[offset+4] = size !== 5 ? (part1 ) | 0x80 : (part1 ) & 0x7F; case 4 : this.buffer[offset+3] = size !== 4 ? (part0 >>> 21) | 0x80 : (part0 >>> 21) & 0x7F; case 3 : this.buffer[offset+2] = size !== 3 ? (part0 >>> 14) | 0x80 : (part0 >>> 14) & 0x7F; case 2 : this.buffer[offset+1] = size !== 2 ? (part0 >>> 7) | 0x80 : (part0 >>> 7) & 0x7F; case 1 : this.buffer[offset ] = size !== 1 ? (part0 ) | 0x80 : (part0 ) & 0x7F; //? } else { case 10: this.view.setUint8(offset+9, (part2 >>> 7) & 0x01); case 9 : this.view.setUint8(offset+8, size !== 9 ? (part2 ) | 0x80 : (part2 ) & 0x7F); case 8 : this.view.setUint8(offset+7, size !== 8 ? (part1 >>> 21) | 0x80 : (part1 >>> 21) & 0x7F); case 7 : this.view.setUint8(offset+6, size !== 7 ? (part1 >>> 14) | 0x80 : (part1 >>> 14) & 0x7F); case 6 : this.view.setUint8(offset+5, size !== 6 ? (part1 >>> 7) | 0x80 : (part1 >>> 7) & 0x7F); case 5 : this.view.setUint8(offset+4, size !== 5 ? (part1 ) | 0x80 : (part1 ) & 0x7F); case 4 : this.view.setUint8(offset+3, size !== 4 ? (part0 >>> 21) | 0x80 : (part0 >>> 21) & 0x7F); case 3 : this.view.setUint8(offset+2, size !== 3 ? (part0 >>> 14) | 0x80 : (part0 >>> 14) & 0x7F); case 2 : this.view.setUint8(offset+1, size !== 2 ? (part0 >>> 7) | 0x80 : (part0 >>> 7) & 0x7F); case 1 : this.view.setUint8(offset , size !== 1 ? (part0 ) | 0x80 : (part0 ) & 0x7F); //? } } if (relative) { this.offset += size; return this; } else { return size; } }; /** * Writes a zig-zag encoded 64bit base 128 variable-length integer. * @param {number|Long} value Value to write * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes * written if omitted. * @returns {!ByteBuffer|number} `this` if offset is omitted, else the actual number of bytes written. * @expose */ ByteBufferPrototype.writeVarint64ZigZag = function(value, offset) { return this.writeVarint64(ByteBuffer.zigZagEncode64(value), offset); }; /** * Reads a 64bit base 128 variable-length integer. Requires Long.js. * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes * read if omitted. * @returns {!Long|!{value: Long, length: number}} The value read if offset is omitted, else the value read and * the actual number of bytes read. * @throws {Error} If it's not a valid varint * @expose */ ByteBufferPrototype.readVarint64 = function(offset) { //? RELATIVE(); if (!this.noAssert) { //? ASSERT_OFFSET(1); } // ref: src/google/protobuf/io/coded_stream.cc var start = offset, part0 = 0, part1 = 0, part2 = 0, b = 0; //? if (NODE) { //? if (INLINE) { // Assert through checking for undefined (not optimal but coherent) b = this.buffer[offset++]; part0 = (b & 0x7F) ; if ( b & 0x80 ) { b = this.buffer[offset++]; part0 |= (b & 0x7F) << 7; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { b = this.buffer[offset++]; part0 |= (b & 0x7F) << 14; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { b = this.buffer[offset++]; part0 |= (b & 0x7F) << 21; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { b = this.buffer[offset++]; part1 = (b & 0x7F) ; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { b = this.buffer[offset++]; part1 |= (b & 0x7F) << 7; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { b = this.buffer[offset++]; part1 |= (b & 0x7F) << 14; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { b = this.buffer[offset++]; part1 |= (b & 0x7F) << 21; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { b = this.buffer[offset++]; part2 = (b & 0x7F) ; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { b = this.buffer[offset++]; part2 |= (b & 0x7F) << 7; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { throw Error("Buffer overrun"); }}}}}}}}}} //? } else { // Assert as usual b = this.buffer.readUint8(offset++, true ); part0 = (b & 0x7F) ; if (b & 0x80) { b = this.buffer.readUint8(offset++, this.noAssert); part0 |= (b & 0x7F) << 7; if (b & 0x80) { b = this.buffer.readUint8(offset++, this.noAssert); part0 |= (b & 0x7F) << 14; if (b & 0x80) { b = this.buffer.readUint8(offset++, this.noAssert); part0 |= (b & 0x7F) << 21; if (b & 0x80) { b = this.buffer.readUint8(offset++, this.noAssert); part1 = (b & 0x7F) ; if (b & 0x80) { b = this.buffer.readUint8(offset++, this.noAssert); part1 |= (b & 0x7F) << 7; if (b & 0x80) { b = this.buffer.readUint8(offset++, this.noAssert); part1 |= (b & 0x7F) << 14; if (b & 0x80) { b = this.buffer.readUint8(offset++, this.noAssert); part1 |= (b & 0x7F) << 21; if (b & 0x80) { b = this.buffer.readUint8(offset++, this.noAssert); part2 = (b & 0x7F) ; if (b & 0x80) { b = this.buffer.readUint8(offset++, this.noAssert); part2 |= (b & 0x7F) << 7; if (b & 0x80) { throw Error("Buffer overrun"); }}}}}}}}}} //? } //? } else { // Asserts on its own b = this.view.getUint8(offset++); part0 = (b & 0x7F) ; if (b & 0x80) { b = this.view.getUint8(offset++); part0 |= (b & 0x7F) << 7; if (b & 0x80) { b = this.view.getUint8(offset++); part0 |= (b & 0x7F) << 14; if (b & 0x80) { b = this.view.getUint8(offset++); part0 |= (b & 0x7F) << 21; if (b & 0x80) { b = this.view.getUint8(offset++); part1 = (b & 0x7F) ; if (b & 0x80) { b = this.view.getUint8(offset++); part1 |= (b & 0x7F) << 7; if (b & 0x80) { b = this.view.getUint8(offset++); part1 |= (b & 0x7F) << 14; if (b & 0x80) { b = this.view.getUint8(offset++); part1 |= (b & 0x7F) << 21; if (b & 0x80) { b = this.view.getUint8(offset++); part2 = (b & 0x7F) ; if (b & 0x80) { b = this.view.getUint8(offset++); part2 |= (b & 0x7F) << 7; if (b & 0x80) { throw Error("Buffer overrun"); }}}}}}}}}} //? } var value = Long.fromBits(part0 | (part1 << 28), (part1 >>> 4) | (part2) << 24, false); if (relative) { this.offset = offset; return value; } else { return { 'value': value, 'length': offset-start }; } }; /** * Reads a zig-zag encoded 64bit base 128 variable-length integer. Requires Long.js. * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes * read if omitted. * @returns {!Long|!{value: Long, length: number}} The value read if offset is omitted, else the value read and * the actual number of bytes read. * @throws {Error} If it's not a valid varint * @expose */ ByteBufferPrototype.readVarint64ZigZag = function(offset) { var val = this.readVarint64(offset); if (val && val['value'] instanceof Long) val["value"] = ByteBuffer.zigZagDecode64(val["value"]); else val = ByteBuffer.zigZagDecode64(val); return val; }; } // Long //? }