var protobuf = protobuf || {}; var base = base || require('./base'); var text = text || require('./text'); protobuf.get = (name) => { protobuf._map = protobuf._map || new Map(); if (!protobuf._map.has(name)) { protobuf._map.set(name, {}); } return protobuf._map.get(name); }; protobuf.BinaryReader = class { static open(buffer) { return new protobuf.BinaryReader(buffer); } constructor(data) { const buffer = data instanceof Uint8Array ? data : data.peek(); this._buffer = buffer; this._length = buffer.length; this._position = 0; this._view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength); this._utf8Decoder = new TextDecoder('utf-8'); } signature() { const tags = new Map(); this._position = 0; try { if (this._length > 0) { const type = this._buffer[0] & 7; if (type !== 4 && type !== 6 && type !== 7) { const length = this.length; while (this._position < length) { const tag = this.uint32(); const field = tag >>> 3; const type = tag & 7; if (type > 5 || field === 0) { tags.clear(); break; } tags.set(field, type); if (!this._skipType(type)) { tags.clear(); break; } } } } } catch (err) { tags.clear(); } this._position = 0; return tags; } decode() { let tags = {}; this._position = 0; try { const decodeMessage = (max) => { const length = this._uint32(); if (length === undefined) { return undefined; } if (length === 0) { // return 2; } const end = this.position + length; if (end > max) { return undefined; } try { const tags = {}; while (this.position < end) { const tag = this._uint32(); if (tag === undefined) { this.seek(end); return 2; } const field = tag >>> 3; const type = tag & 7; if (type > 5 || field === 0) { this.seek(end); return 2; } if (type === 2) { const type = tags[field]; if (type !== 2) { const inner = decodeMessage(end); if (this.position > end) { this.seek(end); return 2; } if (inner === undefined) { this.seek(end); return 2; } if (inner === 2) { tags[field] = inner; } else if (!type) { tags[field] = inner; } else { for (const pair of Object.entries(inner)) { if (type[pair[0]] === 2 && pair[1] !== 2) { continue; } type[pair[0]] = pair[1]; } } continue; } } tags[field] = type; if (!this._skipType(type)) { this.seek(end); return 2; } } if (this.position === end) { return tags; } } catch (err) { // continue regardless of error } this.seek(end); return 2; }; if (this._length > 0) { const type = this._buffer[0] & 7; if (type !== 4 && type !== 6 && type !== 7) { const length = this.length; while (this.position < length) { const tag = this.uint32(); const field = tag >>> 3; const type = tag & 7; if (type > 5 || field === 0) { tags = {}; break; } if (type === 2) { const type = tags[field]; if (type !== 2) { const inner = decodeMessage(length); if (inner === undefined) { tags = {}; break; } if (inner === 2) { tags[field] = inner; } else if (!type) { tags[field] = inner; } else { for (const pair of Object.entries(inner)) { if (type[pair[0]] === 2 && pair[1] !== 2) { continue; } type[pair[0]] = pair[1]; } } continue; } } tags[field] = type; if (!this._skipType(type)) { tags = {}; break; } } } } } catch (err) { tags = {}; } this._position = 0; return tags; } get length() { return this._length; } get position() { return this._position; } seek(position) { this._position = position >= 0 ? position : this._length + position; } string() { return this._utf8Decoder.decode(this.bytes()); } bool() { return this.uint32() !== 0; } byte() { if (this._position < this._length) { return this._buffer[this._position++]; } throw new RangeError('Unexpected end of file.'); } bytes() { const length = this.uint32(); const position = this._position; this.skip(length); return this._buffer.slice(position, this._position); } uint32() { let c; c = this.byte(); let value = (c & 127) >>> 0; if (c < 128) { return value; } c = this.byte(); value = (value | (c & 127) << 7) >>> 0; if (c < 128) { return value; } c = this.byte(); value = (value | (c & 127) << 14) >>> 0; if (c < 128) { return value; } c = this.byte(); value = (value | (c & 127) << 21) >>> 0; if (c < 128) { return value; } c = this.byte(); value = (value | (c & 15) << 28) >>> 0; if (c < 128) { return value; } if (this.byte() !== 255 || this.byte() !== 255 || this.byte() !== 255 || this.byte() !== 255 || this.byte() !== 1) { throw new protobuf.Error('Varint is not 32-bit.'); } return value; } int32() { return this.uint32() | 0; } sint32() { const value = this.uint32(); return value >>> 1 ^ -(value & 1) | 0; } int64() { return this._varint().toInt64(); } uint64() { return this._varint().toInt64(); } sint64() { return this._varint().zzDecode().toInt64(); } fixed64() { const position = this._position; this.skip(8); return this._view.getUint64(position, true); } sfixed64() { const position = this._position; this.skip(8); return this._view.getInt64(position, true); } fixed32() { const position = this._position; this.skip(4); return this._view.getUint32(position, true); } sfixed32() { const position = this._position; this.skip(4); return this._view.getInt32(position, true); } float() { const position = this._position; this.skip(4); return this._view.getFloat32(position, true); } double() { const position = this._position; this.skip(8); return this._view.getFloat64(position, true); } array(obj, item, tag) { if ((tag & 7) === 2) { const end = this.uint32() + this._position; while (this._position < end) { obj.push(item()); } } else { obj.push(item()); } return obj; } floats(obj, tag) { if ((tag & 7) === 2) { if (obj && obj.length > 0) { throw new protobuf.Error('Invalid packed float array.'); } const size = this.uint32(); const end = this._position + size; if (end > this._length) { this._unexpected(); } const length = size >>> 2; obj = size > 1048576 ? new Float32Array(length) : new Array(length); let position = this._position; for (let i = 0; i < length; i++) { obj[i] = this._view.getFloat32(position, true); position += 4; } this._position = end; } else { if (obj !== undefined && obj.length < 1000000) { obj.push(this.float()); } else { obj = undefined; this.float(); } } return obj; } doubles(obj, tag) { if ((tag & 7) === 2) { if (obj && obj.length > 0) { throw new protobuf.Error('Invalid packed float array.'); } const size = this.uint32(); const end = this._position + size; if (end > this._length) { this._unexpected(); } const length = size >>> 3; obj = size > 1048576 ? new Float64Array(length) : new Array(length); let position = this._position; for (let i = 0; i < length; i++) { obj[i] = this._view.getFloat64(position, true); position += 8; } this._position = end; } else { if (obj !== undefined && obj.length < 1000000) { obj.push(this.double()); } else { obj = undefined; this.double(); } } return obj; } skip(offset) { this._position += offset; if (this._position > this._length) { this._unexpected(); } } skipVarint() { do { if (this._position >= this._length) { this._unexpected(); } } while (this._buffer[this._position++] & 128); } _uint32() { let c; if (this._position < this._length) { c = this._buffer[this._position++]; let value = (c & 127) >>> 0; if (c < 128) { return value; } if (this._position < this._length) { c = this._buffer[this._position++]; value = (value | (c & 127) << 7) >>> 0; if (c < 128) { return value; } if (this._position < this._length) { c = this._buffer[this._position++]; value = (value | (c & 127) << 14) >>> 0; if (c < 128) { return value; } if (this._position < this._length) { c = this._buffer[this._position++]; value = (value | (c & 127) << 21) >>> 0; if (c < 128) { return value; } if (this._position < this._length) { c = this._buffer[this._position++]; value = (value | (c & 15) << 28) >>> 0; if (c < 128) { return value; } if (this.byte() !== 255 || this.byte() !== 255 || this.byte() !== 255 || this.byte() !== 255 || this.byte() !== 1) { return undefined; } return value; } } } } } return undefined; } _skipType(wireType) { switch (wireType) { case 0: { // const max = this._position + 9; do { if (this._position >= this._length /* || this._position > max */) { return false; } } while (this._buffer[this._position++] & 128); break; } case 1: { if (this._position + 8 >= this._length) { return false; } this._position += 8; break; } case 2: { const length = this._uint32(); if (length === undefined) { return false; } if (this._position + length > this._end) { return false; } this._position += length; break; } case 3: { for (;;) { const tag = this._uint32(); if (tag === undefined) { return false; } const wireType = tag & 7; if (wireType === 4) { break; } if (!this._skipType(wireType)) { return false; } } break; } case 5: { if (this._position + 4 >= this._length) { return false; } this._position += 4; break; } default: { return false; } } return true; } skipType(wireType) { switch (wireType) { case 0: this.skipVarint(); 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; default: throw new protobuf.Error('Invalid type ' + wireType + ' at offset ' + this._position + '.'); } } entry(obj, key, value) { this.skipVarint(); this._position++; let k = key(); if (!Number.isInteger(k) && typeof k !== 'string') { k = k.toNumber(); } this._position++; const v = value(); obj[k] = v; } _varint() { const bits = new protobuf.LongBits(0, 0); let i = 0; if (this._length - this._position > 4) { // fast route (lo) for (; i < 4; ++i) { // 1st..4th bits.lo = (bits.lo | (this._buffer[this._position] & 127) << i * 7) >>> 0; if (this._buffer[this._position++] < 128) { return bits; } } // 5th bits.lo = (bits.lo | (this._buffer[this._position] & 127) << 28) >>> 0; bits.hi = (bits.hi | (this._buffer[this._position] & 127) >> 4) >>> 0; if (this._buffer[this._position++] < 128) { return bits; } i = 0; } else { for (; i < 3; i++) { if (this._position >= this._length) { this._unexpected(); } bits.lo = (bits.lo | (this._buffer[this._position] & 127) << i * 7) >>> 0; if (this._buffer[this._position++] < 128) { return bits; } } bits.lo = (bits.lo | (this._buffer[this._position++] & 127) << i * 7) >>> 0; return bits; } if (this._length - this._position > 4) { for (; i < 5; ++i) { bits.hi = (bits.hi | (this._buffer[this._position] & 127) << i * 7 + 3) >>> 0; if (this._buffer[this._position++] < 128) { return bits; } } } else { for (; i < 5; ++i) { if (this._position >= this._length) { this._unexpected(); } bits.hi = (bits.hi | (this._buffer[this._position] & 127) << i * 7 + 3) >>> 0; if (this._buffer[this._position++] < 128) { return bits; } } } throw new protobuf.Error('Invalid varint encoding.'); } _unexpected() { throw new RangeError('Unexpected end of file.'); } }; protobuf.TextReader = class { static open(data) { const buffer = data instanceof Uint8Array ? data : data.peek(); const decoder = text.Decoder.open(buffer); let first = true; for (let i = 0; i < 0x100; i++) { const c = decoder.decode(); if (c === undefined) { if (i === 0) { return null; } break; } if (c === '\0') { return null; } const whitespace = c === ' ' || c === '\n' || c === '\r' || c === '\t'; if (c < ' ' && !whitespace) { return null; } if (first && !whitespace) { first = false; if (c === '#') { let c; do { c = decoder.decode(); } while (c !== undefined && c !== '\n'); if (c === undefined) { break; } continue; } if (c === '[') { continue; } if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z') { continue; } return null; } } return new protobuf.TextReader(buffer); } constructor(buffer) { this._decoder = text.Decoder.open(buffer); this.reset(); } signature() { const tags = new Map(); this.reset(); try { this.start(false); while (!this.end()) { const tag = this.tag(); if (this.token() === '{') { this.start(); tags.set(tag, true); while (!this.end()) { const subtag = this.tag(); tags.set(tag + '.' + subtag, true); this.skip(); this.match(','); } } else { this.skip(); tags.set(tag, true); } } } catch (err) { // continue regardless of error } this.reset(); return tags; } reset() { this._decoder.position = 0; this._position = 0; this._token = undefined; this._depth = 0; this._arrayDepth = 0; this._token = ''; this.next(); } start() { if (this._depth > 0) { this.expect('{'); } this._depth++; } end() { if (this._depth <= 0) { throw new protobuf.Error('Invalid depth ' + this.location()); } if (this._token === '}') { this.expect('}'); this.match(';'); this._depth--; return true; } if (this._token === undefined) { if (this._depth !== 1) { throw new protobuf.Error('Unexpected end of input' + this.location()); } this._depth--; return true; } return false; } tag() { const name = this._token; this.next(); if (this._token !== '[' && this._token !== '{') { this.expect(':'); } return name; } integer() { const token = this._token; const value = Number.parseInt(token, 10); if (Number.isNaN(token - value)) { throw new protobuf.Error("Couldn't parse integer '" + token + "'" + this.location()); } this.next(); this.semicolon(); return value; } double() { let value = NaN; let token = this._token; switch (token) { case 'nan': value = NaN; break; case 'inf': value = Infinity; break; case '-inf': value = -Infinity; break; default: if (token.endsWith('f')) { token = token.substring(0, token.length - 1); } value = Number.parseFloat(token); if (Number.isNaN(token - value)) { throw new protobuf.Error("Couldn't parse float '" + token + "'" + this.location()); } break; } this.next(); this.semicolon(); return value; } float() { return this.double(); } uint32() { return this.integer(); } int32() { return this.integer(); } sint32() { return this.integer(); } int64() { return base.Int64.create(this.integer()); } uint64() { return base.Uint64.create(this.integer()); } sint64() { return base.Int64.create(this.integer()); } fixed64() { return base.Uint64.create(this.integer()); } sfixed64() { return base.Int64.create(this.integer()); } fixed32() { return this.integer(); } sfixed32() { return this.integer(); } string() { const token = this._token; if (token.length < 2) { throw new protobuf.Error('String is too short' + this.location()); } const quote = token[0]; if (quote !== "'" && quote !== '"') { throw new protobuf.Error('String is not in quotes' + this.location()); } if (quote !== token[token.length - 1]) { throw new protobuf.Error('String quotes do not match' + this.location()); } const value = token.substring(1, token.length - 1); this.next(); this.semicolon(); return value; } bool() { const token = this._token; switch (token) { case 'true': case 'True': case '1': this.next(); this.semicolon(); return true; case 'false': case 'False': case '0': this.next(); this.semicolon(); return false; } throw new protobuf.Error("Couldn't parse boolean '" + token + "'" + this.location()); } bytes() { const token = this.string(); const length = token.length; const array = new Uint8Array(length); for (let i = 0; i < length; i++) { array[i] = token.charCodeAt(i); } return array; } enum(type) { const token = this._token; let value; if (Object.prototype.hasOwnProperty.call(type, token)) { value = type[token]; } else { value = Number.parseInt(token, 10); if (Number.isNaN(token - value)) { throw new protobuf.Error("Couldn't parse enum '" + (token === undefined ? '' : token) + "'" + this.location()); } } this.next(); this.semicolon(); return value; } any(type) { this.start(); const message = type(); if (this._token.startsWith('[') && this._token.endsWith(']')) { message.type_url = this._token.substring(1, this._token.length - 1).trim(); this.next(); this.match(':'); message.value = this.read(); this.match(';'); if (!this.end()) { this.expect('}'); } } else { while (!this.end()) { const tag = this.tag(); switch (tag) { case "type_url": message.type_url = this.string(); break; case "value": message.value = this.bytes(); break; default: this.field(tag, message); break; } } } return message; } anyarray(obj, type) { this.start(); if (this._token.startsWith('[') && this._token.endsWith(']')) { while (!this.end()) { if (this._token.startsWith('[') && this._token.endsWith(']')) { const message = type(); message.type_url = this._token.substring(1, this._token.length - 1).trim(); this.next(); this.match(':'); message.value = this.read(); this.match(';'); obj.push(message); continue; } this.expect('['); } } else { const message = type(); while (!this.end()) { const tag = this.tag(); switch (tag) { case "type_url": message.type_url = this.string(); break; case "value": message.value = this.bytes(); break; default: this.field(tag, message); break; } } obj.push(message); } } entry(obj, key, value) { this.start(); let k; let v; while (!this.end()) { switch (this.tag()) { case 'key': k = key(); break; case 'value': v = value(); break; } } obj[k] = v; } array(obj, item) { if (this.first()) { while (!this.last()) { obj.push(item()); switch (this._token) { case ',': this.next(); break; case ']': break; default: this.handle(this._token); break; } } } else { obj.push(item()); } } first() { if (this.match('[')) { this._arrayDepth++; return true; } return false; } last() { if (this.match(']')) { this._arrayDepth--; return true; } return false; } read() { const start = this._position; this.skip(); const end = this._position; const position = this._decoder.position; this._decoder.position = start; let content = ''; while (this._decoder.position < end) { content += this._decoder.decode(); } this._decoder.position = position; return content; } skip() { switch (this._token) { case '{': { const depth = this._depth; this.start(); while (!this.end() || depth < this._depth) { if (this._token === '{') { this.start(); } else if (this._token !== '}') { this.next(); this.match(';'); } } break; } case '[': { const depth = this._arrayDepth; this.first(); while (!this.last() || depth < this._arrayDepth) { this.next(); if (this._token === '[') { this.first(); } else if (this._token === undefined) { this.handle(this._token); } } break; } default: { this.next(); this.semicolon(); break; } } } handle(token) { throw new protobuf.Error("Unexpected token '" + token + "'" + this.location()); } field(token /*, module */) { throw new protobuf.Error("Unknown field '" + token + "'" + this.location()); } token() { return this._token; } next() { if (this._token === undefined) { throw new protobuf.Error('Unexpected end of input' + this.location()); } this._position = this._decoder.position; let c = this._decoder.decode(); for (;;) { switch (c) { case ' ': case '\n': case '\r': case '\t': this._position = this._decoder.position; c = this._decoder.decode(); continue; case '#': do { c = this._decoder.decode(); if (c === undefined) { this._token = undefined; return; } } while (c !== '\n'); this._position = this._decoder.position; c = this._decoder.decode(); continue; } break; } if (c === undefined) { this._token = undefined; return; } if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c === '_' || c === '$') { let token = c; let position = this._decoder.position; for (;;) { c = this._decoder.decode(); if (c === undefined || c === '\n') { break; } if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || c === '_' || c === '+' || c === '-') { token += c; position = this._decoder.position; continue; } break; } this._decoder.position = position; this._token = token; return; } switch (c) { case '{': case '}': case ':': case ',': case ']': case ';': this._token = c; return; case '[': { let token = c; let position = this._decoder.position; let x = this._decoder.decode(); if ((x !== undefined) && x >= 'a' && x <= 'z' || x >= 'A' && x <= 'Z') { token += x; for (;;) { x = this._decoder.decode(); if (x === undefined || x === '\n') { break; } if (x >= 'a' && x <= 'z' || x >= 'A' && x <= 'Z' || x >= '0' && x <= '9' || x === '.' || x === '/') { token += x; position = this._decoder.position; continue; } if (x === ']') { this._token = token + x; return; } } } this._decoder.position = position; this._token = '['; return; } case '"': case "'": { const quote = c; let content = c; for (;;) { c = this._decoder.decode(); if (c === undefined || c === '\n') { throw new protobuf.Error('Unexpected end of string' + this.location()); } if (c == '\\') { c = this._decoder.decode(); if (c === undefined || c === '\n') { throw new protobuf.Error('Unexpected end of string' + this.location()); } switch (c) { case '\\': c = '\\'; break; case "'": c = "'"; break; case '"': c = '"'; break; case 'r': c = '\r'; break; case 'n': c = '\n'; break; case 't': c = '\t'; break; case 'b': c = '\b'; break; case 'x': case 'X': { let value = 0; for (let xi = 0; xi < 2; xi++) { let xd = this._decoder.decode(); if (xd === undefined) { throw new protobuf.Error('Unexpected end of string' + this.location()); } xd = xd.charCodeAt(0); xd = xd >= 65 && xd <= 70 ? xd - 55 : xd >= 97 && xd <= 102 ? xd - 87 : xd >= 48 && xd <= 57 ? xd - 48 : -1; if (xd === -1) { throw new protobuf.Error("Unexpected hex digit '" + xd + "' in bytes string" + this.location()); } value = value << 4 | xd; } c = String.fromCharCode(value); break; } default: { if (c < '0' || c > '9') { throw new protobuf.Error("Unexpected character '" + c + "' in string" + this.location()); } let value = 0; let od = c; if (od < '0' || od > '9') { throw new protobuf.Error("Unexpected octal digit '" + od + "' in bytes string" + this.location()); } od = od.charCodeAt(0); value = value << 3 | od - 48; od = this._decoder.decode(); if (od === undefined) { throw new protobuf.Error('Unexpected end of string' + this.location()); } if (od < '0' || od > '9') { throw new protobuf.Error("Unexpected octal digit '" + od + "' in bytes string" + this.location()); } od = od.charCodeAt(0); value = value << 3 | od - 48; od = this._decoder.decode(); if (od === undefined) { throw new protobuf.Error('Unexpected end of string' + this.location()); } if (od < '0' || od > '9') { throw new protobuf.Error("Unexpected octal digit '" + od + "' in bytes string" + this.location()); } od = od.charCodeAt(0); value = value << 3 | od - 48; c = String.fromCharCode(value); break; } } content += c; continue; } else { content += c; if (c === quote) { break; } } } this._token = content; return; } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '-': case '+': case '.': { let token = c; let position = this._decoder.position; for (;;) { c = this._decoder.decode(); if (c === undefined || c === '\n') { break; } if ((c >= '0' && c <= '9') || c === '_' || c === '+' || c === '-' || c === '.' || c === 'e' || c === 'E') { token += c; position = this._decoder.position; continue; } break; } if (token === '-' && c === 'i' && this._decoder.decode() === 'n' && this._decoder.decode() === 'f') { token += 'inf'; position = this._decoder.position; } if (token !== '-' && token !== '+' && token !== '.') { this._decoder.position = position; this._token = token; return; } } } throw new protobuf.Error("Unexpected token '" + c + "'" + this.location()); } expect(value) { if (this._token !== value) { throw new protobuf.Error("Unexpected '" + this._token + "' instead of '" + value + "'" + this.location()); } this.next(); } match(value) { if (value == this._token) { this.next(); return true; } return false; } location() { let line = 1; let column = 1; this._decoder.position = 0; let c; do { if (this._decoder.position === this._position) { return ' at ' + line.toString() + ':' + column.toString() + '.'; } c = this._decoder.decode(); if (c === '\n') { line++; column = 1; } else { column++; } } while (c !== undefined); return ' at ' + line.toString() + ':' + column.toString() + '.'; } semicolon() { if (this._arrayDepth === 0) { this.match(';'); } } }; protobuf.Int64 = base.Int64; protobuf.Uint64 = base.Uint64; protobuf.LongBits = class { constructor(lo, hi) { this.lo = lo >>> 0; this.hi = hi >>> 0; } zzDecode() { const mask = -(this.lo & 1); this.lo = ((this.lo >>> 1 | this.hi << 31) ^ mask) >>> 0; this.hi = ( this.hi >>> 1 ^ mask) >>> 0; return this; } toUint64() { return new base.Uint64(this.lo, this.hi); } toInt64() { return new base.Int64(this.lo, this.hi); } }; protobuf.Error = class extends Error { constructor(message) { super(message); this.name = 'Protocol Buffer Error'; this.message = message; } }; if (typeof module !== 'undefined' && typeof module.exports === 'object') { module.exports.BinaryReader = protobuf.BinaryReader; module.exports.TextReader = protobuf.TextReader; module.exports.Error = protobuf.Error; module.exports.Int64 = protobuf.Int64; module.exports.Uint64 = protobuf.Uint64; module.exports.get = protobuf.get; }