123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416 |
- "use strict";
- module.exports = Reader;
- var util = require("./util/minimal");
- var BufferReader; // cyclic
- var LongBits = util.LongBits,
- utf8 = util.utf8;
- /* istanbul ignore next */
- function indexOutOfRange(reader, writeLength) {
- return RangeError("index out of range: " + reader.pos + " + " + (writeLength || 1) + " > " + reader.len);
- }
- /**
- * Constructs a new reader instance using the specified buffer.
- * @classdesc Wire format reader using `Uint8Array` if available, otherwise `Array`.
- * @constructor
- * @param {Uint8Array} buffer Buffer to read from
- */
- function Reader(buffer) {
- /**
- * Read buffer.
- * @type {Uint8Array}
- */
- this.buf = buffer;
- /**
- * Read buffer position.
- * @type {number}
- */
- this.pos = 0;
- /**
- * Read buffer length.
- * @type {number}
- */
- this.len = buffer.length;
- }
- var create_array = typeof Uint8Array !== "undefined"
- ? function create_typed_array(buffer) {
- if (buffer instanceof Uint8Array || Array.isArray(buffer))
- return new Reader(buffer);
- throw Error("illegal buffer");
- }
- /* istanbul ignore next */
- : function create_array(buffer) {
- if (Array.isArray(buffer))
- return new Reader(buffer);
- throw Error("illegal buffer");
- };
- var create = function create() {
- return util.Buffer
- ? function create_buffer_setup(buffer) {
- return (Reader.create = function create_buffer(buffer) {
- return util.Buffer.isBuffer(buffer)
- ? new BufferReader(buffer)
- /* istanbul ignore next */
- : create_array(buffer);
- })(buffer);
- }
- /* istanbul ignore next */
- : create_array;
- };
- /**
- * Creates a new reader using the specified buffer.
- * @function
- * @param {Uint8Array|Buffer} buffer Buffer to read from
- * @returns {Reader|BufferReader} A {@link BufferReader} if `buffer` is a Buffer, otherwise a {@link Reader}
- * @throws {Error} If `buffer` is not a valid buffer
- */
- Reader.create = create();
- Reader.prototype._slice = util.Array.prototype.subarray || /* istanbul ignore next */ util.Array.prototype.slice;
- /**
- * Reads a varint as an unsigned 32 bit value.
- * @function
- * @returns {number} Value read
- */
- Reader.prototype.uint32 = (function read_uint32_setup() {
- var value = 4294967295; // optimizer type-hint, tends to deopt otherwise (?!)
- return function read_uint32() {
- value = ( this.buf[this.pos] & 127 ) >>> 0; if (this.buf[this.pos++] < 128) return value;
- value = (value | (this.buf[this.pos] & 127) << 7) >>> 0; if (this.buf[this.pos++] < 128) return value;
- value = (value | (this.buf[this.pos] & 127) << 14) >>> 0; if (this.buf[this.pos++] < 128) return value;
- value = (value | (this.buf[this.pos] & 127) << 21) >>> 0; if (this.buf[this.pos++] < 128) return value;
- value = (value | (this.buf[this.pos] & 15) << 28) >>> 0; if (this.buf[this.pos++] < 128) return value;
- /* istanbul ignore if */
- if ((this.pos += 5) > this.len) {
- this.pos = this.len;
- throw indexOutOfRange(this, 10);
- }
- return value;
- };
- })();
- /**
- * Reads a varint as a signed 32 bit value.
- * @returns {number} Value read
- */
- Reader.prototype.int32 = function read_int32() {
- return this.uint32() | 0;
- };
- /**
- * Reads a zig-zag encoded varint as a signed 32 bit value.
- * @returns {number} Value read
- */
- Reader.prototype.sint32 = function read_sint32() {
- var value = this.uint32();
- return value >>> 1 ^ -(value & 1) | 0;
- };
- /* eslint-disable no-invalid-this */
- function readLongVarint() {
- // tends to deopt with local vars for octet etc.
- var bits = new LongBits(0, 0);
- var i = 0;
- if (this.len - this.pos > 4) { // fast route (lo)
- for (; i < 4; ++i) {
- // 1st..4th
- bits.lo = (bits.lo | (this.buf[this.pos] & 127) << i * 7) >>> 0;
- if (this.buf[this.pos++] < 128)
- return bits;
- }
- // 5th
- bits.lo = (bits.lo | (this.buf[this.pos] & 127) << 28) >>> 0;
- bits.hi = (bits.hi | (this.buf[this.pos] & 127) >> 4) >>> 0;
- if (this.buf[this.pos++] < 128)
- return bits;
- i = 0;
- } else {
- for (; i < 3; ++i) {
- /* istanbul ignore if */
- if (this.pos >= this.len)
- throw indexOutOfRange(this);
- // 1st..3th
- bits.lo = (bits.lo | (this.buf[this.pos] & 127) << i * 7) >>> 0;
- if (this.buf[this.pos++] < 128)
- return bits;
- }
- // 4th
- bits.lo = (bits.lo | (this.buf[this.pos++] & 127) << i * 7) >>> 0;
- return bits;
- }
- if (this.len - this.pos > 4) { // fast route (hi)
- for (; i < 5; ++i) {
- // 6th..10th
- bits.hi = (bits.hi | (this.buf[this.pos] & 127) << i * 7 + 3) >>> 0;
- if (this.buf[this.pos++] < 128)
- return bits;
- }
- } else {
- for (; i < 5; ++i) {
- /* istanbul ignore if */
- if (this.pos >= this.len)
- throw indexOutOfRange(this);
- // 6th..10th
- bits.hi = (bits.hi | (this.buf[this.pos] & 127) << i * 7 + 3) >>> 0;
- if (this.buf[this.pos++] < 128)
- return bits;
- }
- }
- /* istanbul ignore next */
- throw Error("invalid varint encoding");
- }
- /* eslint-enable no-invalid-this */
- /**
- * Reads a varint as a signed 64 bit value.
- * @name Reader#int64
- * @function
- * @returns {Long} Value read
- */
- /**
- * Reads a varint as an unsigned 64 bit value.
- * @name Reader#uint64
- * @function
- * @returns {Long} Value read
- */
- /**
- * Reads a zig-zag encoded varint as a signed 64 bit value.
- * @name Reader#sint64
- * @function
- * @returns {Long} Value read
- */
- /**
- * Reads a varint as a boolean.
- * @returns {boolean} Value read
- */
- Reader.prototype.bool = function read_bool() {
- return this.uint32() !== 0;
- };
- function readFixed32_end(buf, end) { // note that this uses `end`, not `pos`
- return (buf[end - 4]
- | buf[end - 3] << 8
- | buf[end - 2] << 16
- | buf[end - 1] << 24) >>> 0;
- }
- /**
- * Reads fixed 32 bits as an unsigned 32 bit integer.
- * @returns {number} Value read
- */
- Reader.prototype.fixed32 = function read_fixed32() {
- /* istanbul ignore if */
- if (this.pos + 4 > this.len)
- throw indexOutOfRange(this, 4);
- return readFixed32_end(this.buf, this.pos += 4);
- };
- /**
- * Reads fixed 32 bits as a signed 32 bit integer.
- * @returns {number} Value read
- */
- Reader.prototype.sfixed32 = function read_sfixed32() {
- /* istanbul ignore if */
- if (this.pos + 4 > this.len)
- throw indexOutOfRange(this, 4);
- return readFixed32_end(this.buf, this.pos += 4) | 0;
- };
- /* eslint-disable no-invalid-this */
- function readFixed64(/* this: Reader */) {
- /* istanbul ignore if */
- if (this.pos + 8 > this.len)
- throw indexOutOfRange(this, 8);
- return new LongBits(readFixed32_end(this.buf, this.pos += 4), readFixed32_end(this.buf, this.pos += 4));
- }
- /* eslint-enable no-invalid-this */
- /**
- * Reads fixed 64 bits.
- * @name Reader#fixed64
- * @function
- * @returns {Long} Value read
- */
- /**
- * Reads zig-zag encoded fixed 64 bits.
- * @name Reader#sfixed64
- * @function
- * @returns {Long} Value read
- */
- /**
- * Reads a float (32 bit) as a number.
- * @function
- * @returns {number} Value read
- */
- Reader.prototype.float = function read_float() {
- /* istanbul ignore if */
- if (this.pos + 4 > this.len)
- throw indexOutOfRange(this, 4);
- var value = util.float.readFloatLE(this.buf, this.pos);
- this.pos += 4;
- return value;
- };
- /**
- * Reads a double (64 bit float) as a number.
- * @function
- * @returns {number} Value read
- */
- Reader.prototype.double = function read_double() {
- /* istanbul ignore if */
- if (this.pos + 8 > this.len)
- throw indexOutOfRange(this, 4);
- var value = util.float.readDoubleLE(this.buf, this.pos);
- this.pos += 8;
- return value;
- };
- /**
- * Reads a sequence of bytes preceeded by its length as a varint.
- * @returns {Uint8Array} Value read
- */
- Reader.prototype.bytes = function read_bytes() {
- var length = this.uint32(),
- start = this.pos,
- end = this.pos + length;
- /* istanbul ignore if */
- if (end > this.len)
- throw indexOutOfRange(this, length);
- this.pos += length;
- if (Array.isArray(this.buf)) // plain array
- return this.buf.slice(start, end);
- if (start === end) { // fix for IE 10/Win8 and others' subarray returning array of size 1
- var nativeBuffer = util.Buffer;
- return nativeBuffer
- ? nativeBuffer.alloc(0)
- : new this.buf.constructor(0);
- }
- return this._slice.call(this.buf, start, end);
- };
- /**
- * Reads a string preceeded by its byte length as a varint.
- * @returns {string} Value read
- */
- Reader.prototype.string = function read_string() {
- var bytes = this.bytes();
- return utf8.read(bytes, 0, bytes.length);
- };
- /**
- * Skips the specified number of bytes if specified, otherwise skips a varint.
- * @param {number} [length] Length if known, otherwise a varint is assumed
- * @returns {Reader} `this`
- */
- Reader.prototype.skip = function skip(length) {
- if (typeof length === "number") {
- /* istanbul ignore if */
- if (this.pos + length > this.len)
- throw indexOutOfRange(this, length);
- this.pos += length;
- } else {
- do {
- /* istanbul ignore if */
- if (this.pos >= this.len)
- throw indexOutOfRange(this);
- } while (this.buf[this.pos++] & 128);
- }
- return this;
- };
- /**
- * Skips the next element of the specified wire type.
- * @param {number} wireType Wire type received
- * @returns {Reader} `this`
- */
- Reader.prototype.skipType = function(wireType) {
- switch (wireType) {
- case 0:
- this.skip();
- break;
- case 1:
- this.skip(8);
- break;
- case 2:
- this.skip(this.uint32());
- break;
- case 3:
- while ((wireType = this.uint32() & 7) !== 4) {
- this.skipType(wireType);
- }
- break;
- case 5:
- this.skip(4);
- break;
- /* istanbul ignore next */
- default:
- throw Error("invalid wire type " + wireType + " at offset " + this.pos);
- }
- return this;
- };
- Reader._configure = function(BufferReader_) {
- BufferReader = BufferReader_;
- Reader.create = create();
- BufferReader._configure();
- var fn = util.Long ? "toLong" : /* istanbul ignore next */ "toNumber";
- util.merge(Reader.prototype, {
- int64: function read_int64() {
- return readLongVarint.call(this)[fn](false);
- },
- uint64: function read_uint64() {
- return readLongVarint.call(this)[fn](true);
- },
- sint64: function read_sint64() {
- return readLongVarint.call(this).zzDecode()[fn](false);
- },
- fixed64: function read_fixed64() {
- return readFixed64.call(this)[fn](true);
- },
- sfixed64: function read_sfixed64() {
- return readFixed64.call(this)[fn](false);
- }
- });
- };
|