From 1abea1a9bb01f695c8ea1dae31a047bf6d9078d0 Mon Sep 17 00:00:00 2001 From: Stephanie DiBenedetto Date: Thu, 15 Feb 2024 17:05:28 +0000 Subject: [PATCH 01/22] Port fix: Fix JSPB binary utf8 decoding to be spec compliant. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Our prior behavior was extremely undefined when confronted with errors, it would read out of bounds, accept overlong encodings, skip over out of range bytes, compose out of range codepoints. The new implementation always detects and handles errors consistently by either throwing or using replacement characters (� aka \uFFFD) This also adds support for aligning with the proto3 spec to the code generator which requires that parsing fail for proto3 messages with invalid utf8 payloads for string fields. For now, actual failing is disabled via the goog.define jspb.binary.ENFORCE_UTF8 which is set to NEVER. A future change will flip this to DEFAULT. --- binary/decoder.js | 101 ++++----- binary/decoder_test.js | 10 +- binary/reader.js | 41 +++- binary/utf8.js | 426 ++++++++++++++++++++++++++++++++++++++ generator/js_generator.cc | 12 +- gulpfile.js | 3 +- 6 files changed, 517 insertions(+), 76 deletions(-) create mode 100644 binary/utf8.js diff --git a/binary/decoder.js b/binary/decoder.js index 1186add..c44053f 100644 --- a/binary/decoder.js +++ b/binary/decoder.js @@ -47,7 +47,7 @@ goog.provide('jspb.BinaryDecoder'); goog.require('jspb.asserts'); -goog.require('goog.crypt'); +goog.require('jspb.binary.utf8'); goog.require('jspb.utils'); @@ -256,7 +256,7 @@ jspb.BinaryDecoder.prototype.setCursor = function(cursor) { */ jspb.BinaryDecoder.prototype.advance = function(count) { this.cursor_ += count; - jspb.asserts.assert(this.cursor_ <= this.end_); + this.checkCursor(); }; @@ -397,6 +397,17 @@ jspb.BinaryDecoder.prototype.readSplitFixed64 = function(convert) { return convert(lowBits, highBits); }; +/** + * Asserts that our cursor is in bounds. + * + * @private + * @return {void} + */ +jspb.BinaryDecoder.prototype.checkCursor = function () { + if (this.cursor_ > this.end_) { + asserts.fail('Read past the end ' + this.cursor_ + ' > ' + this.end_); + } +} /** * Skips over a varint in the block without decoding it. @@ -452,7 +463,7 @@ jspb.BinaryDecoder.prototype.readUnsignedVarint32 = function() { var x = (temp & 0x7F); if (temp < 128) { this.cursor_ += 1; - jspb.asserts.assert(this.cursor_ <= this.end_); + this.checkCursor(); return x; } @@ -460,7 +471,7 @@ jspb.BinaryDecoder.prototype.readUnsignedVarint32 = function() { x |= (temp & 0x7F) << 7; if (temp < 128) { this.cursor_ += 2; - jspb.asserts.assert(this.cursor_ <= this.end_); + this.checkCursor(); return x; } @@ -468,7 +479,7 @@ jspb.BinaryDecoder.prototype.readUnsignedVarint32 = function() { x |= (temp & 0x7F) << 14; if (temp < 128) { this.cursor_ += 3; - jspb.asserts.assert(this.cursor_ <= this.end_); + this.checkCursor(); return x; } @@ -476,7 +487,7 @@ jspb.BinaryDecoder.prototype.readUnsignedVarint32 = function() { x |= (temp & 0x7F) << 21; if (temp < 128) { this.cursor_ += 4; - jspb.asserts.assert(this.cursor_ <= this.end_); + this.checkCursor(); return x; } @@ -486,7 +497,7 @@ jspb.BinaryDecoder.prototype.readUnsignedVarint32 = function() { // We're reading the high bits of an unsigned varint. The byte we just read // also contains bits 33 through 35, which we're going to discard. this.cursor_ += 5; - jspb.asserts.assert(this.cursor_ <= this.end_); + this.checkCursor(); return x >>> 0; } @@ -500,7 +511,7 @@ jspb.BinaryDecoder.prototype.readUnsignedVarint32 = function() { jspb.asserts.assert(false); } - jspb.asserts.assert(this.cursor_ <= this.end_); + this.checkCursor(); return x; }; @@ -679,7 +690,7 @@ jspb.BinaryDecoder.prototype.readZigzagVarint64String = function() { jspb.BinaryDecoder.prototype.readUint8 = function() { var a = this.bytes_[this.cursor_ + 0]; this.cursor_ += 1; - jspb.asserts.assert(this.cursor_ <= this.end_); + this.checkCursor(); return a; }; @@ -694,7 +705,7 @@ jspb.BinaryDecoder.prototype.readUint16 = function() { var a = this.bytes_[this.cursor_ + 0]; var b = this.bytes_[this.cursor_ + 1]; this.cursor_ += 2; - jspb.asserts.assert(this.cursor_ <= this.end_); + this.checkCursor(); return (a << 0) | (b << 8); }; @@ -711,7 +722,7 @@ jspb.BinaryDecoder.prototype.readUint32 = function() { var c = this.bytes_[this.cursor_ + 2]; var d = this.bytes_[this.cursor_ + 3]; this.cursor_ += 4; - jspb.asserts.assert(this.cursor_ <= this.end_); + this.checkCursor(); return ((a << 0) | (b << 8) | (c << 16) | (d << 24)) >>> 0; }; @@ -756,7 +767,7 @@ jspb.BinaryDecoder.prototype.readUint64String = function() { jspb.BinaryDecoder.prototype.readInt8 = function() { var a = this.bytes_[this.cursor_ + 0]; this.cursor_ += 1; - jspb.asserts.assert(this.cursor_ <= this.end_); + this.checkCursor(); return (a << 24) >> 24; }; @@ -771,7 +782,7 @@ jspb.BinaryDecoder.prototype.readInt16 = function() { var a = this.bytes_[this.cursor_ + 0]; var b = this.bytes_[this.cursor_ + 1]; this.cursor_ += 2; - jspb.asserts.assert(this.cursor_ <= this.end_); + this.checkCursor(); return (((a << 0) | (b << 8)) << 16) >> 16; }; @@ -788,7 +799,7 @@ jspb.BinaryDecoder.prototype.readInt32 = function() { var c = this.bytes_[this.cursor_ + 2]; var d = this.bytes_[this.cursor_ + 3]; this.cursor_ += 4; - jspb.asserts.assert(this.cursor_ <= this.end_); + this.checkCursor(); return (a << 0) | (b << 8) | (c << 16) | (d << 24); }; @@ -858,7 +869,9 @@ jspb.BinaryDecoder.prototype.readDouble = function() { * @export */ jspb.BinaryDecoder.prototype.readBool = function() { - return !!this.bytes_[this.cursor_++]; + const b = !!this.bytes_[this.cursor_++]; + this.checkCursor(); + return b; }; @@ -879,59 +892,17 @@ jspb.BinaryDecoder.prototype.readEnum = function() { * Supports codepoints from U+0000 up to U+10FFFF. * (http://en.wikipedia.org/wiki/UTF-8). * @param {number} length The length of the string to read. + * @param {boolean} requireUtf8 Whether to throw when invalid utf8 is found. * @return {string} The decoded string. * @export */ -jspb.BinaryDecoder.prototype.readString = function(length) { - var bytes = this.bytes_; - var cursor = this.cursor_; - var end = cursor + length; - var codeUnits = []; - - var result = ''; - while (cursor < end) { - var c = bytes[cursor++]; - if (c < 128) { // Regular 7-bit ASCII. - codeUnits.push(c); - } else if (c < 192) { - // UTF-8 continuation mark. We are out of sync. This - // might happen if we attempted to read a character - // with more than four bytes. - continue; - } else if (c < 224) { // UTF-8 with two bytes. - var c2 = bytes[cursor++]; - codeUnits.push(((c & 31) << 6) | (c2 & 63)); - } else if (c < 240) { // UTF-8 with three bytes. - var c2 = bytes[cursor++]; - var c3 = bytes[cursor++]; - codeUnits.push(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63)); - } else if (c < 248) { // UTF-8 with 4 bytes. - var c2 = bytes[cursor++]; - var c3 = bytes[cursor++]; - var c4 = bytes[cursor++]; - // Characters written on 4 bytes have 21 bits for a codepoint. - // We can't fit that on 16bit characters, so we use surrogates. - var codepoint = - ((c & 7) << 18) | ((c2 & 63) << 12) | ((c3 & 63) << 6) | (c4 & 63); - // Surrogates formula from wikipedia. - // 1. Subtract 0x10000 from codepoint - codepoint -= 0x10000; - // 2. Split this into the high 10-bit value and the low 10-bit value - // 3. Add 0xD800 to the high value to form the high surrogate - // 4. Add 0xDC00 to the low value to form the low surrogate: - var low = (codepoint & 1023) + 0xDC00; - var high = ((codepoint >> 10) & 1023) + 0xD800; - codeUnits.push(high, low); - } - // Avoid exceeding the maximum stack size when calling `apply`. - if (codeUnits.length >= 8192) { - result += String.fromCharCode.apply(null, codeUnits); - codeUnits.length = 0; - } - } - result += goog.crypt.byteArrayToString(codeUnits); - this.cursor_ = cursor; +jspb.BinaryDecoder.prototype.readString = function (length, requireUtf8) { + const cursor = this.cursor_; + this.cursor_ += length; + this.checkCursor(); + const result = + jspb.binary.utf8.decodeUtf8(jspb.asserts.assert(this.bytes_), cursor, length, requireUtf8); return result; }; @@ -966,7 +937,7 @@ jspb.BinaryDecoder.prototype.readBytes = function(length) { var result = this.bytes_.subarray(this.cursor_, this.cursor_ + length); this.cursor_ += length; - jspb.asserts.assert(this.cursor_ <= this.end_); + this.checkCursor(); return result; }; diff --git a/binary/decoder_test.js b/binary/decoder_test.js index 77f6877..b8e1084 100644 --- a/binary/decoder_test.js +++ b/binary/decoder_test.js @@ -354,7 +354,7 @@ describe('binaryDecoderTest', () => { const decoder = jspb.BinaryDecoder.alloc(encoder.end()); - expect(decoder.readString(len)).toEqual(long_string); + expect(decoder.readString(len, true)).toEqual(long_string); }); /** @@ -375,11 +375,11 @@ describe('binaryDecoderTest', () => { const decoder = jspb.BinaryDecoder.alloc(encoder.end()); - expect(decoder.readString(ascii.length)).toEqual(ascii); - expect(utf8_two_bytes).toEqual(decoder.readString(utf8_two_bytes.length)); + expect(decoder.readString(ascii.length, true)).toEqual(ascii); + expect(utf8_two_bytes).toEqual(decoder.readString(2, true)); expect(utf8_three_bytes) - .toEqual(decoder.readString(utf8_three_bytes.length)); - expect(utf8_four_bytes).toEqual(decoder.readString(utf8_four_bytes.length)); + .toEqual(decoder.readString(3, true)); + expect(utf8_four_bytes).toEqual(decoder.readString(4, true)); }); /** diff --git a/binary/reader.js b/binary/reader.js index 7be3b58..0f8c961 100644 --- a/binary/reader.js +++ b/binary/reader.js @@ -52,6 +52,26 @@ goog.require('jspb.BinaryConstants'); goog.require('jspb.BinaryDecoder'); goog.require('jspb.utils'); +/** + * Whether to enforce that string fields are valid utf8. + * + *

Currently set to `ALWAYS`, can be set to `DEPRECATED_PROTO3_ONLY` to only + * enforce utf8 for proto3 string fields, for proto2 string fields it will use + * replacement characters when encoding errors are found. + * + *

TODO: Remove the flag, simplify BinaryReader to remove + * readStringRequireUtf8 and related support in the code generator et. al. + * + * @define {string} + */ +const ENFORCE_UTF8 = goog.define('jspb.binary.ENFORCE_UTF8', 'ALWAYS'); + +// Constrain the set of values to only these two. +jspb.asserts.assert( + ENFORCE_UTF8 === 'DEPRECATED_PROTO3_ONLY' || ENFORCE_UTF8 === 'ALWAYS'); + +const /** boolean */ UTF8_PARSING_ERRORS_ARE_FATAL = ENFORCE_UTF8 === 'ALWAYS'; + /** @@ -996,10 +1016,29 @@ jspb.BinaryReader.prototype.readEnum = function() { * @export */ jspb.BinaryReader.prototype.readString = function() { + // delegate to the other reader so that inlining can eliminate this method + // in the common case. + if (UTF8_PARSING_ERRORS_ARE_FATAL) { + return this.readStringRequireUtf8(); + } + jspb.asserts.assert( this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED); var length = this.decoder_.readUnsignedVarint32(); - return this.decoder_.readString(length); + return this.decoder_.readString(length, /*requireUtf8=*/ false); +}; + +/** + * Reads a string field from the binary stream, or throws an error if the next + * field in the stream is not of the correct wire type, or if the string is + * not valid utf8. + * + * @return {string} The value of the string field. + */ +jspb.BinaryReader.prototype.readStringRequireUtf8 = function () { + jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED); + const length = this.decoder_.readUnsignedVarint32(); + return this.decoder_.readString(length, /*requireUtf8=*/ true); }; diff --git a/binary/utf8.js b/binary/utf8.js new file mode 100644 index 0000000..b77602b --- /dev/null +++ b/binary/utf8.js @@ -0,0 +1,426 @@ +/** + * @fileoverview UTF8 encoding and decoding routines + */ +goog.provide('jspb.binary.utf8'); + +goog.require('jspb.asserts'); + + +/** + * Whether to use the browser based `TextEncoder` and `TextDecoder` APIs for + * handling utf8. + * + *

Enabled by default for `goog.FEATURESET_YEAR >= 2020`. The code also + * performs feature detection for this API and will always use it if available, + * this variable enables us to not ship the polyfill. + * + *

See http://go/jscompiler-flags#browser-featureset-year-options for the + * behavior here. + * + * @define {boolean} + */ +const USE_TEXT_ENCODING = + goog.define('jspb.binary.USE_TEXTENCODING', goog.FEATURESET_YEAR >= 2020); + +const /** number */ MIN_SURROGATE = 0xD800; +const /** number */ MIN_HIGH_SURROGATE = MIN_SURROGATE; +const /** number */ MAX_HIGH_SURROGATE = 0xDBFF; +const /** number */ MIN_LOW_SURROGATE = 0xDC00; +const /** number */ MAX_LOW_SURROGATE = 0xDFFF; +const /** number */ MAX_SURROGATE = MAX_LOW_SURROGATE; + +/** + * Returns whether the byte is not a valid continuation of the form + * '10XXXXXX'. + * @return {boolean} + */ +function isNotTrailingByte(/** number */ byte) { + // 0xC0 is '11000000' in binary + // 0x80 is '10000000' in binary + return (byte & 0xC0) !== 0x80; +} + + +/** + * Either throws an error or appends a replacement codepoint of invalid utf8 + */ +function invalid( + /** boolean */ parsingErrorsAreFatal, /** !Array */ codeUnits) { + if (parsingErrorsAreFatal) { + throw new Error('Invalid UTF8'); + } + codeUnits.push(0xFFFD); // utf8 replacement character +} + +/** @return {string} */ +function codeUnitsToString( + /** string? */ accum, /** !Array */ utf16CodeUnits) { + const suffix = String.fromCharCode.apply(null, utf16CodeUnits); + return accum == null ? suffix : accum + suffix; +} + +/** + * Our handwritten UTF8 decoder. + * + * https://en.wikipedia.org/wiki/UTF-8#Encoding describes the bit layout + * + * https://en.wikipedia.org/wiki/UTF-8#Invalid_sequences_and_error_handling + * describes important cases to check for which are namely: + * - overlong encodings, meaning a value expressable in N bytes could have been + * expressed in fewer bytes + * - invalid bytes, meaning bytes that are generally out of range + * - surrogate codepoints, utf8 never encodes directly a utf16 surrogate value + * - underflow where there aren't enough bytes for the sequence we are parsing + * - out of range codepoints. + * + * @return {string} + */ +jspb.binary.utf8.polyfillDecodeUtf8 = function ( + /** !Uint8Array */ bytes, /** number */ offset, /** number */ length, + /** boolean */ parsingErrorsAreFatal) { + let cursor = offset; + const end = cursor + length; + const codeUnits = []; + let result = null; + + // This is significantly slower than the TextDecoder implementation. + // Ideas for improving performance: + // 1. Reduce branching with non-shortcircuting operators, e.g. + // https://stackoverflow.com/q/5652363 + // 2. improve isNotTrailingByte using xor? + // 3. consider having a dedicate ascii loop (java impls do this) + let c1, c2, c3, c4; + while (cursor < end) { + c1 = bytes[cursor++]; + if (c1 < 0x80) { // Regular 7-bit ASCII. + codeUnits.push(c1); + } else if (c1 < 0xE0) { // UTF-8 with two bytes. + if (cursor >= end) { + invalid(parsingErrorsAreFatal, codeUnits); + } else { + c2 = bytes[cursor++]; + // Make sure that c1 is a valid leading byte and c2 is a valid + // trailing byte + // 0xC2 is '11000010', if c1 is less than this then we have an overlong + // encoding because there would only be 7 significant bits. + if (c1 < 0xC2 || isNotTrailingByte(c2)) { + cursor--; // push c2 back since it isn't 'accepted' + invalid(parsingErrorsAreFatal, codeUnits); + } else { + // The codeUnit is the lower 6 bits from c2 and the lower 5 bits from + // c1 + const codeUnit = ((c1 & 0x1F) << 6) | (c2 & 0x3F); + // Consistency check that the computed code is in range for a 2 byte + // sequence. + jspb.asserts.assert(codeUnit >= 0x80 && codeUnit <= 0x07FF); + codeUnits.push(codeUnit); + } + } + } else if (c1 < 0xF0) { // UTF-8 with three bytes. + if (cursor >= end - 1) { + invalid(parsingErrorsAreFatal, codeUnits); + } else { + c2 = bytes[cursor++]; + if (isNotTrailingByte(c2) || + // These checks were taken from + // java/com/google/protobuf/Utf8.java + // overlong? 5 most significant bits must not all be zero + (c1 === 0xE0 && c2 < 0xA0) + // check for illegal surrogate codepoints + || (c1 === 0xED && c2 >= 0xA0) || + // We delay reading c3 until now so than an error in c2 or c1 will + // preserve c3 for the next loop iteration + isNotTrailingByte(c3 = bytes[cursor++])) { + cursor--; // push back c2 or c3, depending on how far we made it + invalid(parsingErrorsAreFatal, codeUnits); + } else { + // 4 bits from the first byte + // 6 bits from each of the two lower bytes + // == 16 bits total + const codeUnit = + ((c1 & 0xF) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F); + // Consistency check, this is the valid range for a 3 byte character + jspb.asserts.assert(codeUnit >= 0x800 && codeUnit <= 0xFFFF); + // And that Utf16 surrogates are disallowed + jspb.asserts.assert(codeUnit < MIN_SURROGATE || codeUnit > MAX_SURROGATE); + codeUnits.push(codeUnit); + } + } + } else if (c1 <= 0xF4) { // UTF-8 with 4 bytes. + // 0xF8 matches the bitpattern for utf8 with 4 bytes, but all leading + // bytes > 0xF4 are either overlong encodings or exceed the valid range. + if (cursor >= end - 2) { + invalid(parsingErrorsAreFatal, codeUnits); + } else { + c2 = bytes[cursor++]; + if (isNotTrailingByte(c2) || + // This check was inspired by + // java/com/google/protobuf/Utf8.java + // Tricky optimized form of: + // valid 4-byte leading byte? + // if (byte1 > (byte) 0xF4 || + // overlong? 4 most significant bits must not all be zero + // byte1 == (byte) 0xF0 && byte2 < (byte) 0x90 || + // codepoint larger than the highest code point (U+10FFFF)? + // byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F) + (((c1 << 28) + (c2 - 0x90)) >> 30) !== 0 || + // We delay reading c3 and c4 until now so than an error in c2 or c1 + // will preserve them for the next loop iteration. + isNotTrailingByte(c3 = bytes[cursor++]) || + isNotTrailingByte(c4 = bytes[cursor++])) { + cursor--; // push back c2, c3 or c4 depending on how far we made it + invalid(parsingErrorsAreFatal, codeUnits); + } else { + // Characters written on 4 bytes have 21 bits for a codepoint. + // We can't fit that on 16bit characters, so we use surrogates. + // 3 bits from the uppermost byte, 6 bits from each of the lower 3 + // bytes. This is 21 bits which is too big for a 16 bit utf16 code + // unit so we use surrogates. + let codepoint = ((c1 & 0x7) << 18) | ((c2 & 0x3F) << 12) | + ((c3 & 0x3F) << 6) | (c4 & 0x3F); + // Consistency check, this is the valid range for a 4 byte character. + jspb.asserts.assert(codepoint >= 0x10000 && codepoint <= 0x10FFFF); + // Surrogates formula from wikipedia. + // 1. Subtract 0x10000 from codepoint + codepoint -= 0x10000; + // 2. Split this into the high 10-bit value and the low 10-bit value + // 3. Add 0xD800 to the high value to form the high surrogate + // 4. Add 0xDC00 to the low value to form the low surrogate: + const low = (codepoint & 0x3FF) + MIN_LOW_SURROGATE; + const high = ((codepoint >> 10) & 0x3FF) + MIN_HIGH_SURROGATE; + codeUnits.push(high, low); + } + } + } else { + // initial byte is too large for utf8 + invalid(parsingErrorsAreFatal, codeUnits); + } + // Accumulate as we go to avoid exceeding the maximum stack size when + // calling `apply`. + if (codeUnits.length >= 8192) { + result = codeUnitsToString(result, codeUnits); + codeUnits.length = 0; + } + } + // ensure we don't overflow or underflow + jspb.asserts.assert(cursor === end, `expected ${cursor} === ${end}`); + return codeUnitsToString(result, codeUnits); +} + + +/** @type {boolean|undefined} */ +let isFatalTextDecoderCachableAfterThrowing_ = + // chrome version >= 2020 are not subject to https://crbug.com/910292 + goog.FEATURESET_YEAR >= 2020 ? true : undefined; + +/** @return {boolean} */ +function isFatalTextDecoderCachableAfterThrowing(/** !TextDecoder */ decoder) { + // Test if the decoder is subject to https://crbug.com/910292 + // chrome versions with this bug cause one failed decode to cause all later + // decodes to throw. + if (isFatalTextDecoderCachableAfterThrowing_ === undefined) { + // In theory we shouldn't need to generate an error here since this function + // is only called in the context of a failed decode. However, the buggy + // chrome versions are not 'consistent' in corrupting their internal state + // since it depends on where in the decode stream the error occurs. This + // error however does consistently trigger the bug based on manual testing. + try { + // A lonely continuation byte + decoder.decode(new Uint8Array([0x80])); + } catch (e) { + // expected + } + try { + // 'a' in hex + decoder.decode(new Uint8Array([0x61])); + isFatalTextDecoderCachableAfterThrowing_ = true; + } catch (e) { + // This decode should not throw, if it does it means our chrome version + // is buggy and we need to flush our cached decoder when failures occur + isFatalTextDecoderCachableAfterThrowing_ = false; + } + } + return isFatalTextDecoderCachableAfterThrowing_; +} + +/** @type {!TextDecoder|undefined} */ +let fatalDecoderInstance; + +/** @return {!TextDecoder}*/ +function getFatalDecoderInstance() { + let instance = fatalDecoderInstance; + if (!instance) { + instance = fatalDecoderInstance = new TextDecoder('utf-8', { fatal: true }); + } + return instance; +} + +/** @type {!TextDecoder|undefined} */ +let nonFatalDecoderInstance; + +/** @return {!TextDecoder}*/ +function getNonFatalDecoderInstance() { + let instance = nonFatalDecoderInstance; + if (!instance) { + instance = nonFatalDecoderInstance = + new TextDecoder('utf-8', { fatal: false }); + } + return instance; +} + +/** + * A `subarray` implementation that avoids calling `subarray` if it isn't needed + * + * `subarray` tends to be surprisingly slow. + * @return {!Uint8Array} + */ +function subarray( + /** !Uint8Array*/ bytes, /** number */ offset, /** number */ end) { + return offset === 0 && end === bytes.length ? bytes : + bytes.subarray(offset, end); +} + +/** + * @return {string} + */ +jspb.binary.utf8.textDecoderDecodeUtf8 = function ( + /** !Uint8Array*/ bytes, /** number */ offset, /** number */ length, + /** boolean*/ parsingErrorsAreFatal) { + const /** !TextDecoder */ decoder = parsingErrorsAreFatal ? + getFatalDecoderInstance() : + getNonFatalDecoderInstance(); + + bytes = subarray(bytes, offset, offset + length); + try { + return decoder.decode(bytes); + } catch (e) { + if (parsingErrorsAreFatal && + !isFatalTextDecoderCachableAfterThrowing(decoder)) { + fatalDecoderInstance = undefined; + } + throw e; + } +} + +/** @const {boolean} */ +const useTextDecoderDecode = + USE_TEXT_ENCODING || typeof TextDecoder !== 'undefined'; + +/** + * A utf8 decoding routine either based upon TextDecoder if available or using + * our polyfill implementation + * @return {string} + */ +jspb.binary.utf8.decodeUtf8 = function ( + /** !Uint8Array*/ bytes, /** number */ offset, /** number */ length, + /** boolean*/ parsingErrorsAreFatal) { + return useTextDecoderDecode ? + jspb.binary.utf8.textDecoderDecodeUtf8(bytes, offset, length, parsingErrorsAreFatal) : + jspb.binary.utf8.polyfillDecodeUtf8(bytes, offset, length, parsingErrorsAreFatal); +} + +/** @type {!TextEncoder|undefined} */ +let textEncoderInstance; + +/** @return {!Uint8Array} */ +jspb.binary.utf8.textEncoderEncode = function ( + /** string */ s, /** boolean */ rejectUnpairedSurrogates) { + if (rejectUnpairedSurrogates) { + checkWellFormed(s); + } + + if (!textEncoderInstance) { + textEncoderInstance = new TextEncoder(); + } + return textEncoderInstance.encode(s); +} + +// isWellFormed landed in major browsers in early 2023 so it will only be +// definitely available in 2024 See +// http://go/mdn/JavaScript/Reference/Global_Objects/String/isWellFormed +const /** boolean */ HAS_WELL_FORMED_METHOD = goog.FEATURESET_YEAR > 2023 || + typeof String.prototype.isWellFormed === 'function'; + +jspb.binary.utf8.checkWellFormed = function (/** string */ text) { + if (HAS_WELL_FORMED_METHOD ? + // Externs don't contain the definition of this function yet. + // http://go/mdn/JavaScript/Reference/Global_Objects/String/isWellFormed + !(/** @type{{isWellFormed:function():boolean}}*/ ( + /** @type {?} */ (text)) + .isWellFormed()) : + /(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])/ + .test(text)) { + throw new Error('Found an unpaired surrogate'); + } +} + + +/** @return {!Uint8Array} */ +jspb.binary.utf8.polyfillEncode = function ( + /** string */ s, /** boolean */ rejectUnpairedSurrogates) { + let bi = 0; + // The worse case is that every character requires 3 output bytes, so we + // allocate for this. This assumes that the buffer will be short lived. + // Callers can always `slice` if needed + const buffer = new Uint8Array(3 * s.length); + for (let ci = 0; ci < s.length; ci++) { + let c = s.charCodeAt(ci); + if (c < 0x80) { + buffer[bi++] = c; + } else if (c < 0x800) { + buffer[bi++] = (c >> 6) | 0xC0; + buffer[bi++] = (c & 63) | 0x80; + } else { + jspb.asserts.assert(c < 65536); + // Look for surrogates + // First check if it is surrogate range + if (c >= MIN_SURROGATE && c <= MAX_SURROGATE) { + // is it a high surrogate? + if (c <= MAX_HIGH_SURROGATE && ci < s.length) { + const c2 = s.charCodeAt(++ci); + if (c2 >= MIN_LOW_SURROGATE && c2 <= MAX_LOW_SURROGATE) { + // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae + const codePoint = + (c - MIN_SURROGATE) * 0x400 + c2 - MIN_LOW_SURROGATE + 0x10000; + buffer[bi++] = (codePoint >> 18) | 0xF0; + buffer[bi++] = ((codePoint >> 12) & 63) | 0x80; + buffer[bi++] = ((codePoint >> 6) & 63) | 0x80; + buffer[bi++] = (codePoint & 63) | 0x80; + continue; + } else { + // else c2 not in low surrogate range, treat c as a lone surrogate + // and back up ci so we process c2 on the next loop as an + // independent character + ci--; + } + } // else c not a high surrogate + if (rejectUnpairedSurrogates) { + throw new Error('Found an unpaired surrogate'); + } + c = 0xFFFD; // Error! Unpaired surrogate + } + buffer[bi++] = (c >> 12) | 0xE0; + buffer[bi++] = ((c >> 6) & 63) | 0x80; + buffer[bi++] = (c & 63) | 0x80; + } + } + return subarray(buffer, 0, bi); +} + +/** @const {boolean} */ +const useTextEncoderEncode = + (USE_TEXT_ENCODING || typeof TextEncoder !== 'undefined'); + +/** + * A utf8 encoding routine either based upon TextEncoder if available or using + * our polyfill implementation + * @return {!Uint8Array} + */ +jspb.binary.utf8.encodeUtf8 = function ( + /**string*/ string, /** boolean=*/ rejectUnpairedSurrogates = false) { + jspb.asserts.assertString(string); + return useTextEncoderEncode ? + jspb.binary.utf8.textEncoderEncode(string, rejectUnpairedSurrogates) : + jspb.binary.utf8.polyfillEncode(string, rejectUnpairedSurrogates); +} + diff --git a/generator/js_generator.cc b/generator/js_generator.cc index 84365dc..8136f58 100644 --- a/generator/js_generator.cc +++ b/generator/js_generator.cc @@ -1073,17 +1073,21 @@ std::string JSFieldTypeAnnotation(const GeneratorOptions& options, return jstype; } -std::string JSBinaryReaderMethodType(const FieldDescriptor* field) { +std::string JSBinaryMethodType(const FieldDescriptor* field, bool is_writer) { std::string name = field->type_name(); if (name[0] >= 'a' && name[0] <= 'z') { name[0] = (name[0] - 'a') + 'A'; } + if (!is_writer && field->type() == FieldDescriptor::TYPE_STRING && + field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) { + name = name + "RequireUtf8"; + } return IsIntegralFieldWithStringJSType(field) ? (name + "String") : name; } std::string JSBinaryReadWriteMethodName(const FieldDescriptor* field, bool is_writer) { - std::string name = JSBinaryReaderMethodType(field); + std::string name = JSBinaryMethodType(field, is_writer); if (field->is_packed()) { name = "Packed" + name; } else if (is_writer && field->is_repeated()) { @@ -3128,11 +3132,11 @@ void Generator::GenerateClassDeserializeBinaryField( printer->Print( " var values = /** @type {$fieldtype$} */ " "(reader.isDelimited() " - "? reader.readPacked$reader$() : [reader.read$reader$()]);\n", + "? reader.read$reader$() : [reader.read$reader$()]);\n", "fieldtype", JSFieldTypeAnnotation(options, field, false, true, /* singular_if_not_packed */ false, BYTES_U8), - "reader", JSBinaryReaderMethodType(field)); + "reader", JSBinaryReadWriteMethodName(field, /* is_writer=*/false)); } else { printer->Print( " var value = /** @type {$fieldtype$} */ " diff --git a/gulpfile.js b/gulpfile.js index e7f7511..426e0f1 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -145,6 +145,7 @@ function getClosureCompilerCommand(exportsFile, outputFile) { '--js=binary/decoder.js', '--js=binary/encoder.js', '--js=binary/reader.js', + '--js=binary/utf8.js', '--js=binary/utils.js', '--js=binary/writer.js', `--js=${exportsFile}`, @@ -194,7 +195,7 @@ function commonjs_out(cb) { function closure_make_deps(cb) { exec( - './node_modules/.bin/closure-make-deps --closure-path=. --file=node_modules/google-closure-library/closure/goog/deps.js binary/arith.js binary/constants.js binary/decoder.js binary/encoder.js binary/reader.js binary/utils.js binary/writer.js asserts.js debug.js map.js message.js node_loader.js test_bootstrap.js > deps.js', + './node_modules/.bin/closure-make-deps --closure-path=. --file=node_modules/google-closure-library/closure/goog/deps.js binary/arith.js binary/constants.js binary/decoder.js binary/encoder.js binary/reader.js binary/utf8.js binary/utils.js binary/writer.js asserts.js debug.js map.js message.js node_loader.js test_bootstrap.js > deps.js', make_exec_logging_callback(cb)); } From 27d4277b6eb3c4c0f13e0bc991c50c10272f460d Mon Sep 17 00:00:00 2001 From: Stephanie DiBenedetto Date: Mon, 17 Jun 2024 10:46:27 -0700 Subject: [PATCH 02/22] clarify enforceUtf8 argument Co-authored-by: Luke Sandberg --- binary/decoder_test.js | 8 ++++---- generator/js_generator.cc | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/binary/decoder_test.js b/binary/decoder_test.js index b8e1084..7a71c0d 100644 --- a/binary/decoder_test.js +++ b/binary/decoder_test.js @@ -375,11 +375,11 @@ describe('binaryDecoderTest', () => { const decoder = jspb.BinaryDecoder.alloc(encoder.end()); - expect(decoder.readString(ascii.length, true)).toEqual(ascii); - expect(utf8_two_bytes).toEqual(decoder.readString(2, true)); + expect(decoder.readString(ascii.length, /* enforceUtf8= */ true)).toEqual(ascii); + expect(utf8_two_bytes).toEqual(decoder.readString(2, /* enforceUtf8= */ true)); expect(utf8_three_bytes) - .toEqual(decoder.readString(3, true)); - expect(utf8_four_bytes).toEqual(decoder.readString(4, true)); + .toEqual(decoder.readString(3, /* enforceUtf8= */ true)); + expect(utf8_four_bytes).toEqual(decoder.readString(4, /* enforceUtf8= */ true)); }); /** diff --git a/generator/js_generator.cc b/generator/js_generator.cc index 8136f58..6ca0ad3 100644 --- a/generator/js_generator.cc +++ b/generator/js_generator.cc @@ -1079,7 +1079,7 @@ std::string JSBinaryMethodType(const FieldDescriptor* field, bool is_writer) { name[0] = (name[0] - 'a') + 'A'; } if (!is_writer && field->type() == FieldDescriptor::TYPE_STRING && - field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) { + field->requires_utf8_validation()) { name = name + "RequireUtf8"; } return IsIntegralFieldWithStringJSType(field) ? (name + "String") : name; From 16cb29334f04b6117f1114ead23164f611ce464b Mon Sep 17 00:00:00 2001 From: Stephanie DiBenedetto Date: Tue, 16 Jul 2024 11:01:59 -0700 Subject: [PATCH 03/22] Fix build errors from utf8 enforcement changes This change fixes some minor build issues from not using fully specified function names. There was also a missing parameter issue for BinaryDecoder.readStringWithLength's invocation of readString, but the former appears to be dead code so just removed it. --- binary/decoder.js | 17 ++--------------- binary/utf8.js | 3 +-- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/binary/decoder.js b/binary/decoder.js index c44053f..5dac0dd 100644 --- a/binary/decoder.js +++ b/binary/decoder.js @@ -405,7 +405,7 @@ jspb.BinaryDecoder.prototype.readSplitFixed64 = function(convert) { */ jspb.BinaryDecoder.prototype.checkCursor = function () { if (this.cursor_ > this.end_) { - asserts.fail('Read past the end ' + this.cursor_ + ' > ' + this.end_); + jspb.asserts.fail('Read past the end ' + this.cursor_ + ' > ' + this.end_); } } @@ -902,23 +902,10 @@ jspb.BinaryDecoder.prototype.readString = function (length, requireUtf8) { this.cursor_ += length; this.checkCursor(); const result = - jspb.binary.utf8.decodeUtf8(jspb.asserts.assert(this.bytes_), cursor, length, requireUtf8); + jspb.binary.utf8.decodeUtf8(jspb.asserts.assert(this.bytes_), cursor, length, requireUtf8); return result; }; - -/** - * Reads and parses a UTF-8 encoded unicode string (with length prefix) from - * the stream. - * @return {string} The decoded string. - * @export - */ -jspb.BinaryDecoder.prototype.readStringWithLength = function() { - var length = this.readUnsignedVarint32(); - return this.readString(length); -}; - - /** * Reads a block of raw bytes from the binary stream. * diff --git a/binary/utf8.js b/binary/utf8.js index b77602b..371982d 100644 --- a/binary/utf8.js +++ b/binary/utf8.js @@ -326,7 +326,7 @@ let textEncoderInstance; jspb.binary.utf8.textEncoderEncode = function ( /** string */ s, /** boolean */ rejectUnpairedSurrogates) { if (rejectUnpairedSurrogates) { - checkWellFormed(s); + jspb.binary.utf8.checkWellFormed(s); } if (!textEncoderInstance) { @@ -423,4 +423,3 @@ jspb.binary.utf8.encodeUtf8 = function ( jspb.binary.utf8.textEncoderEncode(string, rejectUnpairedSurrogates) : jspb.binary.utf8.polyfillEncode(string, rejectUnpairedSurrogates); } - From aa988c9ed9413d689ed03ac24e981f88dd9da534 Mon Sep 17 00:00:00 2001 From: Stephanie DiBenedetto Date: Wed, 17 Jul 2024 09:53:08 -0700 Subject: [PATCH 04/22] Specify os and cpu for release name to avoid duplicates actions/upload-artifact@4 made a breaking change to fail on duplicate names. I think we are seeing Windows release errors as a result since both x64_x86 and x64 are named 'releases'. This change just tags the os and cpu onto the release dir name to reflect the specific build. --- .github/workflows/build.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 15b7a35..bda1111 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,10 +27,6 @@ jobs: node-version: 20 cache: ${{ !env.ACT && 'npm' || '' }} # cache API not available in ACT - - uses: bazel-contrib/setup-bazel@0.8.5 - with: - token: ${{ secrets.GITHUB_TOKEN }} - - name: Install Protoc run: | echo "Fetching protoc" @@ -108,7 +104,7 @@ jobs: - uses: actions/upload-artifact@v4 with: - name: releases + name: release-${{ matrix.os }}-${{ matrix.cpu }} path: out release: @@ -122,7 +118,7 @@ jobs: steps: - uses: actions/download-artifact@v4 with: - name: releases + name: release-${{ matrix.os }}-${{ matrix.cpu }} - name: Release uses: svenstaro/upload-release-action@v2 From ae8f8557226f2a11cce63966559619e2c32c3b36 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 12 Sep 2024 01:51:39 +0000 Subject: [PATCH 05/22] Bump micromatch from 4.0.7 to 4.0.8 Bumps [micromatch](https://github.com/micromatch/micromatch) from 4.0.7 to 4.0.8. - [Release notes](https://github.com/micromatch/micromatch/releases) - [Changelog](https://github.com/micromatch/micromatch/blob/master/CHANGELOG.md) - [Commits](https://github.com/micromatch/micromatch/compare/4.0.7...4.0.8) --- updated-dependencies: - dependency-name: micromatch dependency-type: indirect ... Signed-off-by: dependabot[bot] --- package-lock.json | 16 ++++---- yarn.lock | 96 +++++++++++++++++++++++++---------------------- 2 files changed, 60 insertions(+), 52 deletions(-) diff --git a/package-lock.json b/package-lock.json index 556297d..4fe22bb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "google-protobuf", - "version": "3.21.2", + "version": "3.21.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "google-protobuf", - "version": "3.21.2", + "version": "3.21.4", "license": "(BSD-3-Clause AND Apache-2.0)", "devDependencies": { "glob": "~7.1.4", @@ -1279,9 +1279,9 @@ } }, "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "dependencies": { "braces": "^3.0.3", @@ -3036,9 +3036,9 @@ "dev": true }, "micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "requires": { "braces": "^3.0.3", diff --git a/yarn.lock b/yarn.lock index 031949d..0d998f3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -26,14 +26,7 @@ ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" -ansi-styles@^4.0.0: - version "4.3.0" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -ansi-styles@^4.1.0: +ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== @@ -140,14 +133,6 @@ buffer@^6.0.3: base64-js "^1.3.1" ieee754 "^1.2.1" -chalk@^4.1.2: - version "4.1.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - chalk@2.x: version "2.4.2" resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" @@ -157,6 +142,14 @@ chalk@2.x: escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + chokidar@^3.5.3: version "3.6.0" resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz" @@ -219,16 +212,16 @@ color-convert@^2.0.1: dependencies: color-name "~1.1.4" -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - color-name@1.1.3: version "1.1.3" resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" @@ -381,6 +374,11 @@ fs.realpath@^1.0.0: resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== +fsevents@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + function-bind@^1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" @@ -481,6 +479,16 @@ google-closure-compiler-linux@^20190819.0.0: resolved "https://registry.npmjs.org/google-closure-compiler-linux/-/google-closure-compiler-linux-20190819.0.0.tgz" integrity sha512-+ia89Ot4dPyRioLlxvkfYiISwJO+2NV7SY0Zp/KfTt9x+eJaGQ9GRIQage50d1mGkUyPmFfxsdPUePpT1QlpaA== +google-closure-compiler-osx@^20190819.0.0: + version "20190819.0.0" + resolved "https://registry.yarnpkg.com/google-closure-compiler-osx/-/google-closure-compiler-osx-20190819.0.0.tgz#57046952a3f520b942a35d2edaf0379b44b0c84c" + integrity sha512-woANg+oA2zjFebtdYTA4lLtqbOVO9yE9yy8ibGjt76FNlw0bAyxTO4z2ab4CwUNNpOeRoxZyGt9CejlCmNpxJg== + +google-closure-compiler-windows@^20190819.0.0: + version "20190819.0.0" + resolved "https://registry.yarnpkg.com/google-closure-compiler-windows/-/google-closure-compiler-windows-20190819.0.0.tgz#acf1246d65aa9e55a7d449e08188458a9da89867" + integrity sha512-WglPY706c1oN03KiZF02FUWr/7M0eFoev4CQPncSihfjYXpD5E5PMKJ3ppawhzj60CQ9ceC/Omx7VN7Kp0uOQg== + google-closure-compiler@~20190819.0.0: version "20190819.0.0" resolved "https://registry.npmjs.org/google-closure-compiler/-/google-closure-compiler-20190819.0.0.tgz" @@ -594,7 +602,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3, inherits@2: +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: version "2.0.4" resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -744,9 +752,9 @@ map-cache@^0.2.0: integrity sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg== micromatch@^4.0.4: - version "4.0.7" - resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz" - integrity sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q== + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== dependencies: braces "^3.0.3" picomatch "^2.3.1" @@ -768,7 +776,7 @@ mute-stdout@^2.0.0: resolved "https://registry.npmjs.org/mute-stdout/-/mute-stdout-2.0.0.tgz" integrity sha512-32GSKM3Wyc8dg/p39lWPKYu8zci9mJFzV1Np9Of0ZEpe6Fhssn/FbI7ywAMd40uX+p3ZKh3T5EeCFv81qS3HmQ== -normalize-path@^3.0.0, normalize-path@~3.0.0, normalize-path@3.0.0: +normalize-path@3.0.0, normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== @@ -1000,13 +1008,6 @@ streamx@^2.12.0, streamx@^2.12.5, streamx@^2.13.2, streamx@^2.14.0: optionalDependencies: bare-events "^2.2.0" -string_decoder@^1.1.1, string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" @@ -1016,6 +1017,13 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" +string_decoder@^1.1.1, string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" @@ -1159,17 +1167,6 @@ vinyl-sourcemaps-apply@^0.2.0: dependencies: source-map "^0.5.1" -vinyl@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/vinyl/-/vinyl-3.0.0.tgz" - integrity sha512-rC2VRfAVVCGEgjnxHUnpIVh3AGuk62rP3tqVrn+yab0YH7UULisC085+NYH+mnqf3Wx4SpSi1RQMwudL89N03g== - dependencies: - clone "^2.1.2" - clone-stats "^1.0.0" - remove-trailing-separator "^1.1.0" - replace-ext "^2.0.0" - teex "^1.0.1" - vinyl@2.x: version "2.2.1" resolved "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz" @@ -1182,6 +1179,17 @@ vinyl@2.x: remove-trailing-separator "^1.0.1" replace-ext "^1.0.0" +vinyl@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/vinyl/-/vinyl-3.0.0.tgz" + integrity sha512-rC2VRfAVVCGEgjnxHUnpIVh3AGuk62rP3tqVrn+yab0YH7UULisC085+NYH+mnqf3Wx4SpSi1RQMwudL89N03g== + dependencies: + clone "^2.1.2" + clone-stats "^1.0.0" + remove-trailing-separator "^1.1.0" + replace-ext "^2.0.0" + teex "^1.0.1" + which@^1.2.14: version "1.3.1" resolved "https://registry.npmjs.org/which/-/which-1.3.1.tgz" From 426b2e025aa59c23a1b6e19fbacd6b4a11bfad16 Mon Sep 17 00:00:00 2001 From: Stephanie DiBenedetto Date: Tue, 17 Sep 2024 12:10:56 -0700 Subject: [PATCH 06/22] Bump testing protoc version 27.1 -> 28.1 --- .github/workflows/build.yml | 2 +- .github/workflows/codeql.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bda1111..c0aaa70 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,7 +6,7 @@ permissions: read-all # update in build.yml and codeql.yml at same time env: - PROTOC_VERSION: 27.1 + PROTOC_VERSION: 28.1 jobs: build: diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 7136068..dccc072 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -15,7 +15,7 @@ permissions: read-all # update in build.yml and codeql.yml at same time env: - PROTOC_VERSION: 27.1 + PROTOC_VERSION: 28.1 on: push: From eb785a9363664a402b6336dfe96aad27fb33ffa8 Mon Sep 17 00:00:00 2001 From: Stephanie DiBenedetto Date: Mon, 17 Mar 2025 10:02:57 -0700 Subject: [PATCH 07/22] Update to protobuf 30.1 and drop bazel workspace configuration The proto descriptor API has changed to return absl::string_views instead of std::string, which is preventing users from building at HEAD. This change bumps our dependency to protobuf 30.1 and migrates our code generator as needed so we can build with absl::string_view values. At the same time, Bazel is getting ready to drop workspace support (disabled by default as of EOY2024/Bazel 8). Protobuf still seems to support both, but opportunistically taking this opportunity to just use Bazel models. We can temporarily add back workspace support if users actually need it. --- .bazelrc | 4 - .github/workflows/build.yml | 2 +- .github/workflows/codeql.yml | 2 +- .github/workflows/scorecards.yml | 8 +- MODULE.bazel | 5 +- MODULE.bazel.lock | 3710 +++++++++++++++++++++++++++++- WORKSPACE | 30 - WORKSPACE.bzlmod | 2 - generator/BUILD.bazel | 4 +- generator/js_generator.cc | 55 +- yarn.lock | 92 +- 11 files changed, 3757 insertions(+), 157 deletions(-) delete mode 100644 WORKSPACE delete mode 100644 WORKSPACE.bzlmod diff --git a/.bazelrc b/.bazelrc index 65cc8c4..01314ff 100644 --- a/.bazelrc +++ b/.bazelrc @@ -23,10 +23,6 @@ build:ubsan --action_env=UBSAN_OPTIONS=halt_on_error=1:print_stacktrace=1 # https://github.com/bazelbuild/bazel/issues/11122#issuecomment-613746748 build:ubsan --copt=-fno-sanitize=function --copt=-fno-sanitize=vptr -# TODO: migrate all dependencies from WORKSPACE to MODULE.bazel -# https://github.com/protocolbuffers/protobuf/issues/14313 -common --noenable_bzlmod - # Important: this flag ensures that we remain compliant with the C++ layering # check. build --features=layering_check diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c0aaa70..e0423c4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,7 +6,7 @@ permissions: read-all # update in build.yml and codeql.yml at same time env: - PROTOC_VERSION: 28.1 + PROTOC_VERSION: 30.1 jobs: build: diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index dccc072..8ec5102 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -15,7 +15,7 @@ permissions: read-all # update in build.yml and codeql.yml at same time env: - PROTOC_VERSION: 28.1 + PROTOC_VERSION: 30.1 on: push: diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index f266af0..5e59221 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -22,7 +22,7 @@ jobs: # Needs for private repositories. contents: read actions: read - + steps: - name: "Checkout code" uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # v3.0.0 @@ -41,8 +41,8 @@ jobs: # repo_token: ${{ secrets.SCORECARD_READ_TOKEN }} # Publish the results for public repositories to enable scorecard badges. For more details, see - # https://github.com/ossf/scorecard-action#publishing-results. - # For private repositories, `publish_results` will automatically be set to `false`, regardless + # https://github.com/ossf/scorecard-action#publishing-results. + # For private repositories, `publish_results` will automatically be set to `false`, regardless # of the value entered here. publish_results: true @@ -54,7 +54,7 @@ jobs: name: SARIF file path: results.sarif retention-days: 5 - + # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" uses: github/codeql-action/upload-sarif@5f532563584d71fdef14ee64d17bafb34f751ce5 # v1.0.26 diff --git a/MODULE.bazel b/MODULE.bazel index a639a78..ad95b50 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -1,4 +1,5 @@ module(name = "protobuf_javascript", version = "3.21.4") -bazel_dep(name = "protobuf", version = "27.1", repo_name = "com_google_protobuf") -bazel_dep(name = "rules_pkg", version = "0.7.0") +bazel_dep(name = "protobuf", version = "30.1", repo_name = "com_google_protobuf") +bazel_dep(name = "rules_pkg", version = "1.0.1") +bazel_dep(name = "abseil-cpp", version = "20250127.0") diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index 22cecad..c30367f 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -1,100 +1,517 @@ { - "lockFileVersion": 11, + "lockFileVersion": 18, "registryFileHashes": { "https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497", "https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2", "https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589", "https://bcr.bazel.build/modules/abseil-cpp/20230125.1/MODULE.bazel": "89047429cb0207707b2dface14ba7f8df85273d484c2572755be4bab7ce9c3a0", "https://bcr.bazel.build/modules/abseil-cpp/20230802.0.bcr.1/MODULE.bazel": "1c8cec495288dccd14fdae6e3f95f772c1c91857047a098fad772034264cc8cb", - "https://bcr.bazel.build/modules/abseil-cpp/20230802.0.bcr.1/source.json": "14892cc698e02ffedf4967546e6bedb7245015906888d3465fcf27c90a26da10", - "https://bcr.bazel.build/modules/apple_support/1.5.0/MODULE.bazel": "50341a62efbc483e8a2a6aec30994a58749bd7b885e18dd96aa8c33031e558ef", - "https://bcr.bazel.build/modules/apple_support/1.5.0/source.json": "eb98a7627c0bc486b57f598ad8da50f6625d974c8f723e9ea71bd39f709c9862", + "https://bcr.bazel.build/modules/abseil-cpp/20230802.0/MODULE.bazel": "d253ae36a8bd9ee3c5955384096ccb6baf16a1b1e93e858370da0a3b94f77c16", + "https://bcr.bazel.build/modules/abseil-cpp/20230802.1/MODULE.bazel": "fa92e2eb41a04df73cdabeec37107316f7e5272650f81d6cc096418fe647b915", + "https://bcr.bazel.build/modules/abseil-cpp/20240116.1/MODULE.bazel": "37bcdb4440fbb61df6a1c296ae01b327f19e9bb521f9b8e26ec854b6f97309ed", + "https://bcr.bazel.build/modules/abseil-cpp/20240116.2/MODULE.bazel": "73939767a4686cd9a520d16af5ab440071ed75cec1a876bf2fcfaf1f71987a16", + "https://bcr.bazel.build/modules/abseil-cpp/20250127.0/MODULE.bazel": "d1086e248cda6576862b4b3fe9ad76a214e08c189af5b42557a6e1888812c5d5", + "https://bcr.bazel.build/modules/abseil-cpp/20250127.0/source.json": "1b996859f840d8efc7c720efc61dcf2a84b1261cb3974cbbe9b6666ebf567775", + "https://bcr.bazel.build/modules/apple_support/1.11.1/MODULE.bazel": "1843d7cd8a58369a444fc6000e7304425fba600ff641592161d9f15b179fb896", + "https://bcr.bazel.build/modules/apple_support/1.13.0/MODULE.bazel": "7c8cdea7e031b7f9f67f0b497adf6d2c6a2675e9304ca93a9af6ed84eef5a524", + "https://bcr.bazel.build/modules/apple_support/1.15.1/MODULE.bazel": "a0556fefca0b1bb2de8567b8827518f94db6a6e7e7d632b4c48dc5f865bc7c85", + "https://bcr.bazel.build/modules/apple_support/1.15.1/source.json": "517f2b77430084c541bc9be2db63fdcbb7102938c5f64c17ee60ffda2e5cf07b", + "https://bcr.bazel.build/modules/aspect_bazel_lib/1.31.2/MODULE.bazel": "7bee702b4862612f29333590f4b658a5832d433d6f8e4395f090e8f4e85d442f", + "https://bcr.bazel.build/modules/aspect_bazel_lib/1.38.0/MODULE.bazel": "6307fec451ba9962c1c969eb516ebfe1e46528f7fa92e1c9ac8646bef4cdaa3f", + "https://bcr.bazel.build/modules/aspect_bazel_lib/1.40.3/MODULE.bazel": "668e6bcb4d957fc0e284316dba546b705c8d43c857f87119619ee83c4555b859", + "https://bcr.bazel.build/modules/aspect_bazel_lib/1.40.3/source.json": "f5a28b1320e5f444e798b4afc1465c8b720bfaec7522cca38a23583dffe85e6d", + "https://bcr.bazel.build/modules/aspect_rules_js/1.33.1/MODULE.bazel": "db3e7f16e471cf6827059d03af7c21859e7a0d2bc65429a3a11f005d46fc501b", + "https://bcr.bazel.build/modules/aspect_rules_js/1.39.0/MODULE.bazel": "aece421d479e3c31dc3e5f6d49a12acc2700457c03c556650ec7a0ff23fc0d95", + "https://bcr.bazel.build/modules/aspect_rules_js/1.39.0/source.json": "a8f93e4ad8843e8aa407fa5fd7c8b63a63846c0ce255371ff23384582813b13d", + "https://bcr.bazel.build/modules/aspect_rules_lint/0.12.0/MODULE.bazel": "e767c5dbfeb254ec03275a7701b5cfde2c4d2873676804bc7cb27ddff3728fed", + "https://bcr.bazel.build/modules/aspect_rules_lint/0.12.0/source.json": "9a3668e1ee219170e22c0e7f3ab959724c6198fdd12cd503fa10b1c6923a2559", + "https://bcr.bazel.build/modules/bazel_features/0.1.0/MODULE.bazel": "47011d645b0f949f42ee67f2e8775188a9cf4a0a1528aa2fa4952f2fd00906fd", + "https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd", "https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8", - "https://bcr.bazel.build/modules/bazel_features/1.11.0/source.json": "c9320aa53cd1c441d24bd6b716da087ad7e4ff0d9742a9884587596edfe53015", + "https://bcr.bazel.build/modules/bazel_features/1.15.0/MODULE.bazel": "d38ff6e517149dc509406aca0db3ad1efdd890a85e049585b7234d04238e2a4d", + "https://bcr.bazel.build/modules/bazel_features/1.17.0/MODULE.bazel": "039de32d21b816b47bd42c778e0454217e9c9caac4a3cf8e15c7231ee3ddee4d", + "https://bcr.bazel.build/modules/bazel_features/1.18.0/MODULE.bazel": "1be0ae2557ab3a72a57aeb31b29be347bcdc5d2b1eb1e70f39e3851a7e97041a", + "https://bcr.bazel.build/modules/bazel_features/1.19.0/MODULE.bazel": "59adcdf28230d220f0067b1f435b8537dd033bfff8db21335ef9217919c7fb58", + "https://bcr.bazel.build/modules/bazel_features/1.21.0/MODULE.bazel": "675642261665d8eea09989aa3b8afb5c37627f1be178382c320d1b46afba5e3b", + "https://bcr.bazel.build/modules/bazel_features/1.23.0/MODULE.bazel": "fd1ac84bc4e97a5a0816b7fd7d4d4f6d837b0047cf4cbd81652d616af3a6591a", + "https://bcr.bazel.build/modules/bazel_features/1.23.0/source.json": "c72c61b722d7c3f884994fe647afeb2ed1ae66c437f8f370753551f7b4d8be7f", + "https://bcr.bazel.build/modules/bazel_features/1.3.0/MODULE.bazel": "cdcafe83ec318cda34e02948e81d790aab8df7a929cec6f6969f13a489ccecd9", + "https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7", + "https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a", "https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8", + "https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e", "https://bcr.bazel.build/modules/bazel_skylib/1.2.0/MODULE.bazel": "44fe84260e454ed94ad326352a698422dbe372b21a1ac9f3eab76eb531223686", "https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a", "https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5", "https://bcr.bazel.build/modules/bazel_skylib/1.4.1/MODULE.bazel": "a0dcb779424be33100dcae821e9e27e4f2901d9dfd5333efe5ac6a8d7ab75e1d", + "https://bcr.bazel.build/modules/bazel_skylib/1.4.2/MODULE.bazel": "3bd40978e7a1fac911d5989e6b09d8f64921865a45822d8b09e815eaa726a651", + "https://bcr.bazel.build/modules/bazel_skylib/1.5.0/MODULE.bazel": "32880f5e2945ce6a03d1fbd588e9198c0a959bb42297b2cfaf1685b7bc32e138", "https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917", - "https://bcr.bazel.build/modules/bazel_skylib/1.6.1/source.json": "082ed5f9837901fada8c68c2f3ddc958bb22b6d654f71dd73f3df30d45d4b749", + "https://bcr.bazel.build/modules/bazel_skylib/1.7.0/MODULE.bazel": "0db596f4563de7938de764cc8deeabec291f55e8ec15299718b93c4423e9796d", + "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b", + "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/source.json": "f121b43eeefc7c29efbd51b83d08631e2347297c95aac9764a701f2a6a2bb953", "https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84", "https://bcr.bazel.build/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8", + "https://bcr.bazel.build/modules/gazelle/0.27.0/MODULE.bazel": "3446abd608295de6d90b4a8a118ed64a9ce11dcb3dda2dc3290a22056bd20996", + "https://bcr.bazel.build/modules/gazelle/0.30.0/MODULE.bazel": "f888a1effe338491f35f0e0e85003b47bb9d8295ccba73c37e07702d8d31c65b", + "https://bcr.bazel.build/modules/gazelle/0.30.0/source.json": "7af0779f99120aafc73be127615d224f26da2fc5a606b52bdffb221fd9efb737", + "https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb", "https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4", + "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6", "https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f", - "https://bcr.bazel.build/modules/googletest/1.14.0/source.json": "2478949479000fdd7de9a3d0107ba2c85bb5f961c3ecb1aa448f52549ce310b5", + "https://bcr.bazel.build/modules/googletest/1.15.2/MODULE.bazel": "6de1edc1d26cafb0ea1a6ab3f4d4192d91a312fd2d360b63adaa213cd00b2108", + "https://bcr.bazel.build/modules/googletest/1.15.2/source.json": "dbdda654dcb3a0d7a8bc5d0ac5fc7e150b58c2a986025ae5bc634bb2cb61f470", "https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075", - "https://bcr.bazel.build/modules/jsoncpp/1.9.5/source.json": "4108ee5085dd2885a341c7fab149429db457b3169b86eb081fa245eadf69169d", + "https://bcr.bazel.build/modules/jsoncpp/1.9.6/MODULE.bazel": "2f8d20d3b7d54143213c4dfc3d98225c42de7d666011528dc8fe91591e2e17b0", + "https://bcr.bazel.build/modules/jsoncpp/1.9.6/source.json": "a04756d367a2126c3541682864ecec52f92cdee80a35735a3cb249ce015ca000", + "https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902", + "https://bcr.bazel.build/modules/nlohmann_json/3.6.1/MODULE.bazel": "6f7b417dcc794d9add9e556673ad25cb3ba835224290f4f848f8e2db1e1fca74", + "https://bcr.bazel.build/modules/nlohmann_json/3.6.1/source.json": "f448c6e8963fdfa7eb831457df83ad63d3d6355018f6574fb017e8169deb43a9", + "https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5", + "https://bcr.bazel.build/modules/platforms/0.0.10/source.json": "f22828ff4cf021a6b577f1bf6341cb9dcd7965092a439f64fc1bb3b7a5ae4bd5", "https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee", "https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37", "https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615", "https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814", "https://bcr.bazel.build/modules/platforms/0.0.8/MODULE.bazel": "9f142c03e348f6d263719f5074b21ef3adf0b139ee4c5133e2aa35664da9eb2d", "https://bcr.bazel.build/modules/platforms/0.0.9/MODULE.bazel": "4a87a60c927b56ddd67db50c89acaa62f4ce2a1d2149ccb63ffd871d5ce29ebc", - "https://bcr.bazel.build/modules/platforms/0.0.9/source.json": "cd74d854bf16a9e002fb2ca7b1a421f4403cda29f824a765acd3a8c56f8d43e6", "https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7", + "https://bcr.bazel.build/modules/protobuf/27.0/MODULE.bazel": "7873b60be88844a0a1d8f80b9d5d20cfbd8495a689b8763e76c6372998d3f64c", "https://bcr.bazel.build/modules/protobuf/27.1/MODULE.bazel": "703a7b614728bb06647f965264967a8ef1c39e09e8f167b3ca0bb1fd80449c0d", - "https://bcr.bazel.build/modules/protobuf/27.1/source.json": "11a2567425ffebb89ff59e94fc8a55bc78a418d52a4cc415069ce7c793571352", + "https://bcr.bazel.build/modules/protobuf/29.0-rc2/MODULE.bazel": "6241d35983510143049943fc0d57937937122baf1b287862f9dc8590fc4c37df", + "https://bcr.bazel.build/modules/protobuf/29.0-rc3/MODULE.bazel": "33c2dfa286578573afc55a7acaea3cada4122b9631007c594bf0729f41c8de92", + "https://bcr.bazel.build/modules/protobuf/29.0/MODULE.bazel": "319dc8bf4c679ff87e71b1ccfb5a6e90a6dbc4693501d471f48662ac46d04e4e", "https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0", + "https://bcr.bazel.build/modules/protobuf/3.19.2/MODULE.bazel": "532ffe5f2186b69fdde039efe6df13ba726ff338c6bc82275ad433013fa10573", "https://bcr.bazel.build/modules/protobuf/3.19.6/MODULE.bazel": "9233edc5e1f2ee276a60de3eaa47ac4132302ef9643238f23128fea53ea12858", + "https://bcr.bazel.build/modules/protobuf/30.1/MODULE.bazel": "293a47b398800e1efeed6e325f2809c5fab6c692a80384c507afd0ffca3b1bcf", + "https://bcr.bazel.build/modules/protobuf/30.1/source.json": "688ec8aa4fc080a36b48d7b5c22dd3190de2efe07e82f54ccabd2f5e5a59b27e", + "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e", + "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/MODULE.bazel": "e6f4c20442eaa7c90d7190d8dc539d0ab422f95c65a57cc59562170c58ae3d34", + "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/source.json": "6900fdc8a9e95866b8c0d4ad4aba4d4236317b5c1cd04c502df3f0d33afed680", + "https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206", + "https://bcr.bazel.build/modules/re2/2024-07-02/MODULE.bazel": "0eadc4395959969297cbcf31a249ff457f2f1d456228c67719480205aa306daa", + "https://bcr.bazel.build/modules/re2/2024-07-02/source.json": "547d0111a9d4f362db32196fef805abbf3676e8d6afbe44d395d87816c1130ca", + "https://bcr.bazel.build/modules/rules_android/0.1.1/MODULE.bazel": "48809ab0091b07ad0182defb787c4c5328bd3a278938415c00a7b69b50c4d3a8", + "https://bcr.bazel.build/modules/rules_android/0.1.1/source.json": "e6986b41626ee10bdc864937ffb6d6bf275bb5b9c65120e6137d56e6331f089e", + "https://bcr.bazel.build/modules/rules_apple/3.13.0/MODULE.bazel": "b4559a2c6281ca3165275bb36c1f0ac74666632adc5bdb680e366de7ce845f43", + "https://bcr.bazel.build/modules/rules_apple/3.13.0/source.json": "fe31c678e2256daa91a802664b578c1de71dc43a49a7ccc16db001378f312cd3", + "https://bcr.bazel.build/modules/rules_buf/0.1.1/MODULE.bazel": "6189aec18a4f7caff599ad41b851ab7645d4f1e114aa6431acf9b0666eb92162", + "https://bcr.bazel.build/modules/rules_buf/0.1.1/source.json": "021363d254f7438f3f10725355969c974bb2c67e0c28667782ade31a9cdb747f", "https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647", + "https://bcr.bazel.build/modules/rules_cc/0.0.10/MODULE.bazel": "ec1705118f7eaedd6e118508d3d26deba2a4e76476ada7e0e3965211be012002", + "https://bcr.bazel.build/modules/rules_cc/0.0.13/MODULE.bazel": "0e8529ed7b323dad0775ff924d2ae5af7640b23553dfcd4d34344c7e7a867191", + "https://bcr.bazel.build/modules/rules_cc/0.0.14/MODULE.bazel": "5e343a3aac88b8d7af3b1b6d2093b55c347b8eefc2e7d1442f7a02dc8fea48ac", + "https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc", + "https://bcr.bazel.build/modules/rules_cc/0.0.16/MODULE.bazel": "7661303b8fc1b4d7f532e54e9d6565771fea666fbdf839e0a86affcd02defe87", + "https://bcr.bazel.build/modules/rules_cc/0.0.17/MODULE.bazel": "2ae1d8f4238ec67d7185d8861cb0a2cdf4bc608697c331b95bf990e69b62e64a", + "https://bcr.bazel.build/modules/rules_cc/0.0.17/source.json": "4db99b3f55c90ab28d14552aa0632533e3e8e5e9aea0f5c24ac0014282c2a7c5", "https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c", "https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f", "https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e", "https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5", - "https://bcr.bazel.build/modules/rules_cc/0.0.9/source.json": "1f1ba6fea244b616de4a554a0f4983c91a9301640c8fe0dd1d410254115c8430", + "https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6", + "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8", + "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/source.json": "c8b1e2c717646f1702290959a3302a178fb639d987ab61d548105019f11e527e", + "https://bcr.bazel.build/modules/rules_go/0.33.0/MODULE.bazel": "a2b11b64cd24bf94f57454f53288a5dacfe6cb86453eee7761b7637728c1910c", + "https://bcr.bazel.build/modules/rules_go/0.38.1/MODULE.bazel": "fb8e73dd3b6fc4ff9d260ceacd830114891d49904f5bda1c16bc147bcc254f71", + "https://bcr.bazel.build/modules/rules_go/0.39.1/MODULE.bazel": "d34fb2a249403a5f4339c754f1e63dc9e5ad70b47c5e97faee1441fc6636cd61", + "https://bcr.bazel.build/modules/rules_go/0.39.1/source.json": "f21e042154010ae2c944ab230d572b17d71cdb27c5255806d61df6ccaed4354c", "https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74", "https://bcr.bazel.build/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86", + "https://bcr.bazel.build/modules/rules_java/6.0.0/MODULE.bazel": "8a43b7df601a7ec1af61d79345c17b31ea1fedc6711fd4abfd013ea612978e39", + "https://bcr.bazel.build/modules/rules_java/6.4.0/MODULE.bazel": "e986a9fe25aeaa84ac17ca093ef13a4637f6107375f64667a15999f77db6c8f6", + "https://bcr.bazel.build/modules/rules_java/6.5.2/MODULE.bazel": "1d440d262d0e08453fa0c4d8f699ba81609ed0e9a9a0f02cd10b3e7942e61e31", + "https://bcr.bazel.build/modules/rules_java/7.10.0/MODULE.bazel": "530c3beb3067e870561739f1144329a21c851ff771cd752a49e06e3dc9c2e71a", + "https://bcr.bazel.build/modules/rules_java/7.12.2/MODULE.bazel": "579c505165ee757a4280ef83cda0150eea193eed3bef50b1004ba88b99da6de6", + "https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab", + "https://bcr.bazel.build/modules/rules_java/7.3.2/MODULE.bazel": "50dece891cfdf1741ea230d001aa9c14398062f2b7c066470accace78e412bc2", "https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe", - "https://bcr.bazel.build/modules/rules_java/7.6.1/source.json": "8f3f3076554e1558e8e468b2232991c510ecbcbed9e6f8c06ac31c93bcf38362", + "https://bcr.bazel.build/modules/rules_java/8.3.2/MODULE.bazel": "7336d5511ad5af0b8615fdc7477535a2e4e723a357b6713af439fe8cf0195017", + "https://bcr.bazel.build/modules/rules_java/8.5.1/MODULE.bazel": "d8a9e38cc5228881f7055a6079f6f7821a073df3744d441978e7a43e20226939", + "https://bcr.bazel.build/modules/rules_java/8.6.1/MODULE.bazel": "f4808e2ab5b0197f094cabce9f4b006a27766beb6a9975931da07099560ca9c2", + "https://bcr.bazel.build/modules/rules_java/8.6.1/source.json": "f18d9ad3c4c54945bf422ad584fa6c5ca5b3116ff55a5b1bc77e5c1210be5960", "https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7", "https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909", - "https://bcr.bazel.build/modules/rules_jvm_external/5.1/source.json": "5abb45cc9beb27b77aec6a65a11855ef2b55d95dfdc358e9f312b78ae0ba32d5", + "https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036", + "https://bcr.bazel.build/modules/rules_jvm_external/5.3/MODULE.bazel": "bf93870767689637164657731849fb887ad086739bd5d360d90007a581d5527d", + "https://bcr.bazel.build/modules/rules_jvm_external/6.1/MODULE.bazel": "75b5fec090dbd46cf9b7d8ea08cf84a0472d92ba3585b476f44c326eda8059c4", + "https://bcr.bazel.build/modules/rules_jvm_external/6.3/MODULE.bazel": "c998e060b85f71e00de5ec552019347c8bca255062c990ac02d051bb80a38df0", + "https://bcr.bazel.build/modules/rules_jvm_external/6.3/source.json": "6f5f5a5a4419ae4e37c35a5bb0a6ae657ed40b7abc5a5189111b47fcebe43197", + "https://bcr.bazel.build/modules/rules_kotlin/1.9.0/MODULE.bazel": "ef85697305025e5a61f395d4eaede272a5393cee479ace6686dba707de804d59", + "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/MODULE.bazel": "d269a01a18ee74d0335450b10f62c9ed81f2321d7958a2934e44272fe82dcef3", + "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/source.json": "2faa4794364282db7c06600b7e5e34867a564ae91bda7cae7c29c64e9466b7d5", "https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0", "https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d", - "https://bcr.bazel.build/modules/rules_license/0.0.7/source.json": "355cc5737a0f294e560d52b1b7a6492d4fff2caf0bef1a315df5a298fca2d34a", + "https://bcr.bazel.build/modules/rules_license/0.0.8/MODULE.bazel": "5669c6fe49b5134dbf534db681ad3d67a2d49cfc197e4a95f1ca2fd7f3aebe96", + "https://bcr.bazel.build/modules/rules_license/1.0.0/MODULE.bazel": "a7fda60eefdf3d8c827262ba499957e4df06f659330bbe6cdbdb975b768bb65c", + "https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb", + "https://bcr.bazel.build/modules/rules_nodejs/5.8.2/MODULE.bazel": "6bc03c8f37f69401b888023bf511cb6ee4781433b0cb56236b2e55a21e3a026a", + "https://bcr.bazel.build/modules/rules_nodejs/5.8.2/source.json": "6e82cf5753d835ea18308200bc79b9c2e782efe2e2a4edc004a9162ca93382ca", "https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc", - "https://bcr.bazel.build/modules/rules_pkg/0.7.0/source.json": "c2557066e0c0342223ba592510ad3d812d4963b9024831f7f66fd0584dd8c66c", + "https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff", + "https://bcr.bazel.build/modules/rules_pkg/1.0.1/source.json": "bd82e5d7b9ce2d31e380dd9f50c111d678c3bdaca190cb76b0e1c71b05e1ba8a", "https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06", "https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7", - "https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/source.json": "d57902c052424dfda0e71646cb12668d39c4620ee0544294d9d941e7d12bc3a9", + "https://bcr.bazel.build/modules/rules_proto/6.0.0-rc1/MODULE.bazel": "1e5b502e2e1a9e825eef74476a5a1ee524a92297085015a052510b09a1a09483", + "https://bcr.bazel.build/modules/rules_proto/6.0.2/MODULE.bazel": "ce916b775a62b90b61888052a416ccdda405212b6aaeb39522f7dc53431a5e73", + "https://bcr.bazel.build/modules/rules_proto/7.0.2/MODULE.bazel": "bf81793bd6d2ad89a37a40693e56c61b0ee30f7a7fdbaf3eabbf5f39de47dea2", + "https://bcr.bazel.build/modules/rules_proto/7.0.2/source.json": "1e5e7260ae32ef4f2b52fd1d0de8d03b606a44c91b694d2f1afb1d3b28a48ce1", "https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f", - "https://bcr.bazel.build/modules/rules_python/0.22.1/MODULE.bazel": "26114f0c0b5e93018c0c066d6673f1a2c3737c7e90af95eff30cfee38d0bbac7", - "https://bcr.bazel.build/modules/rules_python/0.22.1/source.json": "57226905e783bae7c37c2dd662be078728e48fa28ee4324a7eabcafb5a43d014", + "https://bcr.bazel.build/modules/rules_python/0.23.1/MODULE.bazel": "49ffccf0511cb8414de28321f5fcf2a31312b47c40cc21577144b7447f2bf300", + "https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382", + "https://bcr.bazel.build/modules/rules_python/0.28.0/MODULE.bazel": "cba2573d870babc976664a912539b320cbaa7114cd3e8f053c720171cde331ed", + "https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58", + "https://bcr.bazel.build/modules/rules_python/0.33.2/MODULE.bazel": "3e036c4ad8d804a4dad897d333d8dce200d943df4827cb849840055be8d2e937", "https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c", + "https://bcr.bazel.build/modules/rules_python/0.40.0/MODULE.bazel": "9d1a3cd88ed7d8e39583d9ffe56ae8a244f67783ae89b60caafc9f5cf318ada7", + "https://bcr.bazel.build/modules/rules_python/1.0.0/MODULE.bazel": "898a3d999c22caa585eb062b600f88654bf92efb204fa346fb55f6f8edffca43", + "https://bcr.bazel.build/modules/rules_python/1.0.0/source.json": "b0162a65c6312e45e7912e39abd1a7f8856c2c7e41ecc9b6dc688a6f6400a917", + "https://bcr.bazel.build/modules/rules_rust/0.51.0/MODULE.bazel": "2b6d1617ac8503bfdcc0e4520c20539d4bba3a691100bee01afe193ceb0310f9", + "https://bcr.bazel.build/modules/rules_rust/0.51.0/source.json": "79a530199d9826a93b31d05b7d9b39dc753a80f88856d3ca5376f665a82cc5e6", + "https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c", + "https://bcr.bazel.build/modules/rules_shell/0.2.0/source.json": "7f27af3c28037d9701487c4744b5448d26537cc66cdef0d8df7ae85411f8de95", + "https://bcr.bazel.build/modules/rules_swift/1.16.0/MODULE.bazel": "4a09f199545a60d09895e8281362b1ff3bb08bbde69c6fc87aff5b92fcc916ca", + "https://bcr.bazel.build/modules/rules_swift/2.1.1/MODULE.bazel": "494900a80f944fc7aa61500c2073d9729dff0b764f0e89b824eb746959bc1046", + "https://bcr.bazel.build/modules/rules_swift/2.1.1/source.json": "40fc69dfaac64deddbb75bd99cdac55f4427d9ca0afbe408576a65428427a186", + "https://bcr.bazel.build/modules/stardoc/0.5.0/MODULE.bazel": "f9f1f46ba8d9c3362648eea571c6f9100680efc44913618811b58cc9c02cd678", "https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8", "https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c", - "https://bcr.bazel.build/modules/stardoc/0.5.3/source.json": "cd53fe968dc8cd98197c052db3db6d82562960c87b61e7a90ee96f8e4e0dda97", + "https://bcr.bazel.build/modules/stardoc/0.5.4/MODULE.bazel": "6569966df04610b8520957cb8e97cf2e9faac2c0309657c537ab51c16c18a2a4", + "https://bcr.bazel.build/modules/stardoc/0.5.6/MODULE.bazel": "c43dabc564990eeab55e25ed61c07a1aadafe9ece96a4efabb3f8bf9063b71ef", + "https://bcr.bazel.build/modules/stardoc/0.7.0/MODULE.bazel": "05e3d6d30c099b6770e97da986c53bd31844d7f13d41412480ea265ac9e8079c", + "https://bcr.bazel.build/modules/stardoc/0.7.1/MODULE.bazel": "3548faea4ee5dda5580f9af150e79d0f6aea934fc60c1cc50f4efdd9420759e7", + "https://bcr.bazel.build/modules/stardoc/0.7.2/MODULE.bazel": "fc152419aa2ea0f51c29583fab1e8c99ddefd5b3778421845606ee628629e0e5", + "https://bcr.bazel.build/modules/stardoc/0.7.2/source.json": "58b029e5e901d6802967754adf0a9056747e8176f017cfe3607c0851f4d42216", + "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.1/MODULE.bazel": "5e463fbfba7b1701d957555ed45097d7f984211330106ccd1352c6e0af0dcf91", + "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.1/source.json": "32bd87e5f4d7acc57c5b2ff7c325ae3061d5e242c0c4c214ae87e0f1c13e54cb", "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43", "https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0", "https://bcr.bazel.build/modules/zlib/1.2.12/MODULE.bazel": "3b1a8834ada2a883674be8cbd36ede1b6ec481477ada359cd2d3ddc562340b27", - "https://bcr.bazel.build/modules/zlib/1.3/MODULE.bazel": "6a9c02f19a24dcedb05572b2381446e27c272cd383aed11d41d99da9e3167a72", - "https://bcr.bazel.build/modules/zlib/1.3/source.json": "b6b43d0737af846022636e6e255fd4a96fee0d34f08f3830e6e0bac51465c37c" + "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/MODULE.bazel": "af322bc08976524477c79d1e45e241b6efbeb918c497e8840b8ab116802dda79", + "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/MODULE.bazel": "eec517b5bbe5492629466e11dae908d043364302283de25581e3eb944326c4ca", + "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/source.json": "22bc55c47af97246cfc093d0acf683a7869377de362b5d1c552c2c2e16b7a806", + "https://bcr.bazel.build/modules/zlib/1.3.1/MODULE.bazel": "751c9940dcfe869f5f7274e1295422a34623555916eb98c174c1e945594bf198" }, "selectedYankedVersions": {}, "moduleExtensions": { - "@@apple_support~//crosstool:setup.bzl%apple_cc_configure_extension": { + "@@apple_support+//crosstool:setup.bzl%apple_cc_configure_extension": { "general": { - "bzlTransitiveDigest": "PjIds3feoYE8SGbbIq2SFTZy3zmxeO2tQevJZNDo7iY=", - "usagesDigest": "aLmqbvowmHkkBPve05yyDNGN7oh7QE9kBADr3QIZTZs=", + "bzlTransitiveDigest": "okb7JAyJ9zeL+SDmtbWT0XBLq8WRoLJ0zWAG783RLVI=", + "usagesDigest": "xv9z2c7OWE3Yp+Azbwv1ImqlF3yAZhfTG5FR1K+/isk=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, "envVariables": {}, "generatedRepoSpecs": { + "local_config_apple_cc_toolchains": { + "repoRuleId": "@@apple_support+//crosstool:setup.bzl%_apple_cc_autoconf_toolchains", + "attributes": {} + }, "local_config_apple_cc": { - "bzlFile": "@@apple_support~//crosstool:setup.bzl", - "ruleClassName": "_apple_cc_autoconf", + "repoRuleId": "@@apple_support+//crosstool:setup.bzl%_apple_cc_autoconf", "attributes": {} + } + }, + "recordedRepoMappingEntries": [ + [ + "apple_support+", + "bazel_tools", + "bazel_tools" + ], + [ + "bazel_tools", + "rules_cc", + "rules_cc+" + ] + ] + } + }, + "@@aspect_bazel_lib+//lib:extensions.bzl%toolchains": { + "general": { + "bzlTransitiveDigest": "TGnRoh+5JjQRL6rkWCQneJpM89XjhPyydRXWIn0HmDw=", + "usagesDigest": "HyCD/AMcHKcynL86oRSbi4rhw9cjPb8yfXrC363gBKE=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "copy_directory_darwin_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo", + "attributes": { + "platform": "darwin_amd64" + } }, - "local_config_apple_cc_toolchains": { - "bzlFile": "@@apple_support~//crosstool:setup.bzl", - "ruleClassName": "_apple_cc_autoconf_toolchains", + "copy_directory_darwin_arm64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo", + "attributes": { + "platform": "darwin_arm64" + } + }, + "copy_directory_freebsd_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo", + "attributes": { + "platform": "freebsd_amd64" + } + }, + "copy_directory_linux_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo", + "attributes": { + "platform": "linux_amd64" + } + }, + "copy_directory_linux_arm64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo", + "attributes": { + "platform": "linux_arm64" + } + }, + "copy_directory_windows_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo", + "attributes": { + "platform": "windows_amd64" + } + }, + "copy_directory_toolchains": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_toolchains_repo", + "attributes": { + "user_repository_name": "copy_directory" + } + }, + "copy_to_directory_darwin_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo", + "attributes": { + "platform": "darwin_amd64" + } + }, + "copy_to_directory_darwin_arm64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo", + "attributes": { + "platform": "darwin_arm64" + } + }, + "copy_to_directory_freebsd_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo", + "attributes": { + "platform": "freebsd_amd64" + } + }, + "copy_to_directory_linux_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo", + "attributes": { + "platform": "linux_amd64" + } + }, + "copy_to_directory_linux_arm64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo", + "attributes": { + "platform": "linux_arm64" + } + }, + "copy_to_directory_windows_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo", + "attributes": { + "platform": "windows_amd64" + } + }, + "copy_to_directory_toolchains": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_toolchains_repo", + "attributes": { + "user_repository_name": "copy_to_directory" + } + }, + "jq_darwin_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_platform_repo", + "attributes": { + "platform": "darwin_amd64", + "version": "1.6" + } + }, + "jq_darwin_arm64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_platform_repo", + "attributes": { + "platform": "darwin_arm64", + "version": "1.6" + } + }, + "jq_linux_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_platform_repo", + "attributes": { + "platform": "linux_amd64", + "version": "1.6" + } + }, + "jq_windows_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_platform_repo", + "attributes": { + "platform": "windows_amd64", + "version": "1.6" + } + }, + "jq": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_host_alias_repo", "attributes": {} + }, + "jq_toolchains": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_toolchains_repo", + "attributes": { + "user_repository_name": "jq" + } + }, + "yq_darwin_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo", + "attributes": { + "platform": "darwin_amd64", + "version": "4.25.2" + } + }, + "yq_darwin_arm64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo", + "attributes": { + "platform": "darwin_arm64", + "version": "4.25.2" + } + }, + "yq_linux_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo", + "attributes": { + "platform": "linux_amd64", + "version": "4.25.2" + } + }, + "yq_linux_arm64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo", + "attributes": { + "platform": "linux_arm64", + "version": "4.25.2" + } + }, + "yq_linux_s390x": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo", + "attributes": { + "platform": "linux_s390x", + "version": "4.25.2" + } + }, + "yq_linux_ppc64le": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo", + "attributes": { + "platform": "linux_ppc64le", + "version": "4.25.2" + } + }, + "yq_windows_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo", + "attributes": { + "platform": "windows_amd64", + "version": "4.25.2" + } + }, + "yq": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_host_alias_repo", + "attributes": {} + }, + "yq_toolchains": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_toolchains_repo", + "attributes": { + "user_repository_name": "yq" + } + }, + "coreutils_darwin_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo", + "attributes": { + "platform": "darwin_amd64", + "version": "0.0.16" + } + }, + "coreutils_darwin_arm64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo", + "attributes": { + "platform": "darwin_arm64", + "version": "0.0.16" + } + }, + "coreutils_linux_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo", + "attributes": { + "platform": "linux_amd64", + "version": "0.0.16" + } + }, + "coreutils_linux_arm64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo", + "attributes": { + "platform": "linux_arm64", + "version": "0.0.16" + } + }, + "coreutils_windows_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo", + "attributes": { + "platform": "windows_amd64", + "version": "0.0.16" + } + }, + "coreutils_toolchains": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_toolchains_repo", + "attributes": { + "user_repository_name": "coreutils" + } + }, + "expand_template_darwin_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo", + "attributes": { + "platform": "darwin_amd64" + } + }, + "expand_template_darwin_arm64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo", + "attributes": { + "platform": "darwin_arm64" + } + }, + "expand_template_freebsd_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo", + "attributes": { + "platform": "freebsd_amd64" + } + }, + "expand_template_linux_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo", + "attributes": { + "platform": "linux_amd64" + } + }, + "expand_template_linux_arm64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo", + "attributes": { + "platform": "linux_arm64" + } + }, + "expand_template_windows_amd64": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo", + "attributes": { + "platform": "windows_amd64" + } + }, + "expand_template_toolchains": { + "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_toolchains_repo", + "attributes": { + "user_repository_name": "expand_template" + } } }, "recordedRepoMappingEntries": [ [ - "apple_support~", + "aspect_bazel_lib+", + "aspect_bazel_lib", + "aspect_bazel_lib+" + ], + [ + "aspect_bazel_lib+", + "bazel_skylib", + "bazel_skylib+" + ], + [ + "aspect_bazel_lib+", "bazel_tools", "bazel_tools" ] @@ -104,19 +521,3246 @@ "@@platforms//host:extension.bzl%host_platform": { "general": { "bzlTransitiveDigest": "xelQcPZH8+tmuOHVjL9vDxMnnQNMlwj0SlvgoqBkm4U=", - "usagesDigest": "meSzxn3DUCcYEhq4HQwExWkWtU4EjriRBQLsZN+Q0SU=", + "usagesDigest": "SeQiIN/f8/Qt9vYQk7qcXp4I4wJeEC0RnQDiaaJ4tb8=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, "envVariables": {}, "generatedRepoSpecs": { "host_platform": { - "bzlFile": "@@platforms//host:extension.bzl", - "ruleClassName": "host_platform_repo", + "repoRuleId": "@@platforms//host:extension.bzl%host_platform_repo", "attributes": {} } }, "recordedRepoMappingEntries": [] } + }, + "@@rules_buf+//buf:extensions.bzl%ext": { + "general": { + "bzlTransitiveDigest": "3jGepUu1j86kWsTP3Fgogw/XfktHd4UIQt8zj494n/Y=", + "usagesDigest": "RTc2BMQ2b0wGU8CRvN3EoPz34m3LMe+K/oSkFkN83+M=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "rules_buf_toolchains": { + "repoRuleId": "@@rules_buf+//buf/internal:toolchain.bzl%buf_download_releases", + "attributes": { + "version": "v1.27.0" + } + } + }, + "recordedRepoMappingEntries": [ + [ + "rules_buf+", + "bazel_tools", + "bazel_tools" + ] + ] + } + }, + "@@rules_go+//go:extensions.bzl%go_sdk": { + "general": { + "bzlTransitiveDigest": "GI0gnOeyAURBWF+T+482mWnxAoSjspZNDIVvAHGR7Yk=", + "usagesDigest": "G0DymwAVABR+Olml5OAfLhVRqUVCU372GHdSQxQ1PJw=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "go_default_sdk": { + "repoRuleId": "@@rules_go+//go/private:sdk.bzl%go_download_sdk_rule", + "attributes": { + "goos": "", + "goarch": "", + "sdks": {}, + "urls": [ + "https://dl.google.com/go/{}" + ], + "version": "1.19.8" + } + }, + "go_toolchains": { + "repoRuleId": "@@rules_go+//go/private:sdk.bzl%go_multiple_toolchains", + "attributes": { + "prefixes": [ + "_0000_go_default_sdk_" + ], + "geese": [ + "" + ], + "goarchs": [ + "" + ], + "sdk_repos": [ + "go_default_sdk" + ], + "sdk_types": [ + "remote" + ], + "sdk_versions": [ + "1.19.8" + ] + } + } + }, + "recordedRepoMappingEntries": [ + [ + "rules_go+", + "bazel_tools", + "bazel_tools" + ] + ] + } + }, + "@@rules_java+//java:rules_java_deps.bzl%compatibility_proxy": { + "general": { + "bzlTransitiveDigest": "84xJEZ1jnXXwo8BXMprvBm++rRt4jsTu9liBxz0ivps=", + "usagesDigest": "jTQDdLDxsS43zuRmg1faAjIEPWdLAbDAowI1pInQSoo=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "compatibility_proxy": { + "repoRuleId": "@@rules_java+//java:rules_java_deps.bzl%_compatibility_proxy_repo_rule", + "attributes": {} + } + }, + "recordedRepoMappingEntries": [ + [ + "rules_java+", + "bazel_tools", + "bazel_tools" + ] + ] + } + }, + "@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": { + "general": { + "bzlTransitiveDigest": "sFhcgPbDQehmbD1EOXzX4H1q/CD5df8zwG4kp4jbvr8=", + "usagesDigest": "QI2z8ZUR+mqtbwsf2fLqYdJAkPOHdOV+tF2yVAUgRzw=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "com_github_jetbrains_kotlin_git": { + "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_compiler_git_repository", + "attributes": { + "urls": [ + "https://github.com/JetBrains/kotlin/releases/download/v1.9.23/kotlin-compiler-1.9.23.zip" + ], + "sha256": "93137d3aab9afa9b27cb06a824c2324195c6b6f6179d8a8653f440f5bd58be88" + } + }, + "com_github_jetbrains_kotlin": { + "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_capabilities_repository", + "attributes": { + "git_repository_name": "com_github_jetbrains_kotlin_git", + "compiler_version": "1.9.23" + } + }, + "com_github_google_ksp": { + "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:ksp.bzl%ksp_compiler_plugin_repository", + "attributes": { + "urls": [ + "https://github.com/google/ksp/releases/download/1.9.23-1.0.20/artifacts.zip" + ], + "sha256": "ee0618755913ef7fd6511288a232e8fad24838b9af6ea73972a76e81053c8c2d", + "strip_version": "1.9.23-1.0.20" + } + }, + "com_github_pinterest_ktlint": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file", + "attributes": { + "sha256": "01b2e0ef893383a50dbeb13970fe7fa3be36ca3e83259e01649945b09d736985", + "urls": [ + "https://github.com/pinterest/ktlint/releases/download/1.3.0/ktlint" + ], + "executable": true + } + }, + "rules_android": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "sha256": "cd06d15dd8bb59926e4d65f9003bfc20f9da4b2519985c27e190cddc8b7a7806", + "strip_prefix": "rules_android-0.1.1", + "urls": [ + "https://github.com/bazelbuild/rules_android/archive/v0.1.1.zip" + ] + } + } + }, + "recordedRepoMappingEntries": [ + [ + "rules_kotlin+", + "bazel_tools", + "bazel_tools" + ] + ] + } + }, + "@@rules_nodejs+//nodejs:extensions.bzl%node": { + "general": { + "bzlTransitiveDigest": "btnelILPo3ngQN9vWtsQMclvJZPf3X2vcGTjmW7Owy8=", + "usagesDigest": "CtwJeycIo1YVyKAUrO/7bkpB6yqctQd8XUnRtqUbwRI=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "nodejs_linux_amd64": { + "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%node_repositories", + "attributes": { + "platform": "linux_amd64", + "node_version": "16.19.0" + } + }, + "nodejs_linux_arm64": { + "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%node_repositories", + "attributes": { + "platform": "linux_arm64", + "node_version": "16.19.0" + } + }, + "nodejs_linux_s390x": { + "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%node_repositories", + "attributes": { + "platform": "linux_s390x", + "node_version": "16.19.0" + } + }, + "nodejs_linux_ppc64le": { + "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%node_repositories", + "attributes": { + "platform": "linux_ppc64le", + "node_version": "16.19.0" + } + }, + "nodejs_darwin_amd64": { + "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%node_repositories", + "attributes": { + "platform": "darwin_amd64", + "node_version": "16.19.0" + } + }, + "nodejs_darwin_arm64": { + "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%node_repositories", + "attributes": { + "platform": "darwin_arm64", + "node_version": "16.19.0" + } + }, + "nodejs_windows_amd64": { + "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%node_repositories", + "attributes": { + "platform": "windows_amd64", + "node_version": "16.19.0" + } + }, + "nodejs": { + "repoRuleId": "@@rules_nodejs+//nodejs/private:nodejs_repo_host_os_alias.bzl%nodejs_repo_host_os_alias", + "attributes": { + "user_node_repository_name": "nodejs" + } + }, + "nodejs_host": { + "repoRuleId": "@@rules_nodejs+//nodejs/private:nodejs_repo_host_os_alias.bzl%nodejs_repo_host_os_alias", + "attributes": { + "user_node_repository_name": "nodejs" + } + }, + "nodejs_toolchains": { + "repoRuleId": "@@rules_nodejs+//nodejs/private:toolchains_repo.bzl%toolchains_repo", + "attributes": { + "user_node_repository_name": "nodejs" + } + } + }, + "recordedRepoMappingEntries": [ + [ + "rules_nodejs+", + "bazel_skylib", + "bazel_skylib+" + ], + [ + "rules_nodejs+", + "bazel_tools", + "bazel_tools" + ] + ] + } + }, + "@@rules_rust+//rust:extensions.bzl%rust": { + "general": { + "bzlTransitiveDigest": "tuX+v7uYkywcUGfTOepkhN1oSag3rbqPRCi7hA3BU/Y=", + "usagesDigest": "ozx08ZbgRXTJw0zCaO/xtMUzgGLvwaQkZGnUo6tlyHM=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "rust_analyzer_1.81.0_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_analyzer_toolchain_tools_repository", + "attributes": { + "version": "1.81.0", + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_analyzer_1.81.0": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_analyzer_1.81.0_tools//:rust_analyzer_toolchain", + "toolchain_type": "@rules_rust//rust/rust_analyzer:toolchain_type", + "exec_compatible_with": [], + "target_compatible_with": [] + } + }, + "rust_darwin_aarch64__aarch64-apple-darwin__stable_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "aarch64-apple-darwin", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "aarch64-apple-darwin", + "version": "1.81.0", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_darwin_aarch64__aarch64-apple-darwin__stable": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_darwin_aarch64__aarch64-apple-darwin__stable_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:stable" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:aarch64", + "@platforms//os:osx" + ], + "target_compatible_with": [ + "@platforms//cpu:aarch64", + "@platforms//os:osx" + ] + } + }, + "rust_darwin_aarch64__aarch64-apple-darwin__nightly_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "aarch64-apple-darwin", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "aarch64-apple-darwin", + "version": "nightly/2024-09-05", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_darwin_aarch64__aarch64-apple-darwin__nightly": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_darwin_aarch64__aarch64-apple-darwin__nightly_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:nightly" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:aarch64", + "@platforms//os:osx" + ], + "target_compatible_with": [ + "@platforms//cpu:aarch64", + "@platforms//os:osx" + ] + } + }, + "rust_darwin_aarch64__wasm32-unknown-unknown__stable_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "aarch64-apple-darwin", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "wasm32-unknown-unknown", + "version": "1.81.0", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_darwin_aarch64__wasm32-unknown-unknown__stable": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_darwin_aarch64__wasm32-unknown-unknown__stable_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:stable" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:aarch64", + "@platforms//os:osx" + ], + "target_compatible_with": [ + "@platforms//cpu:wasm32", + "@platforms//os:none" + ] + } + }, + "rust_darwin_aarch64__wasm32-unknown-unknown__nightly_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "aarch64-apple-darwin", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "wasm32-unknown-unknown", + "version": "nightly/2024-09-05", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_darwin_aarch64__wasm32-unknown-unknown__nightly": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_darwin_aarch64__wasm32-unknown-unknown__nightly_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:nightly" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:aarch64", + "@platforms//os:osx" + ], + "target_compatible_with": [ + "@platforms//cpu:wasm32", + "@platforms//os:none" + ] + } + }, + "rust_darwin_aarch64__wasm32-wasi__stable_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "aarch64-apple-darwin", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "wasm32-wasi", + "version": "1.81.0", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_darwin_aarch64__wasm32-wasi__stable": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_darwin_aarch64__wasm32-wasi__stable_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:stable" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:aarch64", + "@platforms//os:osx" + ], + "target_compatible_with": [ + "@platforms//cpu:wasm32", + "@platforms//os:wasi" + ] + } + }, + "rust_darwin_aarch64__wasm32-wasi__nightly_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "aarch64-apple-darwin", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "wasm32-wasi", + "version": "nightly/2024-09-05", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_darwin_aarch64__wasm32-wasi__nightly": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_darwin_aarch64__wasm32-wasi__nightly_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:nightly" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:aarch64", + "@platforms//os:osx" + ], + "target_compatible_with": [ + "@platforms//cpu:wasm32", + "@platforms//os:wasi" + ] + } + }, + "rust_darwin_aarch64": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_set_repository", + "attributes": { + "toolchains": [ + "@rust_darwin_aarch64__aarch64-apple-darwin__stable//:toolchain", + "@rust_darwin_aarch64__aarch64-apple-darwin__nightly//:toolchain", + "@rust_darwin_aarch64__wasm32-unknown-unknown__stable//:toolchain", + "@rust_darwin_aarch64__wasm32-unknown-unknown__nightly//:toolchain", + "@rust_darwin_aarch64__wasm32-wasi__stable//:toolchain", + "@rust_darwin_aarch64__wasm32-wasi__nightly//:toolchain" + ] + } + }, + "rustfmt_nightly-2024-09-05__aarch64-apple-darwin_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rustfmt_toolchain_tools_repository", + "attributes": { + "version": "nightly/2024-09-05", + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": {}, + "exec_triple": "aarch64-apple-darwin" + } + }, + "rustfmt_nightly-2024-09-05__aarch64-apple-darwin": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rustfmt_nightly-2024-09-05__aarch64-apple-darwin_tools//:rustfmt_toolchain", + "toolchain_type": "@rules_rust//rust/rustfmt:toolchain_type", + "target_settings": [], + "exec_compatible_with": [ + "@platforms//cpu:aarch64", + "@platforms//os:osx" + ], + "target_compatible_with": [] + } + }, + "rust_windows_aarch64__aarch64-pc-windows-msvc__stable_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "aarch64-pc-windows-msvc", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "aarch64-pc-windows-msvc", + "version": "1.81.0", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_windows_aarch64__aarch64-pc-windows-msvc__stable": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_windows_aarch64__aarch64-pc-windows-msvc__stable_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:stable" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:aarch64", + "@platforms//os:windows" + ], + "target_compatible_with": [ + "@platforms//cpu:aarch64", + "@platforms//os:windows" + ] + } + }, + "rust_windows_aarch64__aarch64-pc-windows-msvc__nightly_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "aarch64-pc-windows-msvc", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "aarch64-pc-windows-msvc", + "version": "nightly/2024-09-05", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_windows_aarch64__aarch64-pc-windows-msvc__nightly": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_windows_aarch64__aarch64-pc-windows-msvc__nightly_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:nightly" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:aarch64", + "@platforms//os:windows" + ], + "target_compatible_with": [ + "@platforms//cpu:aarch64", + "@platforms//os:windows" + ] + } + }, + "rust_windows_aarch64__wasm32-unknown-unknown__stable_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "aarch64-pc-windows-msvc", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "wasm32-unknown-unknown", + "version": "1.81.0", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_windows_aarch64__wasm32-unknown-unknown__stable": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_windows_aarch64__wasm32-unknown-unknown__stable_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:stable" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:aarch64", + "@platforms//os:windows" + ], + "target_compatible_with": [ + "@platforms//cpu:wasm32", + "@platforms//os:none" + ] + } + }, + "rust_windows_aarch64__wasm32-unknown-unknown__nightly_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "aarch64-pc-windows-msvc", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "wasm32-unknown-unknown", + "version": "nightly/2024-09-05", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_windows_aarch64__wasm32-unknown-unknown__nightly": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_windows_aarch64__wasm32-unknown-unknown__nightly_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:nightly" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:aarch64", + "@platforms//os:windows" + ], + "target_compatible_with": [ + "@platforms//cpu:wasm32", + "@platforms//os:none" + ] + } + }, + "rust_windows_aarch64__wasm32-wasi__stable_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "aarch64-pc-windows-msvc", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "wasm32-wasi", + "version": "1.81.0", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_windows_aarch64__wasm32-wasi__stable": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_windows_aarch64__wasm32-wasi__stable_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:stable" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:aarch64", + "@platforms//os:windows" + ], + "target_compatible_with": [ + "@platforms//cpu:wasm32", + "@platforms//os:wasi" + ] + } + }, + "rust_windows_aarch64__wasm32-wasi__nightly_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "aarch64-pc-windows-msvc", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "wasm32-wasi", + "version": "nightly/2024-09-05", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_windows_aarch64__wasm32-wasi__nightly": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_windows_aarch64__wasm32-wasi__nightly_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:nightly" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:aarch64", + "@platforms//os:windows" + ], + "target_compatible_with": [ + "@platforms//cpu:wasm32", + "@platforms//os:wasi" + ] + } + }, + "rust_windows_aarch64": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_set_repository", + "attributes": { + "toolchains": [ + "@rust_windows_aarch64__aarch64-pc-windows-msvc__stable//:toolchain", + "@rust_windows_aarch64__aarch64-pc-windows-msvc__nightly//:toolchain", + "@rust_windows_aarch64__wasm32-unknown-unknown__stable//:toolchain", + "@rust_windows_aarch64__wasm32-unknown-unknown__nightly//:toolchain", + "@rust_windows_aarch64__wasm32-wasi__stable//:toolchain", + "@rust_windows_aarch64__wasm32-wasi__nightly//:toolchain" + ] + } + }, + "rustfmt_nightly-2024-09-05__aarch64-pc-windows-msvc_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rustfmt_toolchain_tools_repository", + "attributes": { + "version": "nightly/2024-09-05", + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": {}, + "exec_triple": "aarch64-pc-windows-msvc" + } + }, + "rustfmt_nightly-2024-09-05__aarch64-pc-windows-msvc": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rustfmt_nightly-2024-09-05__aarch64-pc-windows-msvc_tools//:rustfmt_toolchain", + "toolchain_type": "@rules_rust//rust/rustfmt:toolchain_type", + "target_settings": [], + "exec_compatible_with": [ + "@platforms//cpu:aarch64", + "@platforms//os:windows" + ], + "target_compatible_with": [] + } + }, + "rust_linux_aarch64__aarch64-unknown-linux-gnu__stable_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "aarch64-unknown-linux-gnu", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "aarch64-unknown-linux-gnu", + "version": "1.81.0", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_linux_aarch64__aarch64-unknown-linux-gnu__stable": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_linux_aarch64__aarch64-unknown-linux-gnu__stable_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:stable" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:aarch64", + "@platforms//os:linux" + ], + "target_compatible_with": [ + "@platforms//cpu:aarch64", + "@platforms//os:linux" + ] + } + }, + "rust_linux_aarch64__aarch64-unknown-linux-gnu__nightly_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "aarch64-unknown-linux-gnu", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "aarch64-unknown-linux-gnu", + "version": "nightly/2024-09-05", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_linux_aarch64__aarch64-unknown-linux-gnu__nightly": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_linux_aarch64__aarch64-unknown-linux-gnu__nightly_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:nightly" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:aarch64", + "@platforms//os:linux" + ], + "target_compatible_with": [ + "@platforms//cpu:aarch64", + "@platforms//os:linux" + ] + } + }, + "rust_linux_aarch64__wasm32-unknown-unknown__stable_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "aarch64-unknown-linux-gnu", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "wasm32-unknown-unknown", + "version": "1.81.0", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_linux_aarch64__wasm32-unknown-unknown__stable": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_linux_aarch64__wasm32-unknown-unknown__stable_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:stable" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:aarch64", + "@platforms//os:linux" + ], + "target_compatible_with": [ + "@platforms//cpu:wasm32", + "@platforms//os:none" + ] + } + }, + "rust_linux_aarch64__wasm32-unknown-unknown__nightly_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "aarch64-unknown-linux-gnu", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "wasm32-unknown-unknown", + "version": "nightly/2024-09-05", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_linux_aarch64__wasm32-unknown-unknown__nightly": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_linux_aarch64__wasm32-unknown-unknown__nightly_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:nightly" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:aarch64", + "@platforms//os:linux" + ], + "target_compatible_with": [ + "@platforms//cpu:wasm32", + "@platforms//os:none" + ] + } + }, + "rust_linux_aarch64__wasm32-wasi__stable_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "aarch64-unknown-linux-gnu", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "wasm32-wasi", + "version": "1.81.0", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_linux_aarch64__wasm32-wasi__stable": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_linux_aarch64__wasm32-wasi__stable_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:stable" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:aarch64", + "@platforms//os:linux" + ], + "target_compatible_with": [ + "@platforms//cpu:wasm32", + "@platforms//os:wasi" + ] + } + }, + "rust_linux_aarch64__wasm32-wasi__nightly_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "aarch64-unknown-linux-gnu", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "wasm32-wasi", + "version": "nightly/2024-09-05", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_linux_aarch64__wasm32-wasi__nightly": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_linux_aarch64__wasm32-wasi__nightly_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:nightly" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:aarch64", + "@platforms//os:linux" + ], + "target_compatible_with": [ + "@platforms//cpu:wasm32", + "@platforms//os:wasi" + ] + } + }, + "rust_linux_aarch64": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_set_repository", + "attributes": { + "toolchains": [ + "@rust_linux_aarch64__aarch64-unknown-linux-gnu__stable//:toolchain", + "@rust_linux_aarch64__aarch64-unknown-linux-gnu__nightly//:toolchain", + "@rust_linux_aarch64__wasm32-unknown-unknown__stable//:toolchain", + "@rust_linux_aarch64__wasm32-unknown-unknown__nightly//:toolchain", + "@rust_linux_aarch64__wasm32-wasi__stable//:toolchain", + "@rust_linux_aarch64__wasm32-wasi__nightly//:toolchain" + ] + } + }, + "rustfmt_nightly-2024-09-05__aarch64-unknown-linux-gnu_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rustfmt_toolchain_tools_repository", + "attributes": { + "version": "nightly/2024-09-05", + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": {}, + "exec_triple": "aarch64-unknown-linux-gnu" + } + }, + "rustfmt_nightly-2024-09-05__aarch64-unknown-linux-gnu": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rustfmt_nightly-2024-09-05__aarch64-unknown-linux-gnu_tools//:rustfmt_toolchain", + "toolchain_type": "@rules_rust//rust/rustfmt:toolchain_type", + "target_settings": [], + "exec_compatible_with": [ + "@platforms//cpu:aarch64", + "@platforms//os:linux" + ], + "target_compatible_with": [] + } + }, + "rust_linux_s390x__s390x-unknown-linux-gnu__stable_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "s390x-unknown-linux-gnu", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "s390x-unknown-linux-gnu", + "version": "1.81.0", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_linux_s390x__s390x-unknown-linux-gnu__stable": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_linux_s390x__s390x-unknown-linux-gnu__stable_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:stable" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:s390x", + "@platforms//os:linux" + ], + "target_compatible_with": [ + "@platforms//cpu:s390x", + "@platforms//os:linux" + ] + } + }, + "rust_linux_s390x__s390x-unknown-linux-gnu__nightly_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "s390x-unknown-linux-gnu", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "s390x-unknown-linux-gnu", + "version": "nightly/2024-09-05", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_linux_s390x__s390x-unknown-linux-gnu__nightly": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_linux_s390x__s390x-unknown-linux-gnu__nightly_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:nightly" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:s390x", + "@platforms//os:linux" + ], + "target_compatible_with": [ + "@platforms//cpu:s390x", + "@platforms//os:linux" + ] + } + }, + "rust_linux_s390x__wasm32-unknown-unknown__stable_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "s390x-unknown-linux-gnu", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "wasm32-unknown-unknown", + "version": "1.81.0", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_linux_s390x__wasm32-unknown-unknown__stable": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_linux_s390x__wasm32-unknown-unknown__stable_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:stable" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:s390x", + "@platforms//os:linux" + ], + "target_compatible_with": [ + "@platforms//cpu:wasm32", + "@platforms//os:none" + ] + } + }, + "rust_linux_s390x__wasm32-unknown-unknown__nightly_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "s390x-unknown-linux-gnu", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "wasm32-unknown-unknown", + "version": "nightly/2024-09-05", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_linux_s390x__wasm32-unknown-unknown__nightly": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_linux_s390x__wasm32-unknown-unknown__nightly_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:nightly" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:s390x", + "@platforms//os:linux" + ], + "target_compatible_with": [ + "@platforms//cpu:wasm32", + "@platforms//os:none" + ] + } + }, + "rust_linux_s390x__wasm32-wasi__stable_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "s390x-unknown-linux-gnu", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "wasm32-wasi", + "version": "1.81.0", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_linux_s390x__wasm32-wasi__stable": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_linux_s390x__wasm32-wasi__stable_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:stable" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:s390x", + "@platforms//os:linux" + ], + "target_compatible_with": [ + "@platforms//cpu:wasm32", + "@platforms//os:wasi" + ] + } + }, + "rust_linux_s390x__wasm32-wasi__nightly_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "s390x-unknown-linux-gnu", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "wasm32-wasi", + "version": "nightly/2024-09-05", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_linux_s390x__wasm32-wasi__nightly": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_linux_s390x__wasm32-wasi__nightly_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:nightly" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:s390x", + "@platforms//os:linux" + ], + "target_compatible_with": [ + "@platforms//cpu:wasm32", + "@platforms//os:wasi" + ] + } + }, + "rust_linux_s390x": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_set_repository", + "attributes": { + "toolchains": [ + "@rust_linux_s390x__s390x-unknown-linux-gnu__stable//:toolchain", + "@rust_linux_s390x__s390x-unknown-linux-gnu__nightly//:toolchain", + "@rust_linux_s390x__wasm32-unknown-unknown__stable//:toolchain", + "@rust_linux_s390x__wasm32-unknown-unknown__nightly//:toolchain", + "@rust_linux_s390x__wasm32-wasi__stable//:toolchain", + "@rust_linux_s390x__wasm32-wasi__nightly//:toolchain" + ] + } + }, + "rustfmt_nightly-2024-09-05__s390x-unknown-linux-gnu_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rustfmt_toolchain_tools_repository", + "attributes": { + "version": "nightly/2024-09-05", + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": {}, + "exec_triple": "s390x-unknown-linux-gnu" + } + }, + "rustfmt_nightly-2024-09-05__s390x-unknown-linux-gnu": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rustfmt_nightly-2024-09-05__s390x-unknown-linux-gnu_tools//:rustfmt_toolchain", + "toolchain_type": "@rules_rust//rust/rustfmt:toolchain_type", + "target_settings": [], + "exec_compatible_with": [ + "@platforms//cpu:s390x", + "@platforms//os:linux" + ], + "target_compatible_with": [] + } + }, + "rust_darwin_x86_64__x86_64-apple-darwin__stable_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "x86_64-apple-darwin", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "x86_64-apple-darwin", + "version": "1.81.0", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_darwin_x86_64__x86_64-apple-darwin__stable": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_darwin_x86_64__x86_64-apple-darwin__stable_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:stable" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:osx" + ], + "target_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:osx" + ] + } + }, + "rust_darwin_x86_64__x86_64-apple-darwin__nightly_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "x86_64-apple-darwin", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "x86_64-apple-darwin", + "version": "nightly/2024-09-05", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_darwin_x86_64__x86_64-apple-darwin__nightly": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_darwin_x86_64__x86_64-apple-darwin__nightly_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:nightly" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:osx" + ], + "target_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:osx" + ] + } + }, + "rust_darwin_x86_64__wasm32-unknown-unknown__stable_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "x86_64-apple-darwin", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "wasm32-unknown-unknown", + "version": "1.81.0", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_darwin_x86_64__wasm32-unknown-unknown__stable": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_darwin_x86_64__wasm32-unknown-unknown__stable_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:stable" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:osx" + ], + "target_compatible_with": [ + "@platforms//cpu:wasm32", + "@platforms//os:none" + ] + } + }, + "rust_darwin_x86_64__wasm32-unknown-unknown__nightly_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "x86_64-apple-darwin", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "wasm32-unknown-unknown", + "version": "nightly/2024-09-05", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_darwin_x86_64__wasm32-unknown-unknown__nightly": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_darwin_x86_64__wasm32-unknown-unknown__nightly_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:nightly" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:osx" + ], + "target_compatible_with": [ + "@platforms//cpu:wasm32", + "@platforms//os:none" + ] + } + }, + "rust_darwin_x86_64__wasm32-wasi__stable_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "x86_64-apple-darwin", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "wasm32-wasi", + "version": "1.81.0", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_darwin_x86_64__wasm32-wasi__stable": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_darwin_x86_64__wasm32-wasi__stable_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:stable" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:osx" + ], + "target_compatible_with": [ + "@platforms//cpu:wasm32", + "@platforms//os:wasi" + ] + } + }, + "rust_darwin_x86_64__wasm32-wasi__nightly_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "x86_64-apple-darwin", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "wasm32-wasi", + "version": "nightly/2024-09-05", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_darwin_x86_64__wasm32-wasi__nightly": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_darwin_x86_64__wasm32-wasi__nightly_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:nightly" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:osx" + ], + "target_compatible_with": [ + "@platforms//cpu:wasm32", + "@platforms//os:wasi" + ] + } + }, + "rust_darwin_x86_64": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_set_repository", + "attributes": { + "toolchains": [ + "@rust_darwin_x86_64__x86_64-apple-darwin__stable//:toolchain", + "@rust_darwin_x86_64__x86_64-apple-darwin__nightly//:toolchain", + "@rust_darwin_x86_64__wasm32-unknown-unknown__stable//:toolchain", + "@rust_darwin_x86_64__wasm32-unknown-unknown__nightly//:toolchain", + "@rust_darwin_x86_64__wasm32-wasi__stable//:toolchain", + "@rust_darwin_x86_64__wasm32-wasi__nightly//:toolchain" + ] + } + }, + "rustfmt_nightly-2024-09-05__x86_64-apple-darwin_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rustfmt_toolchain_tools_repository", + "attributes": { + "version": "nightly/2024-09-05", + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": {}, + "exec_triple": "x86_64-apple-darwin" + } + }, + "rustfmt_nightly-2024-09-05__x86_64-apple-darwin": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rustfmt_nightly-2024-09-05__x86_64-apple-darwin_tools//:rustfmt_toolchain", + "toolchain_type": "@rules_rust//rust/rustfmt:toolchain_type", + "target_settings": [], + "exec_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:osx" + ], + "target_compatible_with": [] + } + }, + "rust_windows_x86_64__x86_64-pc-windows-msvc__stable_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "x86_64-pc-windows-msvc", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "x86_64-pc-windows-msvc", + "version": "1.81.0", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_windows_x86_64__x86_64-pc-windows-msvc__stable": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_windows_x86_64__x86_64-pc-windows-msvc__stable_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:stable" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:windows" + ], + "target_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:windows" + ] + } + }, + "rust_windows_x86_64__x86_64-pc-windows-msvc__nightly_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "x86_64-pc-windows-msvc", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "x86_64-pc-windows-msvc", + "version": "nightly/2024-09-05", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_windows_x86_64__x86_64-pc-windows-msvc__nightly": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_windows_x86_64__x86_64-pc-windows-msvc__nightly_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:nightly" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:windows" + ], + "target_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:windows" + ] + } + }, + "rust_windows_x86_64__wasm32-unknown-unknown__stable_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "x86_64-pc-windows-msvc", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "wasm32-unknown-unknown", + "version": "1.81.0", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_windows_x86_64__wasm32-unknown-unknown__stable": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_windows_x86_64__wasm32-unknown-unknown__stable_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:stable" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:windows" + ], + "target_compatible_with": [ + "@platforms//cpu:wasm32", + "@platforms//os:none" + ] + } + }, + "rust_windows_x86_64__wasm32-unknown-unknown__nightly_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "x86_64-pc-windows-msvc", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "wasm32-unknown-unknown", + "version": "nightly/2024-09-05", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_windows_x86_64__wasm32-unknown-unknown__nightly": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_windows_x86_64__wasm32-unknown-unknown__nightly_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:nightly" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:windows" + ], + "target_compatible_with": [ + "@platforms//cpu:wasm32", + "@platforms//os:none" + ] + } + }, + "rust_windows_x86_64__wasm32-wasi__stable_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "x86_64-pc-windows-msvc", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "wasm32-wasi", + "version": "1.81.0", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_windows_x86_64__wasm32-wasi__stable": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_windows_x86_64__wasm32-wasi__stable_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:stable" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:windows" + ], + "target_compatible_with": [ + "@platforms//cpu:wasm32", + "@platforms//os:wasi" + ] + } + }, + "rust_windows_x86_64__wasm32-wasi__nightly_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "x86_64-pc-windows-msvc", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "wasm32-wasi", + "version": "nightly/2024-09-05", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_windows_x86_64__wasm32-wasi__nightly": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_windows_x86_64__wasm32-wasi__nightly_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:nightly" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:windows" + ], + "target_compatible_with": [ + "@platforms//cpu:wasm32", + "@platforms//os:wasi" + ] + } + }, + "rust_windows_x86_64": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_set_repository", + "attributes": { + "toolchains": [ + "@rust_windows_x86_64__x86_64-pc-windows-msvc__stable//:toolchain", + "@rust_windows_x86_64__x86_64-pc-windows-msvc__nightly//:toolchain", + "@rust_windows_x86_64__wasm32-unknown-unknown__stable//:toolchain", + "@rust_windows_x86_64__wasm32-unknown-unknown__nightly//:toolchain", + "@rust_windows_x86_64__wasm32-wasi__stable//:toolchain", + "@rust_windows_x86_64__wasm32-wasi__nightly//:toolchain" + ] + } + }, + "rustfmt_nightly-2024-09-05__x86_64-pc-windows-msvc_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rustfmt_toolchain_tools_repository", + "attributes": { + "version": "nightly/2024-09-05", + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": {}, + "exec_triple": "x86_64-pc-windows-msvc" + } + }, + "rustfmt_nightly-2024-09-05__x86_64-pc-windows-msvc": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rustfmt_nightly-2024-09-05__x86_64-pc-windows-msvc_tools//:rustfmt_toolchain", + "toolchain_type": "@rules_rust//rust/rustfmt:toolchain_type", + "target_settings": [], + "exec_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:windows" + ], + "target_compatible_with": [] + } + }, + "rust_freebsd_x86_64__x86_64-unknown-freebsd__stable_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "x86_64-unknown-freebsd", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "x86_64-unknown-freebsd", + "version": "1.81.0", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_freebsd_x86_64__x86_64-unknown-freebsd__stable": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_freebsd_x86_64__x86_64-unknown-freebsd__stable_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:stable" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:freebsd" + ], + "target_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:freebsd" + ] + } + }, + "rust_freebsd_x86_64__x86_64-unknown-freebsd__nightly_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "x86_64-unknown-freebsd", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "x86_64-unknown-freebsd", + "version": "nightly/2024-09-05", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_freebsd_x86_64__x86_64-unknown-freebsd__nightly": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_freebsd_x86_64__x86_64-unknown-freebsd__nightly_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:nightly" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:freebsd" + ], + "target_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:freebsd" + ] + } + }, + "rust_freebsd_x86_64__wasm32-unknown-unknown__stable_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "x86_64-unknown-freebsd", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "wasm32-unknown-unknown", + "version": "1.81.0", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_freebsd_x86_64__wasm32-unknown-unknown__stable": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_freebsd_x86_64__wasm32-unknown-unknown__stable_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:stable" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:freebsd" + ], + "target_compatible_with": [ + "@platforms//cpu:wasm32", + "@platforms//os:none" + ] + } + }, + "rust_freebsd_x86_64__wasm32-unknown-unknown__nightly_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "x86_64-unknown-freebsd", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "wasm32-unknown-unknown", + "version": "nightly/2024-09-05", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_freebsd_x86_64__wasm32-unknown-unknown__nightly": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_freebsd_x86_64__wasm32-unknown-unknown__nightly_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:nightly" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:freebsd" + ], + "target_compatible_with": [ + "@platforms//cpu:wasm32", + "@platforms//os:none" + ] + } + }, + "rust_freebsd_x86_64__wasm32-wasi__stable_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "x86_64-unknown-freebsd", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "wasm32-wasi", + "version": "1.81.0", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_freebsd_x86_64__wasm32-wasi__stable": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_freebsd_x86_64__wasm32-wasi__stable_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:stable" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:freebsd" + ], + "target_compatible_with": [ + "@platforms//cpu:wasm32", + "@platforms//os:wasi" + ] + } + }, + "rust_freebsd_x86_64__wasm32-wasi__nightly_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "x86_64-unknown-freebsd", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "wasm32-wasi", + "version": "nightly/2024-09-05", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_freebsd_x86_64__wasm32-wasi__nightly": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_freebsd_x86_64__wasm32-wasi__nightly_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:nightly" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:freebsd" + ], + "target_compatible_with": [ + "@platforms//cpu:wasm32", + "@platforms//os:wasi" + ] + } + }, + "rust_freebsd_x86_64": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_set_repository", + "attributes": { + "toolchains": [ + "@rust_freebsd_x86_64__x86_64-unknown-freebsd__stable//:toolchain", + "@rust_freebsd_x86_64__x86_64-unknown-freebsd__nightly//:toolchain", + "@rust_freebsd_x86_64__wasm32-unknown-unknown__stable//:toolchain", + "@rust_freebsd_x86_64__wasm32-unknown-unknown__nightly//:toolchain", + "@rust_freebsd_x86_64__wasm32-wasi__stable//:toolchain", + "@rust_freebsd_x86_64__wasm32-wasi__nightly//:toolchain" + ] + } + }, + "rustfmt_nightly-2024-09-05__x86_64-unknown-freebsd_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rustfmt_toolchain_tools_repository", + "attributes": { + "version": "nightly/2024-09-05", + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": {}, + "exec_triple": "x86_64-unknown-freebsd" + } + }, + "rustfmt_nightly-2024-09-05__x86_64-unknown-freebsd": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rustfmt_nightly-2024-09-05__x86_64-unknown-freebsd_tools//:rustfmt_toolchain", + "toolchain_type": "@rules_rust//rust/rustfmt:toolchain_type", + "target_settings": [], + "exec_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:freebsd" + ], + "target_compatible_with": [] + } + }, + "rust_linux_x86_64__x86_64-unknown-linux-gnu__stable_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "x86_64-unknown-linux-gnu", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "x86_64-unknown-linux-gnu", + "version": "1.81.0", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_linux_x86_64__x86_64-unknown-linux-gnu__stable": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_linux_x86_64__x86_64-unknown-linux-gnu__stable_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:stable" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:linux" + ], + "target_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:linux" + ] + } + }, + "rust_linux_x86_64__x86_64-unknown-linux-gnu__nightly_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "x86_64-unknown-linux-gnu", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "x86_64-unknown-linux-gnu", + "version": "nightly/2024-09-05", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_linux_x86_64__x86_64-unknown-linux-gnu__nightly": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_linux_x86_64__x86_64-unknown-linux-gnu__nightly_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:nightly" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:linux" + ], + "target_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:linux" + ] + } + }, + "rust_linux_x86_64__wasm32-unknown-unknown__stable_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "x86_64-unknown-linux-gnu", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "wasm32-unknown-unknown", + "version": "1.81.0", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_linux_x86_64__wasm32-unknown-unknown__stable": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_linux_x86_64__wasm32-unknown-unknown__stable_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:stable" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:linux" + ], + "target_compatible_with": [ + "@platforms//cpu:wasm32", + "@platforms//os:none" + ] + } + }, + "rust_linux_x86_64__wasm32-unknown-unknown__nightly_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "x86_64-unknown-linux-gnu", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "wasm32-unknown-unknown", + "version": "nightly/2024-09-05", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_linux_x86_64__wasm32-unknown-unknown__nightly": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_linux_x86_64__wasm32-unknown-unknown__nightly_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:nightly" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:linux" + ], + "target_compatible_with": [ + "@platforms//cpu:wasm32", + "@platforms//os:none" + ] + } + }, + "rust_linux_x86_64__wasm32-wasi__stable_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "x86_64-unknown-linux-gnu", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "wasm32-wasi", + "version": "1.81.0", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_linux_x86_64__wasm32-wasi__stable": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_linux_x86_64__wasm32-wasi__stable_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:stable" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:linux" + ], + "target_compatible_with": [ + "@platforms//cpu:wasm32", + "@platforms//os:wasi" + ] + } + }, + "rust_linux_x86_64__wasm32-wasi__nightly_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", + "attributes": { + "exec_triple": "x86_64-unknown-linux-gnu", + "allocator_library": "@rules_rust//ffi/cc/allocator_library", + "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", + "target_triple": "wasm32-wasi", + "version": "nightly/2024-09-05", + "rustfmt_version": "nightly/2024-09-05", + "edition": "2021", + "dev_components": false, + "extra_rustc_flags": [], + "extra_exec_rustc_flags": [], + "opt_level": {}, + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": [] + } + }, + "rust_linux_x86_64__wasm32-wasi__nightly": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rust_linux_x86_64__wasm32-wasi__nightly_tools//:rust_toolchain", + "target_settings": [ + "@rules_rust//rust/toolchain/channel:nightly" + ], + "toolchain_type": "@rules_rust//rust:toolchain", + "exec_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:linux" + ], + "target_compatible_with": [ + "@platforms//cpu:wasm32", + "@platforms//os:wasi" + ] + } + }, + "rust_linux_x86_64": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_set_repository", + "attributes": { + "toolchains": [ + "@rust_linux_x86_64__x86_64-unknown-linux-gnu__stable//:toolchain", + "@rust_linux_x86_64__x86_64-unknown-linux-gnu__nightly//:toolchain", + "@rust_linux_x86_64__wasm32-unknown-unknown__stable//:toolchain", + "@rust_linux_x86_64__wasm32-unknown-unknown__nightly//:toolchain", + "@rust_linux_x86_64__wasm32-wasi__stable//:toolchain", + "@rust_linux_x86_64__wasm32-wasi__nightly//:toolchain" + ] + } + }, + "rustfmt_nightly-2024-09-05__x86_64-unknown-linux-gnu_tools": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rustfmt_toolchain_tools_repository", + "attributes": { + "version": "nightly/2024-09-05", + "sha256s": {}, + "urls": [ + "https://static.rust-lang.org/dist/{}.tar.xz" + ], + "auth": {}, + "netrc": "", + "auth_patterns": {}, + "exec_triple": "x86_64-unknown-linux-gnu" + } + }, + "rustfmt_nightly-2024-09-05__x86_64-unknown-linux-gnu": { + "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", + "attributes": { + "toolchain": "@rustfmt_nightly-2024-09-05__x86_64-unknown-linux-gnu_tools//:rustfmt_toolchain", + "toolchain_type": "@rules_rust//rust/rustfmt:toolchain_type", + "target_settings": [], + "exec_compatible_with": [ + "@platforms//cpu:x86_64", + "@platforms//os:linux" + ], + "target_compatible_with": [] + } + }, + "rust_toolchains": { + "repoRuleId": "@@rules_rust+//rust/private:repository_utils.bzl%toolchain_repository_hub", + "attributes": { + "toolchain_names": [ + "rust_analyzer_1.81.0", + "rust_darwin_aarch64__aarch64-apple-darwin__stable", + "rust_darwin_aarch64__aarch64-apple-darwin__nightly", + "rust_darwin_aarch64__wasm32-unknown-unknown__stable", + "rust_darwin_aarch64__wasm32-unknown-unknown__nightly", + "rust_darwin_aarch64__wasm32-wasi__stable", + "rust_darwin_aarch64__wasm32-wasi__nightly", + "rustfmt_nightly-2024-09-05__aarch64-apple-darwin", + "rust_windows_aarch64__aarch64-pc-windows-msvc__stable", + "rust_windows_aarch64__aarch64-pc-windows-msvc__nightly", + "rust_windows_aarch64__wasm32-unknown-unknown__stable", + "rust_windows_aarch64__wasm32-unknown-unknown__nightly", + "rust_windows_aarch64__wasm32-wasi__stable", + "rust_windows_aarch64__wasm32-wasi__nightly", + "rustfmt_nightly-2024-09-05__aarch64-pc-windows-msvc", + "rust_linux_aarch64__aarch64-unknown-linux-gnu__stable", + "rust_linux_aarch64__aarch64-unknown-linux-gnu__nightly", + "rust_linux_aarch64__wasm32-unknown-unknown__stable", + "rust_linux_aarch64__wasm32-unknown-unknown__nightly", + "rust_linux_aarch64__wasm32-wasi__stable", + "rust_linux_aarch64__wasm32-wasi__nightly", + "rustfmt_nightly-2024-09-05__aarch64-unknown-linux-gnu", + "rust_linux_s390x__s390x-unknown-linux-gnu__stable", + "rust_linux_s390x__s390x-unknown-linux-gnu__nightly", + "rust_linux_s390x__wasm32-unknown-unknown__stable", + "rust_linux_s390x__wasm32-unknown-unknown__nightly", + "rust_linux_s390x__wasm32-wasi__stable", + "rust_linux_s390x__wasm32-wasi__nightly", + "rustfmt_nightly-2024-09-05__s390x-unknown-linux-gnu", + "rust_darwin_x86_64__x86_64-apple-darwin__stable", + "rust_darwin_x86_64__x86_64-apple-darwin__nightly", + "rust_darwin_x86_64__wasm32-unknown-unknown__stable", + "rust_darwin_x86_64__wasm32-unknown-unknown__nightly", + "rust_darwin_x86_64__wasm32-wasi__stable", + "rust_darwin_x86_64__wasm32-wasi__nightly", + "rustfmt_nightly-2024-09-05__x86_64-apple-darwin", + "rust_windows_x86_64__x86_64-pc-windows-msvc__stable", + "rust_windows_x86_64__x86_64-pc-windows-msvc__nightly", + "rust_windows_x86_64__wasm32-unknown-unknown__stable", + "rust_windows_x86_64__wasm32-unknown-unknown__nightly", + "rust_windows_x86_64__wasm32-wasi__stable", + "rust_windows_x86_64__wasm32-wasi__nightly", + "rustfmt_nightly-2024-09-05__x86_64-pc-windows-msvc", + "rust_freebsd_x86_64__x86_64-unknown-freebsd__stable", + "rust_freebsd_x86_64__x86_64-unknown-freebsd__nightly", + "rust_freebsd_x86_64__wasm32-unknown-unknown__stable", + "rust_freebsd_x86_64__wasm32-unknown-unknown__nightly", + "rust_freebsd_x86_64__wasm32-wasi__stable", + "rust_freebsd_x86_64__wasm32-wasi__nightly", + "rustfmt_nightly-2024-09-05__x86_64-unknown-freebsd", + "rust_linux_x86_64__x86_64-unknown-linux-gnu__stable", + "rust_linux_x86_64__x86_64-unknown-linux-gnu__nightly", + "rust_linux_x86_64__wasm32-unknown-unknown__stable", + "rust_linux_x86_64__wasm32-unknown-unknown__nightly", + "rust_linux_x86_64__wasm32-wasi__stable", + "rust_linux_x86_64__wasm32-wasi__nightly", + "rustfmt_nightly-2024-09-05__x86_64-unknown-linux-gnu" + ], + "toolchain_labels": { + "rust_analyzer_1.81.0": "@rust_analyzer_1.81.0_tools//:rust_analyzer_toolchain", + "rust_darwin_aarch64__aarch64-apple-darwin__stable": "@rust_darwin_aarch64__aarch64-apple-darwin__stable_tools//:rust_toolchain", + "rust_darwin_aarch64__aarch64-apple-darwin__nightly": "@rust_darwin_aarch64__aarch64-apple-darwin__nightly_tools//:rust_toolchain", + "rust_darwin_aarch64__wasm32-unknown-unknown__stable": "@rust_darwin_aarch64__wasm32-unknown-unknown__stable_tools//:rust_toolchain", + "rust_darwin_aarch64__wasm32-unknown-unknown__nightly": "@rust_darwin_aarch64__wasm32-unknown-unknown__nightly_tools//:rust_toolchain", + "rust_darwin_aarch64__wasm32-wasi__stable": "@rust_darwin_aarch64__wasm32-wasi__stable_tools//:rust_toolchain", + "rust_darwin_aarch64__wasm32-wasi__nightly": "@rust_darwin_aarch64__wasm32-wasi__nightly_tools//:rust_toolchain", + "rustfmt_nightly-2024-09-05__aarch64-apple-darwin": "@rustfmt_nightly-2024-09-05__aarch64-apple-darwin_tools//:rustfmt_toolchain", + "rust_windows_aarch64__aarch64-pc-windows-msvc__stable": "@rust_windows_aarch64__aarch64-pc-windows-msvc__stable_tools//:rust_toolchain", + "rust_windows_aarch64__aarch64-pc-windows-msvc__nightly": "@rust_windows_aarch64__aarch64-pc-windows-msvc__nightly_tools//:rust_toolchain", + "rust_windows_aarch64__wasm32-unknown-unknown__stable": "@rust_windows_aarch64__wasm32-unknown-unknown__stable_tools//:rust_toolchain", + "rust_windows_aarch64__wasm32-unknown-unknown__nightly": "@rust_windows_aarch64__wasm32-unknown-unknown__nightly_tools//:rust_toolchain", + "rust_windows_aarch64__wasm32-wasi__stable": "@rust_windows_aarch64__wasm32-wasi__stable_tools//:rust_toolchain", + "rust_windows_aarch64__wasm32-wasi__nightly": "@rust_windows_aarch64__wasm32-wasi__nightly_tools//:rust_toolchain", + "rustfmt_nightly-2024-09-05__aarch64-pc-windows-msvc": "@rustfmt_nightly-2024-09-05__aarch64-pc-windows-msvc_tools//:rustfmt_toolchain", + "rust_linux_aarch64__aarch64-unknown-linux-gnu__stable": "@rust_linux_aarch64__aarch64-unknown-linux-gnu__stable_tools//:rust_toolchain", + "rust_linux_aarch64__aarch64-unknown-linux-gnu__nightly": "@rust_linux_aarch64__aarch64-unknown-linux-gnu__nightly_tools//:rust_toolchain", + "rust_linux_aarch64__wasm32-unknown-unknown__stable": "@rust_linux_aarch64__wasm32-unknown-unknown__stable_tools//:rust_toolchain", + "rust_linux_aarch64__wasm32-unknown-unknown__nightly": "@rust_linux_aarch64__wasm32-unknown-unknown__nightly_tools//:rust_toolchain", + "rust_linux_aarch64__wasm32-wasi__stable": "@rust_linux_aarch64__wasm32-wasi__stable_tools//:rust_toolchain", + "rust_linux_aarch64__wasm32-wasi__nightly": "@rust_linux_aarch64__wasm32-wasi__nightly_tools//:rust_toolchain", + "rustfmt_nightly-2024-09-05__aarch64-unknown-linux-gnu": "@rustfmt_nightly-2024-09-05__aarch64-unknown-linux-gnu_tools//:rustfmt_toolchain", + "rust_linux_s390x__s390x-unknown-linux-gnu__stable": "@rust_linux_s390x__s390x-unknown-linux-gnu__stable_tools//:rust_toolchain", + "rust_linux_s390x__s390x-unknown-linux-gnu__nightly": "@rust_linux_s390x__s390x-unknown-linux-gnu__nightly_tools//:rust_toolchain", + "rust_linux_s390x__wasm32-unknown-unknown__stable": "@rust_linux_s390x__wasm32-unknown-unknown__stable_tools//:rust_toolchain", + "rust_linux_s390x__wasm32-unknown-unknown__nightly": "@rust_linux_s390x__wasm32-unknown-unknown__nightly_tools//:rust_toolchain", + "rust_linux_s390x__wasm32-wasi__stable": "@rust_linux_s390x__wasm32-wasi__stable_tools//:rust_toolchain", + "rust_linux_s390x__wasm32-wasi__nightly": "@rust_linux_s390x__wasm32-wasi__nightly_tools//:rust_toolchain", + "rustfmt_nightly-2024-09-05__s390x-unknown-linux-gnu": "@rustfmt_nightly-2024-09-05__s390x-unknown-linux-gnu_tools//:rustfmt_toolchain", + "rust_darwin_x86_64__x86_64-apple-darwin__stable": "@rust_darwin_x86_64__x86_64-apple-darwin__stable_tools//:rust_toolchain", + "rust_darwin_x86_64__x86_64-apple-darwin__nightly": "@rust_darwin_x86_64__x86_64-apple-darwin__nightly_tools//:rust_toolchain", + "rust_darwin_x86_64__wasm32-unknown-unknown__stable": "@rust_darwin_x86_64__wasm32-unknown-unknown__stable_tools//:rust_toolchain", + "rust_darwin_x86_64__wasm32-unknown-unknown__nightly": "@rust_darwin_x86_64__wasm32-unknown-unknown__nightly_tools//:rust_toolchain", + "rust_darwin_x86_64__wasm32-wasi__stable": "@rust_darwin_x86_64__wasm32-wasi__stable_tools//:rust_toolchain", + "rust_darwin_x86_64__wasm32-wasi__nightly": "@rust_darwin_x86_64__wasm32-wasi__nightly_tools//:rust_toolchain", + "rustfmt_nightly-2024-09-05__x86_64-apple-darwin": "@rustfmt_nightly-2024-09-05__x86_64-apple-darwin_tools//:rustfmt_toolchain", + "rust_windows_x86_64__x86_64-pc-windows-msvc__stable": "@rust_windows_x86_64__x86_64-pc-windows-msvc__stable_tools//:rust_toolchain", + "rust_windows_x86_64__x86_64-pc-windows-msvc__nightly": "@rust_windows_x86_64__x86_64-pc-windows-msvc__nightly_tools//:rust_toolchain", + "rust_windows_x86_64__wasm32-unknown-unknown__stable": "@rust_windows_x86_64__wasm32-unknown-unknown__stable_tools//:rust_toolchain", + "rust_windows_x86_64__wasm32-unknown-unknown__nightly": "@rust_windows_x86_64__wasm32-unknown-unknown__nightly_tools//:rust_toolchain", + "rust_windows_x86_64__wasm32-wasi__stable": "@rust_windows_x86_64__wasm32-wasi__stable_tools//:rust_toolchain", + "rust_windows_x86_64__wasm32-wasi__nightly": "@rust_windows_x86_64__wasm32-wasi__nightly_tools//:rust_toolchain", + "rustfmt_nightly-2024-09-05__x86_64-pc-windows-msvc": "@rustfmt_nightly-2024-09-05__x86_64-pc-windows-msvc_tools//:rustfmt_toolchain", + "rust_freebsd_x86_64__x86_64-unknown-freebsd__stable": "@rust_freebsd_x86_64__x86_64-unknown-freebsd__stable_tools//:rust_toolchain", + "rust_freebsd_x86_64__x86_64-unknown-freebsd__nightly": "@rust_freebsd_x86_64__x86_64-unknown-freebsd__nightly_tools//:rust_toolchain", + "rust_freebsd_x86_64__wasm32-unknown-unknown__stable": "@rust_freebsd_x86_64__wasm32-unknown-unknown__stable_tools//:rust_toolchain", + "rust_freebsd_x86_64__wasm32-unknown-unknown__nightly": "@rust_freebsd_x86_64__wasm32-unknown-unknown__nightly_tools//:rust_toolchain", + "rust_freebsd_x86_64__wasm32-wasi__stable": "@rust_freebsd_x86_64__wasm32-wasi__stable_tools//:rust_toolchain", + "rust_freebsd_x86_64__wasm32-wasi__nightly": "@rust_freebsd_x86_64__wasm32-wasi__nightly_tools//:rust_toolchain", + "rustfmt_nightly-2024-09-05__x86_64-unknown-freebsd": "@rustfmt_nightly-2024-09-05__x86_64-unknown-freebsd_tools//:rustfmt_toolchain", + "rust_linux_x86_64__x86_64-unknown-linux-gnu__stable": "@rust_linux_x86_64__x86_64-unknown-linux-gnu__stable_tools//:rust_toolchain", + "rust_linux_x86_64__x86_64-unknown-linux-gnu__nightly": "@rust_linux_x86_64__x86_64-unknown-linux-gnu__nightly_tools//:rust_toolchain", + "rust_linux_x86_64__wasm32-unknown-unknown__stable": "@rust_linux_x86_64__wasm32-unknown-unknown__stable_tools//:rust_toolchain", + "rust_linux_x86_64__wasm32-unknown-unknown__nightly": "@rust_linux_x86_64__wasm32-unknown-unknown__nightly_tools//:rust_toolchain", + "rust_linux_x86_64__wasm32-wasi__stable": "@rust_linux_x86_64__wasm32-wasi__stable_tools//:rust_toolchain", + "rust_linux_x86_64__wasm32-wasi__nightly": "@rust_linux_x86_64__wasm32-wasi__nightly_tools//:rust_toolchain", + "rustfmt_nightly-2024-09-05__x86_64-unknown-linux-gnu": "@rustfmt_nightly-2024-09-05__x86_64-unknown-linux-gnu_tools//:rustfmt_toolchain" + }, + "toolchain_types": { + "rust_analyzer_1.81.0": "@rules_rust//rust/rust_analyzer:toolchain_type", + "rust_darwin_aarch64__aarch64-apple-darwin__stable": "@rules_rust//rust:toolchain", + "rust_darwin_aarch64__aarch64-apple-darwin__nightly": "@rules_rust//rust:toolchain", + "rust_darwin_aarch64__wasm32-unknown-unknown__stable": "@rules_rust//rust:toolchain", + "rust_darwin_aarch64__wasm32-unknown-unknown__nightly": "@rules_rust//rust:toolchain", + "rust_darwin_aarch64__wasm32-wasi__stable": "@rules_rust//rust:toolchain", + "rust_darwin_aarch64__wasm32-wasi__nightly": "@rules_rust//rust:toolchain", + "rustfmt_nightly-2024-09-05__aarch64-apple-darwin": "@rules_rust//rust/rustfmt:toolchain_type", + "rust_windows_aarch64__aarch64-pc-windows-msvc__stable": "@rules_rust//rust:toolchain", + "rust_windows_aarch64__aarch64-pc-windows-msvc__nightly": "@rules_rust//rust:toolchain", + "rust_windows_aarch64__wasm32-unknown-unknown__stable": "@rules_rust//rust:toolchain", + "rust_windows_aarch64__wasm32-unknown-unknown__nightly": "@rules_rust//rust:toolchain", + "rust_windows_aarch64__wasm32-wasi__stable": "@rules_rust//rust:toolchain", + "rust_windows_aarch64__wasm32-wasi__nightly": "@rules_rust//rust:toolchain", + "rustfmt_nightly-2024-09-05__aarch64-pc-windows-msvc": "@rules_rust//rust/rustfmt:toolchain_type", + "rust_linux_aarch64__aarch64-unknown-linux-gnu__stable": "@rules_rust//rust:toolchain", + "rust_linux_aarch64__aarch64-unknown-linux-gnu__nightly": "@rules_rust//rust:toolchain", + "rust_linux_aarch64__wasm32-unknown-unknown__stable": "@rules_rust//rust:toolchain", + "rust_linux_aarch64__wasm32-unknown-unknown__nightly": "@rules_rust//rust:toolchain", + "rust_linux_aarch64__wasm32-wasi__stable": "@rules_rust//rust:toolchain", + "rust_linux_aarch64__wasm32-wasi__nightly": "@rules_rust//rust:toolchain", + "rustfmt_nightly-2024-09-05__aarch64-unknown-linux-gnu": "@rules_rust//rust/rustfmt:toolchain_type", + "rust_linux_s390x__s390x-unknown-linux-gnu__stable": "@rules_rust//rust:toolchain", + "rust_linux_s390x__s390x-unknown-linux-gnu__nightly": "@rules_rust//rust:toolchain", + "rust_linux_s390x__wasm32-unknown-unknown__stable": "@rules_rust//rust:toolchain", + "rust_linux_s390x__wasm32-unknown-unknown__nightly": "@rules_rust//rust:toolchain", + "rust_linux_s390x__wasm32-wasi__stable": "@rules_rust//rust:toolchain", + "rust_linux_s390x__wasm32-wasi__nightly": "@rules_rust//rust:toolchain", + "rustfmt_nightly-2024-09-05__s390x-unknown-linux-gnu": "@rules_rust//rust/rustfmt:toolchain_type", + "rust_darwin_x86_64__x86_64-apple-darwin__stable": "@rules_rust//rust:toolchain", + "rust_darwin_x86_64__x86_64-apple-darwin__nightly": "@rules_rust//rust:toolchain", + "rust_darwin_x86_64__wasm32-unknown-unknown__stable": "@rules_rust//rust:toolchain", + "rust_darwin_x86_64__wasm32-unknown-unknown__nightly": "@rules_rust//rust:toolchain", + "rust_darwin_x86_64__wasm32-wasi__stable": "@rules_rust//rust:toolchain", + "rust_darwin_x86_64__wasm32-wasi__nightly": "@rules_rust//rust:toolchain", + "rustfmt_nightly-2024-09-05__x86_64-apple-darwin": "@rules_rust//rust/rustfmt:toolchain_type", + "rust_windows_x86_64__x86_64-pc-windows-msvc__stable": "@rules_rust//rust:toolchain", + "rust_windows_x86_64__x86_64-pc-windows-msvc__nightly": "@rules_rust//rust:toolchain", + "rust_windows_x86_64__wasm32-unknown-unknown__stable": "@rules_rust//rust:toolchain", + "rust_windows_x86_64__wasm32-unknown-unknown__nightly": "@rules_rust//rust:toolchain", + "rust_windows_x86_64__wasm32-wasi__stable": "@rules_rust//rust:toolchain", + "rust_windows_x86_64__wasm32-wasi__nightly": "@rules_rust//rust:toolchain", + "rustfmt_nightly-2024-09-05__x86_64-pc-windows-msvc": "@rules_rust//rust/rustfmt:toolchain_type", + "rust_freebsd_x86_64__x86_64-unknown-freebsd__stable": "@rules_rust//rust:toolchain", + "rust_freebsd_x86_64__x86_64-unknown-freebsd__nightly": "@rules_rust//rust:toolchain", + "rust_freebsd_x86_64__wasm32-unknown-unknown__stable": "@rules_rust//rust:toolchain", + "rust_freebsd_x86_64__wasm32-unknown-unknown__nightly": "@rules_rust//rust:toolchain", + "rust_freebsd_x86_64__wasm32-wasi__stable": "@rules_rust//rust:toolchain", + "rust_freebsd_x86_64__wasm32-wasi__nightly": "@rules_rust//rust:toolchain", + "rustfmt_nightly-2024-09-05__x86_64-unknown-freebsd": "@rules_rust//rust/rustfmt:toolchain_type", + "rust_linux_x86_64__x86_64-unknown-linux-gnu__stable": "@rules_rust//rust:toolchain", + "rust_linux_x86_64__x86_64-unknown-linux-gnu__nightly": "@rules_rust//rust:toolchain", + "rust_linux_x86_64__wasm32-unknown-unknown__stable": "@rules_rust//rust:toolchain", + "rust_linux_x86_64__wasm32-unknown-unknown__nightly": "@rules_rust//rust:toolchain", + "rust_linux_x86_64__wasm32-wasi__stable": "@rules_rust//rust:toolchain", + "rust_linux_x86_64__wasm32-wasi__nightly": "@rules_rust//rust:toolchain", + "rustfmt_nightly-2024-09-05__x86_64-unknown-linux-gnu": "@rules_rust//rust/rustfmt:toolchain_type" + }, + "exec_compatible_with": { + "rust_analyzer_1.81.0": [], + "rust_darwin_aarch64__aarch64-apple-darwin__stable": [ + "@platforms//cpu:aarch64", + "@platforms//os:osx" + ], + "rust_darwin_aarch64__aarch64-apple-darwin__nightly": [ + "@platforms//cpu:aarch64", + "@platforms//os:osx" + ], + "rust_darwin_aarch64__wasm32-unknown-unknown__stable": [ + "@platforms//cpu:aarch64", + "@platforms//os:osx" + ], + "rust_darwin_aarch64__wasm32-unknown-unknown__nightly": [ + "@platforms//cpu:aarch64", + "@platforms//os:osx" + ], + "rust_darwin_aarch64__wasm32-wasi__stable": [ + "@platforms//cpu:aarch64", + "@platforms//os:osx" + ], + "rust_darwin_aarch64__wasm32-wasi__nightly": [ + "@platforms//cpu:aarch64", + "@platforms//os:osx" + ], + "rustfmt_nightly-2024-09-05__aarch64-apple-darwin": [ + "@platforms//cpu:aarch64", + "@platforms//os:osx" + ], + "rust_windows_aarch64__aarch64-pc-windows-msvc__stable": [ + "@platforms//cpu:aarch64", + "@platforms//os:windows" + ], + "rust_windows_aarch64__aarch64-pc-windows-msvc__nightly": [ + "@platforms//cpu:aarch64", + "@platforms//os:windows" + ], + "rust_windows_aarch64__wasm32-unknown-unknown__stable": [ + "@platforms//cpu:aarch64", + "@platforms//os:windows" + ], + "rust_windows_aarch64__wasm32-unknown-unknown__nightly": [ + "@platforms//cpu:aarch64", + "@platforms//os:windows" + ], + "rust_windows_aarch64__wasm32-wasi__stable": [ + "@platforms//cpu:aarch64", + "@platforms//os:windows" + ], + "rust_windows_aarch64__wasm32-wasi__nightly": [ + "@platforms//cpu:aarch64", + "@platforms//os:windows" + ], + "rustfmt_nightly-2024-09-05__aarch64-pc-windows-msvc": [ + "@platforms//cpu:aarch64", + "@platforms//os:windows" + ], + "rust_linux_aarch64__aarch64-unknown-linux-gnu__stable": [ + "@platforms//cpu:aarch64", + "@platforms//os:linux" + ], + "rust_linux_aarch64__aarch64-unknown-linux-gnu__nightly": [ + "@platforms//cpu:aarch64", + "@platforms//os:linux" + ], + "rust_linux_aarch64__wasm32-unknown-unknown__stable": [ + "@platforms//cpu:aarch64", + "@platforms//os:linux" + ], + "rust_linux_aarch64__wasm32-unknown-unknown__nightly": [ + "@platforms//cpu:aarch64", + "@platforms//os:linux" + ], + "rust_linux_aarch64__wasm32-wasi__stable": [ + "@platforms//cpu:aarch64", + "@platforms//os:linux" + ], + "rust_linux_aarch64__wasm32-wasi__nightly": [ + "@platforms//cpu:aarch64", + "@platforms//os:linux" + ], + "rustfmt_nightly-2024-09-05__aarch64-unknown-linux-gnu": [ + "@platforms//cpu:aarch64", + "@platforms//os:linux" + ], + "rust_linux_s390x__s390x-unknown-linux-gnu__stable": [ + "@platforms//cpu:s390x", + "@platforms//os:linux" + ], + "rust_linux_s390x__s390x-unknown-linux-gnu__nightly": [ + "@platforms//cpu:s390x", + "@platforms//os:linux" + ], + "rust_linux_s390x__wasm32-unknown-unknown__stable": [ + "@platforms//cpu:s390x", + "@platforms//os:linux" + ], + "rust_linux_s390x__wasm32-unknown-unknown__nightly": [ + "@platforms//cpu:s390x", + "@platforms//os:linux" + ], + "rust_linux_s390x__wasm32-wasi__stable": [ + "@platforms//cpu:s390x", + "@platforms//os:linux" + ], + "rust_linux_s390x__wasm32-wasi__nightly": [ + "@platforms//cpu:s390x", + "@platforms//os:linux" + ], + "rustfmt_nightly-2024-09-05__s390x-unknown-linux-gnu": [ + "@platforms//cpu:s390x", + "@platforms//os:linux" + ], + "rust_darwin_x86_64__x86_64-apple-darwin__stable": [ + "@platforms//cpu:x86_64", + "@platforms//os:osx" + ], + "rust_darwin_x86_64__x86_64-apple-darwin__nightly": [ + "@platforms//cpu:x86_64", + "@platforms//os:osx" + ], + "rust_darwin_x86_64__wasm32-unknown-unknown__stable": [ + "@platforms//cpu:x86_64", + "@platforms//os:osx" + ], + "rust_darwin_x86_64__wasm32-unknown-unknown__nightly": [ + "@platforms//cpu:x86_64", + "@platforms//os:osx" + ], + "rust_darwin_x86_64__wasm32-wasi__stable": [ + "@platforms//cpu:x86_64", + "@platforms//os:osx" + ], + "rust_darwin_x86_64__wasm32-wasi__nightly": [ + "@platforms//cpu:x86_64", + "@platforms//os:osx" + ], + "rustfmt_nightly-2024-09-05__x86_64-apple-darwin": [ + "@platforms//cpu:x86_64", + "@platforms//os:osx" + ], + "rust_windows_x86_64__x86_64-pc-windows-msvc__stable": [ + "@platforms//cpu:x86_64", + "@platforms//os:windows" + ], + "rust_windows_x86_64__x86_64-pc-windows-msvc__nightly": [ + "@platforms//cpu:x86_64", + "@platforms//os:windows" + ], + "rust_windows_x86_64__wasm32-unknown-unknown__stable": [ + "@platforms//cpu:x86_64", + "@platforms//os:windows" + ], + "rust_windows_x86_64__wasm32-unknown-unknown__nightly": [ + "@platforms//cpu:x86_64", + "@platforms//os:windows" + ], + "rust_windows_x86_64__wasm32-wasi__stable": [ + "@platforms//cpu:x86_64", + "@platforms//os:windows" + ], + "rust_windows_x86_64__wasm32-wasi__nightly": [ + "@platforms//cpu:x86_64", + "@platforms//os:windows" + ], + "rustfmt_nightly-2024-09-05__x86_64-pc-windows-msvc": [ + "@platforms//cpu:x86_64", + "@platforms//os:windows" + ], + "rust_freebsd_x86_64__x86_64-unknown-freebsd__stable": [ + "@platforms//cpu:x86_64", + "@platforms//os:freebsd" + ], + "rust_freebsd_x86_64__x86_64-unknown-freebsd__nightly": [ + "@platforms//cpu:x86_64", + "@platforms//os:freebsd" + ], + "rust_freebsd_x86_64__wasm32-unknown-unknown__stable": [ + "@platforms//cpu:x86_64", + "@platforms//os:freebsd" + ], + "rust_freebsd_x86_64__wasm32-unknown-unknown__nightly": [ + "@platforms//cpu:x86_64", + "@platforms//os:freebsd" + ], + "rust_freebsd_x86_64__wasm32-wasi__stable": [ + "@platforms//cpu:x86_64", + "@platforms//os:freebsd" + ], + "rust_freebsd_x86_64__wasm32-wasi__nightly": [ + "@platforms//cpu:x86_64", + "@platforms//os:freebsd" + ], + "rustfmt_nightly-2024-09-05__x86_64-unknown-freebsd": [ + "@platforms//cpu:x86_64", + "@platforms//os:freebsd" + ], + "rust_linux_x86_64__x86_64-unknown-linux-gnu__stable": [ + "@platforms//cpu:x86_64", + "@platforms//os:linux" + ], + "rust_linux_x86_64__x86_64-unknown-linux-gnu__nightly": [ + "@platforms//cpu:x86_64", + "@platforms//os:linux" + ], + "rust_linux_x86_64__wasm32-unknown-unknown__stable": [ + "@platforms//cpu:x86_64", + "@platforms//os:linux" + ], + "rust_linux_x86_64__wasm32-unknown-unknown__nightly": [ + "@platforms//cpu:x86_64", + "@platforms//os:linux" + ], + "rust_linux_x86_64__wasm32-wasi__stable": [ + "@platforms//cpu:x86_64", + "@platforms//os:linux" + ], + "rust_linux_x86_64__wasm32-wasi__nightly": [ + "@platforms//cpu:x86_64", + "@platforms//os:linux" + ], + "rustfmt_nightly-2024-09-05__x86_64-unknown-linux-gnu": [ + "@platforms//cpu:x86_64", + "@platforms//os:linux" + ] + }, + "target_compatible_with": { + "rust_analyzer_1.81.0": [], + "rust_darwin_aarch64__aarch64-apple-darwin__stable": [ + "@platforms//cpu:aarch64", + "@platforms//os:osx" + ], + "rust_darwin_aarch64__aarch64-apple-darwin__nightly": [ + "@platforms//cpu:aarch64", + "@platforms//os:osx" + ], + "rust_darwin_aarch64__wasm32-unknown-unknown__stable": [ + "@platforms//cpu:wasm32", + "@platforms//os:none" + ], + "rust_darwin_aarch64__wasm32-unknown-unknown__nightly": [ + "@platforms//cpu:wasm32", + "@platforms//os:none" + ], + "rust_darwin_aarch64__wasm32-wasi__stable": [ + "@platforms//cpu:wasm32", + "@platforms//os:wasi" + ], + "rust_darwin_aarch64__wasm32-wasi__nightly": [ + "@platforms//cpu:wasm32", + "@platforms//os:wasi" + ], + "rustfmt_nightly-2024-09-05__aarch64-apple-darwin": [], + "rust_windows_aarch64__aarch64-pc-windows-msvc__stable": [ + "@platforms//cpu:aarch64", + "@platforms//os:windows" + ], + "rust_windows_aarch64__aarch64-pc-windows-msvc__nightly": [ + "@platforms//cpu:aarch64", + "@platforms//os:windows" + ], + "rust_windows_aarch64__wasm32-unknown-unknown__stable": [ + "@platforms//cpu:wasm32", + "@platforms//os:none" + ], + "rust_windows_aarch64__wasm32-unknown-unknown__nightly": [ + "@platforms//cpu:wasm32", + "@platforms//os:none" + ], + "rust_windows_aarch64__wasm32-wasi__stable": [ + "@platforms//cpu:wasm32", + "@platforms//os:wasi" + ], + "rust_windows_aarch64__wasm32-wasi__nightly": [ + "@platforms//cpu:wasm32", + "@platforms//os:wasi" + ], + "rustfmt_nightly-2024-09-05__aarch64-pc-windows-msvc": [], + "rust_linux_aarch64__aarch64-unknown-linux-gnu__stable": [ + "@platforms//cpu:aarch64", + "@platforms//os:linux" + ], + "rust_linux_aarch64__aarch64-unknown-linux-gnu__nightly": [ + "@platforms//cpu:aarch64", + "@platforms//os:linux" + ], + "rust_linux_aarch64__wasm32-unknown-unknown__stable": [ + "@platforms//cpu:wasm32", + "@platforms//os:none" + ], + "rust_linux_aarch64__wasm32-unknown-unknown__nightly": [ + "@platforms//cpu:wasm32", + "@platforms//os:none" + ], + "rust_linux_aarch64__wasm32-wasi__stable": [ + "@platforms//cpu:wasm32", + "@platforms//os:wasi" + ], + "rust_linux_aarch64__wasm32-wasi__nightly": [ + "@platforms//cpu:wasm32", + "@platforms//os:wasi" + ], + "rustfmt_nightly-2024-09-05__aarch64-unknown-linux-gnu": [], + "rust_linux_s390x__s390x-unknown-linux-gnu__stable": [ + "@platforms//cpu:s390x", + "@platforms//os:linux" + ], + "rust_linux_s390x__s390x-unknown-linux-gnu__nightly": [ + "@platforms//cpu:s390x", + "@platforms//os:linux" + ], + "rust_linux_s390x__wasm32-unknown-unknown__stable": [ + "@platforms//cpu:wasm32", + "@platforms//os:none" + ], + "rust_linux_s390x__wasm32-unknown-unknown__nightly": [ + "@platforms//cpu:wasm32", + "@platforms//os:none" + ], + "rust_linux_s390x__wasm32-wasi__stable": [ + "@platforms//cpu:wasm32", + "@platforms//os:wasi" + ], + "rust_linux_s390x__wasm32-wasi__nightly": [ + "@platforms//cpu:wasm32", + "@platforms//os:wasi" + ], + "rustfmt_nightly-2024-09-05__s390x-unknown-linux-gnu": [], + "rust_darwin_x86_64__x86_64-apple-darwin__stable": [ + "@platforms//cpu:x86_64", + "@platforms//os:osx" + ], + "rust_darwin_x86_64__x86_64-apple-darwin__nightly": [ + "@platforms//cpu:x86_64", + "@platforms//os:osx" + ], + "rust_darwin_x86_64__wasm32-unknown-unknown__stable": [ + "@platforms//cpu:wasm32", + "@platforms//os:none" + ], + "rust_darwin_x86_64__wasm32-unknown-unknown__nightly": [ + "@platforms//cpu:wasm32", + "@platforms//os:none" + ], + "rust_darwin_x86_64__wasm32-wasi__stable": [ + "@platforms//cpu:wasm32", + "@platforms//os:wasi" + ], + "rust_darwin_x86_64__wasm32-wasi__nightly": [ + "@platforms//cpu:wasm32", + "@platforms//os:wasi" + ], + "rustfmt_nightly-2024-09-05__x86_64-apple-darwin": [], + "rust_windows_x86_64__x86_64-pc-windows-msvc__stable": [ + "@platforms//cpu:x86_64", + "@platforms//os:windows" + ], + "rust_windows_x86_64__x86_64-pc-windows-msvc__nightly": [ + "@platforms//cpu:x86_64", + "@platforms//os:windows" + ], + "rust_windows_x86_64__wasm32-unknown-unknown__stable": [ + "@platforms//cpu:wasm32", + "@platforms//os:none" + ], + "rust_windows_x86_64__wasm32-unknown-unknown__nightly": [ + "@platforms//cpu:wasm32", + "@platforms//os:none" + ], + "rust_windows_x86_64__wasm32-wasi__stable": [ + "@platforms//cpu:wasm32", + "@platforms//os:wasi" + ], + "rust_windows_x86_64__wasm32-wasi__nightly": [ + "@platforms//cpu:wasm32", + "@platforms//os:wasi" + ], + "rustfmt_nightly-2024-09-05__x86_64-pc-windows-msvc": [], + "rust_freebsd_x86_64__x86_64-unknown-freebsd__stable": [ + "@platforms//cpu:x86_64", + "@platforms//os:freebsd" + ], + "rust_freebsd_x86_64__x86_64-unknown-freebsd__nightly": [ + "@platforms//cpu:x86_64", + "@platforms//os:freebsd" + ], + "rust_freebsd_x86_64__wasm32-unknown-unknown__stable": [ + "@platforms//cpu:wasm32", + "@platforms//os:none" + ], + "rust_freebsd_x86_64__wasm32-unknown-unknown__nightly": [ + "@platforms//cpu:wasm32", + "@platforms//os:none" + ], + "rust_freebsd_x86_64__wasm32-wasi__stable": [ + "@platforms//cpu:wasm32", + "@platforms//os:wasi" + ], + "rust_freebsd_x86_64__wasm32-wasi__nightly": [ + "@platforms//cpu:wasm32", + "@platforms//os:wasi" + ], + "rustfmt_nightly-2024-09-05__x86_64-unknown-freebsd": [], + "rust_linux_x86_64__x86_64-unknown-linux-gnu__stable": [ + "@platforms//cpu:x86_64", + "@platforms//os:linux" + ], + "rust_linux_x86_64__x86_64-unknown-linux-gnu__nightly": [ + "@platforms//cpu:x86_64", + "@platforms//os:linux" + ], + "rust_linux_x86_64__wasm32-unknown-unknown__stable": [ + "@platforms//cpu:wasm32", + "@platforms//os:none" + ], + "rust_linux_x86_64__wasm32-unknown-unknown__nightly": [ + "@platforms//cpu:wasm32", + "@platforms//os:none" + ], + "rust_linux_x86_64__wasm32-wasi__stable": [ + "@platforms//cpu:wasm32", + "@platforms//os:wasi" + ], + "rust_linux_x86_64__wasm32-wasi__nightly": [ + "@platforms//cpu:wasm32", + "@platforms//os:wasi" + ], + "rustfmt_nightly-2024-09-05__x86_64-unknown-linux-gnu": [] + } + } + } + }, + "recordedRepoMappingEntries": [ + [ + "bazel_features+", + "bazel_features_globals", + "bazel_features++version_extension+bazel_features_globals" + ], + [ + "bazel_features+", + "bazel_features_version", + "bazel_features++version_extension+bazel_features_version" + ], + [ + "bazel_tools", + "rules_cc", + "rules_cc+" + ], + [ + "rules_cc+", + "bazel_tools", + "bazel_tools" + ], + [ + "rules_rust+", + "bazel_features", + "bazel_features+" + ], + [ + "rules_rust+", + "bazel_skylib", + "bazel_skylib+" + ], + [ + "rules_rust+", + "bazel_tools", + "bazel_tools" + ], + [ + "rules_rust+", + "rules_rust", + "rules_rust+" + ] + ] + } } } } diff --git a/WORKSPACE b/WORKSPACE deleted file mode 100644 index 18e9262..0000000 --- a/WORKSPACE +++ /dev/null @@ -1,30 +0,0 @@ -workspace(name = "com_google_protobuf_javascript") - -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") - -http_archive( - name = "com_google_protobuf", - urls = ["https://github.com/protocolbuffers/protobuf/archive/refs/tags/v27.1.zip"], - sha256 = "9e6dbaefbfc670037e1a25ac4434adea1403821950444ec40fab8b2a9423c2ea", - strip_prefix = "protobuf-27.1", -) - -load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps") -protobuf_deps() - - -# Taken from -# https://github.com/bazelbuild/rules_pkg/blob/main/pkg/deps.bzl. -# -# This is required under bazel 6 according to -# https://github.com/bazelbuild/rules_pkg/issues/872, otherwise we -# will see the same error. -http_archive( - name = "rules_python", - sha256 = "0a8003b044294d7840ac7d9d73eef05d6ceb682d7516781a4ec62eeb34702578", - strip_prefix = "rules_python-0.24.0", - url = "https://github.com/bazelbuild/rules_python/releases/download/0.24.0/rules_python-0.24.0.tar.gz", -) - -load("@rules_pkg//:deps.bzl", "rules_pkg_dependencies") -rules_pkg_dependencies() diff --git a/WORKSPACE.bzlmod b/WORKSPACE.bzlmod deleted file mode 100644 index 7de259e..0000000 --- a/WORKSPACE.bzlmod +++ /dev/null @@ -1,2 +0,0 @@ -# When Bzlmod is enabled, this file replaces the content of the original WORKSPACE and -# makes sure no WORKSPACE prefix or suffix are added when Bzlmod is enabled. diff --git a/generator/BUILD.bazel b/generator/BUILD.bazel index ff3fb8b..b2df875 100644 --- a/generator/BUILD.bazel +++ b/generator/BUILD.bazel @@ -15,8 +15,8 @@ cc_binary( "@com_google_protobuf//src/google/protobuf/io:printer", "@com_google_protobuf//src/google/protobuf/io:tokenizer", "@com_google_protobuf//:protoc_lib", - "@com_google_absl//absl/strings", - "@com_google_absl//absl/strings:str_format", + "@abseil-cpp//absl/strings", + "@abseil-cpp//absl/strings:str_format", ], ) diff --git a/generator/js_generator.cc b/generator/js_generator.cc index 6ca0ad3..f6c3e38 100644 --- a/generator/js_generator.cc +++ b/generator/js_generator.cc @@ -89,7 +89,7 @@ enum BytesMode { BYTES_U8, // Explicitly coerce to Uint8Array where needed. }; -bool IsReserved(const std::string& ident) { +bool IsReserved(absl::string_view ident) { for (int i = 0; i < kNumKeyword; i++) { if (ident == kKeyword[i]) { return true; @@ -98,9 +98,8 @@ bool IsReserved(const std::string& ident) { return false; } -std::string GetSnakeFilename(const std::string& filename) { - std::string snake_name = filename; - return absl::StrReplaceAll(snake_name, {{"/", "_"}}); +std::string GetSnakeFilename(absl::string_view filename) { + return absl::StrReplaceAll(filename, {{"/", "_"}}); } // Given a filename like foo/bar/baz.proto, returns the corresponding JavaScript @@ -135,7 +134,7 @@ std::string GetRootPath(const std::string& from_filename, // Returns the alias we assign to the module of the given .proto filename // when importing. -std::string ModuleAlias(const std::string& filename) { +std::string ModuleAlias(absl::string_view filename) { // This scheme could technically cause problems if a file includes any 2 of: // foo/bar_baz.proto // foo_bar_baz.proto @@ -157,7 +156,7 @@ std::string GetNamespace(const GeneratorOptions& options, if (!options.namespace_prefix.empty()) { return options.namespace_prefix; } else if (!file->package().empty()) { - return "proto." + file->package(); + return absl::StrCat("proto.", file->package()); } else { return "proto"; } @@ -204,7 +203,7 @@ std::string GetMessagePathPrefix(const GeneratorOptions& options, // message descriptor. std::string GetMessagePath(const GeneratorOptions& options, const Descriptor* descriptor) { - return GetMessagePathPrefix(options, descriptor) + descriptor->name(); + return absl::StrCat(GetMessagePathPrefix(options, descriptor), descriptor->name()); } // Returns the fully normalized JavaScript path prefix for the given @@ -219,7 +218,7 @@ std::string GetEnumPathPrefix(const GeneratorOptions& options, // enumeration descriptor. std::string GetEnumPath(const GeneratorOptions& options, const EnumDescriptor* enum_descriptor) { - return GetEnumPathPrefix(options, enum_descriptor) + enum_descriptor->name(); + return absl::StrCat(GetEnumPathPrefix(options, enum_descriptor), enum_descriptor->name()); } std::string MaybeCrossFileRef(const GeneratorOptions& options, @@ -230,9 +229,9 @@ std::string MaybeCrossFileRef(const GeneratorOptions& options, from_file != to_message->file()) { // Cross-file ref in CommonJS needs to use the module alias instead of // the global name. - return ModuleAlias(to_message->file()->name()) + - GetNestedMessageName(to_message->containing_type()) + "." + - to_message->name(); + return absl::StrCat(ModuleAlias(to_message->file()->name()), + GetNestedMessageName(to_message->containing_type()), ".", + to_message->name()); } else { // Within a single file we use a full name. return GetMessagePath(options, to_message); @@ -262,7 +261,7 @@ char ToLowerASCII(char c) { } } -std::vector ParseLowerUnderscore(const std::string& input) { +std::vector ParseLowerUnderscore(absl::string_view input) { std::vector words; std::string running = ""; for (auto c : input) { @@ -281,7 +280,7 @@ std::vector ParseLowerUnderscore(const std::string& input) { return words; } -std::vector ParseUpperCamel(const std::string& input) { +std::vector ParseUpperCamel(absl::string_view input) { std::vector words; std::string running = ""; for (auto c : input) { @@ -326,7 +325,7 @@ std::string ToUpperCamel(const std::vector& words) { // Based on code from descriptor.cc (Thanks Kenton!) // Uppercases the entire string, turning ValueName into // VALUENAME. -std::string ToEnumCase(const std::string& input) { +std::string ToEnumCase(absl::string_view input) { std::string result; result.reserve(input.size()); @@ -341,7 +340,7 @@ std::string ToEnumCase(const std::string& input) { return result; } -std::string ToLower(const std::string& input) { +std::string ToLower(absl::string_view input) { std::string result; result.reserve(input.size()); @@ -625,7 +624,7 @@ uint16_t DecodeUTF8Codepoint(uint8_t* bytes, size_t* length) { // Returns false if |out| was truncated because |in| contained invalid UTF-8 or // codepoints outside the BMP. // TODO(b/115551870): Support codepoints outside the BMP. -bool EscapeJSString(const std::string& in, std::string* out) { +bool EscapeJSString(absl::string_view in, std::string* out) { size_t decoded = 0; for (size_t i = 0; i < in.size(); i += decoded) { uint16_t codepoint = 0; @@ -697,7 +696,7 @@ bool EscapeJSString(const std::string& in, std::string* out) { return true; } -std::string EscapeBase64(const std::string& in) { +std::string EscapeBase64(absl::string_view in) { static const char* kAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; std::string result; @@ -1074,7 +1073,7 @@ std::string JSFieldTypeAnnotation(const GeneratorOptions& options, } std::string JSBinaryMethodType(const FieldDescriptor* field, bool is_writer) { - std::string name = field->type_name(); + std::string name = std::string(field->type_name()); if (name[0] >= 'a' && name[0] <= 'z') { name[0] = (name[0] - 'a') + 'A'; } @@ -1226,9 +1225,9 @@ std::string RelativeTypeName(const FieldDescriptor* field) { field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE); // For a field with an enum or message type, compute a name relative to the // path name of the message type containing this field. - std::string package = field->file()->package(); - std::string containing_type = field->containing_type()->full_name() + "."; - std::string type = (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) + absl::string_view package = field->file()->package(); + std::string containing_type = absl::StrCat(field->containing_type()->full_name(), "."); + absl::string_view type = (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) ? field->enum_type()->full_name() : field->message_type()->full_name(); @@ -1245,7 +1244,7 @@ std::string RelativeTypeName(const FieldDescriptor* field) { } } - return type.substr(prefix); + return std::string(type).substr(prefix); } std::string JSExtensionsObjectName(const GeneratorOptions& options, @@ -1285,8 +1284,8 @@ std::string FieldDefinition(const GeneratorOptions& options, } else { value_type = ProtoTypeName(options, value_field); } - return absl::StrFormat("map<%s, %s> %s = %d;", key_type.c_str(), - value_type.c_str(), field->name().c_str(), + return absl::StrFormat("map<%s, %s> %s = %d;", key_type, + value_type, field->name(), field->number()); } else { std::string qualifier = @@ -3588,8 +3587,8 @@ bool Generator::GenerateFile(const FileDescriptor* file, std::string filename = options.output_dir + "/" + GetJSFilename(options, use_short_name - ? file->name().substr(file->name().rfind('/')) - : file->name()); + ? std::string(file->name().substr(file->name().rfind('/'))) + : std::string(file->name())); std::unique_ptr output(context->Open(filename)); ABSL_CHECK(output); GeneratedCodeInfo annotations; @@ -3649,12 +3648,12 @@ void Generator::GenerateFile(const GeneratorOptions& options, } for (int i = 0; i < file->dependency_count(); i++) { - const std::string& name = file->dependency(i)->name(); + const std::string name = std::string(file->dependency(i)->name()); printer->Print( "var $alias$ = require('$file$');\n" "goog.object.extend(proto, $alias$);\n", "alias", ModuleAlias(name), "file", - GetRootPath(file->name(), name) + GetJSFilename(options, name)); + GetRootPath(std::string(file->name()), name) + GetJSFilename(options, name)); } } diff --git a/yarn.lock b/yarn.lock index 0d998f3..4f70eed 100644 --- a/yarn.lock +++ b/yarn.lock @@ -26,7 +26,14 @@ ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" -ansi-styles@^4.0.0, ansi-styles@^4.1.0: +ansi-styles@^4.0.0: + version "4.3.0" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== @@ -133,6 +140,14 @@ buffer@^6.0.3: base64-js "^1.3.1" ieee754 "^1.2.1" +chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + chalk@2.x: version "2.4.2" resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" @@ -142,14 +157,6 @@ chalk@2.x: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.1.2: - version "4.1.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - chokidar@^3.5.3: version "3.6.0" resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz" @@ -212,16 +219,16 @@ color-convert@^2.0.1: dependencies: color-name "~1.1.4" -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - color-name@~1.1.4: version "1.1.4" resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" @@ -374,11 +381,6 @@ fs.realpath@^1.0.0: resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== -fsevents@~2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" - integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== - function-bind@^1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" @@ -479,16 +481,6 @@ google-closure-compiler-linux@^20190819.0.0: resolved "https://registry.npmjs.org/google-closure-compiler-linux/-/google-closure-compiler-linux-20190819.0.0.tgz" integrity sha512-+ia89Ot4dPyRioLlxvkfYiISwJO+2NV7SY0Zp/KfTt9x+eJaGQ9GRIQage50d1mGkUyPmFfxsdPUePpT1QlpaA== -google-closure-compiler-osx@^20190819.0.0: - version "20190819.0.0" - resolved "https://registry.yarnpkg.com/google-closure-compiler-osx/-/google-closure-compiler-osx-20190819.0.0.tgz#57046952a3f520b942a35d2edaf0379b44b0c84c" - integrity sha512-woANg+oA2zjFebtdYTA4lLtqbOVO9yE9yy8ibGjt76FNlw0bAyxTO4z2ab4CwUNNpOeRoxZyGt9CejlCmNpxJg== - -google-closure-compiler-windows@^20190819.0.0: - version "20190819.0.0" - resolved "https://registry.yarnpkg.com/google-closure-compiler-windows/-/google-closure-compiler-windows-20190819.0.0.tgz#acf1246d65aa9e55a7d449e08188458a9da89867" - integrity sha512-WglPY706c1oN03KiZF02FUWr/7M0eFoev4CQPncSihfjYXpD5E5PMKJ3ppawhzj60CQ9ceC/Omx7VN7Kp0uOQg== - google-closure-compiler@~20190819.0.0: version "20190819.0.0" resolved "https://registry.npmjs.org/google-closure-compiler/-/google-closure-compiler-20190819.0.0.tgz" @@ -602,7 +594,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: +inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3, inherits@2: version "2.0.4" resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -753,7 +745,7 @@ map-cache@^0.2.0: micromatch@^4.0.4: version "4.0.8" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz" integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== dependencies: braces "^3.0.3" @@ -776,7 +768,7 @@ mute-stdout@^2.0.0: resolved "https://registry.npmjs.org/mute-stdout/-/mute-stdout-2.0.0.tgz" integrity sha512-32GSKM3Wyc8dg/p39lWPKYu8zci9mJFzV1Np9Of0ZEpe6Fhssn/FbI7ywAMd40uX+p3ZKh3T5EeCFv81qS3HmQ== -normalize-path@3.0.0, normalize-path@^3.0.0, normalize-path@~3.0.0: +normalize-path@^3.0.0, normalize-path@~3.0.0, normalize-path@3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== @@ -1008,6 +1000,13 @@ streamx@^2.12.0, streamx@^2.12.5, streamx@^2.13.2, streamx@^2.14.0: optionalDependencies: bare-events "^2.2.0" +string_decoder@^1.1.1, string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" @@ -1017,13 +1016,6 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string_decoder@^1.1.1, string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" @@ -1167,6 +1159,17 @@ vinyl-sourcemaps-apply@^0.2.0: dependencies: source-map "^0.5.1" +vinyl@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/vinyl/-/vinyl-3.0.0.tgz" + integrity sha512-rC2VRfAVVCGEgjnxHUnpIVh3AGuk62rP3tqVrn+yab0YH7UULisC085+NYH+mnqf3Wx4SpSi1RQMwudL89N03g== + dependencies: + clone "^2.1.2" + clone-stats "^1.0.0" + remove-trailing-separator "^1.1.0" + replace-ext "^2.0.0" + teex "^1.0.1" + vinyl@2.x: version "2.2.1" resolved "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz" @@ -1179,17 +1182,6 @@ vinyl@2.x: remove-trailing-separator "^1.0.1" replace-ext "^1.0.0" -vinyl@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/vinyl/-/vinyl-3.0.0.tgz" - integrity sha512-rC2VRfAVVCGEgjnxHUnpIVh3AGuk62rP3tqVrn+yab0YH7UULisC085+NYH+mnqf3Wx4SpSi1RQMwudL89N03g== - dependencies: - clone "^2.1.2" - clone-stats "^1.0.0" - remove-trailing-separator "^1.1.0" - replace-ext "^2.0.0" - teex "^1.0.1" - which@^1.2.14: version "1.3.1" resolved "https://registry.npmjs.org/which/-/which-1.3.1.tgz" From 9224d3e2d9b2bf25504da39055f0cf17af1ba11c Mon Sep 17 00:00:00 2001 From: Stephanie DiBenedetto Date: Mon, 17 Mar 2025 12:49:28 -0700 Subject: [PATCH 08/22] Update scorecard.yml This file was generated by re-running the actions marketplace installation. Cleaning up the old scorecards.yml that is obsoleted by this new file. --- .github/workflows/scorecard.yml | 73 ++++++++++++++++++++++++++++++++ .github/workflows/scorecards.yml | 62 --------------------------- 2 files changed, 73 insertions(+), 62 deletions(-) create mode 100644 .github/workflows/scorecard.yml delete mode 100644 .github/workflows/scorecards.yml diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml new file mode 100644 index 0000000..d4588b0 --- /dev/null +++ b/.github/workflows/scorecard.yml @@ -0,0 +1,73 @@ +# This workflow uses actions that are not certified by GitHub. They are provided +# by a third-party and are governed by separate terms of service, privacy +# policy, and support documentation. + +name: Scorecard supply-chain security +on: + # For Branch-Protection check. Only the default branch is supported. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection + branch_protection_rule: + # To guarantee Maintained check is occasionally updated. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained + schedule: + - cron: '32 5 * * 0' + push: + branches: [ "main" ] + +# Declare default permissions as read only. +permissions: read-all + +jobs: + analysis: + name: Scorecard analysis + runs-on: ubuntu-latest + permissions: + # Needed to upload the results to code-scanning dashboard. + security-events: write + # Needed to publish results and get a badge (see publish_results below). + id-token: write + # Uncomment the permissions below if installing in a private repository. + # contents: read + # actions: read + + steps: + - name: "Checkout code" + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + persist-credentials: false + + - name: "Run analysis" + uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1 + with: + results_file: results.sarif + results_format: sarif + # (Optional) "write" PAT token. Uncomment the `repo_token` line below if: + # - you want to enable the Branch-Protection check on a *public* repository, or + # - you are installing Scorecard on a *private* repository + # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action?tab=readme-ov-file#authentication-with-fine-grained-pat-optional. + # repo_token: ${{ secrets.SCORECARD_TOKEN }} + + # Public repositories: + # - Publish results to OpenSSF REST API for easy access by consumers + # - Allows the repository to include the Scorecard badge. + # - See https://github.com/ossf/scorecard-action#publishing-results. + # For private repositories: + # - `publish_results` will always be set to `false`, regardless + # of the value entered here. + publish_results: true + + # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF + # format to the repository Actions tab. + - name: "Upload artifact" + uses: actions/upload-artifact@97a0fba1372883ab732affbe8f94b823f91727db # v3.pre.node20 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + # Upload the results to GitHub's code scanning dashboard (optional). + # Commenting out will disable upload of results to your repo's Code Scanning dashboard + - name: "Upload to code-scanning" + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: results.sarif diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml deleted file mode 100644 index 5e59221..0000000 --- a/.github/workflows/scorecards.yml +++ /dev/null @@ -1,62 +0,0 @@ -name: Scorecards supply-chain security -on: - # Only the default branch is supported. - branch_protection_rule: - schedule: - - cron: '24 19 * * 0' - push: - branches: [ "main" ] - -# Declare default permissions as read only. -permissions: read-all - -jobs: - analysis: - name: Scorecards analysis - runs-on: ubuntu-latest - permissions: - # Needed to upload the results to code-scanning dashboard. - security-events: write - # Used to receive a badge. (Upcoming feature) - id-token: write - # Needs for private repositories. - contents: read - actions: read - - steps: - - name: "Checkout code" - uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # v3.0.0 - with: - persist-credentials: false - - - name: "Run analysis" - uses: ossf/scorecard-action@3e15ea8318eee9b333819ec77a36aca8d39df13e # v1.1.1 - with: - results_file: results.sarif - results_format: sarif - # (Optional) Read-only PAT token. Uncomment the `repo_token` line below if: - # - you want to enable the Branch-Protection check on a *public* repository, or - # - you are installing Scorecards on a *private* repository - # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat. - # repo_token: ${{ secrets.SCORECARD_READ_TOKEN }} - - # Publish the results for public repositories to enable scorecard badges. For more details, see - # https://github.com/ossf/scorecard-action#publishing-results. - # For private repositories, `publish_results` will automatically be set to `false`, regardless - # of the value entered here. - publish_results: true - - # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF - # format to the repository Actions tab. - - name: "Upload artifact" - uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0 - with: - name: SARIF file - path: results.sarif - retention-days: 5 - - # Upload the results to GitHub's code scanning dashboard. - - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@5f532563584d71fdef14ee64d17bafb34f751ce5 # v1.0.26 - with: - sarif_file: results.sarif From 0768cc9f18bec192c393d7c2962ee8ab5ad1931b Mon Sep 17 00:00:00 2001 From: Stephanie DiBenedetto Date: Mon, 17 Mar 2025 12:34:31 -0700 Subject: [PATCH 09/22] Fix path for rules_pkg providers.bzl load We use PackageVariablesInfo from rules_pkg for versioning. The previous change bumped the version of our rules_pkg dependency and it looks like that moved the declaring providers.bzl file change to a `pkg/` subdir. This broke our Windows builds/release automation since they use //:dist_zip. We did not catch this during PR testing because we just do `npm test`. --- protobuf_javascript_release.bzl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protobuf_javascript_release.bzl b/protobuf_javascript_release.bzl index 650fc2c..3f9090a 100644 --- a/protobuf_javascript_release.bzl +++ b/protobuf_javascript_release.bzl @@ -1,7 +1,7 @@ """Generates package naming variables for use with rules_pkg.""" load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain") -load("@rules_pkg//:providers.bzl", "PackageVariablesInfo") +load("@rules_pkg//pkg:providers.bzl", "PackageVariablesInfo") _PROTOBUF_JAVASCRIPT_VERSION = "3.21.4" From 28bf5df73ef2f345a936d9cc95d64ba8ed426a53 Mon Sep 17 00:00:00 2001 From: Stephanie DiBenedetto Date: Thu, 15 May 2025 15:41:00 -0700 Subject: [PATCH 10/22] Bump protobuf version to 31.0 Protobuf 31 contains field descriptor API changes for optional-ness. This change adjusts to the suggested !required && !repeated. --- .github/workflows/build.yml | 2 +- .github/workflows/codeql.yml | 2 +- MODULE.bazel | 2 +- MODULE.bazel.lock | 3528 +--------------------------------- generator/js_generator.cc | 6 +- 5 files changed, 21 insertions(+), 3519 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e0423c4..eca575f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,7 +6,7 @@ permissions: read-all # update in build.yml and codeql.yml at same time env: - PROTOC_VERSION: 30.1 + PROTOC_VERSION: "31.0" jobs: build: diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 8ec5102..197cb6e 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -15,7 +15,7 @@ permissions: read-all # update in build.yml and codeql.yml at same time env: - PROTOC_VERSION: 30.1 + PROTOC_VERSION: "31.0" on: push: diff --git a/MODULE.bazel b/MODULE.bazel index ad95b50..75b5ed7 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -1,5 +1,5 @@ module(name = "protobuf_javascript", version = "3.21.4") -bazel_dep(name = "protobuf", version = "30.1", repo_name = "com_google_protobuf") +bazel_dep(name = "protobuf", version = "31.0", repo_name = "com_google_protobuf") bazel_dep(name = "rules_pkg", version = "1.0.1") bazel_dep(name = "abseil-cpp", version = "20250127.0") diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index c30367f..a17bf63 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -13,19 +13,8 @@ "https://bcr.bazel.build/modules/abseil-cpp/20250127.0/MODULE.bazel": "d1086e248cda6576862b4b3fe9ad76a214e08c189af5b42557a6e1888812c5d5", "https://bcr.bazel.build/modules/abseil-cpp/20250127.0/source.json": "1b996859f840d8efc7c720efc61dcf2a84b1261cb3974cbbe9b6666ebf567775", "https://bcr.bazel.build/modules/apple_support/1.11.1/MODULE.bazel": "1843d7cd8a58369a444fc6000e7304425fba600ff641592161d9f15b179fb896", - "https://bcr.bazel.build/modules/apple_support/1.13.0/MODULE.bazel": "7c8cdea7e031b7f9f67f0b497adf6d2c6a2675e9304ca93a9af6ed84eef5a524", "https://bcr.bazel.build/modules/apple_support/1.15.1/MODULE.bazel": "a0556fefca0b1bb2de8567b8827518f94db6a6e7e7d632b4c48dc5f865bc7c85", "https://bcr.bazel.build/modules/apple_support/1.15.1/source.json": "517f2b77430084c541bc9be2db63fdcbb7102938c5f64c17ee60ffda2e5cf07b", - "https://bcr.bazel.build/modules/aspect_bazel_lib/1.31.2/MODULE.bazel": "7bee702b4862612f29333590f4b658a5832d433d6f8e4395f090e8f4e85d442f", - "https://bcr.bazel.build/modules/aspect_bazel_lib/1.38.0/MODULE.bazel": "6307fec451ba9962c1c969eb516ebfe1e46528f7fa92e1c9ac8646bef4cdaa3f", - "https://bcr.bazel.build/modules/aspect_bazel_lib/1.40.3/MODULE.bazel": "668e6bcb4d957fc0e284316dba546b705c8d43c857f87119619ee83c4555b859", - "https://bcr.bazel.build/modules/aspect_bazel_lib/1.40.3/source.json": "f5a28b1320e5f444e798b4afc1465c8b720bfaec7522cca38a23583dffe85e6d", - "https://bcr.bazel.build/modules/aspect_rules_js/1.33.1/MODULE.bazel": "db3e7f16e471cf6827059d03af7c21859e7a0d2bc65429a3a11f005d46fc501b", - "https://bcr.bazel.build/modules/aspect_rules_js/1.39.0/MODULE.bazel": "aece421d479e3c31dc3e5f6d49a12acc2700457c03c556650ec7a0ff23fc0d95", - "https://bcr.bazel.build/modules/aspect_rules_js/1.39.0/source.json": "a8f93e4ad8843e8aa407fa5fd7c8b63a63846c0ce255371ff23384582813b13d", - "https://bcr.bazel.build/modules/aspect_rules_lint/0.12.0/MODULE.bazel": "e767c5dbfeb254ec03275a7701b5cfde2c4d2873676804bc7cb27ddff3728fed", - "https://bcr.bazel.build/modules/aspect_rules_lint/0.12.0/source.json": "9a3668e1ee219170e22c0e7f3ab959724c6198fdd12cd503fa10b1c6923a2559", - "https://bcr.bazel.build/modules/bazel_features/0.1.0/MODULE.bazel": "47011d645b0f949f42ee67f2e8775188a9cf4a0a1528aa2fa4952f2fd00906fd", "https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd", "https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8", "https://bcr.bazel.build/modules/bazel_features/1.15.0/MODULE.bazel": "d38ff6e517149dc509406aca0db3ad1efdd890a85e049585b7234d04238e2a4d", @@ -52,9 +41,6 @@ "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/source.json": "f121b43eeefc7c29efbd51b83d08631e2347297c95aac9764a701f2a6a2bb953", "https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84", "https://bcr.bazel.build/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8", - "https://bcr.bazel.build/modules/gazelle/0.27.0/MODULE.bazel": "3446abd608295de6d90b4a8a118ed64a9ce11dcb3dda2dc3290a22056bd20996", - "https://bcr.bazel.build/modules/gazelle/0.30.0/MODULE.bazel": "f888a1effe338491f35f0e0e85003b47bb9d8295ccba73c37e07702d8d31c65b", - "https://bcr.bazel.build/modules/gazelle/0.30.0/source.json": "7af0779f99120aafc73be127615d224f26da2fc5a606b52bdffb221fd9efb737", "https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb", "https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4", "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6", @@ -68,7 +54,8 @@ "https://bcr.bazel.build/modules/nlohmann_json/3.6.1/MODULE.bazel": "6f7b417dcc794d9add9e556673ad25cb3ba835224290f4f848f8e2db1e1fca74", "https://bcr.bazel.build/modules/nlohmann_json/3.6.1/source.json": "f448c6e8963fdfa7eb831457df83ad63d3d6355018f6574fb017e8169deb43a9", "https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5", - "https://bcr.bazel.build/modules/platforms/0.0.10/source.json": "f22828ff4cf021a6b577f1bf6341cb9dcd7965092a439f64fc1bb3b7a5ae4bd5", + "https://bcr.bazel.build/modules/platforms/0.0.11/MODULE.bazel": "0daefc49732e227caa8bfa834d65dc52e8cc18a2faf80df25e8caea151a9413f", + "https://bcr.bazel.build/modules/platforms/0.0.11/source.json": "f7e188b79ebedebfe75e9e1d098b8845226c7992b307e28e1496f23112e8fc29", "https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee", "https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37", "https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615", @@ -82,22 +69,19 @@ "https://bcr.bazel.build/modules/protobuf/29.0-rc3/MODULE.bazel": "33c2dfa286578573afc55a7acaea3cada4122b9631007c594bf0729f41c8de92", "https://bcr.bazel.build/modules/protobuf/29.0/MODULE.bazel": "319dc8bf4c679ff87e71b1ccfb5a6e90a6dbc4693501d471f48662ac46d04e4e", "https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0", - "https://bcr.bazel.build/modules/protobuf/3.19.2/MODULE.bazel": "532ffe5f2186b69fdde039efe6df13ba726ff338c6bc82275ad433013fa10573", - "https://bcr.bazel.build/modules/protobuf/3.19.6/MODULE.bazel": "9233edc5e1f2ee276a60de3eaa47ac4132302ef9643238f23128fea53ea12858", - "https://bcr.bazel.build/modules/protobuf/30.1/MODULE.bazel": "293a47b398800e1efeed6e325f2809c5fab6c692a80384c507afd0ffca3b1bcf", - "https://bcr.bazel.build/modules/protobuf/30.1/source.json": "688ec8aa4fc080a36b48d7b5c22dd3190de2efe07e82f54ccabd2f5e5a59b27e", + "https://bcr.bazel.build/modules/protobuf/31.0/MODULE.bazel": "cce0f305064713b382211c4c5af1d4fc1466e1fbc9059aa0941801970f6add5c", + "https://bcr.bazel.build/modules/protobuf/31.0/source.json": "266920c7b95f467db2dc38a640aed7265d948fc38dfb752bb91a027932ee2a99", "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e", "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/MODULE.bazel": "e6f4c20442eaa7c90d7190d8dc539d0ab422f95c65a57cc59562170c58ae3d34", "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/source.json": "6900fdc8a9e95866b8c0d4ad4aba4d4236317b5c1cd04c502df3f0d33afed680", "https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206", + "https://bcr.bazel.build/modules/re2/2024-07-02.bcr.1/MODULE.bazel": "b4963dda9b31080be1905ef085ecd7dd6cd47c05c79b9cdf83ade83ab2ab271a", + "https://bcr.bazel.build/modules/re2/2024-07-02.bcr.1/source.json": "2ff292be6ef3340325ce8a045ecc326e92cbfab47c7cbab4bd85d28971b97ac4", "https://bcr.bazel.build/modules/re2/2024-07-02/MODULE.bazel": "0eadc4395959969297cbcf31a249ff457f2f1d456228c67719480205aa306daa", - "https://bcr.bazel.build/modules/re2/2024-07-02/source.json": "547d0111a9d4f362db32196fef805abbf3676e8d6afbe44d395d87816c1130ca", "https://bcr.bazel.build/modules/rules_android/0.1.1/MODULE.bazel": "48809ab0091b07ad0182defb787c4c5328bd3a278938415c00a7b69b50c4d3a8", "https://bcr.bazel.build/modules/rules_android/0.1.1/source.json": "e6986b41626ee10bdc864937ffb6d6bf275bb5b9c65120e6137d56e6331f089e", - "https://bcr.bazel.build/modules/rules_apple/3.13.0/MODULE.bazel": "b4559a2c6281ca3165275bb36c1f0ac74666632adc5bdb680e366de7ce845f43", - "https://bcr.bazel.build/modules/rules_apple/3.13.0/source.json": "fe31c678e2256daa91a802664b578c1de71dc43a49a7ccc16db001378f312cd3", - "https://bcr.bazel.build/modules/rules_buf/0.1.1/MODULE.bazel": "6189aec18a4f7caff599ad41b851ab7645d4f1e114aa6431acf9b0666eb92162", - "https://bcr.bazel.build/modules/rules_buf/0.1.1/source.json": "021363d254f7438f3f10725355969c974bb2c67e0c28667782ade31a9cdb747f", + "https://bcr.bazel.build/modules/rules_apple/3.16.0/MODULE.bazel": "0d1caf0b8375942ce98ea944be754a18874041e4e0459401d925577624d3a54a", + "https://bcr.bazel.build/modules/rules_apple/3.16.0/source.json": "d8b5fe461272018cc07cfafce11fe369c7525330804c37eec5a82f84cd475366", "https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647", "https://bcr.bazel.build/modules/rules_cc/0.0.10/MODULE.bazel": "ec1705118f7eaedd6e118508d3d26deba2a4e76476ada7e0e3965211be012002", "https://bcr.bazel.build/modules/rules_cc/0.0.13/MODULE.bazel": "0e8529ed7b323dad0775ff924d2ae5af7640b23553dfcd4d34344c7e7a867191", @@ -112,11 +96,6 @@ "https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5", "https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6", "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8", - "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/source.json": "c8b1e2c717646f1702290959a3302a178fb639d987ab61d548105019f11e527e", - "https://bcr.bazel.build/modules/rules_go/0.33.0/MODULE.bazel": "a2b11b64cd24bf94f57454f53288a5dacfe6cb86453eee7761b7637728c1910c", - "https://bcr.bazel.build/modules/rules_go/0.38.1/MODULE.bazel": "fb8e73dd3b6fc4ff9d260ceacd830114891d49904f5bda1c16bc147bcc254f71", - "https://bcr.bazel.build/modules/rules_go/0.39.1/MODULE.bazel": "d34fb2a249403a5f4339c754f1e63dc9e5ad70b47c5e97faee1441fc6636cd61", - "https://bcr.bazel.build/modules/rules_go/0.39.1/source.json": "f21e042154010ae2c944ab230d572b17d71cdb27c5255806d61df6ccaed4354c", "https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74", "https://bcr.bazel.build/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86", "https://bcr.bazel.build/modules/rules_java/6.0.0/MODULE.bazel": "8a43b7df601a7ec1af61d79345c17b31ea1fedc6711fd4abfd013ea612978e39", @@ -127,27 +106,26 @@ "https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab", "https://bcr.bazel.build/modules/rules_java/7.3.2/MODULE.bazel": "50dece891cfdf1741ea230d001aa9c14398062f2b7c066470accace78e412bc2", "https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe", + "https://bcr.bazel.build/modules/rules_java/8.11.0/MODULE.bazel": "c3d280bc5ff1038dcb3bacb95d3f6b83da8dd27bba57820ec89ea4085da767ad", + "https://bcr.bazel.build/modules/rules_java/8.11.0/source.json": "302b52a39259a85aa06ca3addb9787864ca3e03b432a5f964ea68244397e7544", "https://bcr.bazel.build/modules/rules_java/8.3.2/MODULE.bazel": "7336d5511ad5af0b8615fdc7477535a2e4e723a357b6713af439fe8cf0195017", "https://bcr.bazel.build/modules/rules_java/8.5.1/MODULE.bazel": "d8a9e38cc5228881f7055a6079f6f7821a073df3744d441978e7a43e20226939", "https://bcr.bazel.build/modules/rules_java/8.6.1/MODULE.bazel": "f4808e2ab5b0197f094cabce9f4b006a27766beb6a9975931da07099560ca9c2", - "https://bcr.bazel.build/modules/rules_java/8.6.1/source.json": "f18d9ad3c4c54945bf422ad584fa6c5ca5b3116ff55a5b1bc77e5c1210be5960", "https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7", "https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909", "https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036", "https://bcr.bazel.build/modules/rules_jvm_external/5.3/MODULE.bazel": "bf93870767689637164657731849fb887ad086739bd5d360d90007a581d5527d", "https://bcr.bazel.build/modules/rules_jvm_external/6.1/MODULE.bazel": "75b5fec090dbd46cf9b7d8ea08cf84a0472d92ba3585b476f44c326eda8059c4", "https://bcr.bazel.build/modules/rules_jvm_external/6.3/MODULE.bazel": "c998e060b85f71e00de5ec552019347c8bca255062c990ac02d051bb80a38df0", - "https://bcr.bazel.build/modules/rules_jvm_external/6.3/source.json": "6f5f5a5a4419ae4e37c35a5bb0a6ae657ed40b7abc5a5189111b47fcebe43197", + "https://bcr.bazel.build/modules/rules_jvm_external/6.7/MODULE.bazel": "e717beabc4d091ecb2c803c2d341b88590e9116b8bf7947915eeb33aab4f96dd", + "https://bcr.bazel.build/modules/rules_jvm_external/6.7/source.json": "5426f412d0a7fc6b611643376c7e4a82dec991491b9ce5cb1cfdd25fe2e92be4", "https://bcr.bazel.build/modules/rules_kotlin/1.9.0/MODULE.bazel": "ef85697305025e5a61f395d4eaede272a5393cee479ace6686dba707de804d59", "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/MODULE.bazel": "d269a01a18ee74d0335450b10f62c9ed81f2321d7958a2934e44272fe82dcef3", "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/source.json": "2faa4794364282db7c06600b7e5e34867a564ae91bda7cae7c29c64e9466b7d5", "https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0", "https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d", - "https://bcr.bazel.build/modules/rules_license/0.0.8/MODULE.bazel": "5669c6fe49b5134dbf534db681ad3d67a2d49cfc197e4a95f1ca2fd7f3aebe96", "https://bcr.bazel.build/modules/rules_license/1.0.0/MODULE.bazel": "a7fda60eefdf3d8c827262ba499957e4df06f659330bbe6cdbdb975b768bb65c", "https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb", - "https://bcr.bazel.build/modules/rules_nodejs/5.8.2/MODULE.bazel": "6bc03c8f37f69401b888023bf511cb6ee4781433b0cb56236b2e55a21e3a026a", - "https://bcr.bazel.build/modules/rules_nodejs/5.8.2/source.json": "6e82cf5753d835ea18308200bc79b9c2e782efe2e2a4edc004a9162ca93382ca", "https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc", "https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff", "https://bcr.bazel.build/modules/rules_pkg/1.0.1/source.json": "bd82e5d7b9ce2d31e380dd9f50c111d678c3bdaca190cb76b0e1c71b05e1ba8a", @@ -167,17 +145,14 @@ "https://bcr.bazel.build/modules/rules_python/0.40.0/MODULE.bazel": "9d1a3cd88ed7d8e39583d9ffe56ae8a244f67783ae89b60caafc9f5cf318ada7", "https://bcr.bazel.build/modules/rules_python/1.0.0/MODULE.bazel": "898a3d999c22caa585eb062b600f88654bf92efb204fa346fb55f6f8edffca43", "https://bcr.bazel.build/modules/rules_python/1.0.0/source.json": "b0162a65c6312e45e7912e39abd1a7f8856c2c7e41ecc9b6dc688a6f6400a917", - "https://bcr.bazel.build/modules/rules_rust/0.51.0/MODULE.bazel": "2b6d1617ac8503bfdcc0e4520c20539d4bba3a691100bee01afe193ceb0310f9", - "https://bcr.bazel.build/modules/rules_rust/0.51.0/source.json": "79a530199d9826a93b31d05b7d9b39dc753a80f88856d3ca5376f665a82cc5e6", "https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c", - "https://bcr.bazel.build/modules/rules_shell/0.2.0/source.json": "7f27af3c28037d9701487c4744b5448d26537cc66cdef0d8df7ae85411f8de95", + "https://bcr.bazel.build/modules/rules_shell/0.3.0/MODULE.bazel": "de4402cd12f4cc8fda2354fce179fdb068c0b9ca1ec2d2b17b3e21b24c1a937b", + "https://bcr.bazel.build/modules/rules_shell/0.3.0/source.json": "c55ed591aa5009401ddf80ded9762ac32c358d2517ee7820be981e2de9756cf3", "https://bcr.bazel.build/modules/rules_swift/1.16.0/MODULE.bazel": "4a09f199545a60d09895e8281362b1ff3bb08bbde69c6fc87aff5b92fcc916ca", "https://bcr.bazel.build/modules/rules_swift/2.1.1/MODULE.bazel": "494900a80f944fc7aa61500c2073d9729dff0b764f0e89b824eb746959bc1046", "https://bcr.bazel.build/modules/rules_swift/2.1.1/source.json": "40fc69dfaac64deddbb75bd99cdac55f4427d9ca0afbe408576a65428427a186", - "https://bcr.bazel.build/modules/stardoc/0.5.0/MODULE.bazel": "f9f1f46ba8d9c3362648eea571c6f9100680efc44913618811b58cc9c02cd678", "https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8", "https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c", - "https://bcr.bazel.build/modules/stardoc/0.5.4/MODULE.bazel": "6569966df04610b8520957cb8e97cf2e9faac2c0309657c537ab51c16c18a2a4", "https://bcr.bazel.build/modules/stardoc/0.5.6/MODULE.bazel": "c43dabc564990eeab55e25ed61c07a1aadafe9ece96a4efabb3f8bf9063b71ef", "https://bcr.bazel.build/modules/stardoc/0.7.0/MODULE.bazel": "05e3d6d30c099b6770e97da986c53bd31844d7f13d41412480ea265ac9e8079c", "https://bcr.bazel.build/modules/stardoc/0.7.1/MODULE.bazel": "3548faea4ee5dda5580f9af150e79d0f6aea934fc60c1cc50f4efdd9420759e7", @@ -187,7 +162,6 @@ "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.1/source.json": "32bd87e5f4d7acc57c5b2ff7c325ae3061d5e242c0c4c214ae87e0f1c13e54cb", "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43", "https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0", - "https://bcr.bazel.build/modules/zlib/1.2.12/MODULE.bazel": "3b1a8834ada2a883674be8cbd36ede1b6ec481477ada359cd2d3ddc562340b27", "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/MODULE.bazel": "af322bc08976524477c79d1e45e241b6efbeb918c497e8840b8ab116802dda79", "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/MODULE.bazel": "eec517b5bbe5492629466e11dae908d043364302283de25581e3eb944326c4ca", "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/source.json": "22bc55c47af97246cfc093d0acf683a7869377de362b5d1c552c2c2e16b7a806", @@ -198,7 +172,7 @@ "@@apple_support+//crosstool:setup.bzl%apple_cc_configure_extension": { "general": { "bzlTransitiveDigest": "okb7JAyJ9zeL+SDmtbWT0XBLq8WRoLJ0zWAG783RLVI=", - "usagesDigest": "xv9z2c7OWE3Yp+Azbwv1ImqlF3yAZhfTG5FR1K+/isk=", + "usagesDigest": "EJfdUgbJdIRboG70S9dz8HhGVkL2/s3qFQ9xht8y2Rs=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, "envVariables": {}, @@ -226,413 +200,6 @@ ] } }, - "@@aspect_bazel_lib+//lib:extensions.bzl%toolchains": { - "general": { - "bzlTransitiveDigest": "TGnRoh+5JjQRL6rkWCQneJpM89XjhPyydRXWIn0HmDw=", - "usagesDigest": "HyCD/AMcHKcynL86oRSbi4rhw9cjPb8yfXrC363gBKE=", - "recordedFileInputs": {}, - "recordedDirentsInputs": {}, - "envVariables": {}, - "generatedRepoSpecs": { - "copy_directory_darwin_amd64": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo", - "attributes": { - "platform": "darwin_amd64" - } - }, - "copy_directory_darwin_arm64": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo", - "attributes": { - "platform": "darwin_arm64" - } - }, - "copy_directory_freebsd_amd64": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo", - "attributes": { - "platform": "freebsd_amd64" - } - }, - "copy_directory_linux_amd64": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo", - "attributes": { - "platform": "linux_amd64" - } - }, - "copy_directory_linux_arm64": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo", - "attributes": { - "platform": "linux_arm64" - } - }, - "copy_directory_windows_amd64": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_platform_repo", - "attributes": { - "platform": "windows_amd64" - } - }, - "copy_directory_toolchains": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_directory_toolchain.bzl%copy_directory_toolchains_repo", - "attributes": { - "user_repository_name": "copy_directory" - } - }, - "copy_to_directory_darwin_amd64": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo", - "attributes": { - "platform": "darwin_amd64" - } - }, - "copy_to_directory_darwin_arm64": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo", - "attributes": { - "platform": "darwin_arm64" - } - }, - "copy_to_directory_freebsd_amd64": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo", - "attributes": { - "platform": "freebsd_amd64" - } - }, - "copy_to_directory_linux_amd64": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo", - "attributes": { - "platform": "linux_amd64" - } - }, - "copy_to_directory_linux_arm64": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo", - "attributes": { - "platform": "linux_arm64" - } - }, - "copy_to_directory_windows_amd64": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_platform_repo", - "attributes": { - "platform": "windows_amd64" - } - }, - "copy_to_directory_toolchains": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:copy_to_directory_toolchain.bzl%copy_to_directory_toolchains_repo", - "attributes": { - "user_repository_name": "copy_to_directory" - } - }, - "jq_darwin_amd64": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_platform_repo", - "attributes": { - "platform": "darwin_amd64", - "version": "1.6" - } - }, - "jq_darwin_arm64": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_platform_repo", - "attributes": { - "platform": "darwin_arm64", - "version": "1.6" - } - }, - "jq_linux_amd64": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_platform_repo", - "attributes": { - "platform": "linux_amd64", - "version": "1.6" - } - }, - "jq_windows_amd64": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_platform_repo", - "attributes": { - "platform": "windows_amd64", - "version": "1.6" - } - }, - "jq": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_host_alias_repo", - "attributes": {} - }, - "jq_toolchains": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:jq_toolchain.bzl%jq_toolchains_repo", - "attributes": { - "user_repository_name": "jq" - } - }, - "yq_darwin_amd64": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo", - "attributes": { - "platform": "darwin_amd64", - "version": "4.25.2" - } - }, - "yq_darwin_arm64": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo", - "attributes": { - "platform": "darwin_arm64", - "version": "4.25.2" - } - }, - "yq_linux_amd64": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo", - "attributes": { - "platform": "linux_amd64", - "version": "4.25.2" - } - }, - "yq_linux_arm64": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo", - "attributes": { - "platform": "linux_arm64", - "version": "4.25.2" - } - }, - "yq_linux_s390x": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo", - "attributes": { - "platform": "linux_s390x", - "version": "4.25.2" - } - }, - "yq_linux_ppc64le": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo", - "attributes": { - "platform": "linux_ppc64le", - "version": "4.25.2" - } - }, - "yq_windows_amd64": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_platform_repo", - "attributes": { - "platform": "windows_amd64", - "version": "4.25.2" - } - }, - "yq": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_host_alias_repo", - "attributes": {} - }, - "yq_toolchains": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:yq_toolchain.bzl%yq_toolchains_repo", - "attributes": { - "user_repository_name": "yq" - } - }, - "coreutils_darwin_amd64": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo", - "attributes": { - "platform": "darwin_amd64", - "version": "0.0.16" - } - }, - "coreutils_darwin_arm64": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo", - "attributes": { - "platform": "darwin_arm64", - "version": "0.0.16" - } - }, - "coreutils_linux_amd64": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo", - "attributes": { - "platform": "linux_amd64", - "version": "0.0.16" - } - }, - "coreutils_linux_arm64": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo", - "attributes": { - "platform": "linux_arm64", - "version": "0.0.16" - } - }, - "coreutils_windows_amd64": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_platform_repo", - "attributes": { - "platform": "windows_amd64", - "version": "0.0.16" - } - }, - "coreutils_toolchains": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:coreutils_toolchain.bzl%coreutils_toolchains_repo", - "attributes": { - "user_repository_name": "coreutils" - } - }, - "expand_template_darwin_amd64": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo", - "attributes": { - "platform": "darwin_amd64" - } - }, - "expand_template_darwin_arm64": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo", - "attributes": { - "platform": "darwin_arm64" - } - }, - "expand_template_freebsd_amd64": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo", - "attributes": { - "platform": "freebsd_amd64" - } - }, - "expand_template_linux_amd64": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo", - "attributes": { - "platform": "linux_amd64" - } - }, - "expand_template_linux_arm64": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo", - "attributes": { - "platform": "linux_arm64" - } - }, - "expand_template_windows_amd64": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_platform_repo", - "attributes": { - "platform": "windows_amd64" - } - }, - "expand_template_toolchains": { - "repoRuleId": "@@aspect_bazel_lib+//lib/private:expand_template_toolchain.bzl%expand_template_toolchains_repo", - "attributes": { - "user_repository_name": "expand_template" - } - } - }, - "recordedRepoMappingEntries": [ - [ - "aspect_bazel_lib+", - "aspect_bazel_lib", - "aspect_bazel_lib+" - ], - [ - "aspect_bazel_lib+", - "bazel_skylib", - "bazel_skylib+" - ], - [ - "aspect_bazel_lib+", - "bazel_tools", - "bazel_tools" - ] - ] - } - }, - "@@platforms//host:extension.bzl%host_platform": { - "general": { - "bzlTransitiveDigest": "xelQcPZH8+tmuOHVjL9vDxMnnQNMlwj0SlvgoqBkm4U=", - "usagesDigest": "SeQiIN/f8/Qt9vYQk7qcXp4I4wJeEC0RnQDiaaJ4tb8=", - "recordedFileInputs": {}, - "recordedDirentsInputs": {}, - "envVariables": {}, - "generatedRepoSpecs": { - "host_platform": { - "repoRuleId": "@@platforms//host:extension.bzl%host_platform_repo", - "attributes": {} - } - }, - "recordedRepoMappingEntries": [] - } - }, - "@@rules_buf+//buf:extensions.bzl%ext": { - "general": { - "bzlTransitiveDigest": "3jGepUu1j86kWsTP3Fgogw/XfktHd4UIQt8zj494n/Y=", - "usagesDigest": "RTc2BMQ2b0wGU8CRvN3EoPz34m3LMe+K/oSkFkN83+M=", - "recordedFileInputs": {}, - "recordedDirentsInputs": {}, - "envVariables": {}, - "generatedRepoSpecs": { - "rules_buf_toolchains": { - "repoRuleId": "@@rules_buf+//buf/internal:toolchain.bzl%buf_download_releases", - "attributes": { - "version": "v1.27.0" - } - } - }, - "recordedRepoMappingEntries": [ - [ - "rules_buf+", - "bazel_tools", - "bazel_tools" - ] - ] - } - }, - "@@rules_go+//go:extensions.bzl%go_sdk": { - "general": { - "bzlTransitiveDigest": "GI0gnOeyAURBWF+T+482mWnxAoSjspZNDIVvAHGR7Yk=", - "usagesDigest": "G0DymwAVABR+Olml5OAfLhVRqUVCU372GHdSQxQ1PJw=", - "recordedFileInputs": {}, - "recordedDirentsInputs": {}, - "envVariables": {}, - "generatedRepoSpecs": { - "go_default_sdk": { - "repoRuleId": "@@rules_go+//go/private:sdk.bzl%go_download_sdk_rule", - "attributes": { - "goos": "", - "goarch": "", - "sdks": {}, - "urls": [ - "https://dl.google.com/go/{}" - ], - "version": "1.19.8" - } - }, - "go_toolchains": { - "repoRuleId": "@@rules_go+//go/private:sdk.bzl%go_multiple_toolchains", - "attributes": { - "prefixes": [ - "_0000_go_default_sdk_" - ], - "geese": [ - "" - ], - "goarchs": [ - "" - ], - "sdk_repos": [ - "go_default_sdk" - ], - "sdk_types": [ - "remote" - ], - "sdk_versions": [ - "1.19.8" - ] - } - } - }, - "recordedRepoMappingEntries": [ - [ - "rules_go+", - "bazel_tools", - "bazel_tools" - ] - ] - } - }, - "@@rules_java+//java:rules_java_deps.bzl%compatibility_proxy": { - "general": { - "bzlTransitiveDigest": "84xJEZ1jnXXwo8BXMprvBm++rRt4jsTu9liBxz0ivps=", - "usagesDigest": "jTQDdLDxsS43zuRmg1faAjIEPWdLAbDAowI1pInQSoo=", - "recordedFileInputs": {}, - "recordedDirentsInputs": {}, - "envVariables": {}, - "generatedRepoSpecs": { - "compatibility_proxy": { - "repoRuleId": "@@rules_java+//java:rules_java_deps.bzl%_compatibility_proxy_repo_rule", - "attributes": {} - } - }, - "recordedRepoMappingEntries": [ - [ - "rules_java+", - "bazel_tools", - "bazel_tools" - ] - ] - } - }, "@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": { "general": { "bzlTransitiveDigest": "sFhcgPbDQehmbD1EOXzX4H1q/CD5df8zwG4kp4jbvr8=", @@ -696,3071 +263,6 @@ ] ] } - }, - "@@rules_nodejs+//nodejs:extensions.bzl%node": { - "general": { - "bzlTransitiveDigest": "btnelILPo3ngQN9vWtsQMclvJZPf3X2vcGTjmW7Owy8=", - "usagesDigest": "CtwJeycIo1YVyKAUrO/7bkpB6yqctQd8XUnRtqUbwRI=", - "recordedFileInputs": {}, - "recordedDirentsInputs": {}, - "envVariables": {}, - "generatedRepoSpecs": { - "nodejs_linux_amd64": { - "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%node_repositories", - "attributes": { - "platform": "linux_amd64", - "node_version": "16.19.0" - } - }, - "nodejs_linux_arm64": { - "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%node_repositories", - "attributes": { - "platform": "linux_arm64", - "node_version": "16.19.0" - } - }, - "nodejs_linux_s390x": { - "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%node_repositories", - "attributes": { - "platform": "linux_s390x", - "node_version": "16.19.0" - } - }, - "nodejs_linux_ppc64le": { - "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%node_repositories", - "attributes": { - "platform": "linux_ppc64le", - "node_version": "16.19.0" - } - }, - "nodejs_darwin_amd64": { - "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%node_repositories", - "attributes": { - "platform": "darwin_amd64", - "node_version": "16.19.0" - } - }, - "nodejs_darwin_arm64": { - "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%node_repositories", - "attributes": { - "platform": "darwin_arm64", - "node_version": "16.19.0" - } - }, - "nodejs_windows_amd64": { - "repoRuleId": "@@rules_nodejs+//nodejs:repositories.bzl%node_repositories", - "attributes": { - "platform": "windows_amd64", - "node_version": "16.19.0" - } - }, - "nodejs": { - "repoRuleId": "@@rules_nodejs+//nodejs/private:nodejs_repo_host_os_alias.bzl%nodejs_repo_host_os_alias", - "attributes": { - "user_node_repository_name": "nodejs" - } - }, - "nodejs_host": { - "repoRuleId": "@@rules_nodejs+//nodejs/private:nodejs_repo_host_os_alias.bzl%nodejs_repo_host_os_alias", - "attributes": { - "user_node_repository_name": "nodejs" - } - }, - "nodejs_toolchains": { - "repoRuleId": "@@rules_nodejs+//nodejs/private:toolchains_repo.bzl%toolchains_repo", - "attributes": { - "user_node_repository_name": "nodejs" - } - } - }, - "recordedRepoMappingEntries": [ - [ - "rules_nodejs+", - "bazel_skylib", - "bazel_skylib+" - ], - [ - "rules_nodejs+", - "bazel_tools", - "bazel_tools" - ] - ] - } - }, - "@@rules_rust+//rust:extensions.bzl%rust": { - "general": { - "bzlTransitiveDigest": "tuX+v7uYkywcUGfTOepkhN1oSag3rbqPRCi7hA3BU/Y=", - "usagesDigest": "ozx08ZbgRXTJw0zCaO/xtMUzgGLvwaQkZGnUo6tlyHM=", - "recordedFileInputs": {}, - "recordedDirentsInputs": {}, - "envVariables": {}, - "generatedRepoSpecs": { - "rust_analyzer_1.81.0_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_analyzer_toolchain_tools_repository", - "attributes": { - "version": "1.81.0", - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_analyzer_1.81.0": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_analyzer_1.81.0_tools//:rust_analyzer_toolchain", - "toolchain_type": "@rules_rust//rust/rust_analyzer:toolchain_type", - "exec_compatible_with": [], - "target_compatible_with": [] - } - }, - "rust_darwin_aarch64__aarch64-apple-darwin__stable_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "aarch64-apple-darwin", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "aarch64-apple-darwin", - "version": "1.81.0", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_darwin_aarch64__aarch64-apple-darwin__stable": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_darwin_aarch64__aarch64-apple-darwin__stable_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:stable" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:aarch64", - "@platforms//os:osx" - ], - "target_compatible_with": [ - "@platforms//cpu:aarch64", - "@platforms//os:osx" - ] - } - }, - "rust_darwin_aarch64__aarch64-apple-darwin__nightly_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "aarch64-apple-darwin", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "aarch64-apple-darwin", - "version": "nightly/2024-09-05", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_darwin_aarch64__aarch64-apple-darwin__nightly": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_darwin_aarch64__aarch64-apple-darwin__nightly_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:nightly" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:aarch64", - "@platforms//os:osx" - ], - "target_compatible_with": [ - "@platforms//cpu:aarch64", - "@platforms//os:osx" - ] - } - }, - "rust_darwin_aarch64__wasm32-unknown-unknown__stable_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "aarch64-apple-darwin", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "wasm32-unknown-unknown", - "version": "1.81.0", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_darwin_aarch64__wasm32-unknown-unknown__stable": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_darwin_aarch64__wasm32-unknown-unknown__stable_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:stable" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:aarch64", - "@platforms//os:osx" - ], - "target_compatible_with": [ - "@platforms//cpu:wasm32", - "@platforms//os:none" - ] - } - }, - "rust_darwin_aarch64__wasm32-unknown-unknown__nightly_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "aarch64-apple-darwin", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "wasm32-unknown-unknown", - "version": "nightly/2024-09-05", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_darwin_aarch64__wasm32-unknown-unknown__nightly": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_darwin_aarch64__wasm32-unknown-unknown__nightly_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:nightly" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:aarch64", - "@platforms//os:osx" - ], - "target_compatible_with": [ - "@platforms//cpu:wasm32", - "@platforms//os:none" - ] - } - }, - "rust_darwin_aarch64__wasm32-wasi__stable_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "aarch64-apple-darwin", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "wasm32-wasi", - "version": "1.81.0", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_darwin_aarch64__wasm32-wasi__stable": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_darwin_aarch64__wasm32-wasi__stable_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:stable" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:aarch64", - "@platforms//os:osx" - ], - "target_compatible_with": [ - "@platforms//cpu:wasm32", - "@platforms//os:wasi" - ] - } - }, - "rust_darwin_aarch64__wasm32-wasi__nightly_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "aarch64-apple-darwin", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "wasm32-wasi", - "version": "nightly/2024-09-05", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_darwin_aarch64__wasm32-wasi__nightly": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_darwin_aarch64__wasm32-wasi__nightly_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:nightly" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:aarch64", - "@platforms//os:osx" - ], - "target_compatible_with": [ - "@platforms//cpu:wasm32", - "@platforms//os:wasi" - ] - } - }, - "rust_darwin_aarch64": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_set_repository", - "attributes": { - "toolchains": [ - "@rust_darwin_aarch64__aarch64-apple-darwin__stable//:toolchain", - "@rust_darwin_aarch64__aarch64-apple-darwin__nightly//:toolchain", - "@rust_darwin_aarch64__wasm32-unknown-unknown__stable//:toolchain", - "@rust_darwin_aarch64__wasm32-unknown-unknown__nightly//:toolchain", - "@rust_darwin_aarch64__wasm32-wasi__stable//:toolchain", - "@rust_darwin_aarch64__wasm32-wasi__nightly//:toolchain" - ] - } - }, - "rustfmt_nightly-2024-09-05__aarch64-apple-darwin_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rustfmt_toolchain_tools_repository", - "attributes": { - "version": "nightly/2024-09-05", - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": {}, - "exec_triple": "aarch64-apple-darwin" - } - }, - "rustfmt_nightly-2024-09-05__aarch64-apple-darwin": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rustfmt_nightly-2024-09-05__aarch64-apple-darwin_tools//:rustfmt_toolchain", - "toolchain_type": "@rules_rust//rust/rustfmt:toolchain_type", - "target_settings": [], - "exec_compatible_with": [ - "@platforms//cpu:aarch64", - "@platforms//os:osx" - ], - "target_compatible_with": [] - } - }, - "rust_windows_aarch64__aarch64-pc-windows-msvc__stable_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "aarch64-pc-windows-msvc", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "aarch64-pc-windows-msvc", - "version": "1.81.0", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_windows_aarch64__aarch64-pc-windows-msvc__stable": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_windows_aarch64__aarch64-pc-windows-msvc__stable_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:stable" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:aarch64", - "@platforms//os:windows" - ], - "target_compatible_with": [ - "@platforms//cpu:aarch64", - "@platforms//os:windows" - ] - } - }, - "rust_windows_aarch64__aarch64-pc-windows-msvc__nightly_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "aarch64-pc-windows-msvc", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "aarch64-pc-windows-msvc", - "version": "nightly/2024-09-05", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_windows_aarch64__aarch64-pc-windows-msvc__nightly": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_windows_aarch64__aarch64-pc-windows-msvc__nightly_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:nightly" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:aarch64", - "@platforms//os:windows" - ], - "target_compatible_with": [ - "@platforms//cpu:aarch64", - "@platforms//os:windows" - ] - } - }, - "rust_windows_aarch64__wasm32-unknown-unknown__stable_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "aarch64-pc-windows-msvc", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "wasm32-unknown-unknown", - "version": "1.81.0", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_windows_aarch64__wasm32-unknown-unknown__stable": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_windows_aarch64__wasm32-unknown-unknown__stable_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:stable" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:aarch64", - "@platforms//os:windows" - ], - "target_compatible_with": [ - "@platforms//cpu:wasm32", - "@platforms//os:none" - ] - } - }, - "rust_windows_aarch64__wasm32-unknown-unknown__nightly_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "aarch64-pc-windows-msvc", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "wasm32-unknown-unknown", - "version": "nightly/2024-09-05", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_windows_aarch64__wasm32-unknown-unknown__nightly": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_windows_aarch64__wasm32-unknown-unknown__nightly_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:nightly" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:aarch64", - "@platforms//os:windows" - ], - "target_compatible_with": [ - "@platforms//cpu:wasm32", - "@platforms//os:none" - ] - } - }, - "rust_windows_aarch64__wasm32-wasi__stable_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "aarch64-pc-windows-msvc", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "wasm32-wasi", - "version": "1.81.0", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_windows_aarch64__wasm32-wasi__stable": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_windows_aarch64__wasm32-wasi__stable_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:stable" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:aarch64", - "@platforms//os:windows" - ], - "target_compatible_with": [ - "@platforms//cpu:wasm32", - "@platforms//os:wasi" - ] - } - }, - "rust_windows_aarch64__wasm32-wasi__nightly_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "aarch64-pc-windows-msvc", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "wasm32-wasi", - "version": "nightly/2024-09-05", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_windows_aarch64__wasm32-wasi__nightly": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_windows_aarch64__wasm32-wasi__nightly_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:nightly" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:aarch64", - "@platforms//os:windows" - ], - "target_compatible_with": [ - "@platforms//cpu:wasm32", - "@platforms//os:wasi" - ] - } - }, - "rust_windows_aarch64": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_set_repository", - "attributes": { - "toolchains": [ - "@rust_windows_aarch64__aarch64-pc-windows-msvc__stable//:toolchain", - "@rust_windows_aarch64__aarch64-pc-windows-msvc__nightly//:toolchain", - "@rust_windows_aarch64__wasm32-unknown-unknown__stable//:toolchain", - "@rust_windows_aarch64__wasm32-unknown-unknown__nightly//:toolchain", - "@rust_windows_aarch64__wasm32-wasi__stable//:toolchain", - "@rust_windows_aarch64__wasm32-wasi__nightly//:toolchain" - ] - } - }, - "rustfmt_nightly-2024-09-05__aarch64-pc-windows-msvc_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rustfmt_toolchain_tools_repository", - "attributes": { - "version": "nightly/2024-09-05", - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": {}, - "exec_triple": "aarch64-pc-windows-msvc" - } - }, - "rustfmt_nightly-2024-09-05__aarch64-pc-windows-msvc": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rustfmt_nightly-2024-09-05__aarch64-pc-windows-msvc_tools//:rustfmt_toolchain", - "toolchain_type": "@rules_rust//rust/rustfmt:toolchain_type", - "target_settings": [], - "exec_compatible_with": [ - "@platforms//cpu:aarch64", - "@platforms//os:windows" - ], - "target_compatible_with": [] - } - }, - "rust_linux_aarch64__aarch64-unknown-linux-gnu__stable_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "aarch64-unknown-linux-gnu", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "aarch64-unknown-linux-gnu", - "version": "1.81.0", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_linux_aarch64__aarch64-unknown-linux-gnu__stable": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_linux_aarch64__aarch64-unknown-linux-gnu__stable_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:stable" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:aarch64", - "@platforms//os:linux" - ], - "target_compatible_with": [ - "@platforms//cpu:aarch64", - "@platforms//os:linux" - ] - } - }, - "rust_linux_aarch64__aarch64-unknown-linux-gnu__nightly_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "aarch64-unknown-linux-gnu", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "aarch64-unknown-linux-gnu", - "version": "nightly/2024-09-05", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_linux_aarch64__aarch64-unknown-linux-gnu__nightly": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_linux_aarch64__aarch64-unknown-linux-gnu__nightly_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:nightly" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:aarch64", - "@platforms//os:linux" - ], - "target_compatible_with": [ - "@platforms//cpu:aarch64", - "@platforms//os:linux" - ] - } - }, - "rust_linux_aarch64__wasm32-unknown-unknown__stable_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "aarch64-unknown-linux-gnu", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "wasm32-unknown-unknown", - "version": "1.81.0", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_linux_aarch64__wasm32-unknown-unknown__stable": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_linux_aarch64__wasm32-unknown-unknown__stable_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:stable" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:aarch64", - "@platforms//os:linux" - ], - "target_compatible_with": [ - "@platforms//cpu:wasm32", - "@platforms//os:none" - ] - } - }, - "rust_linux_aarch64__wasm32-unknown-unknown__nightly_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "aarch64-unknown-linux-gnu", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "wasm32-unknown-unknown", - "version": "nightly/2024-09-05", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_linux_aarch64__wasm32-unknown-unknown__nightly": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_linux_aarch64__wasm32-unknown-unknown__nightly_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:nightly" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:aarch64", - "@platforms//os:linux" - ], - "target_compatible_with": [ - "@platforms//cpu:wasm32", - "@platforms//os:none" - ] - } - }, - "rust_linux_aarch64__wasm32-wasi__stable_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "aarch64-unknown-linux-gnu", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "wasm32-wasi", - "version": "1.81.0", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_linux_aarch64__wasm32-wasi__stable": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_linux_aarch64__wasm32-wasi__stable_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:stable" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:aarch64", - "@platforms//os:linux" - ], - "target_compatible_with": [ - "@platforms//cpu:wasm32", - "@platforms//os:wasi" - ] - } - }, - "rust_linux_aarch64__wasm32-wasi__nightly_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "aarch64-unknown-linux-gnu", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "wasm32-wasi", - "version": "nightly/2024-09-05", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_linux_aarch64__wasm32-wasi__nightly": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_linux_aarch64__wasm32-wasi__nightly_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:nightly" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:aarch64", - "@platforms//os:linux" - ], - "target_compatible_with": [ - "@platforms//cpu:wasm32", - "@platforms//os:wasi" - ] - } - }, - "rust_linux_aarch64": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_set_repository", - "attributes": { - "toolchains": [ - "@rust_linux_aarch64__aarch64-unknown-linux-gnu__stable//:toolchain", - "@rust_linux_aarch64__aarch64-unknown-linux-gnu__nightly//:toolchain", - "@rust_linux_aarch64__wasm32-unknown-unknown__stable//:toolchain", - "@rust_linux_aarch64__wasm32-unknown-unknown__nightly//:toolchain", - "@rust_linux_aarch64__wasm32-wasi__stable//:toolchain", - "@rust_linux_aarch64__wasm32-wasi__nightly//:toolchain" - ] - } - }, - "rustfmt_nightly-2024-09-05__aarch64-unknown-linux-gnu_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rustfmt_toolchain_tools_repository", - "attributes": { - "version": "nightly/2024-09-05", - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": {}, - "exec_triple": "aarch64-unknown-linux-gnu" - } - }, - "rustfmt_nightly-2024-09-05__aarch64-unknown-linux-gnu": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rustfmt_nightly-2024-09-05__aarch64-unknown-linux-gnu_tools//:rustfmt_toolchain", - "toolchain_type": "@rules_rust//rust/rustfmt:toolchain_type", - "target_settings": [], - "exec_compatible_with": [ - "@platforms//cpu:aarch64", - "@platforms//os:linux" - ], - "target_compatible_with": [] - } - }, - "rust_linux_s390x__s390x-unknown-linux-gnu__stable_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "s390x-unknown-linux-gnu", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "s390x-unknown-linux-gnu", - "version": "1.81.0", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_linux_s390x__s390x-unknown-linux-gnu__stable": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_linux_s390x__s390x-unknown-linux-gnu__stable_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:stable" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:s390x", - "@platforms//os:linux" - ], - "target_compatible_with": [ - "@platforms//cpu:s390x", - "@platforms//os:linux" - ] - } - }, - "rust_linux_s390x__s390x-unknown-linux-gnu__nightly_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "s390x-unknown-linux-gnu", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "s390x-unknown-linux-gnu", - "version": "nightly/2024-09-05", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_linux_s390x__s390x-unknown-linux-gnu__nightly": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_linux_s390x__s390x-unknown-linux-gnu__nightly_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:nightly" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:s390x", - "@platforms//os:linux" - ], - "target_compatible_with": [ - "@platforms//cpu:s390x", - "@platforms//os:linux" - ] - } - }, - "rust_linux_s390x__wasm32-unknown-unknown__stable_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "s390x-unknown-linux-gnu", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "wasm32-unknown-unknown", - "version": "1.81.0", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_linux_s390x__wasm32-unknown-unknown__stable": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_linux_s390x__wasm32-unknown-unknown__stable_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:stable" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:s390x", - "@platforms//os:linux" - ], - "target_compatible_with": [ - "@platforms//cpu:wasm32", - "@platforms//os:none" - ] - } - }, - "rust_linux_s390x__wasm32-unknown-unknown__nightly_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "s390x-unknown-linux-gnu", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "wasm32-unknown-unknown", - "version": "nightly/2024-09-05", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_linux_s390x__wasm32-unknown-unknown__nightly": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_linux_s390x__wasm32-unknown-unknown__nightly_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:nightly" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:s390x", - "@platforms//os:linux" - ], - "target_compatible_with": [ - "@platforms//cpu:wasm32", - "@platforms//os:none" - ] - } - }, - "rust_linux_s390x__wasm32-wasi__stable_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "s390x-unknown-linux-gnu", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "wasm32-wasi", - "version": "1.81.0", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_linux_s390x__wasm32-wasi__stable": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_linux_s390x__wasm32-wasi__stable_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:stable" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:s390x", - "@platforms//os:linux" - ], - "target_compatible_with": [ - "@platforms//cpu:wasm32", - "@platforms//os:wasi" - ] - } - }, - "rust_linux_s390x__wasm32-wasi__nightly_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "s390x-unknown-linux-gnu", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "wasm32-wasi", - "version": "nightly/2024-09-05", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_linux_s390x__wasm32-wasi__nightly": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_linux_s390x__wasm32-wasi__nightly_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:nightly" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:s390x", - "@platforms//os:linux" - ], - "target_compatible_with": [ - "@platforms//cpu:wasm32", - "@platforms//os:wasi" - ] - } - }, - "rust_linux_s390x": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_set_repository", - "attributes": { - "toolchains": [ - "@rust_linux_s390x__s390x-unknown-linux-gnu__stable//:toolchain", - "@rust_linux_s390x__s390x-unknown-linux-gnu__nightly//:toolchain", - "@rust_linux_s390x__wasm32-unknown-unknown__stable//:toolchain", - "@rust_linux_s390x__wasm32-unknown-unknown__nightly//:toolchain", - "@rust_linux_s390x__wasm32-wasi__stable//:toolchain", - "@rust_linux_s390x__wasm32-wasi__nightly//:toolchain" - ] - } - }, - "rustfmt_nightly-2024-09-05__s390x-unknown-linux-gnu_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rustfmt_toolchain_tools_repository", - "attributes": { - "version": "nightly/2024-09-05", - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": {}, - "exec_triple": "s390x-unknown-linux-gnu" - } - }, - "rustfmt_nightly-2024-09-05__s390x-unknown-linux-gnu": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rustfmt_nightly-2024-09-05__s390x-unknown-linux-gnu_tools//:rustfmt_toolchain", - "toolchain_type": "@rules_rust//rust/rustfmt:toolchain_type", - "target_settings": [], - "exec_compatible_with": [ - "@platforms//cpu:s390x", - "@platforms//os:linux" - ], - "target_compatible_with": [] - } - }, - "rust_darwin_x86_64__x86_64-apple-darwin__stable_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "x86_64-apple-darwin", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "x86_64-apple-darwin", - "version": "1.81.0", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_darwin_x86_64__x86_64-apple-darwin__stable": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_darwin_x86_64__x86_64-apple-darwin__stable_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:stable" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:osx" - ], - "target_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:osx" - ] - } - }, - "rust_darwin_x86_64__x86_64-apple-darwin__nightly_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "x86_64-apple-darwin", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "x86_64-apple-darwin", - "version": "nightly/2024-09-05", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_darwin_x86_64__x86_64-apple-darwin__nightly": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_darwin_x86_64__x86_64-apple-darwin__nightly_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:nightly" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:osx" - ], - "target_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:osx" - ] - } - }, - "rust_darwin_x86_64__wasm32-unknown-unknown__stable_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "x86_64-apple-darwin", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "wasm32-unknown-unknown", - "version": "1.81.0", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_darwin_x86_64__wasm32-unknown-unknown__stable": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_darwin_x86_64__wasm32-unknown-unknown__stable_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:stable" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:osx" - ], - "target_compatible_with": [ - "@platforms//cpu:wasm32", - "@platforms//os:none" - ] - } - }, - "rust_darwin_x86_64__wasm32-unknown-unknown__nightly_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "x86_64-apple-darwin", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "wasm32-unknown-unknown", - "version": "nightly/2024-09-05", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_darwin_x86_64__wasm32-unknown-unknown__nightly": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_darwin_x86_64__wasm32-unknown-unknown__nightly_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:nightly" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:osx" - ], - "target_compatible_with": [ - "@platforms//cpu:wasm32", - "@platforms//os:none" - ] - } - }, - "rust_darwin_x86_64__wasm32-wasi__stable_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "x86_64-apple-darwin", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "wasm32-wasi", - "version": "1.81.0", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_darwin_x86_64__wasm32-wasi__stable": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_darwin_x86_64__wasm32-wasi__stable_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:stable" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:osx" - ], - "target_compatible_with": [ - "@platforms//cpu:wasm32", - "@platforms//os:wasi" - ] - } - }, - "rust_darwin_x86_64__wasm32-wasi__nightly_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "x86_64-apple-darwin", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "wasm32-wasi", - "version": "nightly/2024-09-05", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_darwin_x86_64__wasm32-wasi__nightly": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_darwin_x86_64__wasm32-wasi__nightly_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:nightly" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:osx" - ], - "target_compatible_with": [ - "@platforms//cpu:wasm32", - "@platforms//os:wasi" - ] - } - }, - "rust_darwin_x86_64": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_set_repository", - "attributes": { - "toolchains": [ - "@rust_darwin_x86_64__x86_64-apple-darwin__stable//:toolchain", - "@rust_darwin_x86_64__x86_64-apple-darwin__nightly//:toolchain", - "@rust_darwin_x86_64__wasm32-unknown-unknown__stable//:toolchain", - "@rust_darwin_x86_64__wasm32-unknown-unknown__nightly//:toolchain", - "@rust_darwin_x86_64__wasm32-wasi__stable//:toolchain", - "@rust_darwin_x86_64__wasm32-wasi__nightly//:toolchain" - ] - } - }, - "rustfmt_nightly-2024-09-05__x86_64-apple-darwin_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rustfmt_toolchain_tools_repository", - "attributes": { - "version": "nightly/2024-09-05", - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": {}, - "exec_triple": "x86_64-apple-darwin" - } - }, - "rustfmt_nightly-2024-09-05__x86_64-apple-darwin": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rustfmt_nightly-2024-09-05__x86_64-apple-darwin_tools//:rustfmt_toolchain", - "toolchain_type": "@rules_rust//rust/rustfmt:toolchain_type", - "target_settings": [], - "exec_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:osx" - ], - "target_compatible_with": [] - } - }, - "rust_windows_x86_64__x86_64-pc-windows-msvc__stable_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "x86_64-pc-windows-msvc", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "x86_64-pc-windows-msvc", - "version": "1.81.0", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_windows_x86_64__x86_64-pc-windows-msvc__stable": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_windows_x86_64__x86_64-pc-windows-msvc__stable_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:stable" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:windows" - ], - "target_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:windows" - ] - } - }, - "rust_windows_x86_64__x86_64-pc-windows-msvc__nightly_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "x86_64-pc-windows-msvc", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "x86_64-pc-windows-msvc", - "version": "nightly/2024-09-05", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_windows_x86_64__x86_64-pc-windows-msvc__nightly": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_windows_x86_64__x86_64-pc-windows-msvc__nightly_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:nightly" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:windows" - ], - "target_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:windows" - ] - } - }, - "rust_windows_x86_64__wasm32-unknown-unknown__stable_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "x86_64-pc-windows-msvc", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "wasm32-unknown-unknown", - "version": "1.81.0", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_windows_x86_64__wasm32-unknown-unknown__stable": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_windows_x86_64__wasm32-unknown-unknown__stable_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:stable" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:windows" - ], - "target_compatible_with": [ - "@platforms//cpu:wasm32", - "@platforms//os:none" - ] - } - }, - "rust_windows_x86_64__wasm32-unknown-unknown__nightly_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "x86_64-pc-windows-msvc", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "wasm32-unknown-unknown", - "version": "nightly/2024-09-05", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_windows_x86_64__wasm32-unknown-unknown__nightly": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_windows_x86_64__wasm32-unknown-unknown__nightly_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:nightly" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:windows" - ], - "target_compatible_with": [ - "@platforms//cpu:wasm32", - "@platforms//os:none" - ] - } - }, - "rust_windows_x86_64__wasm32-wasi__stable_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "x86_64-pc-windows-msvc", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "wasm32-wasi", - "version": "1.81.0", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_windows_x86_64__wasm32-wasi__stable": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_windows_x86_64__wasm32-wasi__stable_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:stable" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:windows" - ], - "target_compatible_with": [ - "@platforms//cpu:wasm32", - "@platforms//os:wasi" - ] - } - }, - "rust_windows_x86_64__wasm32-wasi__nightly_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "x86_64-pc-windows-msvc", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "wasm32-wasi", - "version": "nightly/2024-09-05", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_windows_x86_64__wasm32-wasi__nightly": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_windows_x86_64__wasm32-wasi__nightly_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:nightly" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:windows" - ], - "target_compatible_with": [ - "@platforms//cpu:wasm32", - "@platforms//os:wasi" - ] - } - }, - "rust_windows_x86_64": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_set_repository", - "attributes": { - "toolchains": [ - "@rust_windows_x86_64__x86_64-pc-windows-msvc__stable//:toolchain", - "@rust_windows_x86_64__x86_64-pc-windows-msvc__nightly//:toolchain", - "@rust_windows_x86_64__wasm32-unknown-unknown__stable//:toolchain", - "@rust_windows_x86_64__wasm32-unknown-unknown__nightly//:toolchain", - "@rust_windows_x86_64__wasm32-wasi__stable//:toolchain", - "@rust_windows_x86_64__wasm32-wasi__nightly//:toolchain" - ] - } - }, - "rustfmt_nightly-2024-09-05__x86_64-pc-windows-msvc_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rustfmt_toolchain_tools_repository", - "attributes": { - "version": "nightly/2024-09-05", - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": {}, - "exec_triple": "x86_64-pc-windows-msvc" - } - }, - "rustfmt_nightly-2024-09-05__x86_64-pc-windows-msvc": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rustfmt_nightly-2024-09-05__x86_64-pc-windows-msvc_tools//:rustfmt_toolchain", - "toolchain_type": "@rules_rust//rust/rustfmt:toolchain_type", - "target_settings": [], - "exec_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:windows" - ], - "target_compatible_with": [] - } - }, - "rust_freebsd_x86_64__x86_64-unknown-freebsd__stable_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "x86_64-unknown-freebsd", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "x86_64-unknown-freebsd", - "version": "1.81.0", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_freebsd_x86_64__x86_64-unknown-freebsd__stable": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_freebsd_x86_64__x86_64-unknown-freebsd__stable_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:stable" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:freebsd" - ], - "target_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:freebsd" - ] - } - }, - "rust_freebsd_x86_64__x86_64-unknown-freebsd__nightly_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "x86_64-unknown-freebsd", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "x86_64-unknown-freebsd", - "version": "nightly/2024-09-05", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_freebsd_x86_64__x86_64-unknown-freebsd__nightly": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_freebsd_x86_64__x86_64-unknown-freebsd__nightly_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:nightly" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:freebsd" - ], - "target_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:freebsd" - ] - } - }, - "rust_freebsd_x86_64__wasm32-unknown-unknown__stable_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "x86_64-unknown-freebsd", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "wasm32-unknown-unknown", - "version": "1.81.0", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_freebsd_x86_64__wasm32-unknown-unknown__stable": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_freebsd_x86_64__wasm32-unknown-unknown__stable_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:stable" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:freebsd" - ], - "target_compatible_with": [ - "@platforms//cpu:wasm32", - "@platforms//os:none" - ] - } - }, - "rust_freebsd_x86_64__wasm32-unknown-unknown__nightly_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "x86_64-unknown-freebsd", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "wasm32-unknown-unknown", - "version": "nightly/2024-09-05", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_freebsd_x86_64__wasm32-unknown-unknown__nightly": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_freebsd_x86_64__wasm32-unknown-unknown__nightly_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:nightly" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:freebsd" - ], - "target_compatible_with": [ - "@platforms//cpu:wasm32", - "@platforms//os:none" - ] - } - }, - "rust_freebsd_x86_64__wasm32-wasi__stable_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "x86_64-unknown-freebsd", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "wasm32-wasi", - "version": "1.81.0", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_freebsd_x86_64__wasm32-wasi__stable": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_freebsd_x86_64__wasm32-wasi__stable_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:stable" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:freebsd" - ], - "target_compatible_with": [ - "@platforms//cpu:wasm32", - "@platforms//os:wasi" - ] - } - }, - "rust_freebsd_x86_64__wasm32-wasi__nightly_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "x86_64-unknown-freebsd", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "wasm32-wasi", - "version": "nightly/2024-09-05", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_freebsd_x86_64__wasm32-wasi__nightly": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_freebsd_x86_64__wasm32-wasi__nightly_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:nightly" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:freebsd" - ], - "target_compatible_with": [ - "@platforms//cpu:wasm32", - "@platforms//os:wasi" - ] - } - }, - "rust_freebsd_x86_64": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_set_repository", - "attributes": { - "toolchains": [ - "@rust_freebsd_x86_64__x86_64-unknown-freebsd__stable//:toolchain", - "@rust_freebsd_x86_64__x86_64-unknown-freebsd__nightly//:toolchain", - "@rust_freebsd_x86_64__wasm32-unknown-unknown__stable//:toolchain", - "@rust_freebsd_x86_64__wasm32-unknown-unknown__nightly//:toolchain", - "@rust_freebsd_x86_64__wasm32-wasi__stable//:toolchain", - "@rust_freebsd_x86_64__wasm32-wasi__nightly//:toolchain" - ] - } - }, - "rustfmt_nightly-2024-09-05__x86_64-unknown-freebsd_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rustfmt_toolchain_tools_repository", - "attributes": { - "version": "nightly/2024-09-05", - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": {}, - "exec_triple": "x86_64-unknown-freebsd" - } - }, - "rustfmt_nightly-2024-09-05__x86_64-unknown-freebsd": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rustfmt_nightly-2024-09-05__x86_64-unknown-freebsd_tools//:rustfmt_toolchain", - "toolchain_type": "@rules_rust//rust/rustfmt:toolchain_type", - "target_settings": [], - "exec_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:freebsd" - ], - "target_compatible_with": [] - } - }, - "rust_linux_x86_64__x86_64-unknown-linux-gnu__stable_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "x86_64-unknown-linux-gnu", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "x86_64-unknown-linux-gnu", - "version": "1.81.0", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_linux_x86_64__x86_64-unknown-linux-gnu__stable": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_linux_x86_64__x86_64-unknown-linux-gnu__stable_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:stable" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:linux" - ], - "target_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:linux" - ] - } - }, - "rust_linux_x86_64__x86_64-unknown-linux-gnu__nightly_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "x86_64-unknown-linux-gnu", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "x86_64-unknown-linux-gnu", - "version": "nightly/2024-09-05", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_linux_x86_64__x86_64-unknown-linux-gnu__nightly": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_linux_x86_64__x86_64-unknown-linux-gnu__nightly_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:nightly" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:linux" - ], - "target_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:linux" - ] - } - }, - "rust_linux_x86_64__wasm32-unknown-unknown__stable_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "x86_64-unknown-linux-gnu", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "wasm32-unknown-unknown", - "version": "1.81.0", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_linux_x86_64__wasm32-unknown-unknown__stable": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_linux_x86_64__wasm32-unknown-unknown__stable_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:stable" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:linux" - ], - "target_compatible_with": [ - "@platforms//cpu:wasm32", - "@platforms//os:none" - ] - } - }, - "rust_linux_x86_64__wasm32-unknown-unknown__nightly_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "x86_64-unknown-linux-gnu", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "wasm32-unknown-unknown", - "version": "nightly/2024-09-05", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_linux_x86_64__wasm32-unknown-unknown__nightly": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_linux_x86_64__wasm32-unknown-unknown__nightly_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:nightly" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:linux" - ], - "target_compatible_with": [ - "@platforms//cpu:wasm32", - "@platforms//os:none" - ] - } - }, - "rust_linux_x86_64__wasm32-wasi__stable_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "x86_64-unknown-linux-gnu", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "wasm32-wasi", - "version": "1.81.0", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_linux_x86_64__wasm32-wasi__stable": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_linux_x86_64__wasm32-wasi__stable_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:stable" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:linux" - ], - "target_compatible_with": [ - "@platforms//cpu:wasm32", - "@platforms//os:wasi" - ] - } - }, - "rust_linux_x86_64__wasm32-wasi__nightly_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_tools_repository", - "attributes": { - "exec_triple": "x86_64-unknown-linux-gnu", - "allocator_library": "@rules_rust//ffi/cc/allocator_library", - "global_allocator_library": "@rules_rust//ffi/cc/global_allocator_library", - "target_triple": "wasm32-wasi", - "version": "nightly/2024-09-05", - "rustfmt_version": "nightly/2024-09-05", - "edition": "2021", - "dev_components": false, - "extra_rustc_flags": [], - "extra_exec_rustc_flags": [], - "opt_level": {}, - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": [] - } - }, - "rust_linux_x86_64__wasm32-wasi__nightly": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rust_linux_x86_64__wasm32-wasi__nightly_tools//:rust_toolchain", - "target_settings": [ - "@rules_rust//rust/toolchain/channel:nightly" - ], - "toolchain_type": "@rules_rust//rust:toolchain", - "exec_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:linux" - ], - "target_compatible_with": [ - "@platforms//cpu:wasm32", - "@platforms//os:wasi" - ] - } - }, - "rust_linux_x86_64": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rust_toolchain_set_repository", - "attributes": { - "toolchains": [ - "@rust_linux_x86_64__x86_64-unknown-linux-gnu__stable//:toolchain", - "@rust_linux_x86_64__x86_64-unknown-linux-gnu__nightly//:toolchain", - "@rust_linux_x86_64__wasm32-unknown-unknown__stable//:toolchain", - "@rust_linux_x86_64__wasm32-unknown-unknown__nightly//:toolchain", - "@rust_linux_x86_64__wasm32-wasi__stable//:toolchain", - "@rust_linux_x86_64__wasm32-wasi__nightly//:toolchain" - ] - } - }, - "rustfmt_nightly-2024-09-05__x86_64-unknown-linux-gnu_tools": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%rustfmt_toolchain_tools_repository", - "attributes": { - "version": "nightly/2024-09-05", - "sha256s": {}, - "urls": [ - "https://static.rust-lang.org/dist/{}.tar.xz" - ], - "auth": {}, - "netrc": "", - "auth_patterns": {}, - "exec_triple": "x86_64-unknown-linux-gnu" - } - }, - "rustfmt_nightly-2024-09-05__x86_64-unknown-linux-gnu": { - "repoRuleId": "@@rules_rust+//rust:repositories.bzl%toolchain_repository_proxy", - "attributes": { - "toolchain": "@rustfmt_nightly-2024-09-05__x86_64-unknown-linux-gnu_tools//:rustfmt_toolchain", - "toolchain_type": "@rules_rust//rust/rustfmt:toolchain_type", - "target_settings": [], - "exec_compatible_with": [ - "@platforms//cpu:x86_64", - "@platforms//os:linux" - ], - "target_compatible_with": [] - } - }, - "rust_toolchains": { - "repoRuleId": "@@rules_rust+//rust/private:repository_utils.bzl%toolchain_repository_hub", - "attributes": { - "toolchain_names": [ - "rust_analyzer_1.81.0", - "rust_darwin_aarch64__aarch64-apple-darwin__stable", - "rust_darwin_aarch64__aarch64-apple-darwin__nightly", - "rust_darwin_aarch64__wasm32-unknown-unknown__stable", - "rust_darwin_aarch64__wasm32-unknown-unknown__nightly", - "rust_darwin_aarch64__wasm32-wasi__stable", - "rust_darwin_aarch64__wasm32-wasi__nightly", - "rustfmt_nightly-2024-09-05__aarch64-apple-darwin", - "rust_windows_aarch64__aarch64-pc-windows-msvc__stable", - "rust_windows_aarch64__aarch64-pc-windows-msvc__nightly", - "rust_windows_aarch64__wasm32-unknown-unknown__stable", - "rust_windows_aarch64__wasm32-unknown-unknown__nightly", - "rust_windows_aarch64__wasm32-wasi__stable", - "rust_windows_aarch64__wasm32-wasi__nightly", - "rustfmt_nightly-2024-09-05__aarch64-pc-windows-msvc", - "rust_linux_aarch64__aarch64-unknown-linux-gnu__stable", - "rust_linux_aarch64__aarch64-unknown-linux-gnu__nightly", - "rust_linux_aarch64__wasm32-unknown-unknown__stable", - "rust_linux_aarch64__wasm32-unknown-unknown__nightly", - "rust_linux_aarch64__wasm32-wasi__stable", - "rust_linux_aarch64__wasm32-wasi__nightly", - "rustfmt_nightly-2024-09-05__aarch64-unknown-linux-gnu", - "rust_linux_s390x__s390x-unknown-linux-gnu__stable", - "rust_linux_s390x__s390x-unknown-linux-gnu__nightly", - "rust_linux_s390x__wasm32-unknown-unknown__stable", - "rust_linux_s390x__wasm32-unknown-unknown__nightly", - "rust_linux_s390x__wasm32-wasi__stable", - "rust_linux_s390x__wasm32-wasi__nightly", - "rustfmt_nightly-2024-09-05__s390x-unknown-linux-gnu", - "rust_darwin_x86_64__x86_64-apple-darwin__stable", - "rust_darwin_x86_64__x86_64-apple-darwin__nightly", - "rust_darwin_x86_64__wasm32-unknown-unknown__stable", - "rust_darwin_x86_64__wasm32-unknown-unknown__nightly", - "rust_darwin_x86_64__wasm32-wasi__stable", - "rust_darwin_x86_64__wasm32-wasi__nightly", - "rustfmt_nightly-2024-09-05__x86_64-apple-darwin", - "rust_windows_x86_64__x86_64-pc-windows-msvc__stable", - "rust_windows_x86_64__x86_64-pc-windows-msvc__nightly", - "rust_windows_x86_64__wasm32-unknown-unknown__stable", - "rust_windows_x86_64__wasm32-unknown-unknown__nightly", - "rust_windows_x86_64__wasm32-wasi__stable", - "rust_windows_x86_64__wasm32-wasi__nightly", - "rustfmt_nightly-2024-09-05__x86_64-pc-windows-msvc", - "rust_freebsd_x86_64__x86_64-unknown-freebsd__stable", - "rust_freebsd_x86_64__x86_64-unknown-freebsd__nightly", - "rust_freebsd_x86_64__wasm32-unknown-unknown__stable", - "rust_freebsd_x86_64__wasm32-unknown-unknown__nightly", - "rust_freebsd_x86_64__wasm32-wasi__stable", - "rust_freebsd_x86_64__wasm32-wasi__nightly", - "rustfmt_nightly-2024-09-05__x86_64-unknown-freebsd", - "rust_linux_x86_64__x86_64-unknown-linux-gnu__stable", - "rust_linux_x86_64__x86_64-unknown-linux-gnu__nightly", - "rust_linux_x86_64__wasm32-unknown-unknown__stable", - "rust_linux_x86_64__wasm32-unknown-unknown__nightly", - "rust_linux_x86_64__wasm32-wasi__stable", - "rust_linux_x86_64__wasm32-wasi__nightly", - "rustfmt_nightly-2024-09-05__x86_64-unknown-linux-gnu" - ], - "toolchain_labels": { - "rust_analyzer_1.81.0": "@rust_analyzer_1.81.0_tools//:rust_analyzer_toolchain", - "rust_darwin_aarch64__aarch64-apple-darwin__stable": "@rust_darwin_aarch64__aarch64-apple-darwin__stable_tools//:rust_toolchain", - "rust_darwin_aarch64__aarch64-apple-darwin__nightly": "@rust_darwin_aarch64__aarch64-apple-darwin__nightly_tools//:rust_toolchain", - "rust_darwin_aarch64__wasm32-unknown-unknown__stable": "@rust_darwin_aarch64__wasm32-unknown-unknown__stable_tools//:rust_toolchain", - "rust_darwin_aarch64__wasm32-unknown-unknown__nightly": "@rust_darwin_aarch64__wasm32-unknown-unknown__nightly_tools//:rust_toolchain", - "rust_darwin_aarch64__wasm32-wasi__stable": "@rust_darwin_aarch64__wasm32-wasi__stable_tools//:rust_toolchain", - "rust_darwin_aarch64__wasm32-wasi__nightly": "@rust_darwin_aarch64__wasm32-wasi__nightly_tools//:rust_toolchain", - "rustfmt_nightly-2024-09-05__aarch64-apple-darwin": "@rustfmt_nightly-2024-09-05__aarch64-apple-darwin_tools//:rustfmt_toolchain", - "rust_windows_aarch64__aarch64-pc-windows-msvc__stable": "@rust_windows_aarch64__aarch64-pc-windows-msvc__stable_tools//:rust_toolchain", - "rust_windows_aarch64__aarch64-pc-windows-msvc__nightly": "@rust_windows_aarch64__aarch64-pc-windows-msvc__nightly_tools//:rust_toolchain", - "rust_windows_aarch64__wasm32-unknown-unknown__stable": "@rust_windows_aarch64__wasm32-unknown-unknown__stable_tools//:rust_toolchain", - "rust_windows_aarch64__wasm32-unknown-unknown__nightly": "@rust_windows_aarch64__wasm32-unknown-unknown__nightly_tools//:rust_toolchain", - "rust_windows_aarch64__wasm32-wasi__stable": "@rust_windows_aarch64__wasm32-wasi__stable_tools//:rust_toolchain", - "rust_windows_aarch64__wasm32-wasi__nightly": "@rust_windows_aarch64__wasm32-wasi__nightly_tools//:rust_toolchain", - "rustfmt_nightly-2024-09-05__aarch64-pc-windows-msvc": "@rustfmt_nightly-2024-09-05__aarch64-pc-windows-msvc_tools//:rustfmt_toolchain", - "rust_linux_aarch64__aarch64-unknown-linux-gnu__stable": "@rust_linux_aarch64__aarch64-unknown-linux-gnu__stable_tools//:rust_toolchain", - "rust_linux_aarch64__aarch64-unknown-linux-gnu__nightly": "@rust_linux_aarch64__aarch64-unknown-linux-gnu__nightly_tools//:rust_toolchain", - "rust_linux_aarch64__wasm32-unknown-unknown__stable": "@rust_linux_aarch64__wasm32-unknown-unknown__stable_tools//:rust_toolchain", - "rust_linux_aarch64__wasm32-unknown-unknown__nightly": "@rust_linux_aarch64__wasm32-unknown-unknown__nightly_tools//:rust_toolchain", - "rust_linux_aarch64__wasm32-wasi__stable": "@rust_linux_aarch64__wasm32-wasi__stable_tools//:rust_toolchain", - "rust_linux_aarch64__wasm32-wasi__nightly": "@rust_linux_aarch64__wasm32-wasi__nightly_tools//:rust_toolchain", - "rustfmt_nightly-2024-09-05__aarch64-unknown-linux-gnu": "@rustfmt_nightly-2024-09-05__aarch64-unknown-linux-gnu_tools//:rustfmt_toolchain", - "rust_linux_s390x__s390x-unknown-linux-gnu__stable": "@rust_linux_s390x__s390x-unknown-linux-gnu__stable_tools//:rust_toolchain", - "rust_linux_s390x__s390x-unknown-linux-gnu__nightly": "@rust_linux_s390x__s390x-unknown-linux-gnu__nightly_tools//:rust_toolchain", - "rust_linux_s390x__wasm32-unknown-unknown__stable": "@rust_linux_s390x__wasm32-unknown-unknown__stable_tools//:rust_toolchain", - "rust_linux_s390x__wasm32-unknown-unknown__nightly": "@rust_linux_s390x__wasm32-unknown-unknown__nightly_tools//:rust_toolchain", - "rust_linux_s390x__wasm32-wasi__stable": "@rust_linux_s390x__wasm32-wasi__stable_tools//:rust_toolchain", - "rust_linux_s390x__wasm32-wasi__nightly": "@rust_linux_s390x__wasm32-wasi__nightly_tools//:rust_toolchain", - "rustfmt_nightly-2024-09-05__s390x-unknown-linux-gnu": "@rustfmt_nightly-2024-09-05__s390x-unknown-linux-gnu_tools//:rustfmt_toolchain", - "rust_darwin_x86_64__x86_64-apple-darwin__stable": "@rust_darwin_x86_64__x86_64-apple-darwin__stable_tools//:rust_toolchain", - "rust_darwin_x86_64__x86_64-apple-darwin__nightly": "@rust_darwin_x86_64__x86_64-apple-darwin__nightly_tools//:rust_toolchain", - "rust_darwin_x86_64__wasm32-unknown-unknown__stable": "@rust_darwin_x86_64__wasm32-unknown-unknown__stable_tools//:rust_toolchain", - "rust_darwin_x86_64__wasm32-unknown-unknown__nightly": "@rust_darwin_x86_64__wasm32-unknown-unknown__nightly_tools//:rust_toolchain", - "rust_darwin_x86_64__wasm32-wasi__stable": "@rust_darwin_x86_64__wasm32-wasi__stable_tools//:rust_toolchain", - "rust_darwin_x86_64__wasm32-wasi__nightly": "@rust_darwin_x86_64__wasm32-wasi__nightly_tools//:rust_toolchain", - "rustfmt_nightly-2024-09-05__x86_64-apple-darwin": "@rustfmt_nightly-2024-09-05__x86_64-apple-darwin_tools//:rustfmt_toolchain", - "rust_windows_x86_64__x86_64-pc-windows-msvc__stable": "@rust_windows_x86_64__x86_64-pc-windows-msvc__stable_tools//:rust_toolchain", - "rust_windows_x86_64__x86_64-pc-windows-msvc__nightly": "@rust_windows_x86_64__x86_64-pc-windows-msvc__nightly_tools//:rust_toolchain", - "rust_windows_x86_64__wasm32-unknown-unknown__stable": "@rust_windows_x86_64__wasm32-unknown-unknown__stable_tools//:rust_toolchain", - "rust_windows_x86_64__wasm32-unknown-unknown__nightly": "@rust_windows_x86_64__wasm32-unknown-unknown__nightly_tools//:rust_toolchain", - "rust_windows_x86_64__wasm32-wasi__stable": "@rust_windows_x86_64__wasm32-wasi__stable_tools//:rust_toolchain", - "rust_windows_x86_64__wasm32-wasi__nightly": "@rust_windows_x86_64__wasm32-wasi__nightly_tools//:rust_toolchain", - "rustfmt_nightly-2024-09-05__x86_64-pc-windows-msvc": "@rustfmt_nightly-2024-09-05__x86_64-pc-windows-msvc_tools//:rustfmt_toolchain", - "rust_freebsd_x86_64__x86_64-unknown-freebsd__stable": "@rust_freebsd_x86_64__x86_64-unknown-freebsd__stable_tools//:rust_toolchain", - "rust_freebsd_x86_64__x86_64-unknown-freebsd__nightly": "@rust_freebsd_x86_64__x86_64-unknown-freebsd__nightly_tools//:rust_toolchain", - "rust_freebsd_x86_64__wasm32-unknown-unknown__stable": "@rust_freebsd_x86_64__wasm32-unknown-unknown__stable_tools//:rust_toolchain", - "rust_freebsd_x86_64__wasm32-unknown-unknown__nightly": "@rust_freebsd_x86_64__wasm32-unknown-unknown__nightly_tools//:rust_toolchain", - "rust_freebsd_x86_64__wasm32-wasi__stable": "@rust_freebsd_x86_64__wasm32-wasi__stable_tools//:rust_toolchain", - "rust_freebsd_x86_64__wasm32-wasi__nightly": "@rust_freebsd_x86_64__wasm32-wasi__nightly_tools//:rust_toolchain", - "rustfmt_nightly-2024-09-05__x86_64-unknown-freebsd": "@rustfmt_nightly-2024-09-05__x86_64-unknown-freebsd_tools//:rustfmt_toolchain", - "rust_linux_x86_64__x86_64-unknown-linux-gnu__stable": "@rust_linux_x86_64__x86_64-unknown-linux-gnu__stable_tools//:rust_toolchain", - "rust_linux_x86_64__x86_64-unknown-linux-gnu__nightly": "@rust_linux_x86_64__x86_64-unknown-linux-gnu__nightly_tools//:rust_toolchain", - "rust_linux_x86_64__wasm32-unknown-unknown__stable": "@rust_linux_x86_64__wasm32-unknown-unknown__stable_tools//:rust_toolchain", - "rust_linux_x86_64__wasm32-unknown-unknown__nightly": "@rust_linux_x86_64__wasm32-unknown-unknown__nightly_tools//:rust_toolchain", - "rust_linux_x86_64__wasm32-wasi__stable": "@rust_linux_x86_64__wasm32-wasi__stable_tools//:rust_toolchain", - "rust_linux_x86_64__wasm32-wasi__nightly": "@rust_linux_x86_64__wasm32-wasi__nightly_tools//:rust_toolchain", - "rustfmt_nightly-2024-09-05__x86_64-unknown-linux-gnu": "@rustfmt_nightly-2024-09-05__x86_64-unknown-linux-gnu_tools//:rustfmt_toolchain" - }, - "toolchain_types": { - "rust_analyzer_1.81.0": "@rules_rust//rust/rust_analyzer:toolchain_type", - "rust_darwin_aarch64__aarch64-apple-darwin__stable": "@rules_rust//rust:toolchain", - "rust_darwin_aarch64__aarch64-apple-darwin__nightly": "@rules_rust//rust:toolchain", - "rust_darwin_aarch64__wasm32-unknown-unknown__stable": "@rules_rust//rust:toolchain", - "rust_darwin_aarch64__wasm32-unknown-unknown__nightly": "@rules_rust//rust:toolchain", - "rust_darwin_aarch64__wasm32-wasi__stable": "@rules_rust//rust:toolchain", - "rust_darwin_aarch64__wasm32-wasi__nightly": "@rules_rust//rust:toolchain", - "rustfmt_nightly-2024-09-05__aarch64-apple-darwin": "@rules_rust//rust/rustfmt:toolchain_type", - "rust_windows_aarch64__aarch64-pc-windows-msvc__stable": "@rules_rust//rust:toolchain", - "rust_windows_aarch64__aarch64-pc-windows-msvc__nightly": "@rules_rust//rust:toolchain", - "rust_windows_aarch64__wasm32-unknown-unknown__stable": "@rules_rust//rust:toolchain", - "rust_windows_aarch64__wasm32-unknown-unknown__nightly": "@rules_rust//rust:toolchain", - "rust_windows_aarch64__wasm32-wasi__stable": "@rules_rust//rust:toolchain", - "rust_windows_aarch64__wasm32-wasi__nightly": "@rules_rust//rust:toolchain", - "rustfmt_nightly-2024-09-05__aarch64-pc-windows-msvc": "@rules_rust//rust/rustfmt:toolchain_type", - "rust_linux_aarch64__aarch64-unknown-linux-gnu__stable": "@rules_rust//rust:toolchain", - "rust_linux_aarch64__aarch64-unknown-linux-gnu__nightly": "@rules_rust//rust:toolchain", - "rust_linux_aarch64__wasm32-unknown-unknown__stable": "@rules_rust//rust:toolchain", - "rust_linux_aarch64__wasm32-unknown-unknown__nightly": "@rules_rust//rust:toolchain", - "rust_linux_aarch64__wasm32-wasi__stable": "@rules_rust//rust:toolchain", - "rust_linux_aarch64__wasm32-wasi__nightly": "@rules_rust//rust:toolchain", - "rustfmt_nightly-2024-09-05__aarch64-unknown-linux-gnu": "@rules_rust//rust/rustfmt:toolchain_type", - "rust_linux_s390x__s390x-unknown-linux-gnu__stable": "@rules_rust//rust:toolchain", - "rust_linux_s390x__s390x-unknown-linux-gnu__nightly": "@rules_rust//rust:toolchain", - "rust_linux_s390x__wasm32-unknown-unknown__stable": "@rules_rust//rust:toolchain", - "rust_linux_s390x__wasm32-unknown-unknown__nightly": "@rules_rust//rust:toolchain", - "rust_linux_s390x__wasm32-wasi__stable": "@rules_rust//rust:toolchain", - "rust_linux_s390x__wasm32-wasi__nightly": "@rules_rust//rust:toolchain", - "rustfmt_nightly-2024-09-05__s390x-unknown-linux-gnu": "@rules_rust//rust/rustfmt:toolchain_type", - "rust_darwin_x86_64__x86_64-apple-darwin__stable": "@rules_rust//rust:toolchain", - "rust_darwin_x86_64__x86_64-apple-darwin__nightly": "@rules_rust//rust:toolchain", - "rust_darwin_x86_64__wasm32-unknown-unknown__stable": "@rules_rust//rust:toolchain", - "rust_darwin_x86_64__wasm32-unknown-unknown__nightly": "@rules_rust//rust:toolchain", - "rust_darwin_x86_64__wasm32-wasi__stable": "@rules_rust//rust:toolchain", - "rust_darwin_x86_64__wasm32-wasi__nightly": "@rules_rust//rust:toolchain", - "rustfmt_nightly-2024-09-05__x86_64-apple-darwin": "@rules_rust//rust/rustfmt:toolchain_type", - "rust_windows_x86_64__x86_64-pc-windows-msvc__stable": "@rules_rust//rust:toolchain", - "rust_windows_x86_64__x86_64-pc-windows-msvc__nightly": "@rules_rust//rust:toolchain", - "rust_windows_x86_64__wasm32-unknown-unknown__stable": "@rules_rust//rust:toolchain", - "rust_windows_x86_64__wasm32-unknown-unknown__nightly": "@rules_rust//rust:toolchain", - "rust_windows_x86_64__wasm32-wasi__stable": "@rules_rust//rust:toolchain", - "rust_windows_x86_64__wasm32-wasi__nightly": "@rules_rust//rust:toolchain", - "rustfmt_nightly-2024-09-05__x86_64-pc-windows-msvc": "@rules_rust//rust/rustfmt:toolchain_type", - "rust_freebsd_x86_64__x86_64-unknown-freebsd__stable": "@rules_rust//rust:toolchain", - "rust_freebsd_x86_64__x86_64-unknown-freebsd__nightly": "@rules_rust//rust:toolchain", - "rust_freebsd_x86_64__wasm32-unknown-unknown__stable": "@rules_rust//rust:toolchain", - "rust_freebsd_x86_64__wasm32-unknown-unknown__nightly": "@rules_rust//rust:toolchain", - "rust_freebsd_x86_64__wasm32-wasi__stable": "@rules_rust//rust:toolchain", - "rust_freebsd_x86_64__wasm32-wasi__nightly": "@rules_rust//rust:toolchain", - "rustfmt_nightly-2024-09-05__x86_64-unknown-freebsd": "@rules_rust//rust/rustfmt:toolchain_type", - "rust_linux_x86_64__x86_64-unknown-linux-gnu__stable": "@rules_rust//rust:toolchain", - "rust_linux_x86_64__x86_64-unknown-linux-gnu__nightly": "@rules_rust//rust:toolchain", - "rust_linux_x86_64__wasm32-unknown-unknown__stable": "@rules_rust//rust:toolchain", - "rust_linux_x86_64__wasm32-unknown-unknown__nightly": "@rules_rust//rust:toolchain", - "rust_linux_x86_64__wasm32-wasi__stable": "@rules_rust//rust:toolchain", - "rust_linux_x86_64__wasm32-wasi__nightly": "@rules_rust//rust:toolchain", - "rustfmt_nightly-2024-09-05__x86_64-unknown-linux-gnu": "@rules_rust//rust/rustfmt:toolchain_type" - }, - "exec_compatible_with": { - "rust_analyzer_1.81.0": [], - "rust_darwin_aarch64__aarch64-apple-darwin__stable": [ - "@platforms//cpu:aarch64", - "@platforms//os:osx" - ], - "rust_darwin_aarch64__aarch64-apple-darwin__nightly": [ - "@platforms//cpu:aarch64", - "@platforms//os:osx" - ], - "rust_darwin_aarch64__wasm32-unknown-unknown__stable": [ - "@platforms//cpu:aarch64", - "@platforms//os:osx" - ], - "rust_darwin_aarch64__wasm32-unknown-unknown__nightly": [ - "@platforms//cpu:aarch64", - "@platforms//os:osx" - ], - "rust_darwin_aarch64__wasm32-wasi__stable": [ - "@platforms//cpu:aarch64", - "@platforms//os:osx" - ], - "rust_darwin_aarch64__wasm32-wasi__nightly": [ - "@platforms//cpu:aarch64", - "@platforms//os:osx" - ], - "rustfmt_nightly-2024-09-05__aarch64-apple-darwin": [ - "@platforms//cpu:aarch64", - "@platforms//os:osx" - ], - "rust_windows_aarch64__aarch64-pc-windows-msvc__stable": [ - "@platforms//cpu:aarch64", - "@platforms//os:windows" - ], - "rust_windows_aarch64__aarch64-pc-windows-msvc__nightly": [ - "@platforms//cpu:aarch64", - "@platforms//os:windows" - ], - "rust_windows_aarch64__wasm32-unknown-unknown__stable": [ - "@platforms//cpu:aarch64", - "@platforms//os:windows" - ], - "rust_windows_aarch64__wasm32-unknown-unknown__nightly": [ - "@platforms//cpu:aarch64", - "@platforms//os:windows" - ], - "rust_windows_aarch64__wasm32-wasi__stable": [ - "@platforms//cpu:aarch64", - "@platforms//os:windows" - ], - "rust_windows_aarch64__wasm32-wasi__nightly": [ - "@platforms//cpu:aarch64", - "@platforms//os:windows" - ], - "rustfmt_nightly-2024-09-05__aarch64-pc-windows-msvc": [ - "@platforms//cpu:aarch64", - "@platforms//os:windows" - ], - "rust_linux_aarch64__aarch64-unknown-linux-gnu__stable": [ - "@platforms//cpu:aarch64", - "@platforms//os:linux" - ], - "rust_linux_aarch64__aarch64-unknown-linux-gnu__nightly": [ - "@platforms//cpu:aarch64", - "@platforms//os:linux" - ], - "rust_linux_aarch64__wasm32-unknown-unknown__stable": [ - "@platforms//cpu:aarch64", - "@platforms//os:linux" - ], - "rust_linux_aarch64__wasm32-unknown-unknown__nightly": [ - "@platforms//cpu:aarch64", - "@platforms//os:linux" - ], - "rust_linux_aarch64__wasm32-wasi__stable": [ - "@platforms//cpu:aarch64", - "@platforms//os:linux" - ], - "rust_linux_aarch64__wasm32-wasi__nightly": [ - "@platforms//cpu:aarch64", - "@platforms//os:linux" - ], - "rustfmt_nightly-2024-09-05__aarch64-unknown-linux-gnu": [ - "@platforms//cpu:aarch64", - "@platforms//os:linux" - ], - "rust_linux_s390x__s390x-unknown-linux-gnu__stable": [ - "@platforms//cpu:s390x", - "@platforms//os:linux" - ], - "rust_linux_s390x__s390x-unknown-linux-gnu__nightly": [ - "@platforms//cpu:s390x", - "@platforms//os:linux" - ], - "rust_linux_s390x__wasm32-unknown-unknown__stable": [ - "@platforms//cpu:s390x", - "@platforms//os:linux" - ], - "rust_linux_s390x__wasm32-unknown-unknown__nightly": [ - "@platforms//cpu:s390x", - "@platforms//os:linux" - ], - "rust_linux_s390x__wasm32-wasi__stable": [ - "@platforms//cpu:s390x", - "@platforms//os:linux" - ], - "rust_linux_s390x__wasm32-wasi__nightly": [ - "@platforms//cpu:s390x", - "@platforms//os:linux" - ], - "rustfmt_nightly-2024-09-05__s390x-unknown-linux-gnu": [ - "@platforms//cpu:s390x", - "@platforms//os:linux" - ], - "rust_darwin_x86_64__x86_64-apple-darwin__stable": [ - "@platforms//cpu:x86_64", - "@platforms//os:osx" - ], - "rust_darwin_x86_64__x86_64-apple-darwin__nightly": [ - "@platforms//cpu:x86_64", - "@platforms//os:osx" - ], - "rust_darwin_x86_64__wasm32-unknown-unknown__stable": [ - "@platforms//cpu:x86_64", - "@platforms//os:osx" - ], - "rust_darwin_x86_64__wasm32-unknown-unknown__nightly": [ - "@platforms//cpu:x86_64", - "@platforms//os:osx" - ], - "rust_darwin_x86_64__wasm32-wasi__stable": [ - "@platforms//cpu:x86_64", - "@platforms//os:osx" - ], - "rust_darwin_x86_64__wasm32-wasi__nightly": [ - "@platforms//cpu:x86_64", - "@platforms//os:osx" - ], - "rustfmt_nightly-2024-09-05__x86_64-apple-darwin": [ - "@platforms//cpu:x86_64", - "@platforms//os:osx" - ], - "rust_windows_x86_64__x86_64-pc-windows-msvc__stable": [ - "@platforms//cpu:x86_64", - "@platforms//os:windows" - ], - "rust_windows_x86_64__x86_64-pc-windows-msvc__nightly": [ - "@platforms//cpu:x86_64", - "@platforms//os:windows" - ], - "rust_windows_x86_64__wasm32-unknown-unknown__stable": [ - "@platforms//cpu:x86_64", - "@platforms//os:windows" - ], - "rust_windows_x86_64__wasm32-unknown-unknown__nightly": [ - "@platforms//cpu:x86_64", - "@platforms//os:windows" - ], - "rust_windows_x86_64__wasm32-wasi__stable": [ - "@platforms//cpu:x86_64", - "@platforms//os:windows" - ], - "rust_windows_x86_64__wasm32-wasi__nightly": [ - "@platforms//cpu:x86_64", - "@platforms//os:windows" - ], - "rustfmt_nightly-2024-09-05__x86_64-pc-windows-msvc": [ - "@platforms//cpu:x86_64", - "@platforms//os:windows" - ], - "rust_freebsd_x86_64__x86_64-unknown-freebsd__stable": [ - "@platforms//cpu:x86_64", - "@platforms//os:freebsd" - ], - "rust_freebsd_x86_64__x86_64-unknown-freebsd__nightly": [ - "@platforms//cpu:x86_64", - "@platforms//os:freebsd" - ], - "rust_freebsd_x86_64__wasm32-unknown-unknown__stable": [ - "@platforms//cpu:x86_64", - "@platforms//os:freebsd" - ], - "rust_freebsd_x86_64__wasm32-unknown-unknown__nightly": [ - "@platforms//cpu:x86_64", - "@platforms//os:freebsd" - ], - "rust_freebsd_x86_64__wasm32-wasi__stable": [ - "@platforms//cpu:x86_64", - "@platforms//os:freebsd" - ], - "rust_freebsd_x86_64__wasm32-wasi__nightly": [ - "@platforms//cpu:x86_64", - "@platforms//os:freebsd" - ], - "rustfmt_nightly-2024-09-05__x86_64-unknown-freebsd": [ - "@platforms//cpu:x86_64", - "@platforms//os:freebsd" - ], - "rust_linux_x86_64__x86_64-unknown-linux-gnu__stable": [ - "@platforms//cpu:x86_64", - "@platforms//os:linux" - ], - "rust_linux_x86_64__x86_64-unknown-linux-gnu__nightly": [ - "@platforms//cpu:x86_64", - "@platforms//os:linux" - ], - "rust_linux_x86_64__wasm32-unknown-unknown__stable": [ - "@platforms//cpu:x86_64", - "@platforms//os:linux" - ], - "rust_linux_x86_64__wasm32-unknown-unknown__nightly": [ - "@platforms//cpu:x86_64", - "@platforms//os:linux" - ], - "rust_linux_x86_64__wasm32-wasi__stable": [ - "@platforms//cpu:x86_64", - "@platforms//os:linux" - ], - "rust_linux_x86_64__wasm32-wasi__nightly": [ - "@platforms//cpu:x86_64", - "@platforms//os:linux" - ], - "rustfmt_nightly-2024-09-05__x86_64-unknown-linux-gnu": [ - "@platforms//cpu:x86_64", - "@platforms//os:linux" - ] - }, - "target_compatible_with": { - "rust_analyzer_1.81.0": [], - "rust_darwin_aarch64__aarch64-apple-darwin__stable": [ - "@platforms//cpu:aarch64", - "@platforms//os:osx" - ], - "rust_darwin_aarch64__aarch64-apple-darwin__nightly": [ - "@platforms//cpu:aarch64", - "@platforms//os:osx" - ], - "rust_darwin_aarch64__wasm32-unknown-unknown__stable": [ - "@platforms//cpu:wasm32", - "@platforms//os:none" - ], - "rust_darwin_aarch64__wasm32-unknown-unknown__nightly": [ - "@platforms//cpu:wasm32", - "@platforms//os:none" - ], - "rust_darwin_aarch64__wasm32-wasi__stable": [ - "@platforms//cpu:wasm32", - "@platforms//os:wasi" - ], - "rust_darwin_aarch64__wasm32-wasi__nightly": [ - "@platforms//cpu:wasm32", - "@platforms//os:wasi" - ], - "rustfmt_nightly-2024-09-05__aarch64-apple-darwin": [], - "rust_windows_aarch64__aarch64-pc-windows-msvc__stable": [ - "@platforms//cpu:aarch64", - "@platforms//os:windows" - ], - "rust_windows_aarch64__aarch64-pc-windows-msvc__nightly": [ - "@platforms//cpu:aarch64", - "@platforms//os:windows" - ], - "rust_windows_aarch64__wasm32-unknown-unknown__stable": [ - "@platforms//cpu:wasm32", - "@platforms//os:none" - ], - "rust_windows_aarch64__wasm32-unknown-unknown__nightly": [ - "@platforms//cpu:wasm32", - "@platforms//os:none" - ], - "rust_windows_aarch64__wasm32-wasi__stable": [ - "@platforms//cpu:wasm32", - "@platforms//os:wasi" - ], - "rust_windows_aarch64__wasm32-wasi__nightly": [ - "@platforms//cpu:wasm32", - "@platforms//os:wasi" - ], - "rustfmt_nightly-2024-09-05__aarch64-pc-windows-msvc": [], - "rust_linux_aarch64__aarch64-unknown-linux-gnu__stable": [ - "@platforms//cpu:aarch64", - "@platforms//os:linux" - ], - "rust_linux_aarch64__aarch64-unknown-linux-gnu__nightly": [ - "@platforms//cpu:aarch64", - "@platforms//os:linux" - ], - "rust_linux_aarch64__wasm32-unknown-unknown__stable": [ - "@platforms//cpu:wasm32", - "@platforms//os:none" - ], - "rust_linux_aarch64__wasm32-unknown-unknown__nightly": [ - "@platforms//cpu:wasm32", - "@platforms//os:none" - ], - "rust_linux_aarch64__wasm32-wasi__stable": [ - "@platforms//cpu:wasm32", - "@platforms//os:wasi" - ], - "rust_linux_aarch64__wasm32-wasi__nightly": [ - "@platforms//cpu:wasm32", - "@platforms//os:wasi" - ], - "rustfmt_nightly-2024-09-05__aarch64-unknown-linux-gnu": [], - "rust_linux_s390x__s390x-unknown-linux-gnu__stable": [ - "@platforms//cpu:s390x", - "@platforms//os:linux" - ], - "rust_linux_s390x__s390x-unknown-linux-gnu__nightly": [ - "@platforms//cpu:s390x", - "@platforms//os:linux" - ], - "rust_linux_s390x__wasm32-unknown-unknown__stable": [ - "@platforms//cpu:wasm32", - "@platforms//os:none" - ], - "rust_linux_s390x__wasm32-unknown-unknown__nightly": [ - "@platforms//cpu:wasm32", - "@platforms//os:none" - ], - "rust_linux_s390x__wasm32-wasi__stable": [ - "@platforms//cpu:wasm32", - "@platforms//os:wasi" - ], - "rust_linux_s390x__wasm32-wasi__nightly": [ - "@platforms//cpu:wasm32", - "@platforms//os:wasi" - ], - "rustfmt_nightly-2024-09-05__s390x-unknown-linux-gnu": [], - "rust_darwin_x86_64__x86_64-apple-darwin__stable": [ - "@platforms//cpu:x86_64", - "@platforms//os:osx" - ], - "rust_darwin_x86_64__x86_64-apple-darwin__nightly": [ - "@platforms//cpu:x86_64", - "@platforms//os:osx" - ], - "rust_darwin_x86_64__wasm32-unknown-unknown__stable": [ - "@platforms//cpu:wasm32", - "@platforms//os:none" - ], - "rust_darwin_x86_64__wasm32-unknown-unknown__nightly": [ - "@platforms//cpu:wasm32", - "@platforms//os:none" - ], - "rust_darwin_x86_64__wasm32-wasi__stable": [ - "@platforms//cpu:wasm32", - "@platforms//os:wasi" - ], - "rust_darwin_x86_64__wasm32-wasi__nightly": [ - "@platforms//cpu:wasm32", - "@platforms//os:wasi" - ], - "rustfmt_nightly-2024-09-05__x86_64-apple-darwin": [], - "rust_windows_x86_64__x86_64-pc-windows-msvc__stable": [ - "@platforms//cpu:x86_64", - "@platforms//os:windows" - ], - "rust_windows_x86_64__x86_64-pc-windows-msvc__nightly": [ - "@platforms//cpu:x86_64", - "@platforms//os:windows" - ], - "rust_windows_x86_64__wasm32-unknown-unknown__stable": [ - "@platforms//cpu:wasm32", - "@platforms//os:none" - ], - "rust_windows_x86_64__wasm32-unknown-unknown__nightly": [ - "@platforms//cpu:wasm32", - "@platforms//os:none" - ], - "rust_windows_x86_64__wasm32-wasi__stable": [ - "@platforms//cpu:wasm32", - "@platforms//os:wasi" - ], - "rust_windows_x86_64__wasm32-wasi__nightly": [ - "@platforms//cpu:wasm32", - "@platforms//os:wasi" - ], - "rustfmt_nightly-2024-09-05__x86_64-pc-windows-msvc": [], - "rust_freebsd_x86_64__x86_64-unknown-freebsd__stable": [ - "@platforms//cpu:x86_64", - "@platforms//os:freebsd" - ], - "rust_freebsd_x86_64__x86_64-unknown-freebsd__nightly": [ - "@platforms//cpu:x86_64", - "@platforms//os:freebsd" - ], - "rust_freebsd_x86_64__wasm32-unknown-unknown__stable": [ - "@platforms//cpu:wasm32", - "@platforms//os:none" - ], - "rust_freebsd_x86_64__wasm32-unknown-unknown__nightly": [ - "@platforms//cpu:wasm32", - "@platforms//os:none" - ], - "rust_freebsd_x86_64__wasm32-wasi__stable": [ - "@platforms//cpu:wasm32", - "@platforms//os:wasi" - ], - "rust_freebsd_x86_64__wasm32-wasi__nightly": [ - "@platforms//cpu:wasm32", - "@platforms//os:wasi" - ], - "rustfmt_nightly-2024-09-05__x86_64-unknown-freebsd": [], - "rust_linux_x86_64__x86_64-unknown-linux-gnu__stable": [ - "@platforms//cpu:x86_64", - "@platforms//os:linux" - ], - "rust_linux_x86_64__x86_64-unknown-linux-gnu__nightly": [ - "@platforms//cpu:x86_64", - "@platforms//os:linux" - ], - "rust_linux_x86_64__wasm32-unknown-unknown__stable": [ - "@platforms//cpu:wasm32", - "@platforms//os:none" - ], - "rust_linux_x86_64__wasm32-unknown-unknown__nightly": [ - "@platforms//cpu:wasm32", - "@platforms//os:none" - ], - "rust_linux_x86_64__wasm32-wasi__stable": [ - "@platforms//cpu:wasm32", - "@platforms//os:wasi" - ], - "rust_linux_x86_64__wasm32-wasi__nightly": [ - "@platforms//cpu:wasm32", - "@platforms//os:wasi" - ], - "rustfmt_nightly-2024-09-05__x86_64-unknown-linux-gnu": [] - } - } - } - }, - "recordedRepoMappingEntries": [ - [ - "bazel_features+", - "bazel_features_globals", - "bazel_features++version_extension+bazel_features_globals" - ], - [ - "bazel_features+", - "bazel_features_version", - "bazel_features++version_extension+bazel_features_version" - ], - [ - "bazel_tools", - "rules_cc", - "rules_cc+" - ], - [ - "rules_cc+", - "bazel_tools", - "bazel_tools" - ], - [ - "rules_rust+", - "bazel_features", - "bazel_features+" - ], - [ - "rules_rust+", - "bazel_skylib", - "bazel_skylib+" - ], - [ - "rules_rust+", - "bazel_tools", - "bazel_tools" - ], - [ - "rules_rust+", - "rules_rust", - "rules_rust+" - ] - ] - } } } } diff --git a/generator/js_generator.cc b/generator/js_generator.cc index f6c3e38..a881c3d 100644 --- a/generator/js_generator.cc +++ b/generator/js_generator.cc @@ -964,7 +964,7 @@ bool UseBrokenPresenceSemantics(const GeneratorOptions& options, bool ReturnsNullWhenUnset(const GeneratorOptions& options, const FieldDescriptor* field) { if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && - field->is_optional()) { + !field->is_required() && !field->is_repeated()) { return true; } @@ -1290,7 +1290,7 @@ std::string FieldDefinition(const GeneratorOptions& options, } else { std::string qualifier = field->is_repeated() ? "repeated" - : (field->is_optional() ? "optional" : "required"); + : (field->is_required() ? "required" : "optional"); std::string type, name; if (field->type() == FieldDescriptor::TYPE_ENUM || field->type() == FieldDescriptor::TYPE_MESSAGE) { @@ -2631,7 +2631,7 @@ void Generator::GenerateClassField(const GeneratorOptions& options, "rpt", (field->is_repeated() ? "Repeated" : ""), "index", JSFieldIndex(field), "wrapperclass", SubmessageTypeRef(options, field), "required", - (field->label() == FieldDescriptor::LABEL_REQUIRED ? ", 1" : "")); + (field->is_required() ? ", 1" : "")); printer->Annotate("gettername", field); printer->Print( "/**\n" From f418f587e0588481a3557eeddc5646c3566fbbe3 Mon Sep 17 00:00:00 2001 From: Stephanie DiBenedetto Date: Fri, 6 Jun 2025 11:21:56 -0700 Subject: [PATCH 11/22] Bump protoc version to 31.1 --- MODULE.bazel | 2 +- MODULE.bazel.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index 75b5ed7..a603777 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -1,5 +1,5 @@ module(name = "protobuf_javascript", version = "3.21.4") -bazel_dep(name = "protobuf", version = "31.0", repo_name = "com_google_protobuf") +bazel_dep(name = "protobuf", version = "31.1", repo_name = "com_google_protobuf") bazel_dep(name = "rules_pkg", version = "1.0.1") bazel_dep(name = "abseil-cpp", version = "20250127.0") diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index a17bf63..f2f6378 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -69,8 +69,8 @@ "https://bcr.bazel.build/modules/protobuf/29.0-rc3/MODULE.bazel": "33c2dfa286578573afc55a7acaea3cada4122b9631007c594bf0729f41c8de92", "https://bcr.bazel.build/modules/protobuf/29.0/MODULE.bazel": "319dc8bf4c679ff87e71b1ccfb5a6e90a6dbc4693501d471f48662ac46d04e4e", "https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0", - "https://bcr.bazel.build/modules/protobuf/31.0/MODULE.bazel": "cce0f305064713b382211c4c5af1d4fc1466e1fbc9059aa0941801970f6add5c", - "https://bcr.bazel.build/modules/protobuf/31.0/source.json": "266920c7b95f467db2dc38a640aed7265d948fc38dfb752bb91a027932ee2a99", + "https://bcr.bazel.build/modules/protobuf/31.1/MODULE.bazel": "379a389bb330b7b8c1cdf331cc90bf3e13de5614799b3b52cdb7c6f389f6b38e", + "https://bcr.bazel.build/modules/protobuf/31.1/source.json": "25af5d0219da0c0fc4d1191a24ce438e6ca7f49d2e1a94f354efeba6ef10426f", "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e", "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/MODULE.bazel": "e6f4c20442eaa7c90d7190d8dc539d0ab422f95c65a57cc59562170c58ae3d34", "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/source.json": "6900fdc8a9e95866b8c0d4ad4aba4d4236317b5c1cd04c502df3f0d33afed680", From 4ce9069d854c02d8aee8bb82b2e509e8cd47a2cb Mon Sep 17 00:00:00 2001 From: Stephanie DiBenedetto Date: Mon, 7 Jul 2025 18:53:09 -0700 Subject: [PATCH 12/22] Enable protobuf edition 2023 support This change backports our binary serialization/deserialization code. The newer code includes several years worth of improvements that improve the overall conformance findings. The improved state of things allows us to enable protobuf edition 2023. Other items: - Add missing export annotation for BinaryReader.readStringRequireUtf8 - promote protobuf conformance testing client to main directory --- .gitignore | 4 + MODULE.bazel.lock | 15 +- binary/any_field_type.js | 14 + binary/arith.js | 532 +-- binary/arith_test.js | 464 ++- binary/binary_constants.js | 241 ++ binary/bytesource.js | 10 + binary/constants.js | 409 --- binary/decoder.js | 1812 ++++----- binary/decoder_alias.js | 9 + binary/decoder_test.js | 636 ++-- binary/encoder.js | 832 ++--- binary/encoder_alias.js | 9 + binary/errors.js | 122 + binary/internal_buffer.js | 96 + binary/message_test.js | 0 binary/proto_test.js | 271 +- binary/reader.js | 2560 ++++++------- binary/reader_alias.js | 9 + binary/reader_test.js | 1063 +++--- binary/repeated_field_type.js | 11 + binary/scalar_field_type.js | 9 + binary/test_utils.js | 51 + binary/utf8.js | 173 +- binary/utils.js | 1119 +++--- binary/utils_test.js | 392 +- binary/writer.js | 3249 ++++++++--------- binary/writer_alias.js | 9 + binary/writer_test.js | 343 +- bytestring.js | 257 ++ commonjs/export.js | 3 + commonjs/export_testdeps.js | 49 + commonjs/rewrite_tests_for_commonjs.js | 8 +- conformance/LICENSE.md | 29 + conformance/failing_tests.txt | 48 + conformance/package.json | 18 + conformance/protos/conformance.proto | 172 + .../protos/test_messages_edition2023.proto | 217 ++ conformance/protos/test_messages_proto2.proto | 416 +++ .../test_messages_proto2_editions.proto | 683 ++++ conformance/protos/test_messages_proto3.proto | 266 ++ .../test_messages_proto3_editions.proto | 309 ++ conformance/runner.js | 175 + .../kernel/conformance/conformance_request.js | 91 - .../conformance/conformance_response.js | 76 - .../kernel/conformance/conformance_testee.js | 103 - .../conformance_testee_runner_node.js | 62 - .../conformance/test_all_types_proto2.js | 309 -- .../conformance/test_all_types_proto3.js | 310 -- .../runtime/kernel/conformance/wire_format.js | 16 - .../runtime/kernel/kernel_repeated_test.js | 2 +- generator/js_generator.cc | 64 +- generator/js_generator.h | 5 +- gulpfile.js | 206 +- internal_bytes.js | 238 ++ internal_options.js | 46 + internal_public.js | 112 + map.js | 39 +- message.js | 11 +- node_loader.js | 18 +- package-lock.json | 466 +-- package.json | 7 +- proto3_test.js | 40 +- unsafe_bytestring.js | 71 + yarn.lock | 118 +- 65 files changed, 10617 insertions(+), 8907 deletions(-) create mode 100755 binary/any_field_type.js mode change 100644 => 100755 binary/arith.js mode change 100644 => 100755 binary/arith_test.js create mode 100755 binary/binary_constants.js create mode 100755 binary/bytesource.js delete mode 100644 binary/constants.js mode change 100644 => 100755 binary/decoder.js create mode 100755 binary/decoder_alias.js mode change 100644 => 100755 binary/decoder_test.js mode change 100644 => 100755 binary/encoder.js create mode 100755 binary/encoder_alias.js create mode 100755 binary/errors.js create mode 100755 binary/internal_buffer.js mode change 100644 => 100755 binary/message_test.js mode change 100644 => 100755 binary/proto_test.js mode change 100644 => 100755 binary/reader.js create mode 100755 binary/reader_alias.js mode change 100644 => 100755 binary/reader_test.js create mode 100755 binary/repeated_field_type.js create mode 100755 binary/scalar_field_type.js create mode 100755 binary/test_utils.js mode change 100644 => 100755 binary/utf8.js mode change 100644 => 100755 binary/utils.js mode change 100644 => 100755 binary/utils_test.js mode change 100644 => 100755 binary/writer.js create mode 100755 binary/writer_alias.js mode change 100644 => 100755 binary/writer_test.js create mode 100644 bytestring.js create mode 100644 conformance/LICENSE.md create mode 100644 conformance/failing_tests.txt create mode 100644 conformance/package.json create mode 100644 conformance/protos/conformance.proto create mode 100644 conformance/protos/test_messages_edition2023.proto create mode 100644 conformance/protos/test_messages_proto2.proto create mode 100644 conformance/protos/test_messages_proto2_editions.proto create mode 100644 conformance/protos/test_messages_proto3.proto create mode 100644 conformance/protos/test_messages_proto3_editions.proto create mode 100755 conformance/runner.js delete mode 100644 experimental/runtime/kernel/conformance/conformance_request.js delete mode 100644 experimental/runtime/kernel/conformance/conformance_response.js delete mode 100755 experimental/runtime/kernel/conformance/conformance_testee.js delete mode 100755 experimental/runtime/kernel/conformance/conformance_testee_runner_node.js delete mode 100644 experimental/runtime/kernel/conformance/test_all_types_proto2.js delete mode 100644 experimental/runtime/kernel/conformance/test_all_types_proto3.js delete mode 100644 experimental/runtime/kernel/conformance/wire_format.js create mode 100644 internal_bytes.js create mode 100644 internal_options.js create mode 100644 internal_public.js create mode 100644 unsafe_bytestring.js diff --git a/.gitignore b/.gitignore index a1690e7..638cee5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .idea +.vscode node_modules commonjs_out google/protobuf @@ -7,3 +8,6 @@ bazel-* /testproto_libs1.js /testproto_libs2.js /google-protobuf.js +/google-protobuf-*.tgz +/conformance/protos/*.js +/conformance/package-lock.json diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index f2f6378..7299fdd 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -23,8 +23,9 @@ "https://bcr.bazel.build/modules/bazel_features/1.19.0/MODULE.bazel": "59adcdf28230d220f0067b1f435b8537dd033bfff8db21335ef9217919c7fb58", "https://bcr.bazel.build/modules/bazel_features/1.21.0/MODULE.bazel": "675642261665d8eea09989aa3b8afb5c37627f1be178382c320d1b46afba5e3b", "https://bcr.bazel.build/modules/bazel_features/1.23.0/MODULE.bazel": "fd1ac84bc4e97a5a0816b7fd7d4d4f6d837b0047cf4cbd81652d616af3a6591a", - "https://bcr.bazel.build/modules/bazel_features/1.23.0/source.json": "c72c61b722d7c3f884994fe647afeb2ed1ae66c437f8f370753551f7b4d8be7f", "https://bcr.bazel.build/modules/bazel_features/1.3.0/MODULE.bazel": "cdcafe83ec318cda34e02948e81d790aab8df7a929cec6f6969f13a489ccecd9", + "https://bcr.bazel.build/modules/bazel_features/1.30.0/MODULE.bazel": "a14b62d05969a293b80257e72e597c2da7f717e1e69fa8b339703ed6731bec87", + "https://bcr.bazel.build/modules/bazel_features/1.30.0/source.json": "b07e17f067fe4f69f90b03b36ef1e08fe0d1f3cac254c1241a1818773e3423bc", "https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7", "https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a", "https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8", @@ -89,11 +90,12 @@ "https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc", "https://bcr.bazel.build/modules/rules_cc/0.0.16/MODULE.bazel": "7661303b8fc1b4d7f532e54e9d6565771fea666fbdf839e0a86affcd02defe87", "https://bcr.bazel.build/modules/rules_cc/0.0.17/MODULE.bazel": "2ae1d8f4238ec67d7185d8861cb0a2cdf4bc608697c331b95bf990e69b62e64a", - "https://bcr.bazel.build/modules/rules_cc/0.0.17/source.json": "4db99b3f55c90ab28d14552aa0632533e3e8e5e9aea0f5c24ac0014282c2a7c5", "https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c", "https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f", "https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e", "https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5", + "https://bcr.bazel.build/modules/rules_cc/0.1.1/MODULE.bazel": "2f0222a6f229f0bf44cd711dc13c858dad98c62d52bd51d8fc3a764a83125513", + "https://bcr.bazel.build/modules/rules_cc/0.1.1/source.json": "d61627377bd7dd1da4652063e368d9366fc9a73920bfa396798ad92172cf645c", "https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6", "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8", "https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74", @@ -106,8 +108,8 @@ "https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab", "https://bcr.bazel.build/modules/rules_java/7.3.2/MODULE.bazel": "50dece891cfdf1741ea230d001aa9c14398062f2b7c066470accace78e412bc2", "https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe", - "https://bcr.bazel.build/modules/rules_java/8.11.0/MODULE.bazel": "c3d280bc5ff1038dcb3bacb95d3f6b83da8dd27bba57820ec89ea4085da767ad", - "https://bcr.bazel.build/modules/rules_java/8.11.0/source.json": "302b52a39259a85aa06ca3addb9787864ca3e03b432a5f964ea68244397e7544", + "https://bcr.bazel.build/modules/rules_java/8.12.0/MODULE.bazel": "8e6590b961f2defdfc2811c089c75716cb2f06c8a4edeb9a8d85eaa64ee2a761", + "https://bcr.bazel.build/modules/rules_java/8.12.0/source.json": "cbd5d55d9d38d4008a7d00bee5b5a5a4b6031fcd4a56515c9accbcd42c7be2ba", "https://bcr.bazel.build/modules/rules_java/8.3.2/MODULE.bazel": "7336d5511ad5af0b8615fdc7477535a2e4e723a357b6713af439fe8cf0195017", "https://bcr.bazel.build/modules/rules_java/8.5.1/MODULE.bazel": "d8a9e38cc5228881f7055a6079f6f7821a073df3744d441978e7a43e20226939", "https://bcr.bazel.build/modules/rules_java/8.6.1/MODULE.bazel": "f4808e2ab5b0197f094cabce9f4b006a27766beb6a9975931da07099560ca9c2", @@ -162,7 +164,6 @@ "https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.1/source.json": "32bd87e5f4d7acc57c5b2ff7c325ae3061d5e242c0c4c214ae87e0f1c13e54cb", "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43", "https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0", - "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/MODULE.bazel": "af322bc08976524477c79d1e45e241b6efbeb918c497e8840b8ab116802dda79", "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/MODULE.bazel": "eec517b5bbe5492629466e11dae908d043364302283de25581e3eb944326c4ca", "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/source.json": "22bc55c47af97246cfc093d0acf683a7869377de362b5d1c552c2c2e16b7a806", "https://bcr.bazel.build/modules/zlib/1.3.1/MODULE.bazel": "751c9940dcfe869f5f7274e1295422a34623555916eb98c174c1e945594bf198" @@ -171,7 +172,7 @@ "moduleExtensions": { "@@apple_support+//crosstool:setup.bzl%apple_cc_configure_extension": { "general": { - "bzlTransitiveDigest": "okb7JAyJ9zeL+SDmtbWT0XBLq8WRoLJ0zWAG783RLVI=", + "bzlTransitiveDigest": "E970FlMbwpgJPdPUQzatKh6BMfeE0ZpWABvwshh7Tmg=", "usagesDigest": "EJfdUgbJdIRboG70S9dz8HhGVkL2/s3qFQ9xht8y2Rs=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, @@ -202,7 +203,7 @@ }, "@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": { "general": { - "bzlTransitiveDigest": "sFhcgPbDQehmbD1EOXzX4H1q/CD5df8zwG4kp4jbvr8=", + "bzlTransitiveDigest": "hUTp2w+RUVdL7ma5esCXZJAFnX7vLbVfLd7FwnQI6bU=", "usagesDigest": "QI2z8ZUR+mqtbwsf2fLqYdJAkPOHdOV+tF2yVAUgRzw=", "recordedFileInputs": {}, "recordedDirentsInputs": {}, diff --git a/binary/any_field_type.js b/binary/any_field_type.js new file mode 100755 index 0000000..1ab21b9 --- /dev/null +++ b/binary/any_field_type.js @@ -0,0 +1,14 @@ +goog.module('jspb.binary.any_field_type'); + +const {RepeatedFieldType} = goog.require('jspb.binary.repeated_field_type'); +const {ScalarFieldType} = goog.requireType('jspb.binary.scalar_field_type'); + + +/** + * A field in jspb can be a scalar, a block of bytes, another proto, or an + * array of any of the above. + * @typedef {?ScalarFieldType|?RepeatedFieldType|!Uint8Array} + */ +let AnyFieldType; + +exports = {AnyFieldType}; diff --git a/binary/arith.js b/binary/arith.js old mode 100644 new mode 100755 index 97c73a4..9f084f5 --- a/binary/arith.js +++ b/binary/arith.js @@ -1,33 +1,3 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://protobuf.dev/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - /** * @fileoverview This file contains helper code used by jspb.utils to * handle 64-bit integer conversion to/from strings. @@ -36,403 +6,185 @@ * * TODO(haberman): move this to javascript/closure/math? */ +goog.module('jspb.arith'); +goog.module.declareLegacyNamespace(); -goog.provide('jspb.arith.Int64'); -goog.provide('jspb.arith.UInt64'); +const {getSplit64High, getSplit64Low, joinSignedDecimalString, joinUnsignedDecimalString, splitDecimalString} = goog.require('jspb.utils'); /** * UInt64 implements some 64-bit arithmetic routines necessary for properly - * handling 64-bit integer fields. It implements lossless integer arithmetic on - * top of JavaScript's number type, which has only 53 bits of precision, by - * representing 64-bit integers as two 32-bit halves. - * - * @param {number} lo The low 32 bits. - * @param {number} hi The high 32 bits. - * @constructor - * @export + * handling 64-bit integer fields from protobuf fields with decimal string + * conversions. + * @final */ -jspb.arith.UInt64 = function(lo, hi) { - /** - * The low 32 bits. - * @type {number} - * @export - */ - this.lo = lo; +class UInt64 { /** - * The high 32 bits. - * @type {number} - * @export + * @param {number} lo The low 32 bits. + * @param {number} hi The high 32 bits. */ - this.hi = hi; -}; - - -/** - * Compare two 64-bit numbers. Returns -1 if the first is - * less, +1 if the first is greater, or 0 if both are equal. - * @param {!jspb.arith.UInt64} other - * @return {number} - * @export - */ -jspb.arith.UInt64.prototype.cmp = function(other) { - if (this.hi < other.hi || (this.hi == other.hi && this.lo < other.lo)) { - return -1; - } else if (this.hi == other.hi && this.lo == other.lo) { - return 0; - } else { - return 1; + constructor(lo, hi) { + /** + * The low 32 bits, always stored as uint32. + * @public @const {number} + */ + this.lo = lo >>> 0; + + /** + * The high 32 bits, always stored as uint32. + * @public @const {number} + */ + this.hi = hi >>> 0; } -}; - - -/** - * Right-shift this number by one bit. - * @return {!jspb.arith.UInt64} - * @export - */ -jspb.arith.UInt64.prototype.rightShift = function() { - var hi = this.hi >>> 1; - var lo = (this.lo >>> 1) | ((this.hi & 1) << 31); - return new jspb.arith.UInt64(lo >>> 0, hi >>> 0); -}; - - -/** - * Left-shift this number by one bit. - * @return {!jspb.arith.UInt64} - * @export - */ -jspb.arith.UInt64.prototype.leftShift = function() { - var lo = this.lo << 1; - var hi = (this.hi << 1) | (this.lo >>> 31); - return new jspb.arith.UInt64(lo >>> 0, hi >>> 0); -}; - - -/** - * Test the MSB. - * @return {boolean} - * @export - */ -jspb.arith.UInt64.prototype.msb = function() { - return !!(this.hi & 0x80000000); -}; - - -/** - * Test the LSB. - * @return {boolean} - * @export - */ -jspb.arith.UInt64.prototype.lsb = function() { - return !!(this.lo & 1); -}; - - -/** - * Test whether this number is zero. - * @return {boolean} - * @export - */ -jspb.arith.UInt64.prototype.zero = function() { - return this.lo == 0 && this.hi == 0; -}; - - -/** - * Add two 64-bit numbers to produce a 64-bit number. - * @param {!jspb.arith.UInt64} other - * @return {!jspb.arith.UInt64} - * @export - */ -jspb.arith.UInt64.prototype.add = function(other) { - var lo = ((this.lo + other.lo) & 0xffffffff) >>> 0; - var hi = - (((this.hi + other.hi) & 0xffffffff) >>> 0) + - (((this.lo + other.lo) >= 0x100000000) ? 1 : 0); - return new jspb.arith.UInt64(lo >>> 0, hi >>> 0); -}; - - -/** - * Subtract two 64-bit numbers to produce a 64-bit number. - * @param {!jspb.arith.UInt64} other - * @return {!jspb.arith.UInt64} - * @export - */ -jspb.arith.UInt64.prototype.sub = function(other) { - var lo = ((this.lo - other.lo) & 0xffffffff) >>> 0; - var hi = - (((this.hi - other.hi) & 0xffffffff) >>> 0) - - (((this.lo - other.lo) < 0) ? 1 : 0); - return new jspb.arith.UInt64(lo >>> 0, hi >>> 0); -}; - - -/** - * Multiply two 32-bit numbers to produce a 64-bit number. - * @param {number} a The first integer: must be in [0, 2^32-1). - * @param {number} b The second integer: must be in [0, 2^32-1). - * @return {!jspb.arith.UInt64} - * @export - */ -jspb.arith.UInt64.mul32x32 = function(a, b) { - // Directly multiplying two 32-bit numbers may produce up to 64 bits of - // precision, thus losing precision because of the 53-bit mantissa of - // JavaScript numbers. So we multiply with 16-bit digits (radix 65536) - // instead. - var aLow = (a & 0xffff); - var aHigh = (a >>> 16); - var bLow = (b & 0xffff); - var bHigh = (b >>> 16); - var productLow = - // 32-bit result, result bits 0-31, take all 32 bits - (aLow * bLow) + - // 32-bit result, result bits 16-47, take bottom 16 as our top 16 - ((aLow * bHigh) & 0xffff) * 0x10000 + - // 32-bit result, result bits 16-47, take bottom 16 as our top 16 - ((aHigh * bLow) & 0xffff) * 0x10000; - var productHigh = - // 32-bit result, result bits 32-63, take all 32 bits - (aHigh * bHigh) + - // 32-bit result, result bits 16-47, take top 16 as our bottom 16 - ((aLow * bHigh) >>> 16) + - // 32-bit result, result bits 16-47, take top 16 as our bottom 16 - ((aHigh * bLow) >>> 16); - - // Carry. Note that we actually have up to *two* carries due to addition of - // three terms. - while (productLow >= 0x100000000) { - productLow -= 0x100000000; - productHigh += 1; - } - - return new jspb.arith.UInt64(productLow >>> 0, productHigh >>> 0); -}; - - -/** - * Multiply this number by a 32-bit number, producing a 96-bit number, then - * truncate the top 32 bits. - * @param {number} a The multiplier. - * @return {!jspb.arith.UInt64} - * @export - */ -jspb.arith.UInt64.prototype.mul = function(a) { - // Produce two parts: at bits 0-63, and 32-95. - var lo = jspb.arith.UInt64.mul32x32(this.lo, a); - var hi = jspb.arith.UInt64.mul32x32(this.hi, a); - // Left-shift hi by 32 bits, truncating its top bits. The parts will then be - // aligned for addition. - hi.hi = hi.lo; - hi.lo = 0; - return lo.add(hi); -}; - - -/** - * Divide a 64-bit number by a 32-bit number to produce a - * 64-bit quotient and a 32-bit remainder. - * @param {number} _divisor - * @return {Array} array of [quotient, remainder], - * unless divisor is 0, in which case an empty array is returned. - * @export - */ -jspb.arith.UInt64.prototype.div = function(_divisor) { - if (_divisor == 0) { - return []; - } - - // We perform long division using a radix-2 algorithm, for simplicity (i.e., - // one bit at a time). TODO: optimize to a radix-2^32 algorithm, taking care - // to get the variable shifts right. - var quotient = new jspb.arith.UInt64(0, 0); - var remainder = new jspb.arith.UInt64(this.lo, this.hi); - var divisor = new jspb.arith.UInt64(_divisor, 0); - var unit = new jspb.arith.UInt64(1, 0); - // Left-shift the divisor and unit until the high bit of divisor is set. - while (!divisor.msb()) { - divisor = divisor.leftShift(); - unit = unit.leftShift(); + /** + * Convert a 64-bit number to a string. + * @return {string} + */ + toDecimalString() { + return joinUnsignedDecimalString(this.lo, this.hi); } - // Perform long division one bit at a time. - while (!unit.zero()) { - // If divisor < remainder, add unit to quotient and subtract divisor from - // remainder. - if (divisor.cmp(remainder) <= 0) { - quotient = quotient.add(unit); - remainder = remainder.sub(divisor); + /** + * Negates this uint64 in twos-complement. + * + * @return {!UInt64} + */ + negateInTwosComplement() { + if (this.lo === 0) { + return new UInt64(0, 1 + ~this.hi); } - // Right-shift the divisor and unit. - divisor = divisor.rightShift(); - unit = unit.rightShift(); + return new UInt64(~this.lo + 1, ~this.hi); } - return [quotient, remainder]; -}; - - -/** - * Convert a 64-bit number to a string. - * @return {string} - * @override - * @export - */ -jspb.arith.UInt64.prototype.toString = function() { - var result = ''; - var num = this; - while (!num.zero()) { - var divResult = num.div(10); - var quotient = divResult[0], remainder = divResult[1]; - result = remainder.lo + result; - num = quotient; - } - if (result == '') { - result = '0'; + /** + * Construct a Uint64 from a bigint + * + * @param {bigint} n + * @return {!UInt64} + */ + static fromBigInt(n) { + const asU64 = BigInt.asUintN(64, n); + return new UInt64( + /* lowBits = */ Number((asU64 & BigInt(0xFFFFFFFF))), + /* highBits = */ Number(asU64 >> BigInt(32))); } - return result; -}; - -/** - * Parse a string into a 64-bit number. Returns `null` on a parse error. - * @param {string} s - * @return {?jspb.arith.UInt64} - * @export - */ -jspb.arith.UInt64.fromString = function(s) { - var result = new jspb.arith.UInt64(0, 0); - // optimization: reuse this instance for each digit. - var digit64 = new jspb.arith.UInt64(0, 0); - for (var i = 0; i < s.length; i++) { - if (s[i] < '0' || s[i] > '9') { + /** + * Parse a string into a 64-bit number. Returns `null` on a parse error. + * + * @param {string} s + * @return {?UInt64} + */ + static fromString(s) { + if (!s) return UInt64.getZero(); + if (!/^\d+$/.test(s)) { + // TODO(web-protos-team): Throw an error rather than returning null. return null; } - var digit = parseInt(s[i], 10); - digit64.lo = digit; - result = result.mul(10).add(digit64); + splitDecimalString(s); + return new UInt64(getSplit64Low(), getSplit64High()); } - return result; -}; + /** + * Construct a Uint64 from a JavaScript number. + * @param {number} n + * @return {!UInt64} + */ + static fromNumber(n) { + return new UInt64(n & ALL_32_BITS, n / TWO_PWR_32_DBL); + } -/** - * Make a copy of the uint64. - * @return {!jspb.arith.UInt64} - * @export - */ -jspb.arith.UInt64.prototype.clone = function() { - return new jspb.arith.UInt64(this.lo, this.hi); -}; + static getZero() { + return uint64Zero || (uint64Zero = new UInt64(0, 0)); + } +} +let /** !UInt64|undefined */ uint64Zero; /** * Int64 is like UInt64, but modifies string conversions to interpret the stored - * 64-bit value as a twos-complement-signed integer. It does *not* support the - * full range of operations that UInt64 does: only add, subtract, and string + * 64-bit value as a twos-complement-signed integer with decimal string * conversions. - * - * N.B. that multiply and divide routines are *NOT* supported. They will throw - * exceptions. (They are not necessary to implement string conversions, which - * are the only operations we really need in jspb.) - * - * @param {number} lo The low 32 bits. - * @param {number} hi The high 32 bits. - * @constructor - * @export + * @final */ -jspb.arith.Int64 = function(lo, hi) { +class Int64 { /** - * The low 32 bits. - * @type {number} - * @export + * @param {number} lo The low 32 bits. + * @param {number} hi The high 32 bits. */ - this.lo = lo; + constructor(lo, hi) { + /** + * The low 32 bits, always stored as uint32. + * @public @const {number} + */ + this.lo = lo >>> 0; + + /** + * The high 32 bits, always stored as uint32. + * @public @const {number} + */ + this.hi = hi >>> 0; + } + /** - * The high 32 bits. - * @type {number} - * @export + * Convert a 64-bit number to a string. + * @return {string} */ - this.hi = hi; -}; - - -/** - * Add two 64-bit numbers to produce a 64-bit number. - * @param {!jspb.arith.Int64} other - * @return {!jspb.arith.Int64} - * @export - */ -jspb.arith.Int64.prototype.add = function(other) { - var lo = ((this.lo + other.lo) & 0xffffffff) >>> 0; - var hi = - (((this.hi + other.hi) & 0xffffffff) >>> 0) + - (((this.lo + other.lo) >= 0x100000000) ? 1 : 0); - return new jspb.arith.Int64(lo >>> 0, hi >>> 0); -}; + toDecimalString() { + return joinSignedDecimalString(this.lo, this.hi); + } + /** + * Construct a Int64 from a bigint + * + * @param {bigint} n + * @return {!Int64} + */ + static fromBigInt(n) { + const asUint64 = BigInt.asUintN(64, n); + return new Int64( + /* lowBits = */ Number((asUint64 & BigInt(0xFFFFFFFF))), + /* highBits = */ Number(asUint64 >> BigInt(32))); + } -/** - * Subtract two 64-bit numbers to produce a 64-bit number. - * @param {!jspb.arith.Int64} other - * @return {!jspb.arith.Int64} - * @export - */ -jspb.arith.Int64.prototype.sub = function(other) { - var lo = ((this.lo - other.lo) & 0xffffffff) >>> 0; - var hi = - (((this.hi - other.hi) & 0xffffffff) >>> 0) - - (((this.lo - other.lo) < 0) ? 1 : 0); - return new jspb.arith.Int64(lo >>> 0, hi >>> 0); -}; + /** + * Parse a string into a 64-bit number. Returns `null` on a parse error. + * @param {string} s + * @return {?Int64} + */ + static fromString(s) { + if (!s) return Int64.getZero(); + if (!/^-?\d+$/.test(s)) { + // TODO: Throw an error rather than returning null. + return null; + } + splitDecimalString(s); + return new Int64(getSplit64Low(), getSplit64High()); + } + /** + * Construct a Uint64 from a JavaScript number. + * @param {number} n + * @return {!Int64} + */ + static fromNumber(n) { + return new Int64(n & ALL_32_BITS, n / TWO_PWR_32_DBL); + } -/** - * Make a copy of the int64. - * @return {!jspb.arith.Int64} - * @export - */ -jspb.arith.Int64.prototype.clone = function() { - return new jspb.arith.Int64(this.lo, this.hi); -}; + static getZero() { + return int64Zero || (int64Zero = new Int64(0, 0)); + } +} +let /** !Int64|undefined */ int64Zero; -/** - * Convert a 64-bit number to a string. - * @return {string} - * @override - * @export - */ -jspb.arith.Int64.prototype.toString = function() { - // If the number is negative, find its twos-complement inverse. - var sign = (this.hi & 0x80000000) != 0; - var num = new jspb.arith.UInt64(this.lo, this.hi); - if (sign) { - num = new jspb.arith.UInt64(0, 0).sub(num); - } - return (sign ? '-' : '') + num.toString(); -}; +/** @const {number} */ +const ALL_32_BITS = 0xFFFFFFFF; +/** @const {number} */ +const TWO_PWR_32_DBL = 0x100000000; -/** - * Parse a string into a 64-bit number. Returns `null` on a parse error. - * @param {string} s - * @return {?jspb.arith.Int64} - * @export - */ -jspb.arith.Int64.fromString = function(s) { - var hasNegative = (s.length > 0 && s[0] == '-'); - if (hasNegative) { - s = s.substring(1); - } - var num = jspb.arith.UInt64.fromString(s); - if (num === null) { - return null; - } - if (hasNegative) { - num = new jspb.arith.UInt64(0, 0).sub(num); - } - return new jspb.arith.Int64(num.lo, num.hi); +exports = { + UInt64, + Int64, }; diff --git a/binary/arith_test.js b/binary/arith_test.js old mode 100644 new mode 100755 index 688b91a..a43a44a --- a/binary/arith_test.js +++ b/binary/arith_test.js @@ -39,242 +39,21 @@ goog.require('jspb.arith.Int64'); goog.require('jspb.arith.UInt64'); +const Int64 = goog.module.get('jspb.arith').Int64; +const UInt64 = goog.module.get('jspb.arith').UInt64; -describe('binaryArithTest', function() { - /** - * Tests comparison operations. - */ - it('testCompare', function() { - const a = new jspb.arith.UInt64(1234, 5678); - const b = new jspb.arith.UInt64(1234, 5678); - expect(a.cmp(b)).toEqual(0); - expect(b.cmp(a)).toEqual(0); - b.lo -= 1; - expect(a.cmp(b)).toEqual(1); - expect(b.cmp(a)).toEqual(-1); - b.lo += 2; - expect(a.cmp(b)).toEqual(-1); - expect(b.cmp(a)).toEqual(1); - b.lo = a.lo; - b.hi = a.hi - 1; - expect(a.cmp(b)).toEqual(1); - expect(b.cmp(a)).toEqual(-1); - expect(a.zero()).toEqual(false); - expect(a.msb()).toEqual(false); - expect(a.lsb()).toEqual(false); - a.hi = 0; - a.lo = 0; - expect(a.zero()).toEqual(true); - a.hi = 0x80000000; - expect(a.zero()).toEqual(false); - expect(a.msb()).toEqual(true); - a.lo = 0x00000001; - expect(a.lsb()).toEqual(true); - }); - - - /** - * Tests shifts. - */ - it('testShifts', function() { - let a = new jspb.arith.UInt64(1, 0); - expect(a.lo).toEqual(1); - expect(a.hi).toEqual(0); - const orig = a; - a = a.leftShift(); - expect(orig.lo).toEqual(1); // original unmodified. - expect(orig.hi).toEqual(0); - expect(a.lo).toEqual(2); - expect(a.hi).toEqual(0); - a = a.leftShift(); - expect(a.lo).toEqual(4); - expect(a.hi).toEqual(0); - for (let i = 0; i < 29; i++) { - a = a.leftShift(); - } - expect(a.lo).toEqual(0x80000000); - expect(a.hi).toEqual(0); - a = a.leftShift(); - expect(a.lo).toEqual(0); - expect(a.hi).toEqual(1); - a = a.leftShift(); - expect(a.lo).toEqual(0); - expect(a.hi).toEqual(2); - a = a.rightShift(); - a = a.rightShift(); - expect(a.lo).toEqual(0x80000000); - expect(a.hi).toEqual(0); - a = a.rightShift(); - expect(a.lo).toEqual(0x40000000); - expect(a.hi).toEqual(0); - }); - - - /** - * Tests additions. - */ - it('testAdd', function() { - const a = new jspb.arith.UInt64( - /* lo = */ 0x89abcdef, - /* hi = */ 0x01234567); - const b = new jspb.arith.UInt64( - /* lo = */ 0xff52ab91, - /* hi = */ 0x92fa2123); - // Addition with carry. - let c = a.add(b); - expect(a.lo).toEqual(0x89abcdef); // originals unmodified. - expect(a.hi).toEqual(0x01234567); - expect(b.lo).toEqual(0xff52ab91); - expect(b.hi).toEqual(0x92fa2123); - expect(c.lo).toEqual(0x88fe7980); - expect(c.hi).toEqual(0x941d668b); - - // Simple addition without carry. - a.lo = 2; - a.hi = 0; - b.lo = 3; - b.hi = 0; - c = a.add(b); - expect(c.lo).toEqual(5); - expect(c.hi).toEqual(0); - }); - - - /** - * Test subtractions. - */ - it('testSub', function() { - const kLength = 10; - const hiValues = [ - 0x1682ef32, 0x583902f7, 0xb62f5955, 0x6ea99bbf, 0x25a39c20, 0x0700a08b, - 0x00f7304d, 0x91a5b5af, 0x89077fd2, 0xe09e347c - ]; - const loValues = [ - 0xe1538b18, 0xbeacd556, 0x74100758, 0x96e3cb26, 0x56c37c3f, 0xe00b3f7d, - 0x859f25d7, 0xc2ee614a, 0xe1d21cd7, 0x30aae6a4 - ]; - for (let i = 0; i < kLength; i++) { - for (let j = 0; j < kLength; j++) { - const a = new jspb.arith.UInt64(loValues[i], hiValues[j]); - const b = new jspb.arith.UInt64(loValues[j], hiValues[i]); - const c = a.add(b).sub(b); - expect(c.hi).toEqual(a.hi); - expect(c.lo).toEqual(a.lo); - } - } - }); - - - /** - * Tests 32-by-32 multiplication. - */ - it('testMul32x32', function() { - const testData = [ - // a b low(a*b) high(a*b) - [0xc0abe2f8, 0x1607898a, 0x5de711b0, 0x109471b8], - [0x915eb3cb, 0x4fb66d0e, 0xbd0d441a, 0x2d43d0bc], - [0xfe4efe70, 0x80b48c37, 0xbcddea10, 0x7fdada0c], - [0xe222fd4a, 0xe43d524a, 0xd5e0eb64, 0xc99d549c], - [0xd171f469, 0xb94ebd01, 0x4be17969, 0x979bc4fa], - [0x829cc1df, 0xe2598b38, 0xf4157dc8, 0x737c12ad], - [0xf10c3767, 0x8382881e, 0x942b3612, 0x7bd428b8], - [0xb0f6dd24, 0x232597e1, 0x079c98a4, 0x184bbce7], - [0xfcdb05a7, 0x902f55bc, 0x636199a4, 0x8e69f412], - [0x0dd0bfa9, 0x916e27b1, 0x6e2542d9, 0x07d92e65] - ]; - - for (let i = 0; i < testData.length; i++) { - const a = testData[i][0] >>> 0; - const b = testData[i][1] >>> 0; - const cLow = testData[i][2] >>> 0; - const cHigh = testData[i][3] >>> 0; - const c = jspb.arith.UInt64.mul32x32(a, b); - expect(c.lo).toEqual(cLow); - expect(c.hi).toEqual(cHigh); - } - }); - - - /** - * Tests 64-by-32 multiplication. - */ - it('testMul', function() { - // 64x32 bits produces 96 bits of product. The multiplication function under - // test truncates the top 32 bits, so we compare against a 64-bit expected - // product. - const testData = [ - // low(a) high(a) low(a*b) high(a*b) - [0xec10955b, 0x360eb168, 0x4b7f3f5b, 0xbfcb7c59, 0x9517da5f], - [0x42b000fc, 0x9d101642, 0x6fa1ab72, 0x2584c438, 0x6a9e6d2b], - [0xf42d4fb4, 0xae366403, 0xa65a1000, 0x92434000, 0x1ff978df], - [0x17e2f56b, 0x25487693, 0xf13f98c7, 0x73794e2d, 0xa96b0c6a], - [0x492f241f, 0x76c0eb67, 0x7377ac44, 0xd4336c3c, 0xfc4b1ebe], - [0xd6b92321, 0xe184fa48, 0xd6e76904, 0x93141584, 0xcbf44da1], - [0x4bf007ea, 0x968c0a9e, 0xf5e4026a, 0x4fdb1ae4, 0x61b9fb7d], - [0x10a83be7, 0x2d685ba6, 0xc9e5fb7f, 0x2ad43499, 0x3742473d], - [0x2f261829, 0x1aca681a, 0x3d3494e3, 0x8213205b, 0x283719f8], - [0xe4f2ce21, 0x2e74b7bd, 0xd801b38b, 0xbc17feeb, 0xc6c44e0f] - ]; - - for (let i = 0; i < testData.length; i++) { - const a = new jspb.arith.UInt64(testData[i][0], testData[i][1]); - const prod = a.mul(testData[i][2]); - expect(prod.lo).toEqual(testData[i][3]); - expect(prod.hi).toEqual(testData[i][4]); - } - }); - - - /** - * Tests 64-div-by-32 division. - */ - it('testDiv', function() { - // Compute a/b, yielding quot = a/b and rem = a%b. - const testData = [ - // --- divisors in (0, 2^32-1) to test full divisor range - // low(a) high(a) b low(quot) high(quot) rem - [0x712443f1, 0xe85cefcc, 0xc1a7050b, 0x332c79ad, 0x00000001, 0x92ffa882], - [0x11912915, 0xb2699eb5, 0x30467cbe, 0xb21b4be4, 0x00000003, 0x283465dd], - [0x0d917982, 0x201f2a6e, 0x3f35bf03, 0x8217c8e4, 0x00000000, 0x153402d6], - [0xa072c108, 0x74020c96, 0xc60568fd, 0x95f9613e, 0x00000000, 0x3f4676c2], - [0xd845d5d8, 0xcdd235c4, 0x20426475, 0x6154e78b, 0x00000006, 0x202fb751], - [0xa4dbf71f, 0x9e90465e, 0xf08e022f, 0xa8be947f, 0x00000000, 0xbe43b5ce], - [0x3dbe627f, 0xa791f4b9, 0x28a5bd89, 0x1f5dfe93, 0x00000004, 0x02bf9ed4], - [0x5c1c53ee, 0xccf5102e, 0x198576e7, 0x07e3ae31, 0x00000008, 0x02ea8fb7], - [0xfef1e581, 0x04714067, 0xca6540c1, 0x059e73ec, 0x00000000, 0x31658095], - [0x1e2dd90c, 0x13dd6667, 0x8b2184c3, 0x248d1a42, 0x00000000, 0x4ca6d0c6], - // --- divisors in (0, 2^16-1) to test larger quotient high-words - // low(a) high(a) b low(quot) high(quot) rem - [0x86722b47, 0x2cd57c9a, 0x00003123, 0x2ae41b7a, 0x0000e995, 0x00000f99], - [0x1dd7884c, 0xf5e839bc, 0x00009eeb, 0x5c886242, 0x00018c21, 0x000099b6], - [0x5c53d625, 0x899fc7e5, 0x000087d7, 0xd625007a, 0x0001035c, 0x000019af], - [0x6932d932, 0x9d0a5488, 0x000051fb, 0x9d976143, 0x0001ea63, 0x00004981], - [0x4d18bb85, 0x0c92fb31, 0x00001d9f, 0x03265ab4, 0x00006cac, 0x000001b9], - [0xbe756768, 0xdea67ccb, 0x00008a03, 0x58add442, 0x00019cff, 0x000056a2], - [0xe2466f9a, 0x2521f114, 0x0000c350, 0xa0c0860d, 0x000030ab, 0x0000a48a], - [0xf00ddad1, 0xe2f5446a, 0x00002cfc, 0x762697a6, 0x00050b96, 0x00000b69], - [0xa879152a, 0x0a70e0a5, 0x00007cdf, 0xb44151b3, 0x00001567, 0x0000363d], - [0x7179a74c, 0x46083fff, 0x0000253c, 0x4d39ba6e, 0x0001e17f, 0x00000f84] - ]; - - for (let i = 0; i < testData.length; i++) { - const a = new jspb.arith.UInt64(testData[i][0], testData[i][1]); - const result = a.div(testData[i][2]); - const quotient = result[0]; - const remainder = result[1]; - expect(quotient.lo).toEqual(testData[i][3]); - expect(quotient.hi).toEqual(testData[i][4]); - expect(remainder.lo).toEqual(testData[i][5]); - } - }); - - - /** - * Tests .toString() and .fromString(). - */ - it('testStrings', function() { - const testData = [ +describe('binaryArithTest', () => { + describe('UInt64', () => { + const /** ReadonlyArray<[number, number, string]> */ testData = Object.freeze([ + [0x0, 0x0, '0'], + [0xffffffff, 0xffffffff, '18446744073709551615'], + [0xffffffff, 0x00000000, '4294967295'], + [0x00000000, 0xffffffff, '18446744069414584320'], + [0x000f4240, 0x00000000, '1000000'], + [0x000f423f, 0x00000000, '999999'], + [0xd4a51000, 0x0000000e8, '1000000000000'], + [0xd4a50fff, 0x0000000e8, '999999999999'], [0x5e84c935, 0xcae33d0e, '14619595947299359029'], [0x62b3b8b8, 0x93480544, '10612738313170434232'], [0x319bfb13, 0xc01c4172, '13843011313344445203'], @@ -294,37 +73,204 @@ describe('binaryArithTest', function() { [0x4a843d8a, 0x864e132b, '9677693725920476554'], [0x25b4e94d, 0x22b54dc6, '2500990681505655117'], [0x6bbe664b, 0x55a5cc0e, '6171563226690381387'], - [0xee916c81, 0xb00aabb3, '12685140089732426881'] - ]; + [0xee916c81, 0xb00aabb3, '12685140089732426881'], + ]); + + // If BigInt is available, verify our test data with that. + if (typeof BigInt !== 'undefined') { + it('is tested with valid test data as verified with BigInt', () => { + for (const testCase of testData) { + const big = (BigInt(testCase[1]) << BigInt(32)) + BigInt(testCase[0]); + expect(big.toString()).toEqual(testCase[2]); + } + }); - for (let i = 0; i < testData.length; i++) { - const a = new jspb.arith.UInt64(testData[i][0], testData[i][1]); - const roundtrip = jspb.arith.UInt64.fromString(a.toString()); - expect(roundtrip.lo).toEqual(a.lo); - expect(roundtrip.hi).toEqual(a.hi); - expect(a.toString()).toEqual(testData[i][2]); + describe('fromBigInt', () => { + it(`parses testData`, () => { + for (const testCase of testData) { + const roundtrip = UInt64.fromBigInt(BigInt(testCase[2])); + expect(roundtrip.lo).withContext(testCase[2]).toEqual(testCase[0]); + expect(roundtrip.hi).withContext(testCase[2]).toEqual(testCase[1]); + } + }); + }); } + + describe('toDecimalString', () => { + it(`serializes testData`, () => { + for (const testCase of testData) { + const a = new UInt64(testCase[0], testCase[1]); + const actualString = a.toDecimalString(); + expect(actualString).withContext(testCase[2]).toEqual(testCase[2]); + } + }); + }); + + describe('fromString', () => { + it(`parses testData`, () => { + for (const testCase of testData) { + const roundtrip = UInt64.fromString(testCase[2]); + expect(roundtrip.lo).withContext(testCase[2]).toEqual(testCase[0]); + expect(roundtrip.hi).withContext(testCase[2]).toEqual(testCase[1]); + } + }); + + it('parses empty string as zero', () => { + expect(UInt64.fromString('')).toEqual(UInt64.fromString('0')); + }); + + it('does not parse non-decimal strings', () => { + expect(UInt64.fromString('0x123')).toBeNull(); + expect(UInt64.fromString(' 123')).toBeNull(); + }); + + it('tolerates extra leading zeros', () => { + expect(UInt64.fromString('0018446744073709551615')).toEqual( + UInt64.fromString('18446744073709551615'), + ); + }); + + it('truncates values that are too big', () => { + // 0x1_FFFF_FFFF_FFFF_FFFF = 36893488147419103231 + // 0xFFFF_FFFF_FFFF_FFFF = 18446744073709551615 + expect(UInt64.fromString('36893488147419103231')).toEqual( + UInt64.fromString('18446744073709551615'), + ); + }); + }); + + describe('negateInTwosComplement', () => { + if (typeof BigInt !== 'undefined') { + it('produces correct values', () => { + for (const testCase of testData) { + if (testCase[0] === 0 && testCase[1] === 0) continue; + const result = new UInt64( + testCase[0], + testCase[1], + ).negateInTwosComplement(); + const resultBigInt = + (BigInt(result.hi) << BigInt(32)) + BigInt(result.lo); + const expected = + (BigInt(1) << BigInt(64)) - + ((BigInt(testCase[1]) << BigInt(32)) + BigInt(testCase[0])); + expect(resultBigInt).toEqual(expected); + } + }); + } + + it('round-trips', () => { + for (const testCase of testData) { + expect( + new UInt64(testCase[0], testCase[1]) + .negateInTwosComplement() + .negateInTwosComplement() + .toDecimalString(), + ).toBe(testCase[2]); + } + }); + }); }); + describe('Int64', () => { + const /** ReadonlyArray<[number, number, string]> */ testData = Object.freeze([ + [0x0, 0x0, '0'], + [0xffffffff, 0xffffffff, '-1'], + [0x00000000, 0x80000000, '-9223372036854775808'], + [0xffffffff, 0x3fffffff, '4611686018427387903'], + [0xffffffff, 0x00000000, '4294967295'], + [0x00000000, 0xffffffff, '-4294967296'], + [0x000f4240, 0x00000000, '1000000'], + [0xd4a51000, 0x0000000e8, '1000000000000'], + [0xc5bb087e, 0x931814a6, '-7847499644178593666'], + [0xb58a5643, 0x3458a55b, '3771946501229139523'], + [0x7113da74, 0x27de6fcf, '2872856549054995060'], + [0x9d22f8c8, 0xafc92384, '-5780049594274350904'], + [0x48c45eb1, 0x2ef59f66, '3383785956695105201'], + [0x4f0a03e2, 0x294269f0, '2973055184857072610'], + [0xd4e95c3a, 0xca29805e, '-3879428459215627206'], + [0x934049d7, 0x3fb24a16, '4589812431064156631'], + [0xd272e654, 0x75bd7dc4, '8484075557333689940'], + [0x21f03f77, 0xeec5322, '1075325817098092407'], + [0x12158d26, 0xc3ad6da7, '-4346697501012292314'], + [0x7247925d, 0x22895b1f, '2488620459718316637'], + [0xb8d3e7a0, 0x54d48381, '6112655187423520672'], + [0xbf4836f8, 0xcd45d7c6, '-3655278273928612104'], + [0xf853f23c, 0x2fba545b, '3439154019435803196'], + [0xc004fc2d, 0xdef52fa, '1004112478843763757'], + [0x394e4b63, 0xa4937731, '-6587790776614368413'], + [0x596ed01a, 0x09382394, '664320065099714586'], + [0xe3244770, 0x42106251, '4760412909973292912'], + [0x92c2b290, 0x9233453d, '-7911903989602274672'], + ]); - /** - * Tests signed Int64s. These are built on UInt64s, so we only need to test - * the explicit overrides: .toString() and .fromString(). - */ - it('testSignedInt64', function() { - const testStrings = [ - '-7847499644178593666', '3771946501229139523', '2872856549054995060', - '-5780049594274350904', '3383785956695105201', '2973055184857072610', - '-3879428459215627206', '4589812431064156631', '8484075557333689940', - '1075325817098092407', '-4346697501012292314', '2488620459718316637', - '6112655187423520672', '-3655278273928612104', '3439154019435803196', - '1004112478843763757', '-6587790776614368413', '664320065099714586', - '4760412909973292912', '-7911903989602274672' - ]; + // If BigInt is available, verify our test data with that. + if (typeof BigInt !== 'undefined') { + it('is tested with valid test data as verified with BigInt', () => { + for (const testCase of testData) { + let big = (BigInt(testCase[1]) << BigInt(32)) + BigInt(testCase[0]); + if (testCase[2][0] === '-') { + big -= BigInt(2 ** 64); + } + expect(big.toString()).toEqual(testCase[2]); + } + }); - for (let i = 0; i < testStrings.length; i++) { - const roundtrip = jspb.arith.Int64.fromString(testStrings[i]).toString(); - expect(roundtrip).toEqual(testStrings[i]); + describe('fromBigInt', () => { + it(`parses testData`, () => { + for (const testCase of testData) { + const roundtrip = Int64.fromBigInt(BigInt(testCase[2])); + expect(roundtrip.lo).withContext(testCase[2]).toEqual(testCase[0]); + expect(roundtrip.hi).withContext(testCase[2]).toEqual(testCase[1]); + } + }); + }); } + + describe('toDecimalString', () => { + it(`serializes testData`, () => { + for (const testCase of testData) { + const a = new Int64(testCase[0], testCase[1]); + const actualString = a.toDecimalString(); + expect(actualString).withContext(testCase[2]).toEqual(testCase[2]); + } + }); + }); + + describe('fromString', () => { + it(`parses testData`, () => { + for (const testCase of testData) { + const roundtrip = Int64.fromString(testCase[2]); + expect(roundtrip.lo).withContext(testCase[2]).toEqual(testCase[0]); + expect(roundtrip.hi).withContext(testCase[2]).toEqual(testCase[1]); + } + }); + + it('parses empty string as zero', () => { + expect(Int64.fromString('')).toEqual(Int64.fromString('0')); + }); + + it('parses -0 string as zero', () => { + expect(Int64.fromString('-0')).toEqual(Int64.fromString('0')); + }); + + it('parses positive values that overflow into the negative space', () => { + expect( + Int64.fromString('9223372036854775808')?.toDecimalString(), + ).toEqual('-9223372036854775808'); + }); + + it('truncates values that are too big', () => { + // 0x1_FFFF_FFFF_FFFF_FFFF = 36893488147419103231 + // 0xFFFF_FFFF_FFFF_FFFF = 18446744073709551615 + expect(Int64.fromString('36893488147419103231')).toEqual( + Int64.fromString('18446744073709551615'), + ); + }); + + it('does not parse non-decimal strings', () => { + expect(Int64.fromString('0x123')).toBeNull(); + expect(Int64.fromString(' 123')).toBeNull(); + }); + }); }); }); diff --git a/binary/binary_constants.js b/binary/binary_constants.js new file mode 100755 index 0000000..a93caf9 --- /dev/null +++ b/binary/binary_constants.js @@ -0,0 +1,241 @@ +goog.module('jspb.BinaryConstants'); +goog.module.declareLegacyNamespace(); + + +/** + * Field type codes, taken from proto2/public/wire_format_lite.h. + * @enum {number} + * @package + */ +const FieldType = { + INVALID: -1, + DOUBLE: 1, + FLOAT: 2, + INT64: 3, + UINT64: 4, + INT32: 5, + FIXED64: 6, + FIXED32: 7, + BOOL: 8, + STRING: 9, + GROUP: 10, + MESSAGE: 11, + BYTES: 12, + UINT32: 13, + ENUM: 14, + SFIXED32: 15, + SFIXED64: 16, + SINT32: 17, + SINT64: 18, +}; + + +/** + * Wire-format type codes, taken from proto2/public/wire_format_lite.h. + * @enum {number} + */ +const WireType = { + INVALID: -1, + VARINT: 0, + FIXED64: 1, + DELIMITED: 2, + START_GROUP: 3, + END_GROUP: 4, + FIXED32: 5 +}; + +/** @return {boolean} */ +function isValidWireType(/** number */ wireType) { + return wireType >= 0 && wireType <= 5; +} + + +/** + * Translates field type to wire type. + * @param {!FieldType} fieldType + * @return {!WireType} + */ +function FieldTypeToWireType(fieldType) { + switch (fieldType) { + case FieldType.INT32: + case FieldType.INT64: + case FieldType.UINT32: + case FieldType.UINT64: + case FieldType.SINT32: + case FieldType.SINT64: + case FieldType.BOOL: + case FieldType.ENUM: + return WireType.VARINT; + + case FieldType.DOUBLE: + case FieldType.FIXED64: + case FieldType.SFIXED64: + return WireType.FIXED64; + + case FieldType.STRING: + case FieldType.MESSAGE: + case FieldType.BYTES: + return WireType.DELIMITED; + + case FieldType.FLOAT: + case FieldType.FIXED32: + case FieldType.SFIXED32: + return WireType.FIXED32; + + case FieldType.INVALID: + case FieldType.GROUP: + default: + return WireType.INVALID; + } +} + + +/** + * Flag to indicate a missing field. + * @const {number} + */ +const INVALID_FIELD_NUMBER = -1; + +/** + * Flag to indicate a missing tag. + * @const {number} + */ +const INVALID_TAG = -1; + + +/** + * The smallest denormal float32 value. + * @const {number} + */ +const FLOAT32_EPS = 1.401298464324817e-45; + + +/** + * The smallest normal float64 value. + * @const {number} + */ +const FLOAT32_MIN = 1.1754943508222875e-38; + + +/** + * The largest finite float32 value. + * @const {number} + */ +const FLOAT32_MAX = 3.4028234663852886e+38; + + +/** + * The smallest denormal float64 value. + * @const {number} + */ +const FLOAT64_EPS = 5e-324; + + +/** + * The smallest normal float64 value. + * @const {number} + */ +const FLOAT64_MIN = 2.2250738585072014e-308; + + +/** + * The largest finite float64 value. + * @const {number} + */ +const FLOAT64_MAX = 1.7976931348623157e+308; + + +/** + * Convenience constant equal to 2^20. + * @const {number} + */ +const TWO_TO_20 = 1048576; + + +/** + * Convenience constant equal to 2^23. + * @const {number} + */ +const TWO_TO_23 = 8388608; + + +/** + * Convenience constant equal to 2^31. + * @const {number} + */ +const TWO_TO_31 = 2147483648; + + +/** + * Convenience constant equal to 2^32. + * @const {number} + */ +const TWO_TO_32 = 4294967296; + + +/** + * Convenience constant equal to 2^52. + * @const {number} + */ +const TWO_TO_52 = 4503599627370496; + + +/** + * Convenience constant equal to 2^63. + * @const {number} + */ +const TWO_TO_63 = 9223372036854775808; + + +/** + * Convenience constant equal to 2^64. + * @const {number} + */ +const TWO_TO_64 = 18446744073709551616; + + +/** + * Eight-character string of zeros, used as the default 64-bit hash value. + * @const {string} + */ +const ZERO_HASH = '\0\0\0\0\0\0\0\0'; + + +// See MessageSet wire format: https://github.com/protocolbuffers/protobuf/blob/735621f7d720fcacc0a05114f407c3817411f296/src/google/protobuf/descriptor.proto#L600 +// message MessageSet { +// repeated group Item = 1 { +// required uint32 type_id = 2; +// required bytes message = 3; +// }; +// }; +const /** number */ MESSAGE_SET_GROUP_NUMBER = 1; +const /** number */ MESSAGE_SET_TYPE_ID_FIELD_NUMBER = 2; +const /** number */ MESSAGE_SET_MESSAGE_FIELD_NUMBER = 3; +const /** number */ MESSAGE_SET_MAX_TYPE_ID = 0xFFFFFFFE; + +exports = { + FieldType, + FieldTypeToWireType, + FLOAT32_EPS, + FLOAT32_MIN, + FLOAT32_MAX, + FLOAT64_EPS, + FLOAT64_MIN, + FLOAT64_MAX, + INVALID_FIELD_NUMBER, + INVALID_TAG, + MESSAGE_SET_GROUP_NUMBER, + MESSAGE_SET_MAX_TYPE_ID, + MESSAGE_SET_MESSAGE_FIELD_NUMBER, + MESSAGE_SET_TYPE_ID_FIELD_NUMBER, + TWO_TO_20, + TWO_TO_23, + TWO_TO_31, + TWO_TO_32, + TWO_TO_52, + TWO_TO_63, + TWO_TO_64, + WireType, + ZERO_HASH, + isValidWireType, +}; diff --git a/binary/bytesource.js b/binary/bytesource.js new file mode 100755 index 0000000..db009d5 --- /dev/null +++ b/binary/bytesource.js @@ -0,0 +1,10 @@ +goog.module('jspb.binary.bytesource'); + +/** + * The types convertible to Uint8Arrays. Strings are assumed to be + * base64-encoded. + * @typedef {?ArrayBuffer|?Uint8Array|?ReadonlyArray|string} + */ +let ByteSource; + +exports = {ByteSource}; diff --git a/binary/constants.js b/binary/constants.js deleted file mode 100644 index 600b26c..0000000 --- a/binary/constants.js +++ /dev/null @@ -1,409 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://protobuf.dev/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -/** - * @fileoverview This file contains constants and typedefs used by - * jspb.BinaryReader and BinaryWriter. - * @suppress {missingRequire} TODO(b/152540451): this shouldn't be needed - * - * @author aappleby@google.com (Austin Appleby) - */ - -goog.provide('jspb.AnyFieldType'); -goog.provide('jspb.BinaryConstants'); -goog.provide('jspb.BinaryMessage'); -goog.provide('jspb.BuilderFunction'); -goog.provide('jspb.ByteSource'); -goog.provide('jspb.ClonerFunction'); -goog.provide('jspb.ComparerFunction'); -goog.provide('jspb.ConstBinaryMessage'); -goog.provide('jspb.PrunerFunction'); -goog.provide('jspb.ReaderFunction'); -goog.provide('jspb.RecyclerFunction'); -goog.provide('jspb.RepeatedFieldType'); -goog.provide('jspb.ScalarFieldType'); -goog.provide('jspb.WriterFunction'); - - -goog.forwardDeclare('jspb.BinaryMessage'); -goog.forwardDeclare('jspb.BinaryReader'); -goog.forwardDeclare('jspb.BinaryWriter'); -goog.forwardDeclare('jspb.Message'); -goog.forwardDeclare('jsprotolib.BinaryExtension'); - - - -/** - * Base interface class for all const messages. - * @interface - * @export - */ -jspb.ConstBinaryMessage = function() {}; - -/** - * Generate a debug string for this proto that is in proto2 text format. - * @return {string} The debug string. - * @export - */ -jspb.ConstBinaryMessage.prototype.toDebugString; - -/** - * Helper to generate a debug string for this proto at some indent level. The - * first line is not indented. - * @param {number} indentLevel The number of spaces by which to indent lines. - * @return {string} The debug string. - * @protected - */ -jspb.ConstBinaryMessage.prototype.toDebugStringInternal; - -/** - * Base interface class for all messages. Does __not__ define any methods, as - * doing so on a widely-used interface defeats dead-code elimination. - * @interface - * @extends {jspb.ConstBinaryMessage} - * @export - */ -jspb.BinaryMessage = function() {}; - - -/** - * The types convertible to Uint8Arrays. Strings are assumed to be - * base64-encoded. - * @typedef {ArrayBuffer|Uint8Array|Array|string} - * @export - */ -jspb.ByteSource; - - -/** - * A scalar field in jspb can be a boolean, number, or string. - * @typedef {boolean|number|string} - * @export - */ -jspb.ScalarFieldType; - - -/** - * A repeated field in jspb is an array of scalars, blobs, or messages. - * @typedef {!Array| - !Array| - !Array| - !Array} -* @export - */ -jspb.RepeatedFieldType; - - -/** - * A field in jspb can be a scalar, a block of bytes, another proto, or an - * array of any of the above. - * @typedef {jspb.ScalarFieldType| - jspb.RepeatedFieldType| - !Uint8Array| - !jspb.ConstBinaryMessage| - !jspb.BinaryMessage| - !jsprotolib.BinaryExtension} - * @export - */ -jspb.AnyFieldType; - - -/** - * A builder function creates an instance of a message object. - * @typedef {function():!jspb.BinaryMessage} - * @export - */ -jspb.BuilderFunction; - - -/** - * A cloner function creates a deep copy of a message object. - * @typedef {function(jspb.ConstBinaryMessage):jspb.BinaryMessage} - * @export - */ -jspb.ClonerFunction; - - -/** - * A recycler function destroys an instance of a message object. - * @typedef {function(!jspb.BinaryMessage):void} - * @export - */ -jspb.RecyclerFunction; - - -/** - * A reader function initializes a message using data from a BinaryReader. - * @typedef {function(!jspb.BinaryMessage, !jspb.BinaryReader):void} - * @export - */ -jspb.ReaderFunction; - - -/** - * A writer function serializes a message to a BinaryWriter. - * @typedef {function((!jspb.Message|!jspb.ConstBinaryMessage), - * !jspb.BinaryWriter):void} - * @export - */ -jspb.WriterFunction; - - -/** - * A pruner function removes default-valued fields and empty submessages from a - * message and returns either the pruned message or null if the entire message - * was pruned away. - * @typedef {function(?jspb.BinaryMessage):?jspb.BinaryMessage} - * @export - */ -jspb.PrunerFunction; - - -/** - * A comparer function returns true if two protos are equal. - * @typedef {function(?jspb.ConstBinaryMessage, - * ?jspb.ConstBinaryMessage):boolean} - * @export - */ -jspb.ComparerFunction; - - -/** - * Field type codes, taken from proto2/public/wire_format_lite.h. - * @enum {number} - * @export - */ -jspb.BinaryConstants.FieldType = { - INVALID: -1, - DOUBLE: 1, - FLOAT: 2, - INT64: 3, - UINT64: 4, - INT32: 5, - FIXED64: 6, - FIXED32: 7, - BOOL: 8, - STRING: 9, - GROUP: 10, - MESSAGE: 11, - BYTES: 12, - UINT32: 13, - ENUM: 14, - SFIXED32: 15, - SFIXED64: 16, - SINT32: 17, - SINT64: 18, - - // Extended types for Javascript - - FHASH64: 30, // 64-bit hash string, fixed-length encoding. - VHASH64: 31 // 64-bit hash string, varint encoding. -}; - - -/** - * Wire-format type codes, taken from proto2/public/wire_format_lite.h. - * @enum {number} - * @export - */ -jspb.BinaryConstants.WireType = { - INVALID: -1, - VARINT: 0, - FIXED64: 1, - DELIMITED: 2, - START_GROUP: 3, - END_GROUP: 4, - FIXED32: 5 -}; - - -/** - * Translates field type to wire type. - * @param {jspb.BinaryConstants.FieldType} fieldType - * @return {jspb.BinaryConstants.WireType} - * @export - */ -jspb.BinaryConstants.FieldTypeToWireType = function(fieldType) { - var fieldTypes = jspb.BinaryConstants.FieldType; - var wireTypes = jspb.BinaryConstants.WireType; - switch (fieldType) { - case fieldTypes.INT32: - case fieldTypes.INT64: - case fieldTypes.UINT32: - case fieldTypes.UINT64: - case fieldTypes.SINT32: - case fieldTypes.SINT64: - case fieldTypes.BOOL: - case fieldTypes.ENUM: - case fieldTypes.VHASH64: - return wireTypes.VARINT; - - case fieldTypes.DOUBLE: - case fieldTypes.FIXED64: - case fieldTypes.SFIXED64: - case fieldTypes.FHASH64: - return wireTypes.FIXED64; - - case fieldTypes.STRING: - case fieldTypes.MESSAGE: - case fieldTypes.BYTES: - return wireTypes.DELIMITED; - - case fieldTypes.FLOAT: - case fieldTypes.FIXED32: - case fieldTypes.SFIXED32: - return wireTypes.FIXED32; - - case fieldTypes.INVALID: - case fieldTypes.GROUP: - default: - return wireTypes.INVALID; - } -}; - - -/** - * Flag to indicate a missing field. - * @const {number} - * @export - */ -jspb.BinaryConstants.INVALID_FIELD_NUMBER = -1; - - -/** - * The smallest denormal float32 value. - * @const {number} - * @export - */ -jspb.BinaryConstants.FLOAT32_EPS = 1.401298464324817e-45; - - -/** - * The smallest normal float64 value. - * @const {number} - * @export - */ -jspb.BinaryConstants.FLOAT32_MIN = 1.1754943508222875e-38; - - -/** - * The largest finite float32 value. - * @const {number} - * @export - */ -jspb.BinaryConstants.FLOAT32_MAX = 3.4028234663852886e+38; - - -/** - * The smallest denormal float64 value. - * @const {number} - * @export - */ -jspb.BinaryConstants.FLOAT64_EPS = 5e-324; - - -/** - * The smallest normal float64 value. - * @const {number} - * @export - */ -jspb.BinaryConstants.FLOAT64_MIN = 2.2250738585072014e-308; - - -/** - * The largest finite float64 value. - * @const {number} - * @export - */ -jspb.BinaryConstants.FLOAT64_MAX = 1.7976931348623157e+308; - - -/** - * Convenience constant equal to 2^20. - * @const {number} - * @export - */ -jspb.BinaryConstants.TWO_TO_20 = 1048576; - - -/** - * Convenience constant equal to 2^23. - * @const {number} - * @export - */ -jspb.BinaryConstants.TWO_TO_23 = 8388608; - - -/** - * Convenience constant equal to 2^31. - * @const {number} - * @export - */ -jspb.BinaryConstants.TWO_TO_31 = 2147483648; - - -/** - * Convenience constant equal to 2^32. - * @const {number} - * @export - */ -jspb.BinaryConstants.TWO_TO_32 = 4294967296; - - -/** - * Convenience constant equal to 2^52. - * @const {number} - * @export - */ -jspb.BinaryConstants.TWO_TO_52 = 4503599627370496; - - -/** - * Convenience constant equal to 2^63. - * @const {number} - * @export - */ -jspb.BinaryConstants.TWO_TO_63 = 9223372036854775808; - - -/** - * Convenience constant equal to 2^64. - * @const {number} - * @export - */ -jspb.BinaryConstants.TWO_TO_64 = 18446744073709551616; - - -/** - * Eight-character string of zeros, used as the default 64-bit hash value. - * @const {string} - * @export - */ -jspb.BinaryConstants.ZERO_HASH = '\0\0\0\0\0\0\0\0'; diff --git a/binary/decoder.js b/binary/decoder.js old mode 100644 new mode 100755 index 5dac0dd..c39cae9 --- a/binary/decoder.js +++ b/binary/decoder.js @@ -1,33 +1,3 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://protobuf.dev/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - /** * @fileoverview This file contains utilities for decoding primitive values * (signed and unsigned integers, varints, booleans, enums, hashes, strings, @@ -37,931 +7,1109 @@ * Major caveat - Javascript is unable to accurately represent integers larger * than 2^53 due to its use of a double-precision floating point format or all * numbers. If you need to guarantee that 64-bit values survive with all bits - * intact, you _must_ read them using one of the Hash64 methods, which return - * an 8-character string. + * intact, you _must_ read them using one of the split methods, which return + * numbers. * - * @suppress {missingRequire} TODO(b/152540451): this shouldn't be needed * @author aappleby@google.com (Austin Appleby) */ -goog.provide('jspb.BinaryDecoder'); - -goog.require('jspb.asserts'); -goog.require('jspb.binary.utf8'); -goog.require('jspb.utils'); +goog.module('jspb.binary.decoder'); +goog.module.declareLegacyNamespace(); +const asserts = goog.require('goog.asserts'); +const errors = goog.require('jspb.binary.errors'); +const utils = goog.require('jspb.utils'); +const {BinaryReaderOptions} = goog.requireType('jspb.binary.reader'); +const {Buffer, bufferFromSource} = goog.require('jspb.binary.internal_buffer'); +const {ByteSource} = goog.require('jspb.binary.bytesource'); +const {ByteString} = goog.require('jspb.bytestring'); +const {decodeUtf8} = goog.require('jspb.binary.utf8'); +const {unsafeByteStringFromUint8Array} = goog.require('jspb.unsafe_bytestring'); /** - * BinaryDecoder implements the decoders for all the wire types specified in - * https://protobuf.dev/programming-guides/encoding/. + * The maximum number of bytes in a varint. * - * @param {jspb.ByteSource=} opt_bytes The bytes we're reading from. - * @param {number=} opt_start The optional offset to start reading at. - * @param {number=} opt_length The optional length of the block to read - - * we'll throw an assertion if we go off the end of the block. - * @constructor - * @struct - * @export + * Every byte in a varint provides 7 bits and the largest number requires 64 + * bits which implies it would take up to 10 bytes to provide all the bits. `10 + * == Math.ceil(64/7)` */ -jspb.BinaryDecoder = function(opt_bytes, opt_start, opt_length) { - /** - * Typed byte-wise view of the source buffer. - * @private {?Uint8Array} - */ - this.bytes_ = null; +const /** number */ MAX_VARINT_SIZE = 10; +class BinaryDecoder { /** - * Start point of the block to read. - * @private {number} + * BinaryDecoder implements the decoders for all the wire types specified in + * https://developers.google.com/protocol-buffers/docs/encoding. + * + * @param {?ByteSource|!ByteString=} bytes The bytes we're reading from. + * @param {number=} start The optional offset to start reading at. + * @param {number=} length The optional length of the block to read - + * we'll throw an assertion if we go off the end of the block. + * @param {!BinaryReaderOptions=} options options for this decoder. */ - this.start_ = 0; + constructor(bytes, start, length, options) { + /** + * Typed byte-wise view of the source buffer. + * @private {?Uint8Array} + */ + this.bytes_ = null; - /** - * End point of the block to read. - * @private {number} - */ - this.end_ = 0; + /** + * Typed byte-wise view of the source buffer, if the data is immutable. + * @private {?Buffer} + */ + this.buffer_ = null; - /** - * Current read location in bytes_. - * @private {number} - */ - this.cursor_ = 0; + /** @private {boolean} */ + this.bytesAreImmutable_ = false; - /** - * Set to true if this decoder encountered an error due to corrupt data. - * @private {boolean} - */ - this.error_ = false; + if (ASSUME_DATAVIEW_IS_FAST) { + /** + * DataView of the source buffer. + * @private {?DataView} + */ + this.dataView_ = null; + } - if (opt_bytes) { - this.setBlock(opt_bytes, opt_start, opt_length); - } -}; + /** + * Start point of the block to read. + * @private {number} + */ + this.start_ = 0; + /** + * End point of the block to read, this is exclusive. + * @private {number} + */ + this.end_ = 0; -/** - * Global pool of BinaryDecoder instances. - * @private {!Array} - */ -jspb.BinaryDecoder.instanceCache_ = []; + /** + * Current read location in bytes_. + * @private {number} + */ + this.cursor_ = 0; + /** + * Set to true if this decoder should use subarray instead of slice. + * @private {boolean} + */ + this.aliasBytesFields; -/** - * @return {number} - * @export - */ -jspb.BinaryDecoder.getInstanceCacheLength = function() { - return jspb.BinaryDecoder.instanceCache_.length; -} + /** + * Whether we should treat newly deserialized data as being immutable. + * + * @private {boolean} + */ + this.treatNewDataAsImmutable; -/** - * Pops an instance off the instance cache, or creates one if the cache is - * empty. - * @param {jspb.ByteSource=} opt_bytes The bytes we're reading from. - * @param {number=} opt_start The optional offset to start reading at. - * @param {number=} opt_length The optional length of the block to read - - * we'll throw an assertion if we go off the end of the block. - * @return {!jspb.BinaryDecoder} - * @export - */ -jspb.BinaryDecoder.alloc = function(opt_bytes, opt_start, opt_length) { - if (jspb.BinaryDecoder.instanceCache_.length) { - var newDecoder = jspb.BinaryDecoder.instanceCache_.pop(); - if (opt_bytes) { - newDecoder.setBlock(opt_bytes, opt_start, opt_length); - } - return newDecoder; - } else { - return new jspb.BinaryDecoder(opt_bytes, opt_start, opt_length); + this.init(bytes, start, length, options); } -}; - -/** - * Puts this instance back in the instance cache. - * @export - */ -jspb.BinaryDecoder.prototype.free = function() { - this.clear(); - if (jspb.BinaryDecoder.instanceCache_.length < 100) { - jspb.BinaryDecoder.instanceCache_.push(this); + /** + * @param {?ByteSource|!ByteString=} bytes The bytes we're reading from. + * @param {number=} start The optional offset to start reading at. + * @param {number=} length The optional length of the block to read - + * we'll throw an assertion if we go off the end of the block. + * @param {!BinaryReaderOptions=} options options for this decoder. + * @private + */ + init( + bytes, start, length, + { aliasBytesFields = false, treatNewDataAsImmutable = false } = {}) { + this.aliasBytesFields = aliasBytesFields; + this.treatNewDataAsImmutable = treatNewDataAsImmutable; + if (bytes) { + this.setBlock(bytes, start, length); + } } -}; - - -/** - * Makes a copy of this decoder. - * @return {!jspb.BinaryDecoder} - * @export - */ -jspb.BinaryDecoder.prototype.clone = function() { - return jspb.BinaryDecoder.alloc( - this.bytes_, this.start_, this.end_ - this.start_); -}; - - -/** - * Clears the decoder. - * @export - */ -jspb.BinaryDecoder.prototype.clear = function() { - this.bytes_ = null; - this.start_ = 0; - this.end_ = 0; - this.cursor_ = 0; - this.error_ = false; -}; - -/** - * Returns the raw buffer. - * @return {?Uint8Array} The raw buffer. - * @export - */ -jspb.BinaryDecoder.prototype.getBuffer = function() { - return this.bytes_; -}; + /** + * Pops an instance off the instance cache, or creates one if the cache is + * empty. + * @param {?ByteSource|!ByteString=} bytes The bytes we're reading from. + * @param {number=} start The optional offset to start reading at. + * @param {number=} length The optional length of the block to read - + * we'll throw an assertion if we go off the end of the block. + * @param {!BinaryReaderOptions=} options options for this decoder. + * @return {!BinaryDecoder} + * @export + */ + static alloc(bytes, start, length, options) { + if (BinaryDecoder.instanceCache_.length) { + const newDecoder = BinaryDecoder.instanceCache_.pop(); + newDecoder.init(bytes, start, length, options); + return newDecoder; + } else { + return new BinaryDecoder(bytes, start, length, options); + } + } + /** + * Puts this instance back in the instance cache. + * @export + */ + free() { + this.clear(); + if (BinaryDecoder.instanceCache_.length < 100) { + BinaryDecoder.instanceCache_.push(this); + } + } -/** - * Changes the block of bytes we're decoding. - * @param {!jspb.ByteSource} data The bytes we're reading from. - * @param {number=} opt_start The optional offset to start reading at. - * @param {number=} opt_length The optional length of the block to read - - * we'll throw an assertion if we go off the end of the block. - * @export - */ -jspb.BinaryDecoder.prototype.setBlock = function(data, opt_start, opt_length) { - this.bytes_ = jspb.utils.byteSourceToUint8Array(data); - this.start_ = (opt_start !== undefined) ? opt_start : 0; - this.end_ = (opt_length !== undefined) ? this.start_ + opt_length : - this.bytes_.length; - this.cursor_ = this.start_; -}; + /** + * Clears the decoder. + * @export + */ + clear() { + this.bytes_ = null; + this.buffer_ = null; + this.bytesAreImmutable_ = false; + if (ASSUME_DATAVIEW_IS_FAST) { + this.dataView_ = null; + } + this.start_ = 0; + this.end_ = 0; + this.cursor_ = 0; + this.aliasBytesFields = false; + } + /** + * @export + * @return {boolean} + */ + dataIsImmutable() { + return this.bytesAreImmutable_; + } -/** - * @return {number} - * @export - */ -jspb.BinaryDecoder.prototype.getEnd = function() { - return this.end_; -}; + /** + * Returns the raw buffer. + * + * Throws if the internal buffer is immutable + * + * @export + * @return {?Uint8Array} The raw buffer. + */ + getBuffer() { + if (this.bytesAreImmutable_) { + throw goog.DEBUG ? + new Error( + 'cannot access the buffer of decoders over immutable data.') : + new Error(); + } + return this.bytes_; + } + /** + * Returns the raw buffer. + * + * Throws if the internal buffer is mutable + * + * @export + * @return {?ByteString} The buffer. + */ + getBufferAsByteString() { + if (this.buffer_ == null) return null; + if (!this.bytesAreImmutable_) { + throw goog.DEBUG ? + new Error( + 'cannot access the buffer of decoders over immutable data.') : + new Error(); + } + return this.buffer_.getBufferAsByteStringIfImmutable(); + } -/** - * @param {number} end - * @export - */ -jspb.BinaryDecoder.prototype.setEnd = function(end) { - this.end_ = end; -}; + /** + * Changes the block of bytes we're decoding. + * @param {!ByteSource|!ByteString} data The bytes we're reading from. + * @param {number=} start The optional offset to start reading at. + * @param {number=} length The optional length of the block to read - + * we'll throw an assertion if we go off the end of the block. + * + * @export + */ + setBlock(data, start, length) { + const unpackedData = bufferFromSource(data, this.treatNewDataAsImmutable); + this.buffer_ = unpackedData; + this.bytes_ = unpackedData.buffer; + this.bytesAreImmutable_ = unpackedData.isImmutable; + if (ASSUME_DATAVIEW_IS_FAST) this.dataView_ = null; + this.start_ = start || 0; + this.end_ = + (length !== undefined) ? this.start_ + length : this.bytes_.length; + this.cursor_ = this.start_; + } + /** + * @export + * @return {number} + */ + getEnd() { + return this.end_; + } -/** - * Moves the read cursor back to the start of the block. - * @export - */ -jspb.BinaryDecoder.prototype.reset = function() { - this.cursor_ = this.start_; -}; + /** + * @param {number} end + * @export + */ + setEnd(end) { + this.end_ = end; + } -/** - * Returns the internal read cursor. - * @return {number} The internal read cursor. - * @export - */ -jspb.BinaryDecoder.prototype.getCursor = function() { - return this.cursor_; -}; + /** + * Moves the read cursor back to the start of the block. + * @export + */ + reset() { + this.cursor_ = this.start_; + } -/** - * Returns the internal read cursor. - * @param {number} cursor The new cursor. - * @export - */ -jspb.BinaryDecoder.prototype.setCursor = function(cursor) { - this.cursor_ = cursor; -}; + /** + * Returns the internal read cursor. + * @export + * @return {number} The internal read cursor. + */ + getCursor() { + return this.cursor_; + } + /** + * Returns the internal read cursor. + * @param {number} cursor The new cursor. + * @export + */ + setCursor(cursor) { + this.cursor_ = cursor; + } -/** - * Advances the stream cursor by the given number of bytes. - * @param {number} count The number of bytes to advance by. - * @export - */ -jspb.BinaryDecoder.prototype.advance = function(count) { - this.cursor_ += count; - this.checkCursor(); -}; + /** + * Advances the stream cursor by the given number of bytes. + * @param {number} count The number of bytes to advance by. + * @export + */ + advance(count) { + const newCursor = this.cursor_ + count; + this.setCursorAndCheck(newCursor); + } -/** - * Returns true if this decoder is at the end of the block. - * @return {boolean} - * @export - */ -jspb.BinaryDecoder.prototype.atEnd = function() { - return this.cursor_ == this.end_; -}; + /** + * Returns true if this decoder is at the end of the block. + * @return {boolean} + * @export + */ + atEnd() { + return this.cursor_ == this.end_; + } -/** - * Returns true if this decoder is at the end of the block. - * @return {boolean} - * @export - */ -jspb.BinaryDecoder.prototype.pastEnd = function() { - return this.cursor_ > this.end_; -}; + /** + * Returns true if this decoder is at the end of the block. + * @return {boolean} + * @export + */ + pastEnd() { + return this.cursor_ > this.end_; + } + /** + * Reads an unsigned varint from the binary stream and invokes the conversion + * function with the value in two signed 32 bit integers to produce the + * result. Since this does not convert the value to a number, no precision is + * lost. + * + * It's possible for an unsigned varint to be incorrectly encoded - more than + * 64 bits' worth of data could be present. If this happens, this method will + * throw an error. + * + * Decoding varints requires doing some funny base-128 math - for more + * details on the format, see + * https://developers.google.com/protocol-buffers/docs/encoding + * + * @param {!BinaryDecoder} decoder + * @param {function(number, number): T} convert Conversion function to produce + * the result value, takes parameters (lowBits, highBits). + * @return {T} + * @export + * @template T + */ + static readSplitVarint64(decoder, convert) { + let temp = 0; + let lowBits = 0; + let highBits = 0; + let shift = 0; + const bytes = decoder.bytes_; + let cursor = decoder.cursor_; + + // Read the first five bytes of the varint, stopping at the terminator if we + // see it. + do { + temp = bytes[cursor++]; + lowBits |= (temp & 0x7F) << shift; + shift += 7; + } while (shift < 32 && temp & 0x80); + + if (shift > 32) { + // The fifth byte was read, which straddles the low and high dwords, + // Save its contribution to the high dword. + highBits |= (temp & 0x7F) >> 4; + } -/** - * Returns true if this decoder encountered an error due to corrupt data. - * @return {boolean} - * @export - */ -jspb.BinaryDecoder.prototype.getError = function() { - return this.error_ || (this.cursor_ < 0) || (this.cursor_ > this.end_); -}; + // Read the sixth through tenth byte. + for (shift = 3; shift < 32 && temp & 0x80; shift += 7) { + temp = bytes[cursor++]; + highBits |= (temp & 0x7F) << shift; + } + decoder.setCursorAndCheck(cursor); -/** - * Reads an unsigned varint from the binary stream and invokes the conversion - * function with the value in two signed 32 bit integers to produce the result. - * Since this does not convert the value to a number, no precision is lost. - * - * It's possible for an unsigned varint to be incorrectly encoded - more than - * 64 bits' worth of data could be present. If this happens, this method will - * throw an error. - * - * Decoding varints requires doing some funny base-128 math - for more - * details on the format, see - * https://protobuf.dev/programming-guides/encoding/ - * - * @param {function(number, number): T} convert Conversion function to produce - * the result value, takes parameters (lowBits, highBits). - * @return {T} - * @template T - * @export - */ -jspb.BinaryDecoder.prototype.readSplitVarint64 = function(convert) { - var temp = 128; - var lowBits = 0; - var highBits = 0; + if (temp < 128) { + return convert(lowBits >>> 0, highBits >>> 0); + } - // Read the first four bytes of the varint, stopping at the terminator if we - // see it. - for (var i = 0; i < 4 && temp >= 128; i++) { - temp = this.bytes_[this.cursor_++]; - lowBits |= (temp & 0x7F) << (i * 7); + // If we did not see the terminator, the encoding was invalid. + throw errors.invalidVarintError(); } - if (temp >= 128) { - // Read the fifth byte, which straddles the low and high dwords. - temp = this.bytes_[this.cursor_++]; - lowBits |= (temp & 0x7F) << 28; - highBits |= (temp & 0x7F) >> 4; + /** + * Reads a signed zigzag encoded varint from the binary stream and invokes + * the conversion function with the value in two signed 32 bit integers to + * produce the result. Since this does not convert the value to a number, no + * precision is lost. + * + * It's possible for an unsigned varint to be incorrectly encoded - more than + * 64 bits' worth of data could be present. If this happens, this method will + * throw an error. + * + * Zigzag encoding is a modification of varint encoding that reduces the + * storage overhead for small negative integers - for more details on the + * format, see https://developers.google.com/protocol-buffers/docs/encoding + * + * @param {!BinaryDecoder} decoder + * @param {function(number, number): T} convert Conversion function to produce + * the result value, takes parameters (lowBits, highBits). + * @return {T} + * @export + * @template T + */ + static readSplitZigzagVarint64(decoder, convert) { + return BinaryDecoder.readSplitVarint64( + decoder, (low, high) => utils.fromZigzag64(low, high, convert)); } - if (temp >= 128) { - // Read the sixth through tenth byte. - for (var i = 0; i < 5 && temp >= 128; i++) { - temp = this.bytes_[this.cursor_++]; - highBits |= (temp & 0x7F) << (i * 7 + 3); + /** + * Reads a 64-bit fixed-width value from the stream and invokes the conversion + * function with the value in two signed 32 bit integers to produce the + * result. Since this does not convert the value to a number, no precision is + * lost. + * + * @param {!BinaryDecoder} decoder + * @param {function(number, number): T} convert Conversion function to produce + * the result value, takes parameters (lowBits, highBits). + * @return {T} + * @export + * @template T + */ + static readSplitFixed64(decoder, convert) { + const bytes = decoder.bytes_; + const cursor = decoder.cursor_; + decoder.advance(8); + let lowBits = 0; + let highBits = 0; + for (let i = cursor + 7; i >= cursor; i--) { + lowBits = (lowBits << 8) | bytes[i]; + highBits = (highBits << 8) | bytes[i + 4]; } + return convert(lowBits, highBits); } - if (temp < 128) { - return convert(lowBits >>> 0, highBits >>> 0); + /** + * Skips over a varint in the block without decoding it. + * @export + */ + skipVarint() { + // readBool does only trivial decoding, delegate to it. + BinaryDecoder.readBool(this); } - // If we did not see the terminator, the encoding was invalid. - jspb.asserts.fail('Failed to read varint, encoding is invalid.'); - this.error_ = true; -}; - - -/** - * Reads a signed zigzag encoded varint from the binary stream and invokes - * the conversion function with the value in two signed 32 bit integers to - * produce the result. Since this does not convert the value to a number, no - * precision is lost. - * - * It's possible for an unsigned varint to be incorrectly encoded - more than - * 64 bits' worth of data could be present. If this happens, this method will - * throw an error. - * - * Zigzag encoding is a modification of varint encoding that reduces the - * storage overhead for small negative integers - for more details on the - * format, see https://protobuf.dev/programming-guides/encoding/ - * - * @param {function(number, number): T} convert Conversion function to produce - * the result value, takes parameters (lowBits, highBits). - * @return {T} - * @template T - * @export - */ -jspb.BinaryDecoder.prototype.readSplitZigzagVarint64 = function(convert) { - return this.readSplitVarint64(function(low, high) { - return jspb.utils.fromZigzag64(low, high, convert); - }); -}; - + /** + * Asserts that our cursor is in bounds. + * + * @private + * @param {number} cursor + * @return {void} + */ + setCursorAndCheck(cursor) { + this.cursor_ = cursor; + if (cursor > this.end_) { + throw errors.readTooFarError(this.end_, cursor); + } + } -/** - * Reads a 64-bit fixed-width value from the stream and invokes the conversion - * function with the value in two signed 32 bit integers to produce the result. - * Since this does not convert the value to a number, no precision is lost. - * - * @param {function(number, number): T} convert Conversion function to produce - * the result value, takes parameters (lowBits, highBits). - * @return {T} - * @template T - * @export - */ -jspb.BinaryDecoder.prototype.readSplitFixed64 = function(convert) { - var bytes = this.bytes_; - var cursor = this.cursor_; - this.cursor_ += 8; - var lowBits = 0; - var highBits = 0; - for (var i = cursor + 7; i >= cursor; i--) { - lowBits = (lowBits << 8) | bytes[i]; - highBits = (highBits << 8) | bytes[i + 4]; - } - return convert(lowBits, highBits); -}; + /** + * Reads a 32-bit varint from the binary stream. + * + * This function is called vastly more frequently than any other in + * BinaryDecoder, so it has been unrolled and tweaked for performance. + * + * Decoding varints requires doing some funny base-128 math - for more + * details on the format, see + * https://developers.google.com/protocol-buffers/docs/encoding + * + * @param {!BinaryDecoder} decoder + * @return {number} The decoded unsigned 32-bit varint. + * @export + */ + static readSignedVarint32(decoder) { + const bytes = decoder.bytes_; + let cursor = decoder.cursor_; + + let temp = bytes[cursor++]; + let x = (temp & 0x7F); + + if (temp & 0x80) { + temp = bytes[cursor++]; + x |= (temp & 0x7F) << 7; + + if (temp & 0x80) { + temp = bytes[cursor++]; + x |= (temp & 0x7F) << 14; + + if (temp & 0x80) { + temp = bytes[cursor++]; + x |= (temp & 0x7F) << 21; + + if (temp & 0x80) { + temp = bytes[cursor++]; + // We're reading the high bits of an unsigned varint. The byte we + // just read also contains bits 33 through 35, which we're going to + // discard. + x |= temp << 28; + + if (temp & 0x80) { + // If we get here, we need to truncate coming bytes. However we + // need to make sure cursor place is correct. + if (bytes[cursor++] & 0x80 && bytes[cursor++] & 0x80 && + bytes[cursor++] & 0x80 && bytes[cursor++] & 0x80 && + bytes[cursor++] & 0x80) { + // If we get here, the varint is too long. + throw errors.invalidVarintError(); + } + } + } + } + } + } -/** - * Asserts that our cursor is in bounds. - * - * @private - * @return {void} - */ -jspb.BinaryDecoder.prototype.checkCursor = function () { - if (this.cursor_ > this.end_) { - jspb.asserts.fail('Read past the end ' + this.cursor_ + ' > ' + this.end_); + decoder.setCursorAndCheck(cursor); + return x; } -} -/** - * Skips over a varint in the block without decoding it. - * @export - */ -jspb.BinaryDecoder.prototype.skipVarint = function() { - while (this.bytes_[this.cursor_] & 0x80) { - this.cursor_++; + /** + * Reads an unsigned 32-bit varint from the binary stream. + * + * @param {!BinaryDecoder} decoder + * @return {number} The decoded signed 32-bit varint. + * @export + */ + static readUnsignedVarint32(decoder) { + return BinaryDecoder.readSignedVarint32(decoder) >>> 0; } - this.cursor_++; -}; - -/** - * Skips backwards over a varint in the block - to do this correctly, we have - * to know the value we're skipping backwards over or things are ambiguous. - * @param {number} value The varint value to unskip. - * @export - */ -jspb.BinaryDecoder.prototype.unskipVarint = function(value) { - while (value > 128) { - this.cursor_--; - value = value >>> 7; + /** + * Peeks into the binary stream. If the value is an unsigned varint matching + * `expected`, returns the initial cursor position and advances the cursor + * past the varint. If the value is different, or the stream ends, returns + * -1. + * + * Designed for peeking to see the field header tag for the next field. + * + * Will only match minimal encodings, will only read up to 35 bits (5 7-bit + * bytes), and will not match over-long encodings even if they are short. + * + * A) These methods are optional optimizations, if they're conservative in + * matching, nothing should break, we'll just see another repeated field the + * normal way if the tag is encoded strangely. + * + * B) We don't want to reuse the "normal" read method, because it will throw + * on invalid formats and reading past the end, which we don't want to fail. + * + * C) If we somehow start to expect a difference in varint encoding, this + * decoder method likely needs to be aware of what information is encoded in + * that deviation anyway. + * + * @param {number} expected + * @return {number} + * @export + */ + readUnsignedVarint32IfEqualTo(expected) { + asserts.assert(expected === expected >>> 0); + const initialCursor = this.cursor_; + let cursor = initialCursor; + const end = this.end_; + const bytes = this.bytes_; + while (cursor < end) { + if (expected > 0x7F) { + const expectedByte = 0x80 | (expected & 0x7F); + if (bytes[cursor++] !== expectedByte) { + return -1; + } + expected >>>= 7; + } else { + // Last byte of the expected value. + if (bytes[cursor++] === expected) { + this.cursor_ = cursor; + return initialCursor; + } else { + return -1; + } + } + } + return -1; } - this.cursor_--; -}; -/** - * Reads a 32-bit varint from the binary stream. Due to a quirk of the encoding - * format and Javascript's handling of bitwise math, this actually works - * correctly for both signed and unsigned 32-bit varints. - * - * This function is called vastly more frequently than any other in - * BinaryDecoder, so it has been unrolled and tweaked for performance. - * - * If there are more than 32 bits of data in the varint, it _must_ be due to - * sign-extension. If we're in debug mode and the high 32 bits don't match the - * expected sign extension, this method will throw an error. - * - * Decoding varints requires doing some funny base-128 math - for more - * details on the format, see - * https://protobuf.dev/programming-guides/encoding/ - * - * @return {number} The decoded unsigned 32-bit varint. - * @export - */ -jspb.BinaryDecoder.prototype.readUnsignedVarint32 = function() { - var temp; - var bytes = this.bytes_; - - temp = bytes[this.cursor_ + 0]; - var x = (temp & 0x7F); - if (temp < 128) { - this.cursor_ += 1; - this.checkCursor(); - return x; + /** + * Reads a signed, zigzag-encoded 32-bit varint from the binary stream. + * + * Zigzag encoding is a modification of varint encoding that reduces the + * storage overhead for small negative integers - for more details on the + * format, see https://developers.google.com/protocol-buffers/docs/encoding + * + * @param {!BinaryDecoder} decoder + * @return {number} The decoded signed, zigzag-encoded 32-bit varint. + * @export + */ + static readZigzagVarint32(decoder) { + return utils.fromZigzag32(BinaryDecoder.readUnsignedVarint32(decoder)); } - temp = bytes[this.cursor_ + 1]; - x |= (temp & 0x7F) << 7; - if (temp < 128) { - this.cursor_ += 2; - this.checkCursor(); - return x; + /** + * Reads an unsigned 64-bit varint from the binary stream. Note that since + * Javascript represents all numbers as double-precision floats, there will be + * precision lost if the absolute value of the varint is larger than 2^53. + * + * @param {!BinaryDecoder} decoder + * @return {number} The decoded unsigned varint. Precision will be lost if the + * integer exceeds 2^53. + * @export + */ + static readUnsignedVarint64(decoder) { + return BinaryDecoder.readSplitVarint64(decoder, utils.joinUint64); } - temp = bytes[this.cursor_ + 2]; - x |= (temp & 0x7F) << 14; - if (temp < 128) { - this.cursor_ += 3; - this.checkCursor(); - return x; + /** + * Reads an unsigned 64-bit varint from the binary stream and returns the + * value as a decimal string. + * + * @param {!BinaryDecoder} decoder + * @return {string} The decoded unsigned varint as a decimal string. + * @export + */ + static readUnsignedVarint64String(decoder) { + return BinaryDecoder.readSplitVarint64( + decoder, utils.joinUnsignedDecimalString); } - temp = bytes[this.cursor_ + 3]; - x |= (temp & 0x7F) << 21; - if (temp < 128) { - this.cursor_ += 4; - this.checkCursor(); - return x; + /** + * Reads a signed 64-bit varint from the binary stream. Note that since + * Javascript represents all numbers as double-precision floats, there will be + * precision lost if the absolute value of the varint is larger than 2^53. + * + * @param {!BinaryDecoder} decoder + * @return {number} The decoded signed varint. Precision will be lost if the + * integer exceeds 2^53. + * @export + */ + static readSignedVarint64(decoder) { + return BinaryDecoder.readSplitVarint64(decoder, utils.joinInt64); } - temp = bytes[this.cursor_ + 4]; - x |= (temp & 0x0F) << 28; - if (temp < 128) { - // We're reading the high bits of an unsigned varint. The byte we just read - // also contains bits 33 through 35, which we're going to discard. - this.cursor_ += 5; - this.checkCursor(); - return x >>> 0; + /** + * Reads an signed 64-bit varint from the binary stream and returns the value + * as a decimal string. + * + * @param {!BinaryDecoder} decoder + * @return {string} The decoded signed varint as a decimal string. + * @export + */ + static readSignedVarint64String(decoder) { + return BinaryDecoder.readSplitVarint64( + decoder, utils.joinSignedDecimalString); } - // If we get here, we need to truncate coming bytes. However we need to make - // sure cursor place is correct. - this.cursor_ += 5; - if (bytes[this.cursor_++] >= 128 && bytes[this.cursor_++] >= 128 && - bytes[this.cursor_++] >= 128 && bytes[this.cursor_++] >= 128 && - bytes[this.cursor_++] >= 128) { - // If we get here, the varint is too long. - jspb.asserts.assert(false); + /** + * Reads a signed, zigzag-encoded 64-bit varint from the binary stream. Note + * that since Javascript represents all numbers as double-precision floats, + * there will be precision lost if the absolute value of the varint is larger + * than 2^53. + * + * Zigzag encoding is a modification of varint encoding that reduces the + * storage overhead for small negative integers - for more details on the + * format, see https://developers.google.com/protocol-buffers/docs/encoding + * + * @param {!BinaryDecoder} decoder + * @return {number} The decoded zigzag varint. Precision will be lost if the + * integer exceeds 2^53. + * @export + */ + static readZigzagVarint64(decoder) { + return BinaryDecoder.readSplitVarint64(decoder, utils.joinZigzag64); } - this.checkCursor(); - return x; -}; - - -/** - * Coerces the output of readUnsignedVarint32 to an int32. - * - * @return {number} The decoded signed 32-bit varint. - * @export - */ -jspb.BinaryDecoder.prototype.readSignedVarint32 = - function() { - // The `~` operator coerces to int32, and `~~` is the shortest expression of a - // cast. This has some edge cases (e.g. NaN becomes 0) but should be okay - // here. - return ~~(this.readUnsignedVarint32()); -} - - - /** - * Reads a 32-bit unsigned variant and returns its value as a string. - * - * @return {string} The decoded unsigned 32-bit varint as a string. - */ - jspb.BinaryDecoder.prototype.readUnsignedVarint32String = function() { - // 32-bit integers fit in JavaScript numbers without loss of precision, so - // string variants of 32-bit varint readers can simply delegate then convert - // to string. - var value = this.readUnsignedVarint32(); - return value.toString(); -}; - - -/** - * Reads a 32-bit signed variant and returns its value as a string. - * - * @return {string} The decoded signed 32-bit varint as a string. - * @export - */ -jspb.BinaryDecoder.prototype.readSignedVarint32String = function() { - // 32-bit integers fit in JavaScript numbers without loss of precision, so - // string variants of 32-bit varint readers can simply delegate then convert - // to string. - var value = this.readSignedVarint32(); - return value.toString(); -}; - - -/** - * Reads a signed, zigzag-encoded 32-bit varint from the binary stream. - * - * Zigzag encoding is a modification of varint encoding that reduces the - * storage overhead for small negative integers - for more details on the - * format, see https://protobuf.dev/programming-guides/encoding/ - * - * @return {number} The decoded signed, zigzag-encoded 32-bit varint. - * @export - */ -jspb.BinaryDecoder.prototype.readZigzagVarint32 = function() { - var result = this.readUnsignedVarint32(); - return (result >>> 1) ^ -(result & 1); -}; - - -/** - * Reads an unsigned 64-bit varint from the binary stream. Note that since - * Javascript represents all numbers as double-precision floats, there will be - * precision lost if the absolute value of the varint is larger than 2^53. - * - * @return {number} The decoded unsigned varint. Precision will be lost if the - * integer exceeds 2^53. - * @export - */ -jspb.BinaryDecoder.prototype.readUnsignedVarint64 = function() { - return this.readSplitVarint64(jspb.utils.joinUint64); -}; - - -/** - * Reads an unsigned 64-bit varint from the binary stream and returns the value - * as a decimal string. - * - * @return {string} The decoded unsigned varint as a decimal string. - * @export - */ -jspb.BinaryDecoder.prototype.readUnsignedVarint64String = function() { - return this.readSplitVarint64(jspb.utils.joinUnsignedDecimalString); -}; - - -/** - * Reads a signed 64-bit varint from the binary stream. Note that since - * Javascript represents all numbers as double-precision floats, there will be - * precision lost if the absolute value of the varint is larger than 2^53. - * - * @return {number} The decoded signed varint. Precision will be lost if the - * integer exceeds 2^53. - * @export - */ -jspb.BinaryDecoder.prototype.readSignedVarint64 = function() { - return this.readSplitVarint64(jspb.utils.joinInt64); -}; - - -/** - * Reads an signed 64-bit varint from the binary stream and returns the value - * as a decimal string. - * - * @return {string} The decoded signed varint as a decimal string. - * @export - */ -jspb.BinaryDecoder.prototype.readSignedVarint64String = function() { - return this.readSplitVarint64(jspb.utils.joinSignedDecimalString); -}; - - -/** - * Reads a signed, zigzag-encoded 64-bit varint from the binary stream. Note - * that since Javascript represents all numbers as double-precision floats, - * there will be precision lost if the absolute value of the varint is larger - * than 2^53. - * - * Zigzag encoding is a modification of varint encoding that reduces the - * storage overhead for small negative integers - for more details on the - * format, see https://protobuf.dev/programming-guides/encoding/ - * - * @return {number} The decoded zigzag varint. Precision will be lost if the - * integer exceeds 2^53. - * @export - */ -jspb.BinaryDecoder.prototype.readZigzagVarint64 = function() { - return this.readSplitVarint64(jspb.utils.joinZigzag64); -}; - -/** - * Reads a signed, zigzag-encoded 64-bit varint from the binary stream - * losslessly and returns it as an 8-character Unicode string for use as a hash - * table key. - * - * Zigzag encoding is a modification of varint encoding that reduces the - * storage overhead for small negative integers - for more details on the - * format, see https://protobuf.dev/programming-guides/encoding/ - * - * @return {string} The decoded zigzag varint in hash64 format. - * @export - */ -jspb.BinaryDecoder.prototype.readZigzagVarintHash64 = function() { - return this.readSplitZigzagVarint64(jspb.utils.joinHash64); -}; + /** + * Reads a signed, zigzag-encoded 64-bit varint from the binary stream and + * returns its value as a string. + * + * Zigzag encoding is a modification of varint encoding that reduces the + * storage overhead for small negative integers - for more details on the + * format, see https://developers.google.com/protocol-buffers/docs/encoding + * + * @param {!BinaryDecoder} decoder + * @return {string} The decoded signed, zigzag-encoded 64-bit varint as a + * string. + * @export + */ + static readZigzagVarint64String(decoder) { + return BinaryDecoder.readSplitZigzagVarint64( + decoder, utils.joinSignedDecimalString); + } + /** + * Reads a raw unsigned 8-bit integer from the binary stream. + * + * @param {!BinaryDecoder} decoder + * @return {number} The unsigned 8-bit integer read from the binary stream. + * @export + */ + static readUint8(decoder) { + const a = decoder.bytes_[decoder.cursor_ + 0]; + decoder.advance(1); + return a; + } -/** - * Reads a signed, zigzag-encoded 64-bit varint from the binary stream and - * returns its value as a string. - * - * Zigzag encoding is a modification of varint encoding that reduces the - * storage overhead for small negative integers - for more details on the - * format, see https://protobuf.dev/programming-guides/encoding/ - * - * @return {string} The decoded signed, zigzag-encoded 64-bit varint as a - * string. - * @export - */ -jspb.BinaryDecoder.prototype.readZigzagVarint64String = function() { - return this.readSplitZigzagVarint64(jspb.utils.joinSignedDecimalString); -}; + /** + * Reads a raw unsigned 16-bit integer from the binary stream. + * + * @param {!BinaryDecoder} decoder + * @return {number} The unsigned 16-bit integer read from the binary stream. + * @export + */ + static readUint16(decoder) { + const a = decoder.bytes_[decoder.cursor_ + 0]; + const b = decoder.bytes_[decoder.cursor_ + 1]; + decoder.advance(2); + return (a << 0) | (b << 8); + } -/** - * Reads a raw unsigned 8-bit integer from the binary stream. - * - * @return {number} The unsigned 8-bit integer read from the binary stream. - * @export - */ -jspb.BinaryDecoder.prototype.readUint8 = function() { - var a = this.bytes_[this.cursor_ + 0]; - this.cursor_ += 1; - this.checkCursor(); - return a; -}; + /** + * Reads a raw unsigned 32-bit integer from the binary stream. + * + * @param {!BinaryDecoder} decoder + * @return {number} The unsigned 32-bit integer read from the binary stream. + * @export + */ + static readUint32(decoder) { + const bytes = decoder.bytes_; + const cursor = decoder.cursor_; + const a = bytes[cursor + 0]; + const b = bytes[cursor + 1]; + const c = bytes[cursor + 2]; + const d = bytes[cursor + 3]; + decoder.advance(4); + return ((a << 0) | (b << 8) | (c << 16) | (d << 24)) >>> 0; + } -/** - * Reads a raw unsigned 16-bit integer from the binary stream. - * - * @return {number} The unsigned 16-bit integer read from the binary stream. - * @export - */ -jspb.BinaryDecoder.prototype.readUint16 = function() { - var a = this.bytes_[this.cursor_ + 0]; - var b = this.bytes_[this.cursor_ + 1]; - this.cursor_ += 2; - this.checkCursor(); - return (a << 0) | (b << 8); -}; + /** + * Reads a raw unsigned 64-bit integer from the binary stream. Note that since + * Javascript represents all numbers as double-precision floats, there will be + * precision lost if the absolute value of the integer is larger than 2^53. + * + * @param {!BinaryDecoder} decoder + * @return {number} The unsigned 64-bit integer read from the binary stream. + * Precision will be lost if the integer exceeds 2^53. + * @export + */ + static readUint64(decoder) { + const bitsLow = BinaryDecoder.readUint32(decoder); + const bitsHigh = BinaryDecoder.readUint32(decoder); + return utils.joinUint64(bitsLow, bitsHigh); + } + /** + * Reads a raw unsigned 64-bit integer from the binary stream. + * + * @param {!BinaryDecoder} decoder + * @return {string} The unsigned 64-bit integer read from the binary stream. + * @export + */ + static readUint64String(decoder) { + const bitsLow = BinaryDecoder.readUint32(decoder); + const bitsHigh = BinaryDecoder.readUint32(decoder); + return utils.joinUnsignedDecimalString(bitsLow, bitsHigh); + } -/** - * Reads a raw unsigned 32-bit integer from the binary stream. - * - * @return {number} The unsigned 32-bit integer read from the binary stream. - * @export - */ -jspb.BinaryDecoder.prototype.readUint32 = function() { - var a = this.bytes_[this.cursor_ + 0]; - var b = this.bytes_[this.cursor_ + 1]; - var c = this.bytes_[this.cursor_ + 2]; - var d = this.bytes_[this.cursor_ + 3]; - this.cursor_ += 4; - this.checkCursor(); - return ((a << 0) | (b << 8) | (c << 16) | (d << 24)) >>> 0; -}; + /** + * Reads a raw signed 8-bit integer from the binary stream. + * + * @param {!BinaryDecoder} decoder + * @return {number} The signed 8-bit integer read from the binary stream. + * @export + */ + static readInt8(decoder) { + const a = decoder.bytes_[decoder.cursor_ + 0]; + decoder.advance(1); + return (a << 24) >> 24; + } -/** - * Reads a raw unsigned 64-bit integer from the binary stream. Note that since - * Javascript represents all numbers as double-precision floats, there will be - * precision lost if the absolute value of the integer is larger than 2^53. - * - * @return {number} The unsigned 64-bit integer read from the binary stream. - * Precision will be lost if the integer exceeds 2^53. - * @export - */ -jspb.BinaryDecoder.prototype.readUint64 = function() { - var bitsLow = this.readUint32(); - var bitsHigh = this.readUint32(); - return jspb.utils.joinUint64(bitsLow, bitsHigh); -}; + /** + * Reads a raw signed 16-bit integer from the binary stream. + * + * @param {!BinaryDecoder} decoder + * @return {number} The signed 16-bit integer read from the binary stream. + * @export + */ + static readInt16(decoder) { + const a = decoder.bytes_[decoder.cursor_ + 0]; + const b = decoder.bytes_[decoder.cursor_ + 1]; + decoder.advance(2); + return (((a << 0) | (b << 8)) << 16) >> 16; + } -/** - * Reads a raw unsigned 64-bit integer from the binary stream. Note that since - * Javascript represents all numbers as double-precision floats, there will be - * precision lost if the absolute value of the integer is larger than 2^53. - * - * @return {string} The unsigned 64-bit integer read from the binary stream. - * @export - */ -jspb.BinaryDecoder.prototype.readUint64String = function() { - var bitsLow = this.readUint32(); - var bitsHigh = this.readUint32(); - return jspb.utils.joinUnsignedDecimalString(bitsLow, bitsHigh); -}; + /** + * Reads a raw signed 32-bit integer from the binary stream. + * + * @param {!BinaryDecoder} decoder + * @return {number} The signed 32-bit integer read from the binary stream. + * @export + */ + static readInt32(decoder) { + const bytes = decoder.bytes_; + const cursor = decoder.cursor_; + const a = bytes[cursor + 0]; + const b = bytes[cursor + 1]; + const c = bytes[cursor + 2]; + const d = bytes[cursor + 3]; + decoder.advance(4); + return (a << 0) | (b << 8) | (c << 16) | (d << 24); + } + /** + * Reads a raw signed 64-bit integer from the binary stream. Note that since + * Javascript represents all numbers as double-precision floats, there will be + * precision lost if the absolute value of the integer is larger than 2^53. + * + * @param {!BinaryDecoder} decoder + * @return {number} The signed 64-bit integer read from the binary stream. + * Precision will be lost if the integer exceeds 2^53. + * @export + */ + static readInt64(decoder) { + const bitsLow = BinaryDecoder.readUint32(decoder); + const bitsHigh = BinaryDecoder.readUint32(decoder); + return utils.joinInt64(bitsLow, bitsHigh); + } -/** - * Reads a raw signed 8-bit integer from the binary stream. - * - * @return {number} The signed 8-bit integer read from the binary stream. - * @export - */ -jspb.BinaryDecoder.prototype.readInt8 = function() { - var a = this.bytes_[this.cursor_ + 0]; - this.cursor_ += 1; - this.checkCursor(); - return (a << 24) >> 24; -}; + /** + * Reads a raw signed 64-bit integer from the binary stream and returns it as + * a string. + * + * @param {!BinaryDecoder} decoder + * @return {string} The signed 64-bit integer read from the binary stream. + * Precision will be lost if the integer exceeds 2^53. + * @export + */ + static readInt64String(decoder) { + const bitsLow = BinaryDecoder.readUint32(decoder); + const bitsHigh = BinaryDecoder.readUint32(decoder); + return utils.joinSignedDecimalString(bitsLow, bitsHigh); + } + /** + * Reads a 32-bit floating-point number from the binary stream, using the + * temporary buffer to realign the data. + * + * @param {!BinaryDecoder} decoder + * @return {number} The float read from the binary stream. + * @export + */ + static readFloat(decoder) { + const bitsLow = BinaryDecoder.readUint32(decoder); + const bitsHigh = 0; + return utils.joinFloat32(bitsLow, bitsHigh); + } -/** - * Reads a raw signed 16-bit integer from the binary stream. - * - * @return {number} The signed 16-bit integer read from the binary stream. - * @export - */ -jspb.BinaryDecoder.prototype.readInt16 = function() { - var a = this.bytes_[this.cursor_ + 0]; - var b = this.bytes_[this.cursor_ + 1]; - this.cursor_ += 2; - this.checkCursor(); - return (((a << 0) | (b << 8)) << 16) >> 16; -}; + /** + * Reads a 64-bit floating-point number from the binary stream, using the + * temporary buffer to realign the data. + * + * @param {!BinaryDecoder} decoder + * @return {number} The double read from the binary stream. + * @export + */ + static readDouble(decoder) { + if (ASSUME_DATAVIEW_IS_FAST) { + const result = decoder.getDataView().getFloat64( + decoder.cursor_, true /* little endian */); + decoder.advance(8); + return result; + } else { + const bitsLow = BinaryDecoder.readUint32(decoder); + const bitsHigh = BinaryDecoder.readUint32(decoder); + return utils.joinFloat64(bitsLow, bitsHigh); + } + } + /** + * Reads an array of 64-bit floating-point numbers from the binary stream. + * + * @param {number} len The number of doubles to read. + * @param {!Array} dst Where to append the result to. + * @export + */ + readDoubleArrayInto(len, dst) { + const cursor = this.cursor_; + const byteLength = 8 * len; + if (cursor + byteLength > this.end_) { + throw errors.readTooFarError(byteLength, this.end_ - cursor); + } -/** - * Reads a raw signed 32-bit integer from the binary stream. - * - * @return {number} The signed 32-bit integer read from the binary stream. - * @export - */ -jspb.BinaryDecoder.prototype.readInt32 = function() { - var a = this.bytes_[this.cursor_ + 0]; - var b = this.bytes_[this.cursor_ + 1]; - var c = this.bytes_[this.cursor_ + 2]; - var d = this.bytes_[this.cursor_ + 3]; - this.cursor_ += 4; - this.checkCursor(); - return (a << 0) | (b << 8) | (c << 16) | (d << 24); -}; + const bytes = this.bytes_; + const bufferStart = cursor + bytes.byteOffset; + + if (ASSUME_DATAVIEW_IS_FAST) { + // We create a subview that we'll traverse in its entirety, so that our + // "end of loop" condition matches the bounds check that the JIT will + // insert, in the hopes that the JIT only needs to run one of those checks + // instead of both. This seems to help benchmarks. + this.cursor_ += byteLength; + const subView = new DataView(bytes.buffer, bufferStart, byteLength); + let i = 0; + while (true) { + let next_i = i + 8; + if (next_i > subView.byteLength) { + break; + } + dst.push(subView.getFloat64(i, /*littleEndian=*/ true)); + i = next_i; + } + } else if (OPTIMIZE_LITTLE_ENDIAN_MACHINES && isLittleEndian()) { + // We can use Float64Array to directly interpret the bytes as float64 + // values, since this is a little endian machine. However, Float64Array + // will reject non-multiple-of-8 byte offsets, so we create a copy of the + // underlying ArrayBuffer. + this.cursor_ += byteLength; + const doubleArray = new Float64Array( + bytes.buffer.slice(bufferStart, bufferStart + byteLength)); + for (let i = 0; i < doubleArray.length; i++) { + dst.push(doubleArray[i]); + } + } else { + for (let i = 0; i < len; i++) { + dst.push(BinaryDecoder.readDouble( + this, + )); + } + } + } + /** + * Reads a boolean value from the binary stream. + * @param {!BinaryDecoder} decoder + * @return {boolean} The boolean read from the binary stream. + * @export + */ + static readBool(decoder) { + let varintBits = 0; + let cursor = decoder.cursor_; + const invalidCursor = cursor + MAX_VARINT_SIZE; + const bytes = decoder.bytes_; + while (cursor < invalidCursor) { + // scan for the first byte where the uppermost bit is 0 which signals the + // end of the varint + const byte = bytes[cursor++]; + varintBits |= byte; + if ((byte & 0x80) === 0) { + decoder.setCursorAndCheck(cursor); + // Varints store their 'values' in the lower 7 bits, so if we + // accumulated any non-zero bits then the varint is non-zero and the + // bool is true. + return !!(varintBits & 0x7f); + } + } + throw errors.invalidVarintError(); + } -/** - * Reads a raw signed 64-bit integer from the binary stream. Note that since - * Javascript represents all numbers as double-precision floats, there will be - * precision lost if the absolute value of the integer is larger than 2^53. - * - * @return {number} The signed 64-bit integer read from the binary stream. - * Precision will be lost if the integer exceeds 2^53. - * @export - */ -jspb.BinaryDecoder.prototype.readInt64 = function() { - var bitsLow = this.readUint32(); - var bitsHigh = this.readUint32(); - return jspb.utils.joinInt64(bitsLow, bitsHigh); -}; + /** + * Reads an enum value from the binary stream, which are always encoded as + * signed varints. + * @param {!BinaryDecoder} decoder + * @return {number} The enum value read from the binary stream. + * @export + */ + static readEnum(decoder) { + return BinaryDecoder.readSignedVarint32(decoder); + } + /** + * @return {number} original cursor. + * @private + */ + checkReadLengthAndAdvance(/** number */ length) { + if (length < 0) { + throw errors.negativeByteLengthError(length); + } + const cursor = this.cursor_; + const newCursor = cursor + length; + if (newCursor > this.end_) { + throw errors.readTooFarError(length, this.end_ - cursor); + } + this.cursor_ = newCursor; + return cursor; + } -/** - * Reads a raw signed 64-bit integer from the binary stream and returns it as a - * string. - * - * @return {string} The signed 64-bit integer read from the binary stream. - * Precision will be lost if the integer exceeds 2^53. - * @export - */ -jspb.BinaryDecoder.prototype.readInt64String = function() { - var bitsLow = this.readUint32(); - var bitsHigh = this.readUint32(); - return jspb.utils.joinSignedDecimalString(bitsLow, bitsHigh); -}; + /** + * Reads and parses a UTF-8 encoded unicode string from the stream. + * The code is inspired by maps.vectortown.parse.StreamedDataViewReader. + * Supports codepoints from U+0000 up to U+10FFFF. + * (http://en.wikipedia.org/wiki/UTF-8). + * @param {number} length The length of the string to read. + * @param {boolean} parsingErrorsAreFatal Whether to throw when invalid utf8 + * is found. + * @return {string} The decoded string. + * @export + */ + readString(length, parsingErrorsAreFatal) { + const cursor = this.checkReadLengthAndAdvance(length); + const result = decodeUtf8( + asserts.assert(this.bytes_), cursor, length, parsingErrorsAreFatal); + return result; + } -/** - * Reads a 32-bit floating-point number from the binary stream, using the - * temporary buffer to realign the data. - * - * @return {number} The float read from the binary stream. - * @export - */ -jspb.BinaryDecoder.prototype.readFloat = function() { - var bitsLow = this.readUint32(); - var bitsHigh = 0; - return jspb.utils.joinFloat32(bitsLow, bitsHigh); -}; + /** + * Reads a block of raw bytes from the binary stream. + * + * @param {number} length The number of bytes to read. + * @return {!Uint8Array} The decoded block of bytes. + * @export + */ + readBytes(length) { + const cursor = this.checkReadLengthAndAdvance(length); + // Take care not to return mutable references to immutable data. + const result = this.aliasBytesFields && !this.bytesAreImmutable_ ? + this.bytes_.subarray(cursor, cursor + length) : + utils.sliceUint8Array( + asserts.assert(this.bytes_), cursor, cursor + length); + return result; + } + /** + * Reads a block of raw bytes from the binary stream as a ByteString + * + * @param {number} length The number of bytes to read. + * @return {!ByteString} The decoded block of bytes. + * @export + */ + readByteString(length) { + if (length == 0) { + // Special case because slice is relatively slow, even on empty slices. + return ByteString.empty(); + } + const cursor = this.checkReadLengthAndAdvance(length); + // We can return a view if the source is also immutable + const result = this.aliasBytesFields && this.bytesAreImmutable_ ? + this.bytes_.subarray(cursor, cursor + length) : + utils.sliceUint8Array( + asserts.assert(this.bytes_), cursor, cursor + length); + // no need to checkCursor, we already checked above + // This unsafe call is actually safe because we either have sliced the array + // above, or we know the source of the 'subarray' view is immutable and so + // we can reference it from an immutable ByteString + return unsafeByteStringFromUint8Array(result); + } -/** - * Reads a 64-bit floating-point number from the binary stream, using the - * temporary buffer to realign the data. - * - * @return {number} The double read from the binary stream. - * @export - */ -jspb.BinaryDecoder.prototype.readDouble = function() { - var bitsLow = this.readUint32(); - var bitsHigh = this.readUint32(); - return jspb.utils.joinFloat64(bitsLow, bitsHigh); -}; + /** + * @return {!DataView} + * @private + */ + getDataView() { + let dataView = this.dataView_; + if (!dataView) { + const bytes = this.bytes_; + dataView = this.dataView_ = + new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength); + } + return dataView; + } + /** + * Visible for testing. + * @export + * @package + */ + static resetInstanceCache() { + BinaryDecoder.instanceCache_ = []; + } -/** - * Reads a boolean value from the binary stream. - * @return {boolean} The boolean read from the binary stream. - * @export - */ -jspb.BinaryDecoder.prototype.readBool = function() { - const b = !!this.bytes_[this.cursor_++]; - this.checkCursor(); - return b; -}; + /** + * Visible for testing. + * @return {!Array} + * @export + * @package + */ + static getInstanceCache() { + return BinaryDecoder.instanceCache_; + } +} /** - * Reads an enum value from the binary stream, which are always encoded as - * signed varints. - * @return {number} The enum value read from the binary stream. - * @export + * Global pool of BinaryDecoder instances. + * @private {!Array} */ -jspb.BinaryDecoder.prototype.readEnum = function() { - return this.readSignedVarint32(); -}; - +BinaryDecoder.instanceCache_ = []; /** - * Reads and parses a UTF-8 encoded unicode string from the stream. - * The code is inspired by maps.vectortown.parse.StreamedDataViewReader. - * Supports codepoints from U+0000 up to U+10FFFF. - * (http://en.wikipedia.org/wiki/UTF-8). - * @param {number} length The length of the string to read. - * @param {boolean} requireUtf8 Whether to throw when invalid utf8 is found. - * @return {string} The decoded string. - * @export + * Is this machine little endian? + * @return {boolean} */ +function isLittleEndian() { + if (isLittleEndianCache === undefined) { + // Do a trial memory load. + isLittleEndianCache = + new Uint16Array(new Uint8Array([1, 2]).buffer)[0] == (1 + 256 * 2); + } + return asserts.assertBoolean(isLittleEndianCache); +} -jspb.BinaryDecoder.prototype.readString = function (length, requireUtf8) { - const cursor = this.cursor_; - this.cursor_ += length; - this.checkCursor(); - const result = - jspb.binary.utf8.decodeUtf8(jspb.asserts.assert(this.bytes_), cursor, length, requireUtf8); - return result; -}; +/** Global cache of the isLittleEndian check. */ +let isLittleEndianCache = undefined; /** - * Reads a block of raw bytes from the binary stream. - * - * @param {number} length The number of bytes to read. - * @return {!Uint8Array} The decoded block of bytes, or an empty block if the - * length was invalid. - * @export + * @define {boolean} + * Whether DataView is known to be present and has a fast implementation. + * Chrome's implementation was slow until late 2018: + * https://v8.dev/blog/dataview. Unsure of the performance on other browsers. */ -jspb.BinaryDecoder.prototype.readBytes = function(length) { - if (length < 0 || this.cursor_ + length > this.bytes_.length) { - this.error_ = true; - jspb.asserts.fail('Invalid byte length!'); - return new Uint8Array(0); - } - - var result = this.bytes_.subarray(this.cursor_, this.cursor_ + length); - - this.cursor_ += length; - this.checkCursor(); - return result; -}; - +const ASSUME_DATAVIEW_IS_FAST = goog.define( + 'jspb.BinaryDecoder.ASSUME_DATAVIEW_IS_FAST', goog.FEATURESET_YEAR >= 2019); /** - * Reads a 64-bit varint from the stream and returns it as an 8-character - * Unicode string for use as a hash table key. + * @define {boolean} If true, on little endian machines we'll enable the fast + * path for float64 decoding. * - * @return {string} The hash value. - * @export + * Only exists for testing. */ -jspb.BinaryDecoder.prototype.readVarintHash64 = function() { - return this.readSplitVarint64(jspb.utils.joinHash64); -}; +const OPTIMIZE_LITTLE_ENDIAN_MACHINES = + goog.define('jspb.BinaryDecoder.OPTIMIZE_LITTLE_ENDIAN_MACHINES', true); -/** - * Reads a 64-bit fixed-width value from the stream and returns it as an - * 8-character Unicode string for use as a hash table key. - * - * @return {string} The hash value. - * @export - */ -jspb.BinaryDecoder.prototype.readFixedHash64 = function() { - var bytes = this.bytes_; - var cursor = this.cursor_; - - var a = bytes[cursor + 0]; - var b = bytes[cursor + 1]; - var c = bytes[cursor + 2]; - var d = bytes[cursor + 3]; - var e = bytes[cursor + 4]; - var f = bytes[cursor + 5]; - var g = bytes[cursor + 6]; - var h = bytes[cursor + 7]; - - this.cursor_ += 8; - - return String.fromCharCode(a, b, c, d, e, f, g, h); +exports = { + BinaryDecoder, }; diff --git a/binary/decoder_alias.js b/binary/decoder_alias.js new file mode 100755 index 0000000..42367e9 --- /dev/null +++ b/binary/decoder_alias.js @@ -0,0 +1,9 @@ +/** + * @fileoverview Legacy alias for the old namespace used by encoder.js + */ +goog.module('jspb.BinaryDecoder'); +goog.module.declareLegacyNamespace(); + +const {BinaryDecoder} = goog.require('jspb.binary.decoder'); + +exports = BinaryDecoder; diff --git a/binary/decoder_test.js b/binary/decoder_test.js old mode 100644 new mode 100755 index 7a71c0d..626118f --- a/binary/decoder_test.js +++ b/binary/decoder_test.js @@ -42,24 +42,41 @@ */ goog.require('jspb.BinaryConstants'); -goog.require('jspb.BinaryDecoder'); -goog.require('jspb.BinaryEncoder'); - goog.require('jspb.utils'); +goog.require('jspb.binary.decoder'); +goog.require('jspb.binary.encoder'); +goog.require('jspb.binary.utf8'); +goog.require('jspb.bytestring'); + +const BinaryConstants = goog.module.get('jspb.BinaryConstants'); +const utils = goog.module.get('jspb.utils'); +const BinaryDecoder = goog.module.get('jspb.binary.decoder').BinaryDecoder; +const BinaryEncoder = goog.module.get('jspb.binary.encoder').BinaryEncoder; +const ByteString = goog.module.get('jspb.bytestring').ByteString; +const encodeUtf8 = goog.module.get('jspb.binary.utf8').encodeUtf8; +/** + * + * @param {number|string|bigint} x + * @returns number + */ +function asNumberOrString(x) { + const num = Number(x); + return Number.isSafeInteger(num) ? num : (/** @type{number} */(String(x))); +} /** * Tests encoding and decoding of unsigned types. - * @param {Function} readValue - * @param {Function} writeValue + * @param {!Function} readValue + * @param {!Function} writeValue * @param {number} epsilon * @param {number} upperLimit - * @param {Function} filter + * @param {!Function} filter * @suppress {missingProperties|visibility} */ -function doTestUnsignedValue( - readValue, writeValue, epsilon, upperLimit, filter) { - const encoder = new jspb.BinaryEncoder(); +function doTestUnsignedValue(readValue, + writeValue, epsilon, upperLimit, filter) { + const encoder = new BinaryEncoder(); // Encode zero and limits. writeValue.call(encoder, filter(0)); @@ -71,16 +88,16 @@ function doTestUnsignedValue( writeValue.call(encoder, filter(cursor)); } - const decoder = jspb.BinaryDecoder.alloc(encoder.end()); + const decoder = BinaryDecoder.alloc(encoder.end()); // Check zero and limits. - expect(readValue.call(decoder)).toEqual(filter(0)); - expect(readValue.call(decoder)).toEqual(filter(epsilon)); - expect(readValue.call(decoder)).toEqual(filter(upperLimit)); + expect(readValue(decoder)).toEqual(filter(0)); + expect(readValue(decoder)).toEqual(filter(epsilon)); + expect(readValue(decoder)).toEqual(filter(upperLimit)); // Check positive values. for (let cursor = epsilon; cursor < upperLimit; cursor *= 1.1) { - if (filter(cursor) != readValue.call(decoder)) throw 'fail!'; + if (filter(cursor) != readValue(decoder)) throw 'fail!'; } // Encoding values outside the valid range should assert. @@ -92,20 +109,19 @@ function doTestUnsignedValue( }).toThrow(); } - /** * Tests encoding and decoding of signed types. - * @param {Function} readValue - * @param {Function} writeValue + * @param {!Function} readValue + * @param {!Function} writeValue * @param {number} epsilon * @param {number} lowerLimit * @param {number} upperLimit - * @param {Function} filter + * @param {!Function} filter * @suppress {missingProperties} */ -function doTestSignedValue( - readValue, writeValue, epsilon, lowerLimit, upperLimit, filter) { - const encoder = new jspb.BinaryEncoder(); +function doTestSignedValue(readValue, + writeValue, epsilon, lowerLimit, upperLimit, filter) { + const encoder = new BinaryEncoder(); // Encode zero and limits. writeValue.call(encoder, filter(lowerLimit)); @@ -118,7 +134,7 @@ function doTestSignedValue( // Encode negative values. for (let cursor = lowerLimit; cursor < -epsilon; cursor /= 1.1) { - let val = filter(cursor); + const val = filter(cursor); writeValue.call(encoder, val); inputValues.push(val); } @@ -130,18 +146,25 @@ function doTestSignedValue( inputValues.push(val); } - const decoder = jspb.BinaryDecoder.alloc(encoder.end()); + const decoder = BinaryDecoder.alloc(encoder.end()); // Check zero and limits. - expect(readValue.call(decoder)).toEqual(filter(lowerLimit)); - expect(readValue.call(decoder)).toEqual(filter(-epsilon)); - expect(readValue.call(decoder)).toEqual(filter(0)); - expect(readValue.call(decoder)).toEqual(filter(epsilon)); - expect(readValue.call(decoder)).toEqual(filter(upperLimit)); + expect(readValue(decoder)).toEqual(filter(lowerLimit)); + expect(readValue(decoder)).toEqual(filter(-epsilon)); + expect(readValue(decoder)).toEqual(filter(0)); + expect(readValue(decoder)).toEqual(filter(epsilon)); + expect(readValue(decoder)).toEqual(filter(upperLimit)); // Verify decoded values. + const nestedData = + new Uint8Array(decoder.getBuffer().buffer, decoder.getCursor()); + for (let i = 0; i < inputValues.length; i++) { + expect(readValue(decoder)).toEqual(inputValues[i]); + } + // Verify we can read from a nested Uint8Array. + const nestedDecoder = BinaryDecoder.alloc(nestedData); for (let i = 0; i < inputValues.length; i++) { - expect(readValue.call(decoder)).toEqual(inputValues[i]); + expect(readValue(nestedDecoder)).toEqual(inputValues[i]); } // Encoding values outside the valid range should assert. @@ -155,349 +178,411 @@ function doTestSignedValue( } } +/** + * @param {function(!BinaryDecoder):number} readValue + * @param {function(!BinaryEncoder, number)} writeValue + */ +function doTestSigned64BitIntValue( + readValue, + writeValue +) { + const encoder = new BinaryEncoder(); + + const lowerLimit = -Math.pow(2, 63); + const upperLimit = Math.pow(2, 63) - 1024; + + const inputValues = []; + function addValue(/** number */v, /**string|undefined*/withPrecision) { + writeValue.call(encoder, v); + inputValues.push(withPrecision ? asNumberOrString(withPrecision) : v); + } + // Encode zero and limits. + addValue(lowerLimit, '-9223372036854775808'); + addValue(-1); + addValue(0); + addValue(1); + addValue(upperLimit, '9223372036854774784'); + + // Encode negative values. + for ( + let cursor = BigInt('-9223372036854775808'); + cursor < BigInt(-1); + cursor /= BigInt(2) + ) { + addValue(Number(cursor), String(cursor)); + } + + // Encode positive values. + for ( + let cursor = BigInt(1); + cursor < BigInt('9223372036854774784'); + cursor *= BigInt(2) + ) { + addValue(Number(cursor), String(cursor)); + } + + const encodedData = encoder.end(); + const decoder = BinaryDecoder.alloc(encodedData); + const u8 = new Uint8Array(encodedData.length + 5); + u8.set(encodedData, 5); + // Verify we can read from a Uint8Array that has a byteoffset + const offsetDecoder = BinaryDecoder.alloc(new Uint8Array(u8.buffer, 5)); + + // Verify decoded values. + for (let i = 0; i < inputValues.length; i++) { + expect(readValue(decoder)).toBe(inputValues[i]); + expect(readValue(offsetDecoder)).toBe(inputValues[i]); + } + // Encoding values outside the valid range should assert. + const pastLowerLimit = lowerLimit * 1.1; + const pastUpperLimit = upperLimit * 1.1; + expect(() => { writeValue.call(encoder, pastLowerLimit); }).toThrow(); + expect(() => { writeValue.call(encoder, pastUpperLimit); }).toThrow(); +} + +/** + * @param {function(!BinaryDecoder):number} readValue + * @param {function(!BinaryEncoder, number)} writeValue + */ +function doTestUnsigned64BitIntValue( + readValue, + writeValue +) { + const encoder = new BinaryEncoder(); + const upperLimit = Math.pow(2, 64) - 2048; + + // Encode zero and limits. + writeValue.call(encoder, 0); + writeValue.call(encoder, 1); + writeValue.call(encoder, upperLimit); + // Encode positive values. + for ( + let cursor = BigInt(1); + cursor < BigInt('18446744073709549568'); + cursor *= BigInt(2) + ) { + writeValue.call(encoder, asNumberOrString(cursor.toString())); + } + + const decoder = BinaryDecoder.alloc(encoder.end()); + + // Check zero and limits. + expect(readValue(decoder)).toEqual(0); + expect(readValue(decoder)).toEqual(1); + expect(readValue(decoder)).toEqual( + /** @type{number}*/('18446744073709549568') + ); + + // Check positive values. + for ( + let cursor = BigInt(1); + cursor < BigInt('18446744073709549568'); + cursor *= BigInt(2) + ) { + expect(readValue(decoder)).toEqual(asNumberOrString(cursor.toString())); + } + + // Encoding values outside the valid range should assert. + expect(() => { + writeValue.call(encoder, -1); + }).toThrow(); + expect(() => { + writeValue.call( + encoder, + Number( + BigInt('18446744073709549568') * BigInt(2), + ), + ); + }).toThrow(); +} + describe('binaryDecoderTest', () => { - /** - * Tests the decoder instance cache. - */ - it('testInstanceCache', /** @suppress {visibility} */ () => { + /** Tests the decoder instance cache. */ + it('testInstanceCache', () => { // Empty the instance caches. - jspb.BinaryDecoder.instanceCache_ = []; + BinaryDecoder.resetInstanceCache(); // Allocating and then freeing a decoder should put it in the instance // cache. - jspb.BinaryDecoder.alloc().free(); + BinaryDecoder.alloc().free(); - expect(jspb.BinaryDecoder.getInstanceCacheLength()).toEqual(1); + expect(BinaryDecoder.getInstanceCache().length).toEqual(1); // Allocating and then freeing three decoders should leave us with three in // the cache. - const decoder1 = jspb.BinaryDecoder.alloc(); - const decoder2 = jspb.BinaryDecoder.alloc(); - const decoder3 = jspb.BinaryDecoder.alloc(); + const decoder1 = BinaryDecoder.alloc(); + const decoder2 = BinaryDecoder.alloc(); + const decoder3 = BinaryDecoder.alloc(); decoder1.free(); decoder2.free(); decoder3.free(); - expect(jspb.BinaryDecoder.getInstanceCacheLength()).toEqual(3); + expect(BinaryDecoder.getInstanceCache().length).toEqual(3); }); - describe('varint64', () => { - let /** !jspb.BinaryEncoder */ encoder; - let /** !jspb.BinaryDecoder */ decoder; - - const hashA = - String.fromCharCode(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - const hashB = - String.fromCharCode(0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - const hashC = - String.fromCharCode(0x12, 0x34, 0x56, 0x78, 0x87, 0x65, 0x43, 0x21); - const hashD = - String.fromCharCode(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); - beforeEach(() => { - encoder = new jspb.BinaryEncoder(); - - encoder.writeVarintHash64(hashA); - encoder.writeVarintHash64(hashB); - encoder.writeVarintHash64(hashC); - encoder.writeVarintHash64(hashD); + let /** !BinaryEncoder */ encoder; + let /** !BinaryDecoder */ decoder; - encoder.writeFixedHash64(hashA); - encoder.writeFixedHash64(hashB); - encoder.writeFixedHash64(hashC); - encoder.writeFixedHash64(hashD); + const a = { lo: 0x00000000, hi: 0x00000000 }; + const b = { lo: 0x00003412, hi: 0x00000000 }; + const c = { lo: 0x78563412, hi: 0x21436587 }; + const d = { lo: 0xFFFFFFFF, hi: 0xFFFFFFFF }; + beforeEach(() => { + encoder = new BinaryEncoder(); - decoder = jspb.BinaryDecoder.alloc(encoder.end()); - }); + encoder.writeSplitVarint64(a.lo, a.hi); + encoder.writeSplitVarint64(b.lo, b.hi); + encoder.writeSplitVarint64(c.lo, c.hi); + encoder.writeSplitVarint64(d.lo, d.hi); - it('reads 64-bit integers as hash strings', () => { - expect(hashA).toEqual(decoder.readVarintHash64()); - expect(hashB).toEqual(decoder.readVarintHash64()); - expect(hashC).toEqual(decoder.readVarintHash64()); - expect(hashD).toEqual(decoder.readVarintHash64()); + encoder.writeSplitFixed64(a.lo, a.hi); + encoder.writeSplitFixed64(b.lo, b.hi); + encoder.writeSplitFixed64(c.lo, c.hi); + encoder.writeSplitFixed64(d.lo, d.hi); - expect(hashA).toEqual(decoder.readFixedHash64()); - expect(hashB).toEqual(decoder.readFixedHash64()); - expect(hashC).toEqual(decoder.readFixedHash64()); - expect(hashD).toEqual(decoder.readFixedHash64()); + decoder = BinaryDecoder.alloc(encoder.end()); }); it('reads split 64 bit integers', () => { function hexJoin(bitsLow, bitsHigh) { - return `0x${(bitsHigh >>> 0).toString(16)}:0x${ - (bitsLow >>> 0).toString(16)}`; + return `0x${(bitsHigh >>> 0).toString(16)}:0x${(bitsLow >>> 0).toString(16)}`; } - function hexJoinHash(hash64) { - jspb.utils.splitHash64(hash64, true); - - return hexJoin(jspb.utils.getSplit64Low(), jspb.utils.getSplit64High()); + function hexJoinPair(p) { + return hexJoin(p.lo, p.hi); } - expect(decoder.readSplitVarint64(hexJoin)).toEqual(hexJoinHash(hashA)); - expect(decoder.readSplitVarint64(hexJoin)).toEqual(hexJoinHash(hashB)); - expect(decoder.readSplitVarint64(hexJoin)).toEqual(hexJoinHash(hashC)); - expect(decoder.readSplitVarint64(hexJoin)).toEqual(hexJoinHash(hashD)); + expect(BinaryDecoder.readSplitVarint64(decoder, hexJoin)).toEqual(hexJoinPair(a)); + expect(BinaryDecoder.readSplitVarint64(decoder, hexJoin)).toEqual(hexJoinPair(b)); + expect(BinaryDecoder.readSplitVarint64(decoder, hexJoin)).toEqual(hexJoinPair(c)); + expect(BinaryDecoder.readSplitVarint64(decoder, hexJoin)).toEqual(hexJoinPair(d)); - expect(decoder.readSplitFixed64(hexJoin)).toEqual(hexJoinHash(hashA)); - expect(decoder.readSplitFixed64(hexJoin)).toEqual(hexJoinHash(hashB)); - expect(decoder.readSplitFixed64(hexJoin)).toEqual(hexJoinHash(hashC)); - expect(decoder.readSplitFixed64(hexJoin)).toEqual(hexJoinHash(hashD)); + expect(BinaryDecoder.readSplitFixed64(decoder, hexJoin)).toEqual(hexJoinPair(a)); + expect(BinaryDecoder.readSplitFixed64(decoder, hexJoin)).toEqual(hexJoinPair(b)); + expect(BinaryDecoder.readSplitFixed64(decoder, hexJoin)).toEqual(hexJoinPair(c)); + expect(BinaryDecoder.readSplitFixed64(decoder, hexJoin)).toEqual(hexJoinPair(d)); + }); + it('split 64 out of range', () => { + decoder = BinaryDecoder.alloc(new Uint8Array([0, 1, 2])); + expect(() => BinaryDecoder.readSplitFixed64(decoder, (hi, low) => { + throw new Error(); + })).toThrowError('Tried to read past the end of the data 8 > 3'); }); }); describe('sint64', () => { - let /** !jspb.BinaryDecoder */ decoder; - - const hashA = - String.fromCharCode(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - const hashB = - String.fromCharCode(0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); - const hashC = - String.fromCharCode(0x12, 0x34, 0x56, 0x78, 0x87, 0x65, 0x43, 0x21); - const hashD = - String.fromCharCode(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF); + let /** !BinaryDecoder */ decoder; + + const a = { lo: 0x00000000, hi: 0x00000000 }; + const b = { lo: 0x00003412, hi: 0x00000000 }; + const c = { lo: 0x78563412, hi: 0x21436587 }; + const d = { lo: 0xFFFFFFFF, hi: 0xFFFFFFFF }; beforeEach(() => { - const encoder = new jspb.BinaryEncoder(); + const encoder = new BinaryEncoder(); - encoder.writeZigzagVarintHash64(hashA); - encoder.writeZigzagVarintHash64(hashB); - encoder.writeZigzagVarintHash64(hashC); - encoder.writeZigzagVarintHash64(hashD); + encoder.writeSplitZigzagVarint64(a.lo, a.hi); + encoder.writeSplitZigzagVarint64(b.lo, b.hi); + encoder.writeSplitZigzagVarint64(c.lo, c.hi); + encoder.writeSplitZigzagVarint64(d.lo, d.hi); - decoder = jspb.BinaryDecoder.alloc(encoder.end()); + decoder = BinaryDecoder.alloc(encoder.end()); }); it('reads 64-bit integers as decimal strings', () => { - const signed = true; - expect(decoder.readZigzagVarint64String()) - .toEqual(jspb.utils.hash64ToDecimalString(hashA, signed)); - expect(decoder.readZigzagVarint64String()) - .toEqual(jspb.utils.hash64ToDecimalString(hashB, signed)); - expect(decoder.readZigzagVarint64String()) - .toEqual(jspb.utils.hash64ToDecimalString(hashC, signed)); - expect(decoder.readZigzagVarint64String()) - .toEqual(jspb.utils.hash64ToDecimalString(hashD, signed)); - }); - - it('reads 64-bit integers as hash strings', () => { - expect(decoder.readZigzagVarintHash64()).toEqual(hashA); - expect(decoder.readZigzagVarintHash64()).toEqual(hashB); - expect(decoder.readZigzagVarintHash64()).toEqual(hashC); - expect(decoder.readZigzagVarintHash64()).toEqual(hashD); + expect(BinaryDecoder.readZigzagVarint64String(decoder)) + .toEqual(utils.joinSignedDecimalString(a.lo, a.hi)); + expect(BinaryDecoder.readZigzagVarint64String(decoder)) + .toEqual(utils.joinSignedDecimalString(b.lo, b.hi)); + expect(BinaryDecoder.readZigzagVarint64String(decoder)) + .toEqual(utils.joinSignedDecimalString(c.lo, c.hi)); + expect(BinaryDecoder.readZigzagVarint64String(decoder)) + .toEqual(utils.joinSignedDecimalString(d.lo, d.hi)); }); it('reads split 64 bit zigzag integers', () => { function hexJoin(bitsLow, bitsHigh) { - return `0x${(bitsHigh >>> 0).toString(16)}:0x${ - (bitsLow >>> 0).toString(16)}`; + return `0x${(bitsHigh >>> 0).toString(16)}:0x${(bitsLow >>> 0).toString(16)}`; } - function hexJoinHash(hash64) { - jspb.utils.splitHash64(hash64); - return hexJoin(jspb.utils.getSplit64Low(), jspb.utils.getSplit64High()); + function hexJoinPair(p) { + return hexJoin(p.lo, p.hi); } - expect(decoder.readSplitZigzagVarint64(hexJoin)) - .toEqual(hexJoinHash(hashA)); - expect(decoder.readSplitZigzagVarint64(hexJoin)) - .toEqual(hexJoinHash(hashB)); - expect(decoder.readSplitZigzagVarint64(hexJoin)) - .toEqual(hexJoinHash(hashC)); - expect(decoder.readSplitZigzagVarint64(hexJoin)) - .toEqual(hexJoinHash(hashD)); + expect(BinaryDecoder.readSplitZigzagVarint64(decoder, hexJoin)).toEqual(hexJoinPair(a)); + expect(BinaryDecoder.readSplitZigzagVarint64(decoder, hexJoin)).toEqual(hexJoinPair(b)); + expect(BinaryDecoder.readSplitZigzagVarint64(decoder, hexJoin)).toEqual(hexJoinPair(c)); + expect(BinaryDecoder.readSplitZigzagVarint64(decoder, hexJoin)).toEqual(hexJoinPair(d)); }); it('does zigzag encoding properly', () => { - // Test cases directly from the protobuf dev guide. + // Test cases direcly from the protobuf dev guide. // https://engdoc.corp.google.com/eng/howto/protocolbuffers/developerguide/encoding.shtml?cl=head#types const testCases = [ - {original: '0', zigzag: '0'}, - {original: '-1', zigzag: '1'}, - {original: '1', zigzag: '2'}, - {original: '-2', zigzag: '3'}, - {original: '2147483647', zigzag: '4294967294'}, - {original: '-2147483648', zigzag: '4294967295'}, + { original: '0', zigzag: '0' }, + { original: '-1', zigzag: '1' }, + { original: '1', zigzag: '2' }, + { original: '-2', zigzag: '3' }, + { original: '2147483647', zigzag: '4294967294' }, + { original: '-2147483648', zigzag: '4294967295' }, // 64-bit extremes, not in dev guide. - {original: '9223372036854775807', zigzag: '18446744073709551614'}, - {original: '-9223372036854775808', zigzag: '18446744073709551615'}, - // None of the above catch: bitsLow < 0 && bitsHigh > 0 && bitsHigh < - // 0x1FFFFF. The following used to be broken. - {original: '72000000000', zigzag: '144000000000'}, + { original: '9223372036854775807', zigzag: '18446744073709551614' }, + { original: '-9223372036854775808', zigzag: '18446744073709551615' }, ]; - const encoder = new jspb.BinaryEncoder(); - testCases.forEach(function(c) { + const encoder = new BinaryEncoder(); + testCases.forEach((c) => { encoder.writeZigzagVarint64String(c.original); }); const buffer = encoder.end(); - const zigzagDecoder = jspb.BinaryDecoder.alloc(buffer); - const varintDecoder = jspb.BinaryDecoder.alloc(buffer); - testCases.forEach(function(c) { - expect(zigzagDecoder.readZigzagVarint64String()).toEqual(c.original); - expect(varintDecoder.readUnsignedVarint64String()).toEqual(c.zigzag); + const zigzagDecoder = BinaryDecoder.alloc(buffer); + const varintDecoder = BinaryDecoder.alloc(buffer); + testCases.forEach((c) => { + expect(BinaryDecoder.readZigzagVarint64String(zigzagDecoder)).toEqual(c.original); + expect(BinaryDecoder.readUnsignedVarint64String(varintDecoder)).toEqual(c.zigzag); }); }); }); - /** - * Tests reading and writing large strings - */ + /** Tests reading and writing large strings */ it('testLargeStrings', () => { - const encoder = new jspb.BinaryEncoder(); - const len = 150000; let long_string = ''; for (let i = 0; i < len; i++) { long_string += 'a'; } - - encoder.writeString(long_string); - - const decoder = jspb.BinaryDecoder.alloc(encoder.end()); + const decoder = BinaryDecoder.alloc(encodeUtf8(long_string)); expect(decoder.readString(len, true)).toEqual(long_string); }); - /** - * Test encoding and decoding utf-8. - */ + /** Test encoding and decoding utf-8. */ it('testUtf8', () => { - const encoder = new jspb.BinaryEncoder(); const ascii = 'ASCII should work in 3, 2, 1...'; const utf8_two_bytes = '©'; const utf8_three_bytes = '❄'; const utf8_four_bytes = '😁'; - encoder.writeString(ascii); - encoder.writeString(utf8_two_bytes); - encoder.writeString(utf8_three_bytes); - encoder.writeString(utf8_four_bytes); + expect(encodeUtf8(ascii).length).toBe(ascii.length); + expect(encodeUtf8(utf8_two_bytes).length).toBe(2); + expect(encodeUtf8(utf8_three_bytes).length).toBe(3); + expect(encodeUtf8(utf8_four_bytes).length).toBe(4); - const decoder = jspb.BinaryDecoder.alloc(encoder.end()); + const decoder = BinaryDecoder.alloc(new Uint8Array([ + ...encodeUtf8(ascii), ...encodeUtf8(utf8_two_bytes), ...encodeUtf8(utf8_three_bytes), ...encodeUtf8(utf8_four_bytes) + ])); - expect(decoder.readString(ascii.length, /* enforceUtf8= */ true)).toEqual(ascii); - expect(utf8_two_bytes).toEqual(decoder.readString(2, /* enforceUtf8= */ true)); - expect(utf8_three_bytes) - .toEqual(decoder.readString(3, /* enforceUtf8= */ true)); - expect(utf8_four_bytes).toEqual(decoder.readString(4, /* enforceUtf8= */ true)); + expect(decoder.readString(ascii.length, true)).toEqual(ascii); + expect(decoder.readString(2, true)).toEqual(utf8_two_bytes); + expect(decoder.readString(3, true)).toEqual(utf8_three_bytes); + expect(decoder.readString(4, true)).toEqual(utf8_four_bytes); }); - /** - * Verifies that passing a non-string to writeString raises an error. - */ - it('testBadString', () => { - const encoder = new jspb.BinaryEncoder(); - - expect(() => { - encoder.writeString(42) - }).toThrow(); - expect(() => { - encoder.writeString(null) - }).toThrow(); + it('test invalid utf8, repro b/191931501', () => { + // "J\x06*e\xA9`\xF8'H8\x05\xC0" an errant value from b/191931501 + const decoder = BinaryDecoder.alloc(new Uint8Array([ + 0x4A, 0x06, 0x2A, 0x65, 0xA9, 0x60, 0xF8, 0x27, 0x48, 0x38, 0x05, 0xC0 + ])); + // This text is corrupted! Not surprising since it is invalid utf8 of + // course. + expect(decoder.readString(12, false)).toEqual('J\u0006*e�`�\'H8\u0005�'); + expect(decoder.getCursor()).toEqual(12); // but we didn't read past the end + decoder.setCursor(0); + // When we set requireUtf8, we get an error. + expect(() => decoder.readString(12, true)).toThrow(); }); - /** - * Verifies that misuse of the decoder class triggers assertions. - */ - it('testDecodeErrors', () => { - // Reading a value past the end of the stream should trigger an assertion. - const decoder = jspb.BinaryDecoder.alloc([0, 1, 2]); - expect(() => { - decoder.readUint64() - }).toThrow(); - - // Overlong varints should trigger assertions. - decoder.setBlock( - [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0]); - expect(() => { - decoder.readUnsignedVarint64() - }).toThrow(); - decoder.reset(); - expect(() => { - decoder.readSignedVarint64() - }).toThrow(); - decoder.reset(); - expect(() => { - decoder.readZigzagVarint64() - }).toThrow(); - decoder.reset(); - expect(() => { - decoder.readUnsignedVarint32() - }).toThrow(); - }); + describe('bytes', () => { + let /** Uint8Array */source; + let /** Uint8Array */sourceCopy; + beforeEach(() => { + source = new Uint8Array([1, 2, 3, 255, 1, 2, 8, 4]); + sourceCopy = new Uint8Array(source); + }); - /** - * Tests encoding and decoding of unsigned integers. - */ - it('testUnsignedIntegers', () => { - doTestUnsignedValue( - jspb.BinaryDecoder.prototype.readUint8, - jspb.BinaryEncoder.prototype.writeUint8, 1, 0xFF, Math.round); + it('empty readBytes', () => { + expect(BinaryDecoder.alloc(source).readBytes(0)).toEqual( + new Uint8Array(0), + ); + }); + it('empty readByteString', () => { + expect(BinaryDecoder.alloc(source).readByteString(0)).toBe( + ByteString.empty(), + ); + }); - doTestUnsignedValue( - jspb.BinaryDecoder.prototype.readUint16, - jspb.BinaryEncoder.prototype.writeUint16, 1, 0xFFFF, Math.round); + it('mutations to the source are not reflected in the output', () => { + const decoded = BinaryDecoder.alloc(source).readBytes(source.length); - doTestUnsignedValue( - jspb.BinaryDecoder.prototype.readUint32, - jspb.BinaryEncoder.prototype.writeUint32, 1, 0xFFFFFFFF, Math.round); + expect(decoded).toEqual(sourceCopy); + // Change the source array and ensure the underlying data was copied. + source.set(new Uint8Array([7, 6, 5, 4, 3, 2, 1, 101])); + + // Assert that the decoded array hasn't changed. + expect(decoded).toEqual(sourceCopy); + }); + + it('mutations to the source are not reflected in the output ByteString', () => { + const decoded = BinaryDecoder.alloc(source).readByteString(source.length); + expect(decoded.asUint8Array()).toEqual(sourceCopy); + // Change the source array and ensure the underlying data was copied. + source.set(new Uint8Array([7, 6, 5, 4, 3, 2, 1, 101])); + + // Assert that the decoded array hasn't changed. + expect(decoded.asUint8Array()).toEqual(sourceCopy); + }); + + it('mutations to the output are not reflected in the source', () => { + const decoded = BinaryDecoder.alloc(source).readBytes(source.length); + + // Change the output array and ensure the underlying data was copied. + decoded.set(new Uint8Array([7, 6, 5, 4, 3, 2, 1, 101])); + + // Assert that the source hasn't changed. + expect(sourceCopy).toEqual(source); + }); + }); + + + /** Tests encoding and decoding of unsigned integers. */ + it('testUnsignedIntegers', () => { doTestUnsignedValue( - jspb.BinaryDecoder.prototype.readUnsignedVarint32, - jspb.BinaryEncoder.prototype.writeUnsignedVarint32, 1, 0xFFFFFFFF, - Math.round); + BinaryDecoder.readUint8, BinaryEncoder.prototype.writeUint8, + 1, 0xFF, Math.round); doTestUnsignedValue( - jspb.BinaryDecoder.prototype.readUint64, - jspb.BinaryEncoder.prototype.writeUint64, 1, Math.pow(2, 64) - 1025, - Math.round); + BinaryDecoder.readUint16, BinaryEncoder.prototype.writeUint16, + 1, 0xFFFF, Math.round); doTestUnsignedValue( - jspb.BinaryDecoder.prototype.readUnsignedVarint64, - jspb.BinaryEncoder.prototype.writeUnsignedVarint64, 1, - Math.pow(2, 64) - 1025, Math.round); - }); + BinaryDecoder.readUint32, BinaryEncoder.prototype.writeUint32, + 1, 0xFFFFFFFF, Math.round); + doTestUnsigned64BitIntValue(BinaryDecoder.readUint64, + BinaryEncoder.prototype.writeUint64); + }); - /** - * Tests encoding and decoding of signed integers. - */ + /** Tests encoding and decoding of signed integers. */ it('testSignedIntegers', () => { doTestSignedValue( - jspb.BinaryDecoder.prototype.readInt8, - jspb.BinaryEncoder.prototype.writeInt8, 1, -0x80, 0x7F, Math.round); + BinaryDecoder.readInt8, BinaryEncoder.prototype.writeInt8, 1, + -0x80, 0x7F, Math.round); doTestSignedValue( - jspb.BinaryDecoder.prototype.readInt16, - jspb.BinaryEncoder.prototype.writeInt16, 1, -0x8000, 0x7FFF, - Math.round); + BinaryDecoder.readInt16, BinaryEncoder.prototype.writeInt16, + 1, -0x8000, 0x7FFF, Math.round); doTestSignedValue( - jspb.BinaryDecoder.prototype.readInt32, - jspb.BinaryEncoder.prototype.writeInt32, 1, -0x80000000, 0x7FFFFFFF, - Math.round); + BinaryDecoder.readInt32, BinaryEncoder.prototype.writeInt32, + 1, -0x80000000, 0x7FFFFFFF, Math.round); - doTestSignedValue( - jspb.BinaryDecoder.prototype.readSignedVarint32, - jspb.BinaryEncoder.prototype.writeSignedVarint32, 1, -0x80000000, - 0x7FFFFFFF, Math.round); - - doTestSignedValue( - jspb.BinaryDecoder.prototype.readInt64, - jspb.BinaryEncoder.prototype.writeInt64, 1, -Math.pow(2, 63), - Math.pow(2, 63) - 513, Math.round); - doTestSignedValue( - jspb.BinaryDecoder.prototype.readSignedVarint64, - jspb.BinaryEncoder.prototype.writeSignedVarint64, 1, -Math.pow(2, 63), - Math.pow(2, 63) - 513, Math.round); + doTestSigned64BitIntValue( + BinaryDecoder.readInt64, BinaryEncoder.prototype.writeInt64); }); - - /** - * Tests encoding and decoding of floats. - */ + /** Tests encoding and decoding of floats. */ it('testFloats', () => { /** * @param {number} x @@ -509,18 +594,13 @@ describe('binaryDecoderTest', () => { return temp[0]; } doTestSignedValue( - jspb.BinaryDecoder.prototype.readFloat, - jspb.BinaryEncoder.prototype.writeFloat, - jspb.BinaryConstants.FLOAT32_EPS, -jspb.BinaryConstants.FLOAT32_MAX, - jspb.BinaryConstants.FLOAT32_MAX, truncate); + BinaryDecoder.readFloat, BinaryEncoder.prototype.writeFloat, + BinaryConstants.FLOAT32_EPS, -BinaryConstants.FLOAT32_MAX, + BinaryConstants.FLOAT32_MAX, truncate); doTestSignedValue( - jspb.BinaryDecoder.prototype.readDouble, - jspb.BinaryEncoder.prototype.writeDouble, - jspb.BinaryConstants.FLOAT64_EPS * 10, - -jspb.BinaryConstants.FLOAT64_MAX, jspb.BinaryConstants.FLOAT64_MAX, - function(x) { - return x; - }); + BinaryDecoder.readDouble, BinaryEncoder.prototype.writeDouble, + BinaryConstants.FLOAT64_EPS * 10, -BinaryConstants.FLOAT64_MAX, + BinaryConstants.FLOAT64_MAX, (x) => x); }); }); diff --git a/binary/encoder.js b/binary/encoder.js old mode 100644 new mode 100755 index d6e35c6..216bd14 --- a/binary/encoder.js +++ b/binary/encoder.js @@ -1,33 +1,3 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://protobuf.dev/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - /** * @fileoverview BinaryEncode defines methods for encoding Javascript values * into arrays of bytes compatible with the Protocol Buffer wire format. @@ -35,512 +5,376 @@ * @author aappleby@google.com (Austin Appleby) */ -goog.provide('jspb.BinaryEncoder'); - -goog.require('jspb.asserts'); -goog.require('jspb.BinaryConstants'); -goog.require('jspb.utils'); - +goog.module('jspb.binary.encoder'); +goog.module.declareLegacyNamespace(); +const BinaryConstants = goog.require('jspb.BinaryConstants'); +const asserts = goog.require('goog.asserts'); +const utils = goog.require('jspb.utils'); +// The maximum number of bytes to push onto `buffer_` at a time, limited to +// prevent stack overflow errors. +const MAX_PUSH = 8192; /** * BinaryEncoder implements encoders for all the wire types specified in - * https://protobuf.dev/programming-guides/encoding/. - * - * @constructor - * @struct - * @export - */ -jspb.BinaryEncoder = function() { - /** @private {!Array} */ - this.buffer_ = []; -}; - - -/** - * @return {number} - * @export - */ -jspb.BinaryEncoder.prototype.length = function() { - return this.buffer_.length; -}; - - -/** - * @return {!Array} - * @export - */ -jspb.BinaryEncoder.prototype.end = function() { - var buffer = this.buffer_; - this.buffer_ = []; - return buffer; -}; - - -/** - * Encodes a 64-bit integer in 32:32 split representation into its wire-format - * varint representation and stores it in the buffer. - * @param {number} lowBits The low 32 bits of the int. - * @param {number} highBits The high 32 bits of the int. - * @export + * https://developers.google.com/protocol-buffers/docs/encoding. */ -jspb.BinaryEncoder.prototype.writeSplitVarint64 = function(lowBits, highBits) { - jspb.asserts.assert(lowBits == Math.floor(lowBits)); - jspb.asserts.assert(highBits == Math.floor(highBits)); - jspb.asserts.assert( - (lowBits >= 0) && (lowBits < jspb.BinaryConstants.TWO_TO_32)); - jspb.asserts.assert( - (highBits >= 0) && (highBits < jspb.BinaryConstants.TWO_TO_32)); - - // Break the binary representation into chunks of 7 bits, set the 8th bit - // in each chunk if it's not the final chunk, and append to the result. - while (highBits > 0 || lowBits > 127) { - this.buffer_.push((lowBits & 0x7f) | 0x80); - lowBits = ((lowBits >>> 7) | (highBits << 25)) >>> 0; - highBits = highBits >>> 7; +class BinaryEncoder { + constructor() { + /** @private {!Array} */ + this.buffer_ = []; } - this.buffer_.push(lowBits); -}; - - -/** - * Encodes a 64-bit integer in 32:32 split representation into its wire-format - * fixed representation and stores it in the buffer. - * @param {number} lowBits The low 32 bits of the int. - * @param {number} highBits The high 32 bits of the int. - * @export - */ -jspb.BinaryEncoder.prototype.writeSplitFixed64 = function(lowBits, highBits) { - jspb.asserts.assert(lowBits == Math.floor(lowBits)); - jspb.asserts.assert(highBits == Math.floor(highBits)); - jspb.asserts.assert( - (lowBits >= 0) && (lowBits < jspb.BinaryConstants.TWO_TO_32)); - jspb.asserts.assert( - (highBits >= 0) && (highBits < jspb.BinaryConstants.TWO_TO_32)); - this.writeUint32(lowBits); - this.writeUint32(highBits); -}; - -/** - * Encodes a 32-bit unsigned integer into its wire-format varint representation - * and stores it in the buffer. - * @param {number} value The integer to convert. - * @export - */ -jspb.BinaryEncoder.prototype.writeUnsignedVarint32 = function(value) { - jspb.asserts.assert(value == Math.floor(value)); - jspb.asserts.assert( - (value >= 0) && (value < jspb.BinaryConstants.TWO_TO_32)); - - while (value > 127) { - this.buffer_.push((value & 0x7f) | 0x80); - value = value >>> 7; + /** + * @return {number} + */ + length() { + return this.buffer_.length; } - this.buffer_.push(value); -}; - - -/** - * Encodes a 32-bit signed integer into its wire-format varint representation - * and stores it in the buffer. - * @param {number} value The integer to convert. - * @export - */ -jspb.BinaryEncoder.prototype.writeSignedVarint32 = function(value) { - jspb.asserts.assert(value == Math.floor(value)); - jspb.asserts.assert( - (value >= -jspb.BinaryConstants.TWO_TO_31) && - (value < jspb.BinaryConstants.TWO_TO_31)); - - // Use the unsigned version if the value is not negative. - if (value >= 0) { - this.writeUnsignedVarint32(value); - return; + /** + * @return {!Array} + */ + end() { + const buffer = this.buffer_; + this.buffer_ = []; + return buffer; } - // Write nine bytes with a _signed_ right shift so we preserve the sign bit. - for (var i = 0; i < 9; i++) { - this.buffer_.push((value & 0x7f) | 0x80); - value = value >> 7; + /** + * Encodes a 64-bit integer in 32:32 split representation into its wire-format + * varint representation and stores it in the buffer. + * @param {number} lowBits The low 32 bits of the int. + * @param {number} highBits The high 32 bits of the int. + */ + writeSplitVarint64(lowBits, highBits) { + asserts.assert(lowBits == Math.floor(lowBits)); + asserts.assert(highBits == Math.floor(highBits)); + asserts.assert((lowBits >= 0) && (lowBits < BinaryConstants.TWO_TO_32)); + asserts.assert((highBits >= 0) && (highBits < BinaryConstants.TWO_TO_32)); + + // Break the binary representation into chunks of 7 bits, set the 8th bit + // in each chunk if it's not the final chunk, and append to the result. + while (highBits > 0 || lowBits > 127) { + this.buffer_.push((lowBits & 0x7f) | 0x80); + lowBits = ((lowBits >>> 7) | (highBits << 25)) >>> 0; + highBits = highBits >>> 7; + } + this.buffer_.push(lowBits); } - // The above loop writes out 63 bits, so the last byte is always the sign bit - // which is always set for negative numbers. - this.buffer_.push(1); -}; - - -/** - * Encodes a 64-bit unsigned integer into its wire-format varint representation - * and stores it in the buffer. Integers that are not representable in 64 bits - * will be truncated. - * @param {number} value The integer to convert. - * @export - */ -jspb.BinaryEncoder.prototype.writeUnsignedVarint64 = function(value) { - jspb.asserts.assert(value == Math.floor(value)); - jspb.asserts.assert( - (value >= 0) && (value < jspb.BinaryConstants.TWO_TO_64)); - jspb.utils.splitInt64(value); - this.writeSplitVarint64(jspb.utils.getSplit64Low(), jspb.utils.getSplit64High()); -}; - - -/** - * Encodes a 64-bit signed integer into its wire-format varint representation - * and stores it in the buffer. Integers that are not representable in 64 bits - * will be truncated. - * @param {number} value The integer to convert. - * @export - */ -jspb.BinaryEncoder.prototype.writeSignedVarint64 = function(value) { - jspb.asserts.assert(value == Math.floor(value)); - jspb.asserts.assert( - (value >= -jspb.BinaryConstants.TWO_TO_63) && - (value < jspb.BinaryConstants.TWO_TO_63)); - jspb.utils.splitInt64(value); - this.writeSplitVarint64(jspb.utils.getSplit64Low(), jspb.utils.getSplit64High()); -}; - - -/** - * Encodes a JavaScript integer into its wire-format, zigzag-encoded varint - * representation and stores it in the buffer. - * @param {number} value The integer to convert. - * @export - */ -jspb.BinaryEncoder.prototype.writeZigzagVarint32 = function(value) { - jspb.asserts.assert(value == Math.floor(value)); - jspb.asserts.assert( - (value >= -jspb.BinaryConstants.TWO_TO_31) && - (value < jspb.BinaryConstants.TWO_TO_31)); - this.writeUnsignedVarint32(((value << 1) ^ (value >> 31)) >>> 0); -}; - - -/** - * Encodes a JavaScript integer into its wire-format, zigzag-encoded varint - * representation and stores it in the buffer. Integers not representable in 64 - * bits will be truncated. - * @param {number} value The integer to convert. - * @export - */ -jspb.BinaryEncoder.prototype.writeZigzagVarint64 = function(value) { - jspb.asserts.assert(value == Math.floor(value)); - jspb.asserts.assert( - (value >= -jspb.BinaryConstants.TWO_TO_63) && - (value < jspb.BinaryConstants.TWO_TO_63)); - jspb.utils.splitZigzag64(value); - this.writeSplitVarint64(jspb.utils.getSplit64Low(), jspb.utils.getSplit64High()); -}; - - -/** - * Encodes a JavaScript decimal string into its wire-format, zigzag-encoded - * varint representation and stores it in the buffer. Integers not representable - * in 64 bits will be truncated. - * @param {string} value The integer to convert. - * @export - */ -jspb.BinaryEncoder.prototype.writeZigzagVarint64String = function(value) { - this.writeZigzagVarintHash64(jspb.utils.decimalStringToHash64(value)); -}; - - -/** - * Writes a 64-bit hash string (8 characters @ 8 bits of data each) to the - * buffer as a zigzag varint. - * @param {string} hash The hash to write. - * @export - */ -jspb.BinaryEncoder.prototype.writeZigzagVarintHash64 = function(hash) { - var self = this; - jspb.utils.splitHash64(hash); - jspb.utils.toZigzag64( - jspb.utils.getSplit64Low(), jspb.utils.getSplit64High(), function(lo, hi) { - self.writeSplitVarint64(lo >>> 0, hi >>> 0); - }); -}; - - -/** - * Writes an 8-bit unsigned integer to the buffer. Numbers outside the range - * [0,2^8) will be truncated. - * @param {number} value The value to write. - * @export - */ -jspb.BinaryEncoder.prototype.writeUint8 = function(value) { - jspb.asserts.assert(value == Math.floor(value)); - jspb.asserts.assert((value >= 0) && (value < 256)); - this.buffer_.push((value >>> 0) & 0xFF); -}; - - -/** - * Writes a 16-bit unsigned integer to the buffer. Numbers outside the - * range [0,2^16) will be truncated. - * @param {number} value The value to write. - * @export - */ -jspb.BinaryEncoder.prototype.writeUint16 = function(value) { - jspb.asserts.assert(value == Math.floor(value)); - jspb.asserts.assert((value >= 0) && (value < 65536)); - this.buffer_.push((value >>> 0) & 0xFF); - this.buffer_.push((value >>> 8) & 0xFF); -}; - - -/** - * Writes a 32-bit unsigned integer to the buffer. Numbers outside the - * range [0,2^32) will be truncated. - * @param {number} value The value to write. - * @export - */ -jspb.BinaryEncoder.prototype.writeUint32 = function(value) { - jspb.asserts.assert(value == Math.floor(value)); - jspb.asserts.assert( - (value >= 0) && (value < jspb.BinaryConstants.TWO_TO_32)); - this.buffer_.push((value >>> 0) & 0xFF); - this.buffer_.push((value >>> 8) & 0xFF); - this.buffer_.push((value >>> 16) & 0xFF); - this.buffer_.push((value >>> 24) & 0xFF); -}; - - -/** - * Writes a 64-bit unsigned integer to the buffer. Numbers outside the - * range [0,2^64) will be truncated. - * @param {number} value The value to write. - * @export - */ -jspb.BinaryEncoder.prototype.writeUint64 = function(value) { - jspb.asserts.assert(value == Math.floor(value)); - jspb.asserts.assert( - (value >= 0) && (value < jspb.BinaryConstants.TWO_TO_64)); - jspb.utils.splitUint64(value); - this.writeUint32(jspb.utils.getSplit64Low()); - this.writeUint32(jspb.utils.getSplit64High()); -}; - - -/** - * Writes an 8-bit integer to the buffer. Numbers outside the range - * [-2^7,2^7) will be truncated. - * @param {number} value The value to write. - * @export - */ -jspb.BinaryEncoder.prototype.writeInt8 = function(value) { - jspb.asserts.assert(value == Math.floor(value)); - jspb.asserts.assert((value >= -128) && (value < 128)); - this.buffer_.push((value >>> 0) & 0xFF); -}; + /** + * Encodes a 64-bit integer in 32:32 split representation into its wire-format + * fixed representation and stores it in the buffer. + * @param {number} lowBits The low 32 bits of the int. + * @param {number} highBits The high 32 bits of the int. + */ + writeSplitFixed64(lowBits, highBits) { + asserts.assert(lowBits == Math.floor(lowBits)); + asserts.assert(highBits == Math.floor(highBits)); + asserts.assert((lowBits >= 0) && (lowBits < BinaryConstants.TWO_TO_32)); + asserts.assert((highBits >= 0) && (highBits < BinaryConstants.TWO_TO_32)); + this.writeUint32(lowBits); + this.writeUint32(highBits); + } + /** + * Encodes a 64-bit integer in 32:32 split representation into its wire-format + * a zigzag varint representation and stores it in the buffer. + * @param {number} lowBits The low 32 bits of the int. + * @param {number} highBits The high 32 bits of the int. + */ + writeSplitZigzagVarint64(lowBits, highBits) { + utils.toZigzag64(lowBits, highBits, (lo, hi) => { + this.writeSplitVarint64(lo >>> 0, hi >>> 0); + }); + } -/** - * Writes a 16-bit integer to the buffer. Numbers outside the range - * [-2^15,2^15) will be truncated. - * @param {number} value The value to write. - * @export - */ -jspb.BinaryEncoder.prototype.writeInt16 = function(value) { - jspb.asserts.assert(value == Math.floor(value)); - jspb.asserts.assert((value >= -32768) && (value < 32768)); - this.buffer_.push((value >>> 0) & 0xFF); - this.buffer_.push((value >>> 8) & 0xFF); -}; + /** + * Encodes a 32-bit unsigned integer into its wire-format varint + * representation and stores it in the buffer. + * @param {number} value The integer to convert. + */ + writeUnsignedVarint32(value) { + asserts.assert(value == Math.floor(value)); + asserts.assert((value >= 0) && (value < BinaryConstants.TWO_TO_32)); + + while (value > 127) { + this.buffer_.push((value & 0x7f) | 0x80); + value = value >>> 7; + } + this.buffer_.push(value); + } -/** - * Writes a 32-bit integer to the buffer. Numbers outside the range - * [-2^31,2^31) will be truncated. - * @param {number} value The value to write. - * @export - */ -jspb.BinaryEncoder.prototype.writeInt32 = function(value) { - jspb.asserts.assert(value == Math.floor(value)); - jspb.asserts.assert( - (value >= -jspb.BinaryConstants.TWO_TO_31) && - (value < jspb.BinaryConstants.TWO_TO_31)); - this.buffer_.push((value >>> 0) & 0xFF); - this.buffer_.push((value >>> 8) & 0xFF); - this.buffer_.push((value >>> 16) & 0xFF); - this.buffer_.push((value >>> 24) & 0xFF); -}; + /** + * Encodes a 32-bit signed integer into its wire-format varint representation + * and stores it in the buffer. + * @param {number} value The integer to convert. + */ + writeSignedVarint32(value) { + asserts.assert(value == Math.floor(value)); + asserts.assert( + (value >= -BinaryConstants.TWO_TO_31) && + (value < BinaryConstants.TWO_TO_31)); + + // Use the unsigned version if the value is not negative. + if (value >= 0) { + this.writeUnsignedVarint32(value); + return; + } + // Write nine bytes with a _signed_ right shift so we preserve the sign bit. + for (let i = 0; i < 9; i++) { + this.buffer_.push((value & 0x7f) | 0x80); + value = value >> 7; + } -/** - * Writes a 64-bit integer to the buffer. Numbers outside the range - * [-2^63,2^63) will be truncated. - * @param {number} value The value to write. - * @export - */ -jspb.BinaryEncoder.prototype.writeInt64 = function(value) { - jspb.asserts.assert(value == Math.floor(value)); - jspb.asserts.assert( - (value >= -jspb.BinaryConstants.TWO_TO_63) && - (value < jspb.BinaryConstants.TWO_TO_63)); - jspb.utils.splitInt64(value); - this.writeSplitFixed64(jspb.utils.getSplit64Low(), jspb.utils.getSplit64High()); -}; + // The above loop writes out 63 bits, so the last byte is always the sign + // bit which is always set for negative numbers. + this.buffer_.push(1); + } + /** + * Encodes a 64-bit unsigned integer into its wire-format varint + * representation and stores it in the buffer. Integers that are not + * representable in 64 bits will be truncated. + * @param {number} value The integer to convert. + */ + writeUnsignedVarint64(value) { + asserts.assert(value == Math.floor(value)); + asserts.assert((value >= 0) && (value < BinaryConstants.TWO_TO_64)); + utils.splitInt64(value); + this.writeSplitVarint64(utils.getSplit64Low(), utils.getSplit64High()); + } -/** - * Writes a 64-bit integer decimal strings to the buffer. Numbers outside the - * range [-2^63,2^63) will be truncated. - * @param {string} value The value to write. - * @export - */ -jspb.BinaryEncoder.prototype.writeInt64String = function(value) { - jspb.asserts.assert(value == Math.floor(value)); - jspb.asserts.assert( - (+value >= -jspb.BinaryConstants.TWO_TO_63) && - (+value < jspb.BinaryConstants.TWO_TO_63)); - jspb.utils.splitHash64(jspb.utils.decimalStringToHash64(value)); - this.writeSplitFixed64(jspb.utils.getSplit64Low(), jspb.utils.getSplit64High()); -}; + /** + * Encodes a 64-bit signed integer into its wire-format varint representation + * and stores it in the buffer. Integers that are not representable in 64 bits + * will be truncated. + * @param {number} value The integer to convert. + */ + writeSignedVarint64(value) { + asserts.assert(value == Math.floor(value)); + asserts.assert( + (value >= -BinaryConstants.TWO_TO_63) && + (value < BinaryConstants.TWO_TO_63)); + utils.splitInt64(value); + this.writeSplitVarint64(utils.getSplit64Low(), utils.getSplit64High()); + } + /** + * Encodes a JavaScript integer into its wire-format, zigzag-encoded varint + * representation and stores it in the buffer. + * @param {number} value The integer to convert. + */ + writeZigzagVarint32(value) { + asserts.assert(value == Math.floor(value)); + asserts.assert( + (value >= -BinaryConstants.TWO_TO_31) && + (value < BinaryConstants.TWO_TO_31)); + this.writeUnsignedVarint32(utils.toZigzag32(value)); + } -/** - * Writes a single-precision floating point value to the buffer. Numbers - * requiring more than 32 bits of precision will be truncated. - * @param {number} value The value to write. - * @export - */ -jspb.BinaryEncoder.prototype.writeFloat = function(value) { - jspb.asserts.assert( - value === Infinity || value === -Infinity || isNaN(value) || - ((value >= -jspb.BinaryConstants.FLOAT32_MAX) && - (value <= jspb.BinaryConstants.FLOAT32_MAX))); - jspb.utils.splitFloat32(value); - this.writeUint32(jspb.utils.getSplit64Low()); -}; + /** + * Encodes a JavaScript integer into its wire-format, zigzag-encoded varint + * representation and stores it in the buffer. Integers not representable in + * 64 bits will be truncated. + * @param {number} value The integer to convert. + */ + writeZigzagVarint64(value) { + asserts.assert(value == Math.floor(value)); + asserts.assert( + (value >= -BinaryConstants.TWO_TO_63) && + (value < BinaryConstants.TWO_TO_63)); + utils.splitZigzag64(value); + this.writeSplitVarint64(utils.getSplit64Low(), utils.getSplit64High()); + } + /** + * Encodes a JavaScript decimal string into its wire-format, zigzag-encoded + * varint representation and stores it in the buffer. Integers not + * representable in 64 bits will be truncated. + * @param {string} value The integer to convert. + */ + writeZigzagVarint64String(value) { + utils.splitDecimalString(value); + utils.toZigzag64( + utils.getSplit64Low(), utils.getSplit64High(), (lo, hi) => { + this.writeSplitVarint64(lo >>> 0, hi >>> 0); + }); + } -/** - * Writes a double-precision floating point value to the buffer. As this is - * the native format used by JavaScript, no precision will be lost. - * @param {number} value The value to write. - * @export - */ -jspb.BinaryEncoder.prototype.writeDouble = function(value) { - jspb.asserts.assert( - value === Infinity || value === -Infinity || isNaN(value) || - ((value >= -jspb.BinaryConstants.FLOAT64_MAX) && - (value <= jspb.BinaryConstants.FLOAT64_MAX))); - jspb.utils.splitFloat64(value); - this.writeUint32(jspb.utils.getSplit64Low()); - this.writeUint32(jspb.utils.getSplit64High()); -}; + /** + * Writes an 8-bit unsigned integer to the buffer. Numbers outside the range + * [0,2^8) will be truncated. + * @param {number} value The value to write. + */ + writeUint8(value) { + asserts.assert(value == Math.floor(value)); + asserts.assert((value >= 0) && (value < 256)); + this.buffer_.push((value >>> 0) & 0xFF); + } + /** + * Writes a 16-bit unsigned integer to the buffer. Numbers outside the + * range [0,2^16) will be truncated. + * @param {number} value The value to write. + */ + writeUint16(value) { + asserts.assert(value == Math.floor(value)); + asserts.assert((value >= 0) && (value < 65536)); + this.buffer_.push((value >>> 0) & 0xFF); + this.buffer_.push((value >>> 8) & 0xFF); + } -/** - * Writes a boolean value to the buffer as a varint. We allow numbers as input - * because the JSPB code generator uses 0/1 instead of true/false to save space - * in the string representation of the proto. - * @param {boolean|number} value The value to write. - * @export - */ -jspb.BinaryEncoder.prototype.writeBool = function(value) { - jspb.asserts.assert( - typeof value === 'boolean' || typeof value === 'number'); - this.buffer_.push(value ? 1 : 0); -}; + /** + * Writes a 32-bit unsigned integer to the buffer. Numbers outside the + * range [0,2^32) will be truncated. + * @param {number} value The value to write. + */ + writeUint32(value) { + asserts.assert(value == Math.floor(value)); + asserts.assert((value >= 0) && (value < BinaryConstants.TWO_TO_32)); + this.buffer_.push((value >>> 0) & 0xFF); + this.buffer_.push((value >>> 8) & 0xFF); + this.buffer_.push((value >>> 16) & 0xFF); + this.buffer_.push((value >>> 24) & 0xFF); + } + /** + * Writes a 64-bit unsigned integer to the buffer. Numbers outside the + * range [0,2^64) will be truncated. + * @param {number} value The value to write. + */ + writeUint64(value) { + asserts.assert(value == Math.floor(value)); + asserts.assert((value >= 0) && (value < BinaryConstants.TWO_TO_64)); + utils.splitUint64(value); + this.writeUint32(utils.getSplit64Low()); + this.writeUint32(utils.getSplit64High()); + } -/** - * Writes an enum value to the buffer as a varint. - * @param {number} value The value to write. - * @export - */ -jspb.BinaryEncoder.prototype.writeEnum = function(value) { - jspb.asserts.assert(value == Math.floor(value)); - jspb.asserts.assert( - (value >= -jspb.BinaryConstants.TWO_TO_31) && - (value < jspb.BinaryConstants.TWO_TO_31)); - this.writeSignedVarint32(value); -}; + /** + * Writes an 8-bit integer to the buffer. Numbers outside the range + * [-2^7,2^7) will be truncated. + * @param {number} value The value to write. + */ + writeInt8(value) { + asserts.assert(value == Math.floor(value)); + asserts.assert((value >= -128) && (value < 128)); + this.buffer_.push((value >>> 0) & 0xFF); + } + /** + * Writes a 16-bit integer to the buffer. Numbers outside the range + * [-2^15,2^15) will be truncated. + * @param {number} value The value to write. + */ + writeInt16(value) { + asserts.assert(value == Math.floor(value)); + asserts.assert((value >= -32768) && (value < 32768)); + this.buffer_.push((value >>> 0) & 0xFF); + this.buffer_.push((value >>> 8) & 0xFF); + } -/** - * Writes an arbitrary byte array to the buffer. - * @param {!Uint8Array} bytes The array of bytes to write. - * @export - */ -jspb.BinaryEncoder.prototype.writeBytes = function(bytes) { - this.buffer_.push.apply(this.buffer_, bytes); -}; + /** + * Writes a 32-bit integer to the buffer. Numbers outside the range + * [-2^31,2^31) will be truncated. + * @param {number} value The value to write. + */ + writeInt32(value) { + asserts.assert(value == Math.floor(value)); + asserts.assert( + (value >= -BinaryConstants.TWO_TO_31) && + (value < BinaryConstants.TWO_TO_31)); + this.buffer_.push((value >>> 0) & 0xFF); + this.buffer_.push((value >>> 8) & 0xFF); + this.buffer_.push((value >>> 16) & 0xFF); + this.buffer_.push((value >>> 24) & 0xFF); + } + /** + * Writes a 64-bit integer to the buffer. Numbers outside the range + * [-2^63,2^63) will be truncated. + * @param {number} value The value to write. + */ + writeInt64(value) { + asserts.assert(value == Math.floor(value)); + asserts.assert( + (value >= -BinaryConstants.TWO_TO_63) && + (value < BinaryConstants.TWO_TO_63)); + utils.splitInt64(value); + this.writeSplitFixed64(utils.getSplit64Low(), utils.getSplit64High()); + } -/** - * Writes a 64-bit hash string (8 characters @ 8 bits of data each) to the - * buffer as a varint. - * @param {string} hash The hash to write. - * @export - */ -jspb.BinaryEncoder.prototype.writeVarintHash64 = function(hash) { - jspb.utils.splitHash64(hash); - this.writeSplitVarint64(jspb.utils.getSplit64Low(), jspb.utils.getSplit64High()); -}; + /** + * Writes a single-precision floating point value to the buffer. Numbers + * requiring more than 32 bits of precision will be truncated. + * @param {number|string} value The value to write, accepts + * 'Infinity'/'-Infinity'/'NaN' for JSPB wire format compatibility. + */ + writeFloat(value) { + asserts.assert( + // Explicitly using == to accept strings + (value == Infinity || value == -Infinity || isNaN(value) || + (typeof value === 'number' && + (value >= -BinaryConstants.FLOAT32_MAX) && + (value <= BinaryConstants.FLOAT32_MAX)))); + utils.splitFloat32(value); + this.writeUint32(utils.getSplit64Low()); + } + /** + * Writes a double-precision floating point value to the buffer. As this is + * the native format used by JavaScript, no precision will be lost. + * @param {number|string} value The value to write, accepts + * 'Infinity'/'-Infinity'/'NaN' for JSPB wire format compatibility. + */ + writeDouble(value) { + asserts.assert( + typeof value === 'number' || value === 'Infinity' || + value === '-Infinity' || value === 'NaN'); + utils.splitFloat64(value); + this.writeUint32(utils.getSplit64Low()); + this.writeUint32(utils.getSplit64High()); + } -/** - * Writes a 64-bit hash string (8 characters @ 8 bits of data each) to the - * buffer as a fixed64. - * @param {string} hash The hash to write. - * @export - */ -jspb.BinaryEncoder.prototype.writeFixedHash64 = function(hash) { - jspb.utils.splitHash64(hash); - this.writeUint32(jspb.utils.getSplit64Low()); - this.writeUint32(jspb.utils.getSplit64High()); -}; + /** + * Writes a boolean value to the buffer as a varint. We allow numbers as input + * because the JSPB code generator uses 0/1 instead of true/false to save + * space in the string representation of the proto. + * @param {boolean|number} value The value to write. + */ + writeBool(value) { + asserts.assert(typeof value === 'boolean' || typeof value === 'number'); + this.buffer_.push(value ? 1 : 0); + } + /** + * Writes an enum value to the buffer as a varint. + * @param {number} value The value to write. + */ + writeEnum(value) { + asserts.assert(value == Math.floor(value)); + asserts.assert( + (value >= -BinaryConstants.TWO_TO_31) && + (value < BinaryConstants.TWO_TO_31)); + this.writeSignedVarint32(value); + } -/** - * Writes a UTF16 Javascript string to the buffer encoded as UTF8. - * TODO(aappleby): Add support for surrogate pairs, reject unpaired surrogates. - * @param {string} value The string to write. - * @return {number} The number of bytes used to encode the string. - * @export - */ -jspb.BinaryEncoder.prototype.writeString = function(value) { - var oldLength = this.buffer_.length; - - // Protect against non-string values being silently ignored. - jspb.asserts.assertString(value); - - for (var i = 0; i < value.length; i++) { - var c = value.charCodeAt(i); - - if (c < 128) { - this.buffer_.push(c); - } else if (c < 2048) { - this.buffer_.push((c >> 6) | 192); - this.buffer_.push((c & 63) | 128); - } else if (c < 65536) { - // Look for surrogates - if (c >= 0xD800 && c <= 0xDBFF && i + 1 < value.length) { - var second = value.charCodeAt(i + 1); - if (second >= 0xDC00 && second <= 0xDFFF) { // low surrogate - // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae - c = (c - 0xD800) * 0x400 + second - 0xDC00 + 0x10000; - - this.buffer_.push((c >> 18) | 240); - this.buffer_.push(((c >> 12) & 63) | 128); - this.buffer_.push(((c >> 6) & 63) | 128); - this.buffer_.push((c & 63) | 128); - i++; - } - } else { - this.buffer_.push((c >> 12) | 224); - this.buffer_.push(((c >> 6) & 63) | 128); - this.buffer_.push((c & 63) | 128); - } + /** + * Writes a byte array to our buffer. + * @param {!Uint8Array} bytes The array of bytes to write. + */ + writeBytes(bytes) { + // avoid a stackoverflow on large arrays. + while (bytes.length > MAX_PUSH) { + Array.prototype.push.apply(this.buffer_, bytes.subarray(0, MAX_PUSH)); + bytes = bytes.subarray(MAX_PUSH); } + Array.prototype.push.apply(this.buffer_, bytes); } +} - var length = this.buffer_.length - oldLength; - return length; -}; +exports = {BinaryEncoder}; diff --git a/binary/encoder_alias.js b/binary/encoder_alias.js new file mode 100755 index 0000000..187507f --- /dev/null +++ b/binary/encoder_alias.js @@ -0,0 +1,9 @@ +/** + * @fileoverview Legacy alias for the old namespace used by encoder.js + */ +goog.module('jspb.BinaryEncoder'); +goog.module.declareLegacyNamespace(); + +const {BinaryEncoder} = goog.require('jspb.binary.encoder'); + +exports = BinaryEncoder; diff --git a/binary/errors.js b/binary/errors.js new file mode 100755 index 0000000..dbd6d64 --- /dev/null +++ b/binary/errors.js @@ -0,0 +1,122 @@ +/** + * @fileoverview Standard error messages for errors detected when parsing + * binary protos. + */ +goog.module('jspb.binary.errors'); + +// N.B. In the functions below invoke the `Error` constructor directly in order +// to be compatible with the string replacement semantics in the JsCompiler, +// which typically matches on strings passed to the Error constructor. + +/** + * Reports that we didn't read the number of expected bytes for a message. + * @return {!Error} + */ +function messageLengthMismatchError( + /** number */ messageLength, /** number */ readLength) { + // NOTE: we directly throw here instead of report because this is what we used + // to do as well. + return new Error( + `Message parsing ended unexpectedly. Expected to read ` + + `${messageLength} bytes, instead read ${readLength} bytes, either the ` + + `data ended unexpectedly or the message misreported its own length`); +} + + +/** + * Reports an invalid wire type value. + * + * @return {!Error} + */ +function invalidWireTypeError(/** number */ wireType, /** number */ position) { + return new Error(`Invalid wire type: ${wireType} (at position ${position})`); +} + +/** + * Reports an invalid field number. + * + * @return {!Error} + */ +function invalidFieldNumberError( + /** number */ fieldNumber, /** number */ position) { + return new Error( + `Invalid field number: ${fieldNumber} (at position ${position})`); +} + +/** + * Reports message-set parsing faield + * @return {!Error} + */ +function malformedBinaryBytesForMessageSet() { + return new Error('Malformed binary bytes for message set'); +} + +/** + * Reports a failure to find an END_GROUP tag because we hit end of stream. + * + * @return {!Error} + */ +function unmatchedStartGroupEofError() { + return new Error('Unmatched start-group tag: stream EOF'); +} + +/** + * Reports a general failure to find an END_GROUP tag matching a START_GROUP. + * + * @return {!Error} + */ +function unmatchedStartGroupError() { + return new Error('Unmatched end-group tag'); +} + +/** + * Reports that parsing a group did not end on an END_GROUP tag. + * + * @return {!Error} + */ +function groupDidNotEndWithEndGroupError() { + return new Error('Group submessage did not end with an END_GROUP tag'); +} + +/** + * Reports that the varint is invalid in some way. + * + * @return {!Error} + */ +function invalidVarintError() { + return new Error('Failed to read varint, encoding is invalid.'); +} + +/** + * Reports that we read more bytes than were available. + * + * @return {!Error} + */ +function readTooFarError( + /** number */ expectedLength, /** number */ readLength) { + return new Error(`Tried to read past the end of the data ${readLength} > ${ + expectedLength}`); +} + +/** + * Reports that we read more bytes than were available. + * + * @return {!Error} + */ +function negativeByteLengthError( + /** number */ length) { + return new Error(`Tried to read a negative byte length: ${length}`); +} + +exports = { + messageLengthMismatchError, + groupDidNotEndWithEndGroupError, + invalidFieldNumberError, + invalidVarintError, + invalidWireTypeError, + malformedBinaryBytesForMessageSet, + negativeByteLengthError, + readTooFarError, + unmatchedStartGroupError, + unmatchedStartGroupEofError, +}; diff --git a/binary/internal_buffer.js b/binary/internal_buffer.js new file mode 100755 index 0000000..5bb2d88 --- /dev/null +++ b/binary/internal_buffer.js @@ -0,0 +1,96 @@ +/** + * @fileoverview Internal utilities for working with buffers. + * @package + * + * DO NOT USE THIS OUTSIDE OF THIS PACKAGE. + */ +goog.module('jspb.binary.internal_buffer'); + +const {ByteSource} = goog.require('jspb.binary.bytesource'); +const {ByteString} = goog.require('jspb.bytestring'); +const {decodeByteArray} = goog.require('jspb.internal_bytes'); +const {unsafeByteStringFromUint8Array, unsafeUint8ArrayFromByteString} = goog.require('jspb.unsafe_bytestring'); + + +class Buffer { + constructor(/** !Uint8Array */ buffer, /** boolean */ isImmutable, + /** !ByteString= */ maybeByteString) { + /** @const {!Uint8Array}*/ + this.buffer = buffer; + + /** @private {!ByteString|undefined} */ + this.bufferAsByteStringInternal = maybeByteString; + if (maybeByteString && !isImmutable) { + throw goog.DEBUG ? + new Error('Buffer must be immutable if a ByteString is provided.') : + new Error(); + } + + /** + * Whether our input must be immutable and we cannot allow callers to + * mutate it. + * + * @const {boolean} + */ + this.isImmutable = isImmutable; + } + + /** @return {?ByteString} */ + getBufferAsByteStringIfImmutable() { + if (!this.isImmutable) { + throw goog.DEBUG ? + new Error('Cannot get ByteString from mutable buffer.') : + new Error(); + } + if (this.buffer == null) return null; + return this.bufferAsByteStringInternal ??= + unsafeByteStringFromUint8Array(this.buffer); + } +} + +/** + * Converts any type defined in ByteSource into a Uint8Array. + * @param {!ByteSource|!ByteString} data + * @param {boolean} treatNewDataAsImmutable Whether to treat new data as + * immutable. + * @return {!Buffer} a tuple of the data and + * whether or not this is an immutable reference + */ +function bufferFromSource(data, treatNewDataAsImmutable) { + if (typeof data === 'string') { + return new Buffer(decodeByteArray(data), treatNewDataAsImmutable); + } else if (Array.isArray(data)) { + return new Buffer(new Uint8Array(data), treatNewDataAsImmutable); + } else if (data.constructor === Uint8Array) { + const u8 = /** @type {!Uint8Array}*/ (data); + return new Buffer(u8, /* isImmutable= */ false); + } else if (data.constructor === ArrayBuffer) { + const u8 = new Uint8Array(/** @type {!ArrayBuffer} */ (data)); + return new Buffer(u8, /* isImmutable= */ false); + } else if (data.constructor === ByteString) { + const byteString = /** @type {!ByteString} */ (data); + const u8 = unsafeUint8ArrayFromByteString(byteString); + return new Buffer(u8, /* isImmutable= */ true, byteString); + } else if (data instanceof Uint8Array) { + // If this is a node subclass, wrap a new Uint8Array around the buffer to + // ensure jspb code only ever deals with Uint8Array exactly to ensure + // monomorphism. + const u8 = (data.constructor === Uint8Array) ? + data : + new Uint8Array(data.buffer, data.byteOffset, data.byteLength); + return new Buffer(u8, /* isImmutable= */ false); + } else { + throw goog.DEBUG ? + new Error( + 'Type not convertible to a Uint8Array, expected a Uint8Array, an ' + + 'ArrayBuffer, a base64 encoded string, a ByteString or an Array of ' + + 'numbers') : + new Error(); + } +} + + +exports = { + Buffer, + bufferFromSource, +}; diff --git a/binary/message_test.js b/binary/message_test.js old mode 100644 new mode 100755 diff --git a/binary/proto_test.js b/binary/proto_test.js old mode 100644 new mode 100755 index 6720cec..608d6d0 --- a/binary/proto_test.js +++ b/binary/proto_test.js @@ -91,7 +91,9 @@ goog.require('proto.jspb.test.extendRepeatedUint64List'); // clang-format off // CommonJS-LoadFromFile: ../node_modules/google-protobuf/google/protobuf/any_pb proto.google.protobuf goog.require('proto.google.protobuf.Any'); +// clang-format on +const BinaryWriter = goog.module.get('jspb.BinaryWriter'); const suite = {}; @@ -108,15 +110,15 @@ function fillAllFields(msg) { msg.setOptionalInt32(-42); // can be exactly represented by JS number (64-bit double, i.e., 52-bit // mantissa). - msg.setOptionalInt64(-0x7fffffff00000000); + msg.setOptionalInt64(String(-BigInt('0x7fffffff00000000'))); msg.setOptionalUint32(0x80000000); - msg.setOptionalUint64(0xf000000000000000); + msg.setOptionalUint64(String(BigInt('0xf000000000000000'))); msg.setOptionalSint32(-100); - msg.setOptionalSint64(-0x8000000000000000); + msg.setOptionalSint64(String(-BigInt('0x8000000000000000'))); msg.setOptionalFixed32(1234); - msg.setOptionalFixed64(0x1234567800000000); + msg.setOptionalFixed64(String(BigInt('0x1234567800000000'))); msg.setOptionalSfixed32(-1234); - msg.setOptionalSfixed64(-0x1234567800000000); + msg.setOptionalSfixed64(String(-BigInt('0x1234567800000000'))); msg.setOptionalFloat(1.5); msg.setOptionalDouble(-1.5); msg.setOptionalBool(true); @@ -132,15 +134,15 @@ function fillAllFields(msg) { msg.setRepeatedInt32List([-42]); - msg.setRepeatedInt64List([-0x7fffffff00000000]); + msg.setRepeatedInt64List([String(-BigInt('0x7fffffff00000000'))]); msg.setRepeatedUint32List([0x80000000]); - msg.setRepeatedUint64List([0xf000000000000000]); + msg.setRepeatedUint64List([String(BigInt('0xf000000000000000'))]); msg.setRepeatedSint32List([-100]); - msg.setRepeatedSint64List([-0x8000000000000000]); + msg.setRepeatedSint64List([String(-BigInt('0x8000000000000000'))]); msg.setRepeatedFixed32List([1234]); - msg.setRepeatedFixed64List([0x1234567800000000]); + msg.setRepeatedFixed64List([String(BigInt('0x1234567800000000'))]); msg.setRepeatedSfixed32List([-1234]); - msg.setRepeatedSfixed64List([-0x1234567800000000]); + msg.setRepeatedSfixed64List([String(-BigInt('0x1234567800000000'))]); msg.setRepeatedFloatList([1.5]); msg.setRepeatedDoubleList([-1.5]); msg.setRepeatedBoolList([true]); @@ -154,15 +156,15 @@ function fillAllFields(msg) { msg.setRepeatedForeignEnumList([proto.jspb.test.ForeignEnum.FOREIGN_FOO]); msg.setPackedRepeatedInt32List([-42]); - msg.setPackedRepeatedInt64List([-0x7fffffff00000000]); + msg.setPackedRepeatedInt64List([String(-BigInt('0x7fffffff00000000'))]); msg.setPackedRepeatedUint32List([0x80000000]); - msg.setPackedRepeatedUint64List([0xf000000000000000]); + msg.setPackedRepeatedUint64List([String(BigInt('0xf000000000000000'))]); msg.setPackedRepeatedSint32List([-100]); - msg.setPackedRepeatedSint64List([-0x8000000000000000]); + msg.setPackedRepeatedSint64List([String(-BigInt('0x8000000000000000'))]); msg.setPackedRepeatedFixed32List([1234]); - msg.setPackedRepeatedFixed64List([0x1234567800000000]); + msg.setPackedRepeatedFixed64List([String(BigInt('0x1234567800000000'))]); msg.setPackedRepeatedSfixed32List([-1234]); - msg.setPackedRepeatedSfixed64List([-0x1234567800000000]); + msg.setPackedRepeatedSfixed64List([String(-BigInt('0x1234567800000000'))]); msg.setPackedRepeatedFloatList([1.5]); msg.setPackedRepeatedDoubleList([-1.5]); msg.setPackedRepeatedBoolList([true]); @@ -199,15 +201,15 @@ function bytesCompare(arr, expected) { */ function checkAllFields(original, copy) { expect(copy.getOptionalInt32()).toEqual(-42); - expect(copy.getOptionalInt64()).toEqual(-0x7fffffff00000000); + expect(copy.getOptionalInt64()).toEqual(String(-BigInt('0x7fffffff00000000'))); expect(copy.getOptionalUint32()).toEqual(0x80000000); - expect(copy.getOptionalUint64()).toEqual(0xf000000000000000); + expect(copy.getOptionalUint64()).toEqual(String(BigInt('0xf000000000000000'))); expect(copy.getOptionalSint32()).toEqual(-100); - expect(copy.getOptionalSint64()).toEqual(-0x8000000000000000); + expect(copy.getOptionalSint64()).toEqual(String(-BigInt('0x8000000000000000'))); expect(copy.getOptionalFixed32()).toEqual(1234); - expect(copy.getOptionalFixed64()).toEqual(0x1234567800000000); + expect(copy.getOptionalFixed64()).toEqual(String(BigInt('0x1234567800000000'))); expect(copy.getOptionalSfixed32()).toEqual(-1234); - expect(copy.getOptionalSfixed64()).toEqual(-0x1234567800000000); + expect(copy.getOptionalSfixed64()).toEqual(String(-BigInt('0x1234567800000000'))); expect(copy.getOptionalFloat()).toEqual(1.5); expect(copy.getOptionalDouble()).toEqual(-1.5); expect(copy.getOptionalBool()).toBeTrue(); @@ -215,38 +217,41 @@ function checkAllFields(original, copy) { expect(bytesCompare(copy.getOptionalBytes(), BYTES)).toEqual(true); expect(true).toEqual(bytesCompare(copy.getOptionalBytes_asU8(), BYTES)); expect(copy.getOptionalBytes_asB64()) - .toEqual(goog.crypt.base64.encodeByteArray(BYTES)); + .toEqual(goog.crypt.base64.encodeByteArray(BYTES)); expect(copy.getOptionalGroup().getA()).toEqual(100); expect(copy.getOptionalForeignMessage().getC()).toEqual(16); expect(proto.jspb.test.ForeignEnum.FOREIGN_FOO) - .toEqual(copy.getOptionalForeignEnum()); + .toEqual(copy.getOptionalForeignEnum()); expect(copy.getOneofString()).toEqual('oneof'); expect(proto.jspb.test.TestAllTypes.OneofFieldCase.ONEOF_STRING) - .toEqual(copy.getOneofFieldCase()); + .toEqual(copy.getOneofFieldCase()); expect(copy.getRepeatedInt32List()).toEqual([-42]); - expect(copy.getRepeatedInt64List()).toEqual([-0x7fffffff00000000]); + expect(copy.getRepeatedInt64List()) + .toEqual([String(-BigInt('0x7fffffff00000000'))]); expect(copy.getRepeatedUint32List()).toEqual([0x80000000]); - expect(copy.getRepeatedUint64List()).toEqual([0xf000000000000000]); + expect(copy.getRepeatedUint64List()) + .toEqual([String(BigInt('0xf000000000000000'))]); expect(copy.getRepeatedSint32List()).toEqual([-100]); - expect(copy.getRepeatedSint64List()).toEqual([-0x8000000000000000]); + expect(copy.getRepeatedSint64List()) + .toEqual([String(-BigInt('0x8000000000000000'))]); expect(copy.getRepeatedFixed32List()).toEqual([1234]); - expect(copy.getRepeatedFixed64List()).toEqual([0x1234567800000000]); + expect(copy.getRepeatedFixed64List()).toEqual([String(BigInt('0x1234567800000000'))]); expect(copy.getRepeatedSfixed32List()).toEqual([-1234]); - expect(copy.getRepeatedSfixed64List()).toEqual([-0x1234567800000000]); + expect(copy.getRepeatedSfixed64List()).toEqual([String(-BigInt('0x1234567800000000'))]); expect(copy.getRepeatedFloatList()).toEqual([1.5]); expect(copy.getRepeatedDoubleList()).toEqual([-1.5]); expect(copy.getRepeatedBoolList()).toEqual([true]); expect(copy.getRepeatedStringList()).toEqual(['hello world']); expect(copy.getRepeatedBytesList().length).toEqual(2); expect(true).toEqual( - bytesCompare(copy.getRepeatedBytesList_asU8()[0], BYTES)); + bytesCompare(copy.getRepeatedBytesList_asU8()[0], BYTES)); expect(true).toEqual(bytesCompare(copy.getRepeatedBytesList()[0], BYTES)); expect(true).toEqual( - bytesCompare(copy.getRepeatedBytesList_asU8()[1], BYTES)); + bytesCompare(copy.getRepeatedBytesList_asU8()[1], BYTES)); expect(copy.getRepeatedBytesList_asB64()[0]).toEqual(BYTES_B64); expect(copy.getRepeatedBytesList_asB64()[1]).toEqual(BYTES_B64); expect(copy.getRepeatedGroupList().length).toEqual(1); @@ -258,15 +263,18 @@ function checkAllFields(original, copy) { ]).toEqual(copy.getRepeatedForeignEnumList()); expect(copy.getPackedRepeatedInt32List()).toEqual([-42]); - expect(copy.getPackedRepeatedInt64List()).toEqual([-0x7fffffff00000000]); + expect(copy.getPackedRepeatedInt64List()) + .toEqual([String(-BigInt('0x7fffffff00000000'))]); expect(copy.getPackedRepeatedUint32List()).toEqual([0x80000000]); - expect(copy.getPackedRepeatedUint64List()).toEqual([0xf000000000000000]); + expect(copy.getPackedRepeatedUint64List()) + .toEqual([String(BigInt('0xf000000000000000'))]); expect(copy.getPackedRepeatedSint32List()).toEqual([-100]); - expect(copy.getPackedRepeatedSint64List()).toEqual([-0x8000000000000000]); + expect(copy.getPackedRepeatedSint64List()) + .toEqual([String(-BigInt('0x8000000000000000'))]); expect(copy.getPackedRepeatedFixed32List()).toEqual([1234]); - expect(copy.getPackedRepeatedFixed64List()).toEqual([0x1234567800000000]); + expect(copy.getPackedRepeatedFixed64List()).toEqual([String(BigInt('0x1234567800000000'))]); expect(copy.getPackedRepeatedSfixed32List()).toEqual([-1234]); - expect(copy.getPackedRepeatedSfixed64List()).toEqual([-0x1234567800000000]); + expect(copy.getPackedRepeatedSfixed64List()).toEqual([String(-BigInt('0x1234567800000000'))]); expect(copy.getPackedRepeatedFloatList()).toEqual([1.5]); expect(copy.getPackedRepeatedDoubleList()).toEqual([-1.5]); @@ -282,65 +290,63 @@ function checkAllFields(original, copy) { */ function checkExtensions(msg) { expect(0).toEqual(msg.getExtension(proto.jspb.test.extendOptionalInt32)); - expect(-0x7fffffff00000000) - .toEqual(msg.getExtension(proto.jspb.test.extendOptionalInt64)); + expect(String(-BigInt('0x7fffffff00000000'))) + .toEqual(msg.getExtension(proto.jspb.test.extendOptionalInt64)); expect(0x80000000) - .toEqual(msg.getExtension(proto.jspb.test.extendOptionalUint32)); - expect(0xf000000000000000) - .toEqual(msg.getExtension(proto.jspb.test.extendOptionalUint64)); + .toEqual(msg.getExtension(proto.jspb.test.extendOptionalUint32)); + expect(String(BigInt('0xf000000000000000'))) + .toEqual(msg.getExtension(proto.jspb.test.extendOptionalUint64)); expect(-100).toEqual(msg.getExtension(proto.jspb.test.extendOptionalSint32)); - expect(-0x8000000000000000) - .toEqual(msg.getExtension(proto.jspb.test.extendOptionalSint64)); + expect(String(-BigInt('0x8000000000000000'))) + .toEqual(msg.getExtension(proto.jspb.test.extendOptionalSint64)); expect(1234).toEqual(msg.getExtension(proto.jspb.test.extendOptionalFixed32)); - expect(0x1234567800000000) - .toEqual(msg.getExtension(proto.jspb.test.extendOptionalFixed64)); + expect(String(BigInt('0x1234567800000000'))) + .toEqual(msg.getExtension(proto.jspb.test.extendOptionalFixed64)); expect(-1234).toEqual( - msg.getExtension(proto.jspb.test.extendOptionalSfixed32)); - expect(-0x1234567800000000) - .toEqual(msg.getExtension(proto.jspb.test.extendOptionalSfixed64)); + msg.getExtension(proto.jspb.test.extendOptionalSfixed32)); + expect(String(-BigInt('0x1234567800000000'))) + .toEqual(msg.getExtension(proto.jspb.test.extendOptionalSfixed64)); expect(msg.getExtension(proto.jspb.test.extendOptionalFloat)).toEqual(1.5); expect(msg.getExtension(proto.jspb.test.extendOptionalDouble)).toEqual(-1.5); expect(msg.getExtension(proto.jspb.test.extendOptionalBool)).toEqual(true); expect(msg.getExtension(proto.jspb.test.extendOptionalString)) - .toEqual('hello world'); + .toEqual('hello world'); expect(bytesCompare( - msg.getExtension(proto.jspb.test.extendOptionalBytes), BYTES)) - .toEqual(true); + msg.getExtension(proto.jspb.test.extendOptionalBytes), BYTES)) + .toEqual(true); expect(msg.getExtension(proto.jspb.test.ExtendsWithMessage.optionalExtension) - .getFoo()) - .toEqual(16); + .getFoo()) + .toEqual(16); expect(msg.getExtension(proto.jspb.test.extendRepeatedInt32List)).toEqual([ -42 ]); expect(msg.getExtension(proto.jspb.test.extendRepeatedInt64List)).toEqual([ - -0x7fffffff00000000 + String(-BigInt('0x7fffffff00000000')) ]); expect(msg.getExtension(proto.jspb.test.extendRepeatedUint32List)).toEqual([ 0x80000000 ]); expect(msg.getExtension(proto.jspb.test.extendRepeatedUint64List)).toEqual([ - 0xf000000000000000 + String(BigInt('0xf000000000000000')) ]); expect(msg.getExtension(proto.jspb.test.extendRepeatedSint32List)).toEqual([ -100 ]); expect(msg.getExtension(proto.jspb.test.extendRepeatedSint64List)).toEqual([ - -0x8000000000000000 + String(-BigInt('0x8000000000000000')) ]); expect(msg.getExtension(proto.jspb.test.extendRepeatedFixed32List)).toEqual([ 1234 ]); - expect(msg.getExtension(proto.jspb.test.extendRepeatedFixed64List)).toEqual([ - 0x1234567800000000 - ]); + expect(msg.getExtension(proto.jspb.test.extendRepeatedFixed64List)) + .toEqual([String(BigInt('0x1234567800000000'))]); expect(msg.getExtension(proto.jspb.test.extendRepeatedSfixed32List)).toEqual([ -1234 ]); - expect(msg.getExtension(proto.jspb.test.extendRepeatedSfixed64List)).toEqual([ - -0x1234567800000000 - ]); + expect(msg.getExtension(proto.jspb.test.extendRepeatedSfixed64List)) + .toEqual([String(-BigInt('0x1234567800000000'))]); expect(msg.getExtension(proto.jspb.test.extendRepeatedFloatList)).toEqual([ 1.5 ]); @@ -354,45 +360,45 @@ function checkExtensions(msg) { 'hello world' ]); expect(true).toEqual(bytesCompare( - msg.getExtension(proto.jspb.test.extendRepeatedBytesList)[0], BYTES)); + msg.getExtension(proto.jspb.test.extendRepeatedBytesList)[0], BYTES)); expect(1000).toEqual( - msg.getExtension( - proto.jspb.test.ExtendsWithMessage.repeatedExtensionList)[0] - .getFoo()); + msg.getExtension( + proto.jspb.test.ExtendsWithMessage.repeatedExtensionList)[0] + .getFoo()); expect([ proto.jspb.test.ForeignEnum.FOREIGN_FOO ]).toEqual(msg.getExtension(proto.jspb.test.extendRepeatedForeignEnumList)); expect(msg.getExtension(proto.jspb.test.extendPackedRepeatedInt32List)) - .toEqual([-42]); + .toEqual([-42]); expect(msg.getExtension(proto.jspb.test.extendPackedRepeatedInt64List)) - .toEqual([-0x7fffffff00000000]); + .toEqual([String(-BigInt('0x7fffffff00000000'))]); expect(msg.getExtension(proto.jspb.test.extendPackedRepeatedUint32List)) - .toEqual([0x80000000]); + .toEqual([0x80000000]); expect(msg.getExtension(proto.jspb.test.extendPackedRepeatedUint64List)) - .toEqual([0xf000000000000000]); + .toEqual([String(BigInt('0xf000000000000000'))]); expect(msg.getExtension(proto.jspb.test.extendPackedRepeatedSint32List)) - .toEqual([-100]); + .toEqual([-100]); expect(msg.getExtension(proto.jspb.test.extendPackedRepeatedSint64List)) - .toEqual([-0x8000000000000000]); + .toEqual([String(-BigInt('0x8000000000000000'))]); expect(msg.getExtension(proto.jspb.test.extendPackedRepeatedFixed32List)) - .toEqual([1234]); + .toEqual([1234]); expect(msg.getExtension(proto.jspb.test.extendPackedRepeatedFixed64List)) - .toEqual([0x1234567800000000]); + .toEqual([String(BigInt('0x1234567800000000'))]); expect(msg.getExtension(proto.jspb.test.extendPackedRepeatedSfixed32List)) - .toEqual([-1234]); + .toEqual([-1234]); expect(msg.getExtension(proto.jspb.test.extendPackedRepeatedSfixed64List)) - .toEqual([-0x1234567800000000]); + .toEqual([String(-BigInt('0x1234567800000000'))]); expect(msg.getExtension(proto.jspb.test.extendPackedRepeatedFloatList)) - .toEqual([1.5]); + .toEqual([1.5]); expect(msg.getExtension(proto.jspb.test.extendPackedRepeatedDoubleList)) - .toEqual([-1.5]); + .toEqual([-1.5]); expect(msg.getExtension(proto.jspb.test.extendPackedRepeatedBoolList)) - .toEqual([true]); + .toEqual([true]); expect([proto.jspb.test.ForeignEnum.FOREIGN_FOO]) - .toEqual(msg.getExtension( - proto.jspb.test.extendPackedRepeatedForeignEnumList)); + .toEqual(msg.getExtension( + proto.jspb.test.extendPackedRepeatedForeignEnumList)); } @@ -460,20 +466,20 @@ describe('protoBinaryTest', () => { expect(typeof msg.getRepeatedBytesList_asB64()[0]).toEqual('string'); expect(typeof msg.getRepeatedBytesList_asB64()[1]).toEqual('string'); expect(msg.getRepeatedBytesList_asU8()[0] instanceof Uint8Array) - .toBeTrue(); + .toBeTrue(); expect(msg.getRepeatedBytesList_asU8()[1] instanceof Uint8Array) - .toBeTrue(); + .toBeTrue(); expect(bytesCompare(msg.getRepeatedBytesList()[0], BYTES)).toBeTrue(); expect(bytesCompare(msg.getRepeatedBytesList()[1], BYTES)).toBeTrue(); expect(bytesCompare(msg.getRepeatedBytesList_asB64()[0], BYTES)) - .toBeTrue(); + .toBeTrue(); expect(bytesCompare(msg.getRepeatedBytesList_asB64()[1], BYTES)) - .toBeTrue(); + .toBeTrue(); expect(bytesCompare(msg.getRepeatedBytesList_asU8()[0], BYTES)) - .toBeTrue(); + .toBeTrue(); expect(bytesCompare(msg.getRepeatedBytesList_asU8()[1], BYTES)) - .toBeTrue(); + .toBeTrue(); } msg.setRepeatedBytesList([BYTES, BYTES]); assertGetters(); @@ -493,16 +499,21 @@ describe('protoBinaryTest', () => { */ function fillExtensions(msg) { msg.setExtension(proto.jspb.test.extendOptionalInt32, 0); - msg.setExtension(proto.jspb.test.extendOptionalInt64, -0x7fffffff00000000); + msg.setExtension( + proto.jspb.test.extendOptionalInt64, String(-BigInt('0x7fffffff00000000'))); msg.setExtension(proto.jspb.test.extendOptionalUint32, 0x80000000); - msg.setExtension(proto.jspb.test.extendOptionalUint64, 0xf000000000000000); + msg.setExtension( + proto.jspb.test.extendOptionalUint64, String(BigInt('0xf000000000000000'))); msg.setExtension(proto.jspb.test.extendOptionalSint32, -100); - msg.setExtension(proto.jspb.test.extendOptionalSint64, -0x8000000000000000); + msg.setExtension( + proto.jspb.test.extendOptionalSint64, String(-BigInt('0x8000000000000000'))); msg.setExtension(proto.jspb.test.extendOptionalFixed32, 1234); - msg.setExtension(proto.jspb.test.extendOptionalFixed64, 0x1234567800000000); + msg.setExtension( + proto.jspb.test.extendOptionalFixed64, String(BigInt('0x1234567800000000'))); msg.setExtension(proto.jspb.test.extendOptionalSfixed32, -1234); msg.setExtension( - proto.jspb.test.extendOptionalSfixed64, -0x1234567800000000); + proto.jspb.test.extendOptionalSfixed64, + String(-BigInt('0x1234567800000000'))); msg.setExtension(proto.jspb.test.extendOptionalFloat, 1.5); msg.setExtension(proto.jspb.test.extendOptionalDouble, -1.5); msg.setExtension(proto.jspb.test.extendOptionalBool, true); @@ -511,27 +522,32 @@ describe('protoBinaryTest', () => { let submsg = new proto.jspb.test.ExtendsWithMessage(); submsg.setFoo(16); msg.setExtension( - proto.jspb.test.ExtendsWithMessage.optionalExtension, submsg); + proto.jspb.test.ExtendsWithMessage.optionalExtension, submsg); msg.setExtension( - proto.jspb.test.extendOptionalForeignEnum, - proto.jspb.test.ForeignEnum.FOREIGN_FOO); + proto.jspb.test.extendOptionalForeignEnum, + proto.jspb.test.ForeignEnum.FOREIGN_FOO); msg.setExtension(proto.jspb.test.extendRepeatedInt32List, [-42]); - msg.setExtension( - proto.jspb.test.extendRepeatedInt64List, [-0x7fffffff00000000]); + msg.setExtension(proto.jspb.test.extendRepeatedInt64List, [ + String(-BigInt('0x7fffffff00000000')) + ]); msg.setExtension(proto.jspb.test.extendRepeatedUint32List, [0x80000000]); - msg.setExtension( - proto.jspb.test.extendRepeatedUint64List, [0xf000000000000000]); + msg.setExtension(proto.jspb.test.extendRepeatedUint64List, [ + String(BigInt('0xf000000000000000')) + ]); msg.setExtension(proto.jspb.test.extendRepeatedSint32List, [-100]); - msg.setExtension( - proto.jspb.test.extendRepeatedSint64List, [-0x8000000000000000]); + msg.setExtension(proto.jspb.test.extendRepeatedSint64List, [ + String(-BigInt('0x8000000000000000')) + ]); msg.setExtension(proto.jspb.test.extendRepeatedFixed32List, [1234]); - msg.setExtension( - proto.jspb.test.extendRepeatedFixed64List, [0x1234567800000000]); + msg.setExtension(proto.jspb.test.extendRepeatedFixed64List, [ + String(BigInt('0x1234567800000000')) + ]); msg.setExtension(proto.jspb.test.extendRepeatedSfixed32List, [-1234]); - msg.setExtension( - proto.jspb.test.extendRepeatedSfixed64List, [-0x1234567800000000]); + msg.setExtension(proto.jspb.test.extendRepeatedSfixed64List, [ + String(-BigInt('0x1234567800000000')) + ]); msg.setExtension(proto.jspb.test.extendRepeatedFloatList, [1.5]); msg.setExtension(proto.jspb.test.extendRepeatedDoubleList, [-1.5]); msg.setExtension(proto.jspb.test.extendRepeatedBoolList, [true]); @@ -540,35 +556,39 @@ describe('protoBinaryTest', () => { submsg = new proto.jspb.test.ExtendsWithMessage(); submsg.setFoo(1000); msg.setExtension( - proto.jspb.test.ExtendsWithMessage.repeatedExtensionList, [submsg]); + proto.jspb.test.ExtendsWithMessage.repeatedExtensionList, [submsg]); msg.setExtension( - proto.jspb.test.extendRepeatedForeignEnumList, - [proto.jspb.test.ForeignEnum.FOREIGN_FOO]); + proto.jspb.test.extendRepeatedForeignEnumList, + [proto.jspb.test.ForeignEnum.FOREIGN_FOO]); msg.setExtension(proto.jspb.test.extendPackedRepeatedInt32List, [-42]); + msg.setExtension(proto.jspb.test.extendPackedRepeatedInt64List, [ + String(-BigInt('0x7fffffff00000000')) + ]); msg.setExtension( - proto.jspb.test.extendPackedRepeatedInt64List, [-0x7fffffff00000000]); - msg.setExtension( - proto.jspb.test.extendPackedRepeatedUint32List, [0x80000000]); - msg.setExtension( - proto.jspb.test.extendPackedRepeatedUint64List, [0xf000000000000000]); + proto.jspb.test.extendPackedRepeatedUint32List, [0x80000000]); + msg.setExtension(proto.jspb.test.extendPackedRepeatedUint64List, [ + String(BigInt('0xf000000000000000')) + ]); msg.setExtension(proto.jspb.test.extendPackedRepeatedSint32List, [-100]); - msg.setExtension( - proto.jspb.test.extendPackedRepeatedSint64List, [-0x8000000000000000]); + msg.setExtension(proto.jspb.test.extendPackedRepeatedSint64List, [ + String(-BigInt('0x8000000000000000')) + ]); msg.setExtension(proto.jspb.test.extendPackedRepeatedFixed32List, [1234]); - msg.setExtension( - proto.jspb.test.extendPackedRepeatedFixed64List, [0x1234567800000000]); + msg.setExtension(proto.jspb.test.extendPackedRepeatedFixed64List, [ + String(BigInt('0x1234567800000000')) + ]); msg.setExtension(proto.jspb.test.extendPackedRepeatedSfixed32List, [-1234]); - msg.setExtension( - proto.jspb.test.extendPackedRepeatedSfixed64List, - [-0x1234567800000000]); + msg.setExtension(proto.jspb.test.extendPackedRepeatedSfixed64List, [ + String(-BigInt('0x1234567800000000')) + ]); msg.setExtension(proto.jspb.test.extendPackedRepeatedFloatList, [1.5]); msg.setExtension(proto.jspb.test.extendPackedRepeatedDoubleList, [-1.5]); msg.setExtension(proto.jspb.test.extendPackedRepeatedBoolList, [true]); msg.setExtension( - proto.jspb.test.extendPackedRepeatedForeignEnumList, - [proto.jspb.test.ForeignEnum.FOREIGN_FOO]); + proto.jspb.test.extendPackedRepeatedForeignEnumList, + [proto.jspb.test.ForeignEnum.FOREIGN_FOO]); } @@ -589,7 +609,7 @@ describe('protoBinaryTest', () => { it('testUnknownExtension', () => { const msg = new proto.jspb.test.TestExtendable(); fillExtensions(msg); - const writer = new jspb.BinaryWriter(); + const writer = new BinaryWriter(); writer.writeBool((1 << 29) - 1, true); proto.jspb.test.TestExtendable.serializeBinaryToWriter(msg, writer); const encoded = writer.getResultBuffer(); @@ -606,12 +626,13 @@ describe('protoBinaryTest', () => { any.pack(msg.serializeBinary(), 'jspb.test.TestAllTypes'); expect(any.getTypeUrl()) - .toEqual('type.googleapis.com/jspb.test.TestAllTypes'); + .toEqual('type.googleapis.com/jspb.test.TestAllTypes'); const msg2 = any.unpack( - proto.jspb.test.TestAllTypes.deserializeBinary, - 'jspb.test.TestAllTypes'); + proto.jspb.test.TestAllTypes.deserializeBinary, + 'jspb.test.TestAllTypes'); checkAllFields(msg, msg2); }); + }); diff --git a/binary/reader.js b/binary/reader.js old mode 100644 new mode 100755 index 0f8c961..15cbe6d --- a/binary/reader.js +++ b/binary/reader.js @@ -1,33 +1,3 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://protobuf.dev/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - /** * @fileoverview This file contains utilities for converting binary, * wire-format protocol buffers into Javascript data structures. @@ -41,16 +11,19 @@ * using the typed jspb code generator, but if you bypass that you'll need * to keep things in sync by hand. * - * @suppress {missingRequire} TODO(b/152540451): this shouldn't be needed * @author aappleby@google.com (Austin Appleby) */ -goog.provide('jspb.BinaryReader'); +goog.module('jspb.binary.reader'); +goog.module.declareLegacyNamespace(); -goog.require('jspb.asserts'); -goog.require('jspb.BinaryConstants'); -goog.require('jspb.BinaryDecoder'); -goog.require('jspb.utils'); +const BinaryConstants = goog.require('jspb.BinaryConstants'); +const asserts = goog.require('goog.asserts'); +const errors = goog.require('jspb.binary.errors'); +const utils = goog.require('jspb.utils'); +const { BinaryDecoder } = goog.require('jspb.binary.decoder'); +const { ByteSource } = goog.require('jspb.binary.bytesource'); +const { ByteString } = goog.requireType('jspb.bytestring'); /** * Whether to enforce that string fields are valid utf8. @@ -67,1365 +40,1510 @@ goog.require('jspb.utils'); const ENFORCE_UTF8 = goog.define('jspb.binary.ENFORCE_UTF8', 'ALWAYS'); // Constrain the set of values to only these two. -jspb.asserts.assert( +asserts.assert( ENFORCE_UTF8 === 'DEPRECATED_PROTO3_ONLY' || ENFORCE_UTF8 === 'ALWAYS'); const /** boolean */ UTF8_PARSING_ERRORS_ARE_FATAL = ENFORCE_UTF8 === 'ALWAYS'; +/** + * Describes options for BinaryReaders. + * + * @record + */ +class BinaryReaderOptions { + constructor() { + /** + * Whether to ignore unknown fields found when parsing. + * + * Normally, if unknown tag numbers are encountered when parsing a message, + * the tag and value are stored in the message instance and then written + * back out when the message is serialized. This allows applications to + * preserve data in messages that have new field definitions which they + * don't yet know about. However, this behavior can have performance + * implications. This property disables this behavior during parsing. + * + * @type {boolean|undefined} + */ + this.discardUnknownFields; + + /** + * When set to `true` bytes fields will be views into the original buffer + * instead of being copies. + * + * This allows teams to reduce copies at the cost of pinning the original + * `ByteSource` in memory. + * + * How this works ultimate depends on how `bytes` fields are parsed. + * + * If `bytes` fields are read as `Uint8Array` via the `readBytes` method (as + * is done by jsproto and immutablejs): `readBytes` will return views onto + * the original buffer as `Uint8Array` objects. Additionally, because + * Uint8Array objects are mutable this may allow unexpected mutations of the + * `ByteSource` or for mutations of the bytesource to affect later read + * operations. If the source is a ByteString, this option is ignored in + * order to preserve the immutability semantics of ByteStrings. + * + * If the `bytes` are read as `ByteString` via the `readByteString` method, + * then this option is only effective if the + * source is also a `ByteString`, otherwise copies need to be made to + * preserve the immutability of the produced `ByteString` objects. + * + * The default is `false` + * @type {boolean|undefined} + */ + this.aliasBytesFields; + + /** + * Whether we should treat newly deserialized data as being immutable. + * + * With this option, we treat newly deserialized data (e.g. from a + * base64-encoded string) as being immutable, so that it can be safely + * aliased in a ByteString. If you set this option, you then cannot alias + * into a Uint8Array, as its underlying ArrayBuffer could be unwrapped. + * + * @type {boolean|undefined} + */ + this.treatNewDataAsImmutable; + } +} +/* + * Handling Errors + * + * There are two classes of errors that should be considered below. + * + * Simple consistency checks: use `goog.asserts` + * + * These are cases related to function invariants. For example, in order to + * call `readString` the current field must have WireType.DELIMITED. Since we + * also control all the callsites it is reasonable to rely on our own tests to + * catch mistakes. + * + * Data based conditions: use `jspb.binary.invalid_encoding_errors` + * + * These are conditions where the _data_ is wrong in some way. For example, a + * varint is overlong, a delimited field overflows/underflows. These cases + * cannot be eliminated by better testing since they depend on the structure of + * data supplied to the parsing routines, so `goog.asserts` are not a good + * approach + */ /** * BinaryReader implements the decoders for all the wire types specified in - * https://protobuf.dev/programming-guides/encoding/. + * https://developers.google.com/protocol-buffers/docs/encoding. * - * @param {jspb.ByteSource=} opt_bytes The bytes we're reading from. - * @param {number=} opt_start The optional offset to start reading at. - * @param {number=} opt_length The optional length of the block to read - - * we'll throw an assertion if we go off the end of the block. - * @constructor * @struct - * @export + * @final */ -jspb.BinaryReader = function(opt_bytes, opt_start, opt_length) { +class BinaryReader { /** - * Wire-format decoder. - * @private {!jspb.BinaryDecoder} + * @param {?ByteSource|!ByteString=} bytes The bytes we're reading from. + * @param {number=} start The optional offset to start reading at. + * @param {number=} length The optional length of the block to read - + * we'll throw an assertion if we go off the end of the block. + * @param {!BinaryReaderOptions=} options Options for this BinaryReader. */ - this.decoder_ = jspb.BinaryDecoder.alloc(opt_bytes, opt_start, opt_length); + constructor(bytes, start, length, options) { + /** + * Current options for this reader + * @private {boolean} + */ + this.discardUnknownFields; + /** + * Wire-format decoder. + * @const {!BinaryDecoder} + */ + this.decoder_ = BinaryDecoder.alloc(bytes, start, length, options); + + /** + * Cursor immediately before the field tag. + * @private {number} + */ + this.fieldCursor_ = this.decoder_.getCursor(); + + /** + * Field number of the next field in the buffer, filled in by nextField(). + * @private {number} + */ + this.nextField_ = BinaryConstants.INVALID_FIELD_NUMBER; + + /** + * The combined wire-type and field number of the next field in the buffer, + * filled in by nextField(). + * @private {number} + */ + this.nextTag_ = BinaryConstants.INVALID_TAG; + + /** + * Wire type of the next proto field in the buffer, filled in by + * nextField(). + * @private {!BinaryConstants.WireType} + */ + this.nextWireType_ = BinaryConstants.WireType.INVALID; + this.setOptions(options); + } /** - * Cursor immediately before the field tag. - * @private {number} + * @param {!BinaryReaderOptions=} options options for this decoder. + * @private */ - this.fieldCursor_ = this.decoder_.getCursor(); + setOptions({ discardUnknownFields = false } = {}) { + this.discardUnknownFields = discardUnknownFields; + } + /** - * Field number of the next field in the buffer, filled in by nextField(). - * @private {number} + * Pops an instance off the instance cache, or creates one if the cache is + * empty. + * @param {?ByteSource|!ByteString=} bytes The bytes we're reading from. + * @param {number=} start The optional offset to start reading at. + * @param {number=} length The optional length of the block to read - + * we'll throw an assertion if we go off the end of the block. + * @param {!BinaryReaderOptions=} options + * @return {!BinaryReader} + * @suppress {visibility} accesses private properties of decoder */ - this.nextField_ = jspb.BinaryConstants.INVALID_FIELD_NUMBER; + static alloc(bytes, start, length, options) { + if (BinaryReader.instanceCache_.length) { + const newReader = BinaryReader.instanceCache_.pop(); + newReader.setOptions(options); + newReader.decoder_.init(bytes, start, length, options); + return newReader; + } else { + return new BinaryReader(bytes, start, length, options); + } + } + + /** - * Wire type of the next proto field in the buffer, filled in by - * nextField(). - * @private {jspb.BinaryConstants.WireType} + * Puts this instance back in the instance cache. */ - this.nextWireType_ = jspb.BinaryConstants.WireType.INVALID; + free() { + this.decoder_.clear(); + this.nextTag_ = BinaryConstants.INVALID_TAG; + this.nextField_ = BinaryConstants.INVALID_FIELD_NUMBER; + this.nextWireType_ = BinaryConstants.WireType.INVALID; + + if (BinaryReader.instanceCache_.length < 100) { + BinaryReader.instanceCache_.push(this); + } + } + /** - * Set to true if this reader encountered an error due to corrupt data. - * @private {boolean} + * Returns the cursor immediately before the current field's tag. + * @return {number} The internal read cursor. */ - this.error_ = false; + getFieldCursor() { + return this.fieldCursor_; + } + /** - * User-defined reader callbacks. - * @private {?Object} + * Returns the internal read cursor. + * @return {number} The internal read cursor. */ - this.readCallbacks_ = null; -}; + getCursor() { + return this.decoder_.getCursor(); + } + /** @return {boolean} */ + dataIsImmutable() { + return this.decoder_.dataIsImmutable(); + } -/** - * Global pool of BinaryReader instances. - * @private {!Array} - */ -jspb.BinaryReader.instanceCache_ = []; + /** + * Returns the raw buffer. + * + * Throws if the internal buffer is immutable. + * + * @return {?Uint8Array} The raw buffer. + */ + getBuffer() { + return this.decoder_.getBuffer(); + } + /** + * Returns the raw buffer as a byte string. + * + * Throws if the internal buffer is mutable. + * + * @return {?ByteString} The raw buffer. + */ + getBufferAsByteString() { + return this.decoder_.getBufferAsByteString(); + } -/** - * @export - */ -jspb.BinaryReader.clearInstanceCache = function() { - jspb.BinaryReader.instanceCache_ = []; -} + /** + * @return {number} The combined wire type and field number of the next field + * in the buffer, or INVALID_TAG if there is no next field. This is an + * unsigned 32-bit integer value with the lower three bits the wire type + * and the upper 29 bits the field number. + */ + getTag() { + return this.nextTag_; + } -/** - @return {number} - * @export - */ -jspb.BinaryReader.getInstanceCacheLength = function() { - return jspb.BinaryReader.instanceCache_.length; -} + /** + * @return {number} The field number of the next field in the buffer, or + * INVALID_FIELD_NUMBER if there is no next field. + */ + getFieldNumber() { + return this.nextField_; + } -/** - * Pops an instance off the instance cache, or creates one if the cache is - * empty. - * @param {jspb.ByteSource=} opt_bytes The bytes we're reading from. - * @param {number=} opt_start The optional offset to start reading at. - * @param {number=} opt_length The optional length of the block to read - - * we'll throw an assertion if we go off the end of the block. - * @return {!jspb.BinaryReader} - * @export - */ -jspb.BinaryReader.alloc = function(opt_bytes, opt_start, opt_length) { - if (jspb.BinaryReader.instanceCache_.length) { - var newReader = jspb.BinaryReader.instanceCache_.pop(); - if (opt_bytes) { - newReader.decoder_.setBlock(opt_bytes, opt_start, opt_length); - } - return newReader; - } else { - return new jspb.BinaryReader(opt_bytes, opt_start, opt_length); + /** + * @return {!BinaryConstants.WireType} The wire type of the next field + * in the stream, or WireType.INVALID if there is no next field. + */ + getWireType() { + return this.nextWireType_; } -}; -/** - * Alias for the above method. - * @param {jspb.ByteSource=} opt_bytes The bytes we're reading from. - * @param {number=} opt_start The optional offset to start reading at. - * @param {number=} opt_length The optional length of the block to read - - * we'll throw an assertion if we go off the end of the block. - * @return {!jspb.BinaryReader} - * @export - */ -jspb.BinaryReader.prototype.alloc = jspb.BinaryReader.alloc; + /** + * @return {boolean} Whether the current wire type is an end-group tag. Used + * as + * an exit condition in decoder loops in generated code. + */ + isEndGroup() { + return this.nextWireType_ == BinaryConstants.WireType.END_GROUP; + } + /** + * @return {boolean} Whether the current wire type is a delimited field. Used + * to + * conditionally parse packed repeated fields. + */ + isDelimited() { + return this.nextWireType_ == BinaryConstants.WireType.DELIMITED; + } -/** - * Puts this instance back in the instance cache. - * @export - */ -jspb.BinaryReader.prototype.free = function() { - this.decoder_.clear(); - this.nextField_ = jspb.BinaryConstants.INVALID_FIELD_NUMBER; - this.nextWireType_ = jspb.BinaryConstants.WireType.INVALID; - this.error_ = false; - this.readCallbacks_ = null; - if (jspb.BinaryReader.instanceCache_.length < 100) { - jspb.BinaryReader.instanceCache_.push(this); + /** + * Rewinds the stream cursor to the beginning of the buffer and resets all + * internal state. + * @package + */ + reset() { + this.decoder_.reset(); + this.fieldCursor_ = this.decoder_.getCursor(); + this.nextTag_ = BinaryConstants.INVALID_TAG; + this.nextField_ = BinaryConstants.INVALID_FIELD_NUMBER; + this.nextWireType_ = BinaryConstants.WireType.INVALID; } -}; -/** - * Returns the cursor immediately before the current field's tag. - * @return {number} The internal read cursor. - * @export - */ -jspb.BinaryReader.prototype.getFieldCursor = function() { - return this.fieldCursor_; -}; + /** + * Advances the stream cursor by the given number of bytes. + * @param {number} count The number of bytes to advance by. + */ + advance(count) { + this.decoder_.advance(count); + } -/** - * Returns the internal read cursor. - * @return {number} The internal read cursor. - * @export - */ -jspb.BinaryReader.prototype.getCursor = function() { - return this.decoder_.getCursor(); -}; + /** + * Reads the next field header in the stream if there is one, returns true if + * we saw a valid field header or false if we've read the whole stream. + * Throws an error if we encountered a deprecated START_GROUP/END_GROUP field. + * @return {boolean} True if the stream contains more fields. + */ + nextField() { + // If we're at the end of the block, there are no more fields. + if (this.decoder_.atEnd()) { + return false; + } + this.assertPriorFieldWasRead(); + // No need to check cursor position here, as that is readUnsignedVarint32s + // responsibility. + // Otherwise just read the header of the next field. + this.fieldCursor_ = this.decoder_.getCursor(); + const header = BinaryDecoder.readUnsignedVarint32(this.decoder_); -/** - * Returns the raw buffer. - * @return {?Uint8Array} The raw buffer. - * @export - */ -jspb.BinaryReader.prototype.getBuffer = function() { - return this.decoder_.getBuffer(); -}; + const nextField = parseFieldNumber(header); + const nextWireType = parseWireType(header); + // If the wire type isn't one of the valid ones, something's broken. + if (!BinaryConstants.isValidWireType(nextWireType)) { + throw errors.invalidWireTypeError(nextWireType, this.fieldCursor_); + } -/** - * @return {number} The field number of the next field in the buffer, or - * INVALID_FIELD_NUMBER if there is no next field. - * @export - */ -jspb.BinaryReader.prototype.getFieldNumber = function() { - return this.nextField_; -}; + // Zero is not a valid field number and we should never see a negative as + // we've already shifted right unsigned. + if (nextField < 1) { + throw errors.invalidFieldNumberError(nextField, this.fieldCursor_); + } + this.nextTag_ = header; + this.nextField_ = nextField; + this.nextWireType_ = nextWireType; -/** - * @return {jspb.BinaryConstants.WireType} The wire type of the next field - * in the stream, or WireType.INVALID if there is no next field. - * @export - */ -jspb.BinaryReader.prototype.getWireType = function() { - return this.nextWireType_; -}; + return true; + } + /** + * If the stream contains a following field with the specified tag (field + * number and wire type), reads its field header and makes the reader ready to + * read its value. If the stream does not contain another field, or its tag is + * different, does not change the state of the stream. + * + * TIP: methods like `readMessage` may destroy the reader state for the tag, + * so call `getTag()` outside a loop, before calling reader methods to pass + * into this method. + * + * @param {number} tag The field tag to look for. + * @return {boolean} Whether another instance of the current tag is read. + */ + nextFieldIfTagEqualTo(tag) { + this.assertPriorFieldWasRead(); + asserts.assert( + BinaryConstants.isValidWireType(parseWireType(tag)) && + parseFieldNumber(tag) > 0, + 'Must pass a valid tag.'); + + const fieldCursorOrNegative = + this.decoder_.readUnsignedVarint32IfEqualTo(tag); + const matched = fieldCursorOrNegative >= 0; + if (matched) { + this.fieldCursor_ = fieldCursorOrNegative; + + this.nextTag_ = tag; + this.nextField_ = parseFieldNumber(tag); + this.nextWireType_ = parseWireType(tag); + } + return matched; + } -/** - * @return {boolean} Whether the current wire type is a delimited field. Used to - * conditionally parse packed repeated fields. - * @export - */ -jspb.BinaryReader.prototype.isDelimited = function() { - return this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED; -}; + /** + * Helper to ensure that the prior field was correctly read by advancing the + * cursor. + * @private + */ + assertPriorFieldWasRead() { + if (asserts.ENABLE_ASSERTS && + this.nextTag_ !== BinaryConstants.INVALID_TAG) { + // If we aren't at the first field, make sure that the previous caller of + // nextField actually read the field (by calling an appropriate `read*` or + // `skip*` method). + // To do this we go back and redo the work to move cursor to where it was + // at the end of the last nextField() call and just ensure that we have + // advanced beyond that + const currentCursor = this.decoder_.getCursor(); + this.decoder_.setCursor(this.fieldCursor_); + BinaryDecoder.readUnsignedVarint32(this.decoder_); + if (this.nextWireType_ === BinaryConstants.WireType.END_GROUP || + this.nextWireType_ === BinaryConstants.WireType.START_GROUP) { + // This case should be impossible, as every read* skip* method would + // likely throw. Direct mutation of the cursor could do it. + asserts.assert( + currentCursor === this.decoder_.getCursor(), + 'Expected to not advance the cursor. Group tags do not have values.'); + } else { + asserts.assert( + currentCursor > this.decoder_.getCursor(), + 'Expected to read the field, did you forget to call a read or skip method?'); + } + this.decoder_.setCursor(currentCursor); + } + } -/** - * @return {boolean} Whether the current wire type is an end-group tag. Used as - * an exit condition in decoder loops in generated code. - * @export - */ -jspb.BinaryReader.prototype.isEndGroup = function() { - return this.nextWireType_ == jspb.BinaryConstants.WireType.END_GROUP; -}; + /** + * Skips over the next varint field in the binary stream. + */ + skipVarintField() { + // This case should be impossible but jsproto calls this method without + // first checking wiretype + if (this.nextWireType_ != BinaryConstants.WireType.VARINT) { + asserts.fail('Invalid wire type for skipVarintField'); + this.skipField(); + return; + } + this.decoder_.skipVarint(); + } -/** - * Returns true if this reader hit an error due to corrupt data. - * @return {boolean} - * @export - */ -jspb.BinaryReader.prototype.getError = function() { - return this.error_ || this.decoder_.getError(); -}; + /** + * Skips over the next delimited field in the binary stream. + * @return {number} The length of the delimited field payload, not including + * the field header. + */ + skipDelimitedField() { + // This case should be impossible but jsproto calls this method without + // first checking wiretype + if (this.nextWireType_ != BinaryConstants.WireType.DELIMITED) { + asserts.fail('Invalid wire type for skipDelimitedField'); + this.skipField(); + return 0; + } -/** - * Points this reader at a new block of bytes. - * @param {!Uint8Array} bytes The block of bytes we're reading from. - * @param {number} start The offset to start reading at. - * @param {number} length The length of the block to read. - * @export - */ -jspb.BinaryReader.prototype.setBlock = function(bytes, start, length) { - this.decoder_.setBlock(bytes, start, length); - this.nextField_ = jspb.BinaryConstants.INVALID_FIELD_NUMBER; - this.nextWireType_ = jspb.BinaryConstants.WireType.INVALID; -}; + const length = BinaryDecoder.readUnsignedVarint32(this.decoder_); + this.decoder_.advance(length); + return length; + } -/** - * Rewinds the stream cursor to the beginning of the buffer and resets all - * internal state. - * @export - */ -jspb.BinaryReader.prototype.reset = function() { - this.decoder_.reset(); - this.nextField_ = jspb.BinaryConstants.INVALID_FIELD_NUMBER; - this.nextWireType_ = jspb.BinaryConstants.WireType.INVALID; -}; + /** + * Skips over the next fixed32 field in the binary stream. + * @private + */ + skipFixed32Field() { + asserts.assert(this.nextWireType_ === BinaryConstants.WireType.FIXED32); + this.decoder_.advance(4); + } -/** - * Advances the stream cursor by the given number of bytes. - * @param {number} count The number of bytes to advance by. - * @export - */ -jspb.BinaryReader.prototype.advance = function(count) { - this.decoder_.advance(count); -}; + /** + * Skips over the next fixed64 field in the binary stream. + * @private + */ + skipFixed64Field() { + asserts.assert(this.nextWireType_ === BinaryConstants.WireType.FIXED64); + this.decoder_.advance(8); + } -/** - * Reads the next field header in the stream if there is one, returns true if - * we saw a valid field header or false if we've read the whole stream. - * Throws an error if we encountered a deprecated START_GROUP/END_GROUP field. - * @return {boolean} True if the stream contains more fields. - * @export - */ -jspb.BinaryReader.prototype.nextField = function() { - // If we're at the end of the block, there are no more fields. - if (this.decoder_.atEnd()) { - return false; + /** + * Skips over the next group field in the binary stream. + * @private + */ + skipGroup() { + const previousField = this.nextField_; + do { + if (!this.nextField()) { + throw errors.unmatchedStartGroupEofError(); + } + if (this.nextWireType_ == BinaryConstants.WireType.END_GROUP) { + // Group end: check that it matches top-of-stack. + if (this.nextField_ != previousField) { + throw errors.unmatchedStartGroupError(); + } + return; + } + this.skipField(); + } while (true); } - // If we hit an error decoding the previous field, stop now before we - // try to decode anything else - if (this.getError()) { - jspb.asserts.fail('Decoder hit an error'); - return false; + + /** + * Skips over the next field in the binary stream - this is useful if we're + * decoding a message that contain unknown fields. + */ + skipField() { + switch (this.nextWireType_) { + case BinaryConstants.WireType.VARINT: + this.skipVarintField(); + break; + case BinaryConstants.WireType.FIXED64: + this.skipFixed64Field(); + break; + case BinaryConstants.WireType.DELIMITED: + this.skipDelimitedField(); + break; + case BinaryConstants.WireType.FIXED32: + this.skipFixed32Field(); + break; + case BinaryConstants.WireType.START_GROUP: + this.skipGroup(); + break; + default: + throw errors.invalidWireTypeError( + this.nextWireType_, this.fieldCursor_); + } } - // Otherwise just read the header of the next field. - this.fieldCursor_ = this.decoder_.getCursor(); - var header = this.decoder_.readUnsignedVarint32(); + /** + * Skips over the entire content to the end of the stream. + */ + skipToEnd() { + this.decoder_.setCursor(this.decoder_.getEnd()); + } - var nextField = header >>> 3; - var nextWireType = /** @type {jspb.BinaryConstants.WireType} */ - (header & 0x7); + /** + * Reads a single field as an uninterpreted bytestring. + * @return {!ByteString|undefined} + */ + readUnknownField() { + // read the field cursor prior to calling skipField, otherwise skipping + // a group will reset the field cursor. + const begin = this.getFieldCursor(); + this.skipField(); + return this.readUnknownFieldsStartingFrom(begin); + } - // If the wire type isn't one of the valid ones, something's broken. - if (nextWireType != jspb.BinaryConstants.WireType.VARINT && - nextWireType != jspb.BinaryConstants.WireType.FIXED32 && - nextWireType != jspb.BinaryConstants.WireType.FIXED64 && - nextWireType != jspb.BinaryConstants.WireType.DELIMITED && - nextWireType != jspb.BinaryConstants.WireType.START_GROUP && - nextWireType != jspb.BinaryConstants.WireType.END_GROUP) { - jspb.asserts.fail( - 'Invalid wire type: %s (at position %s)', nextWireType, - this.fieldCursor_); - this.error_ = true; - return false; + /** + * Reads a range of unknown field(s) as a single bytestring. + * @param {number} fieldOffset + * @return {!ByteString|undefined} + */ + readUnknownFieldsStartingFrom(fieldOffset) { + if (!this.discardUnknownFields) { + // It is important that this is actually an immutable reference since the + // unknownFieldset takes 'ownership' over the data. So we read as a + // ByteString. + const currentOffset = this.decoder_.getCursor(); + const fieldLength = currentOffset - fieldOffset; + this.decoder_.setCursor(fieldOffset); + const unknownField = this.decoder_.readByteString(fieldLength); + // double check our own math. + asserts.assert(currentOffset == this.decoder_.getCursor()); + // lazily instantiate the unknown fields structure. + return unknownField; + } + return undefined; } - this.nextField_ = nextField; - this.nextWireType_ = nextWireType; + /** + * Reads a field of any valid non-message type from the binary stream. + * + * Returns `null` if the type could not be parsed because the data on the wire + * doesn't match the `fieldType`. + * @param {!BinaryConstants.FieldType} fieldType + * @return {boolean|number|string|!Uint8Array|null} + */ + readAny(fieldType) { + // If the wire types don't match just return null, it means that there is an + // invalid value on the wire. In normal apps/jspb we handle this as an + // 'unknown field' but in this API we just skip over it as we have no place + // to store unknowns + if (BinaryConstants.FieldTypeToWireType(fieldType) !== this.nextWireType_) { + return null; + } + const fieldTypes = BinaryConstants.FieldType; + switch (fieldType) { + case fieldTypes.DOUBLE: + return this.readDouble(); + case fieldTypes.FLOAT: + return this.readFloat(); + case fieldTypes.INT64: + return this.readInt64(); + case fieldTypes.UINT64: + return this.readUint64(); + case fieldTypes.INT32: + return this.readInt32(); + case fieldTypes.FIXED64: + return this.readFixed64(); + case fieldTypes.FIXED32: + return this.readFixed32(); + case fieldTypes.BOOL: + return this.readBool(); + case fieldTypes.STRING: + return this.readString(); + case fieldTypes.GROUP: + asserts.fail('Group field type not supported in readAny()'); + case fieldTypes.MESSAGE: + asserts.fail('Message field type not supported in readAny()'); + case fieldTypes.BYTES: + return this.readBytes(); + case fieldTypes.UINT32: + return this.readUint32(); + case fieldTypes.ENUM: + return this.readEnum(); + case fieldTypes.SFIXED32: + return this.readSfixed32(); + case fieldTypes.SFIXED64: + return this.readSfixed64(); + case fieldTypes.SINT32: + return this.readSint32(); + case fieldTypes.SINT64: + return this.readSint64(); + default: + asserts.fail('Invalid field type in readAny()'); + } + return null; + } - return true; -}; + /** + * Deserialize a proto into the provided message object using the provided + * reader function. This function is templated as we currently have one client + * who is using manual deserialization instead of the code-generated versions. + * @template T,A,B,C + * @param {T} message + * @param {function(T, !BinaryReader, A, B, C)} reader + * @param {A=} contextA + * @param {B=} contextB + * @param {C=} contextC + * @return {T} + */ + readMessage(message, reader, contextA, contextB, contextC) { + asserts.assert(this.nextWireType_ == BinaryConstants.WireType.DELIMITED); + + // Save the current endpoint of the decoder and move it to the end of the + // embedded message. + const oldEnd = this.decoder_.getEnd(); + const length = BinaryDecoder.readUnsignedVarint32(this.decoder_); + const newEnd = this.decoder_.getCursor() + length; + let underflowLength = newEnd - oldEnd; + if (underflowLength <= 0) { + this.decoder_.setEnd(newEnd); + + // Deserialize the embedded message. + reader(message, this, contextA, contextB, contextC); + + underflowLength = newEnd - this.decoder_.getCursor(); + } + if (underflowLength) { + throw errors.messageLengthMismatchError(length, length - underflowLength); + } + // Advance the decoder past the embedded message and restore the endpoint. + this.decoder_.setCursor(newEnd); + this.decoder_.setEnd(oldEnd); + return message; + } -/** - * Winds the reader back to just before this field's header. - * @export - */ -jspb.BinaryReader.prototype.unskipHeader = function() { - this.decoder_.unskipVarint((this.nextField_ << 3) | this.nextWireType_); -}; + /** + * Deserialize a proto into the provided message object using the provided + * reader function, assuming that the message is serialized as a group + * with the given tag. + * @template T + * @param {number} field + * @param {T} message + * @param {function(T, !BinaryReader)} reader + * @return {T} + */ + readGroup(field, message, reader) { + // Ensure that the wire type is correct. + asserts.assert(this.nextWireType_ == BinaryConstants.WireType.START_GROUP); + // Ensure that the field number is correct. + asserts.assert(this.nextField_ == field); + + // Deserialize the message. The deserialization will stop at an END_GROUP + // tag. + reader(message, this); + + if (this.nextWireType_ !== BinaryConstants.WireType.END_GROUP) { + // This case should be impossible assuming we trust all the reader + // callbacks. In other words this really means the `reader` did the + // wrong thing. + throw errors.groupDidNotEndWithEndGroupError(); + } else if (this.nextField_ !== field) { + // this can happen if start and end group tags are nested improperly + throw errors.unmatchedStartGroupError(); + } + return message; + } + /** + * Whether the current field could be a valid start of a message set group. + * @return {boolean} + */ + isMessageSetGroup() { + return this.getTag() === MESSAGE_SET_START_GROUP_TAG; + } -/** - * Skips all contiguous fields whose header matches the one we just read. - * @export - */ -jspb.BinaryReader.prototype.skipMatchingFields = function() { - var field = this.nextField_; - this.unskipHeader(); + /** + * Deserialize a message-set wire-format group, calling the provided callaback + * with the type ID and reader to read the message with. + * + * See go/messageset-wire-format + * @param {function(number, !BinaryReader): void} readerCallback Function + * called with the type ID and a reader for the message content. + */ + readMessageSetGroup(readerCallback) { + asserts.assert(this.isMessageSetGroup()); + + // A message set group is encodes like: + // repeated group Item = 1 { + // required uint32 typeId = 2; + // required bytes message = 3; + // } + // + let typeId = 0; + // The offset to the message payload, or -1 if consumed. + let messageCursor = 0; + while (this.nextField() && !this.isEndGroup()) { + // See go/malformed-message-set-parsing If malformed messages repeat the + // typeId or message fields, only use the first value of either within + // the group. + if (this.getTag() === MESSAGE_SET_TYPE_ID_TAG && !typeId) { + typeId = this.readUint32(); + if (messageCursor) { + asserts.assert(messageCursor > 0); + // Backup the parsing to the message payload. + // No need to restore the position, we'll simply reread the type id + // again, but skip doing anything because its already been read once. + + // Reset these. Because we are going to modify the cursor we need to + // skip the consistency checks in nextField() and pretend like this is + // a fresh BinaryReader instance. + if (asserts.ENABLE_ASSERTS) { + this.nextTag_ = BinaryConstants.INVALID_TAG; + this.nextWireType_ = BinaryConstants.WireType.INVALID; + } + + // Reset our cursor to where the message was, and pretend like we had + // not seen the message payload yet. + this.decoder_.setCursor(messageCursor); + messageCursor = 0; + } + } else if (this.getTag() === MESSAGE_SET_MESSAGE_TAG && !messageCursor) { + if (typeId) { + messageCursor = -1; + this.readMessage(typeId, readerCallback); + } else { + // Save the cursor to read the message + // after we have the type ID. + messageCursor = this.getFieldCursor(); + this.skipDelimitedField(); + } + } else { + // Either we have already read the payload or this is not a valid + // messageset member. As a practical matter we don't have a place to + // store this unknown field and simply skipping is consistent with the + // Java and C++ impls + this.skipField(); + } + } - while (this.nextField() && (this.getFieldNumber() == field)) { - this.skipField(); + // If we do not have an end tag, if we did not have a message, or if we + // did not have a field number, drop out. + if (this.getTag() !== MESSAGE_SET_END_TAG || !messageCursor || !typeId) { + throw errors.malformedBinaryBytesForMessageSet(); + } } - if (!this.decoder_.atEnd()) { - this.unskipHeader(); + /** + * Reads a signed 32-bit integer field from the binary stream, or throws an + * error if the next field in the stream is not of the correct wire type. + * + * @return {number} The value of the signed 32-bit integer field. + */ + readInt32() { + asserts.assert(this.nextWireType_ == BinaryConstants.WireType.VARINT); + return BinaryDecoder.readSignedVarint32(this.decoder_); } -}; -/** - * Skips over the next varint field in the binary stream. - * @export - */ -jspb.BinaryReader.prototype.skipVarintField = function() { - if (this.nextWireType_ != jspb.BinaryConstants.WireType.VARINT) { - jspb.asserts.fail('Invalid wire type for skipVarintField'); - this.skipField(); - return; + /** + * Reads a signed 64-bit integer field from the binary stream, or throws an + * error if the next field in the stream is not of the correct wire type. + * + * @return {number} The value of the signed 64-bit integer field. + */ + readInt64() { + asserts.assert(this.nextWireType_ == BinaryConstants.WireType.VARINT); + return BinaryDecoder.readSignedVarint64(this.decoder_); } - this.decoder_.skipVarint(); -}; + + /** + * Reads a signed 64-bit integer field from the binary stream, or throws an + * error if the next field in the stream is not of the correct wire type. + * + * Returns the value as a string. + * + * @return {string} The value of the signed 64-bit integer field as a decimal + * string. + */ + readInt64String() { + asserts.assert(this.nextWireType_ == BinaryConstants.WireType.VARINT); + return BinaryDecoder.readSignedVarint64String(this.decoder_); + } -/** - * Skips over the next delimited field in the binary stream. - * @export - */ -jspb.BinaryReader.prototype.skipDelimitedField = function() { - if (this.nextWireType_ != jspb.BinaryConstants.WireType.DELIMITED) { - jspb.asserts.fail('Invalid wire type for skipDelimitedField'); - this.skipField(); - return; + /** + * Reads an unsigned 32-bit integer field from the binary stream, or throws an + * error if the next field in the stream is not of the correct wire type. + * + * @return {number} The value of the unsigned 32-bit integer field. + */ + readUint32() { + asserts.assert(this.nextWireType_ == BinaryConstants.WireType.VARINT); + return BinaryDecoder.readUnsignedVarint32(this.decoder_); } - var length = this.decoder_.readUnsignedVarint32(); - this.decoder_.advance(length); -}; + /** + * Reads an unsigned 64-bit integer field from the binary stream, or throws an + * error if the next field in the stream is not of the correct wire type. + * + * @return {number} The value of the unsigned 64-bit integer field. + */ + readUint64() { + asserts.assert(this.nextWireType_ == BinaryConstants.WireType.VARINT); + return BinaryDecoder.readUnsignedVarint64(this.decoder_); + } -/** - * Skips over the next fixed32 field in the binary stream. - * @export - */ -jspb.BinaryReader.prototype.skipFixed32Field = function() { - if (this.nextWireType_ != jspb.BinaryConstants.WireType.FIXED32) { - jspb.asserts.fail('Invalid wire type for skipFixed32Field'); - this.skipField(); - return; + /** + * Reads an unsigned 64-bit integer field from the binary stream, or throws an + * error if the next field in the stream is not of the correct wire type. + * + * Returns the value as a string. + * + * @return {string} The value of the unsigned 64-bit integer field as a + * decimal string. + */ + readUint64String() { + asserts.assert(this.nextWireType_ == BinaryConstants.WireType.VARINT); + return BinaryDecoder.readUnsignedVarint64String(this.decoder_); } - this.decoder_.advance(4); -}; + /** + * Reads a signed zigzag-encoded 32-bit integer field from the binary stream, + * or throws an error if the next field in the stream is not of the correct + * wire type. + * + * @return {number} The value of the signed 32-bit integer field. + */ + readSint32() { + asserts.assert(this.nextWireType_ == BinaryConstants.WireType.VARINT); + return BinaryDecoder.readZigzagVarint32(this.decoder_); + } -/** - * Skips over the next fixed64 field in the binary stream. - * @export - */ -jspb.BinaryReader.prototype.skipFixed64Field = function() { - if (this.nextWireType_ != jspb.BinaryConstants.WireType.FIXED64) { - jspb.asserts.fail('Invalid wire type for skipFixed64Field'); - this.skipField(); - return; + /** + * Reads a signed zigzag-encoded 64-bit integer field from the binary stream, + * or throws an error if the next field in the stream is not of the correct + * wire type. + * + * @return {number} The value of the signed 64-bit integer field. + */ + readSint64() { + asserts.assert(this.nextWireType_ == BinaryConstants.WireType.VARINT); + return BinaryDecoder.readZigzagVarint64(this.decoder_); } - this.decoder_.advance(8); -}; + /** + * Reads a signed zigzag-encoded 64-bit integer field from the binary stream, + * or throws an error if the next field in the stream is not of the correct + * wire type. + * + * @return {string} The value of the signed 64-bit integer field as a decimal + * string. + */ + readSint64String() { + asserts.assert(this.nextWireType_ == BinaryConstants.WireType.VARINT); + return BinaryDecoder.readZigzagVarint64String(this.decoder_); + } -/** - * Skips over the next group field in the binary stream. - * @export - */ -jspb.BinaryReader.prototype.skipGroup = function() { - var previousField = this.nextField_; - do { - if (!this.nextField()) { - jspb.asserts.fail('Unmatched start-group tag: stream EOF'); - this.error_ = true; - return; - } - if (this.nextWireType_ == jspb.BinaryConstants.WireType.END_GROUP) { - // Group end: check that it matches top-of-stack. - if (this.nextField_ != previousField) { - jspb.asserts.fail('Unmatched end-group tag'); - this.error_ = true; - return; - } - return; - } - this.skipField(); - } while (true); -}; + /** + * Reads an unsigned 32-bit fixed-length integer fiield from the binary + * stream, or throws an error if the next field in the stream is not of the + * correct wire type. + * + * @return {number} The value of the double field. + */ + readFixed32() { + asserts.assert(this.nextWireType_ == BinaryConstants.WireType.FIXED32); + return BinaryDecoder.readUint32(this.decoder_); + } -/** - * Skips over the next field in the binary stream - this is useful if we're - * decoding a message that contain unknown fields. - * @export - */ -jspb.BinaryReader.prototype.skipField = function() { - switch (this.nextWireType_) { - case jspb.BinaryConstants.WireType.VARINT: - this.skipVarintField(); - break; - case jspb.BinaryConstants.WireType.FIXED64: - this.skipFixed64Field(); - break; - case jspb.BinaryConstants.WireType.DELIMITED: - this.skipDelimitedField(); - break; - case jspb.BinaryConstants.WireType.FIXED32: - this.skipFixed32Field(); - break; - case jspb.BinaryConstants.WireType.START_GROUP: - this.skipGroup(); - break; - default: - jspb.asserts.fail('Invalid wire encoding for field.'); + /** + * Reads an unsigned 64-bit fixed-length integer fiield from the binary + * stream, or throws an error if the next field in the stream is not of the + * correct wire type. + * + * @return {number} The value of the float field. + */ + readFixed64() { + asserts.assert(this.nextWireType_ == BinaryConstants.WireType.FIXED64); + return BinaryDecoder.readUint64(this.decoder_); } -}; -/** - * Registers a user-defined read callback. - * @param {string} callbackName - * @param {function(!jspb.BinaryReader):*} callback - * @export - */ -jspb.BinaryReader.prototype.registerReadCallback = function( - callbackName, callback) { - if (this.readCallbacks_ === null) { - this.readCallbacks_ = {}; + /** + * Reads an unsigned 64-bit integer field from the binary stream as a string, + * or throws an error if the next field in the stream is not of the correct + * wire type. + * + * Returns the value as a string. + * + * @return {string} The value of the unsigned 64-bit integer field as a + * decimal string. + */ + readFixed64String() { + asserts.assert(this.nextWireType_ == BinaryConstants.WireType.FIXED64); + return BinaryDecoder.readUint64String(this.decoder_); } - jspb.asserts.assert(!this.readCallbacks_[callbackName]); - this.readCallbacks_[callbackName] = callback; -}; + /** + * Reads a signed 32-bit fixed-length integer fiield from the binary stream, + * or throws an error if the next field in the stream is not of the correct + * wire type. + * + * @return {number} The value of the signed 32-bit integer field. + */ + readSfixed32() { + asserts.assert(this.nextWireType_ == BinaryConstants.WireType.FIXED32); + return BinaryDecoder.readInt32(this.decoder_); + } -/** - * Runs a registered read callback. - * @param {string} callbackName The name the callback is registered under. - * @return {*} The value returned by the callback. - * @export - */ -jspb.BinaryReader.prototype.runReadCallback = function(callbackName) { - jspb.asserts.assert(this.readCallbacks_ !== null); - var callback = this.readCallbacks_[callbackName]; - jspb.asserts.assert(callback); - return callback(this); -}; - -/** - * Reads a field of any valid non-message type from the binary stream. - * @param {jspb.BinaryConstants.FieldType} fieldType - * @return {jspb.AnyFieldType} - */ -jspb.BinaryReader.prototype.readAny = function(fieldType) { - this.nextWireType_ = jspb.BinaryConstants.FieldTypeToWireType(fieldType); - var fieldTypes = jspb.BinaryConstants.FieldType; - switch (fieldType) { - case fieldTypes.DOUBLE: - return this.readDouble(); - case fieldTypes.FLOAT: - return this.readFloat(); - case fieldTypes.INT64: - return this.readInt64(); - case fieldTypes.UINT64: - return this.readUint64(); - case fieldTypes.INT32: - return this.readInt32(); - case fieldTypes.FIXED64: - return this.readFixed64(); - case fieldTypes.FIXED32: - return this.readFixed32(); - case fieldTypes.BOOL: - return this.readBool(); - case fieldTypes.STRING: - return this.readString(); - case fieldTypes.GROUP: - jspb.asserts.fail('Group field type not supported in readAny()'); - case fieldTypes.MESSAGE: - jspb.asserts.fail('Message field type not supported in readAny()'); - case fieldTypes.BYTES: - return this.readBytes(); - case fieldTypes.UINT32: - return this.readUint32(); - case fieldTypes.ENUM: - return this.readEnum(); - case fieldTypes.SFIXED32: - return this.readSfixed32(); - case fieldTypes.SFIXED64: - return this.readSfixed64(); - case fieldTypes.SINT32: - return this.readSint32(); - case fieldTypes.SINT64: - return this.readSint64(); - case fieldTypes.FHASH64: - return this.readFixedHash64(); - case fieldTypes.VHASH64: - return this.readVarintHash64(); - default: - jspb.asserts.fail('Invalid field type in readAny()'); - } - return 0; -}; - - -/** - * Deserialize a proto into the provided message object using the provided - * reader function. This function is templated as we currently have one client - * who is using manual deserialization instead of the code-generated versions. - * @template T - * @param {T} message - * @param {function(T, !jspb.BinaryReader)} reader - * @export - */ -jspb.BinaryReader.prototype.readMessage = function(message, reader) { - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED); - - // Save the current endpoint of the decoder and move it to the end of the - // embedded message. - var oldEnd = this.decoder_.getEnd(); - var length = this.decoder_.readUnsignedVarint32(); - var newEnd = this.decoder_.getCursor() + length; - this.decoder_.setEnd(newEnd); - - // Deserialize the embedded message. - reader(message, this); - - // Advance the decoder past the embedded message and restore the endpoint. - this.decoder_.setCursor(newEnd); - this.decoder_.setEnd(oldEnd); -}; + /** + * Reads a signed 32-bit fixed-length integer fiield from the binary stream, + * or throws an error if the next field in the stream is not of the correct + * wire type. + * + * @return {string} The value of the signed 32-bit integer field as a decimal + * string. + */ + readSfixed32String() { + asserts.assert(this.nextWireType_ == BinaryConstants.WireType.FIXED32); + return BinaryDecoder.readInt32(this.decoder_).toString(); + } -/** - * Deserialize a proto into the provided message object using the provided - * reader function, assuming that the message is serialized as a group - * with the given tag. - * @template T - * @param {number} field - * @param {T} message - * @param {function(T, !jspb.BinaryReader)} reader - * @export - */ -jspb.BinaryReader.prototype.readGroup = function(field, message, reader) { - // Ensure that the wire type is correct. - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.START_GROUP); - // Ensure that the field number is correct. - jspb.asserts.assert(this.nextField_ == field); - - // Deserialize the message. The deserialization will stop at an END_GROUP tag. - reader(message, this); - - if (!this.error_ && - this.nextWireType_ != jspb.BinaryConstants.WireType.END_GROUP) { - jspb.asserts.fail('Group submessage did not end with an END_GROUP tag'); - this.error_ = true; + /** + * Reads a signed 64-bit fixed-length integer fiield from the binary stream, + * or throws an error if the next field in the stream is not of the correct + * wire type. + * + * @return {number} The value of the sfixed64 field. + */ + readSfixed64() { + asserts.assert(this.nextWireType_ == BinaryConstants.WireType.FIXED64); + return BinaryDecoder.readInt64(this.decoder_); } -}; - - -/** - * Return a decoder that wraps the current delimited field. - * @return {!jspb.BinaryDecoder} - * @export - */ -jspb.BinaryReader.prototype.getFieldDecoder = function() { - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED); - - var length = this.decoder_.readUnsignedVarint32(); - var start = this.decoder_.getCursor(); - var end = start + length; - - var innerDecoder = - jspb.BinaryDecoder.alloc(this.decoder_.getBuffer(), start, length); - this.decoder_.setCursor(end); - return innerDecoder; -}; - - -/** - * Reads a signed 32-bit integer field from the binary stream, or throws an - * error if the next field in the stream is not of the correct wire type. - * - * @return {number} The value of the signed 32-bit integer field. - * @export - */ -jspb.BinaryReader.prototype.readInt32 = function() { - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); - return this.decoder_.readSignedVarint32(); -}; - - -/** - * Reads a signed 32-bit integer field from the binary stream, or throws an - * error if the next field in the stream is not of the correct wire type. - * - * Returns the value as a string. - * - * @return {string} The value of the signed 32-bit integer field as a decimal - * string. - * @export - */ -jspb.BinaryReader.prototype.readInt32String = function() { - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); - return this.decoder_.readSignedVarint32String(); -}; - - -/** - * Reads a signed 64-bit integer field from the binary stream, or throws an - * error if the next field in the stream is not of the correct wire type. - * - * @return {number} The value of the signed 64-bit integer field. - * @export - */ -jspb.BinaryReader.prototype.readInt64 = function() { - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); - return this.decoder_.readSignedVarint64(); -}; - - -/** - * Reads a signed 64-bit integer field from the binary stream, or throws an - * error if the next field in the stream is not of the correct wire type. - * - * Returns the value as a string. - * - * @return {string} The value of the signed 64-bit integer field as a decimal - * string. - * @export - */ -jspb.BinaryReader.prototype.readInt64String = function() { - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); - return this.decoder_.readSignedVarint64String(); -}; - - -/** - * Reads an unsigned 32-bit integer field from the binary stream, or throws an - * error if the next field in the stream is not of the correct wire type. - * - * @return {number} The value of the unsigned 32-bit integer field. - * @export - */ -jspb.BinaryReader.prototype.readUint32 = function() { - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); - return this.decoder_.readUnsignedVarint32(); -}; - - -/** - * Reads an unsigned 32-bit integer field from the binary stream, or throws an - * error if the next field in the stream is not of the correct wire type. - * - * Returns the value as a string. - * - * @return {string} The value of the unsigned 32-bit integer field as a decimal - * string. - * @export - */ -jspb.BinaryReader.prototype.readUint32String = function() { - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); - return this.decoder_.readUnsignedVarint32String(); -}; - - -/** - * Reads an unsigned 64-bit integer field from the binary stream, or throws an - * error if the next field in the stream is not of the correct wire type. - * - * @return {number} The value of the unsigned 64-bit integer field. - * @export - */ -jspb.BinaryReader.prototype.readUint64 = function() { - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); - return this.decoder_.readUnsignedVarint64(); -}; - - -/** - * Reads an unsigned 64-bit integer field from the binary stream, or throws an - * error if the next field in the stream is not of the correct wire type. - * - * Returns the value as a string. - * - * @return {string} The value of the unsigned 64-bit integer field as a decimal - * string. - * @export - */ -jspb.BinaryReader.prototype.readUint64String = function() { - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); - return this.decoder_.readUnsignedVarint64String(); -}; - - -/** - * Reads a signed zigzag-encoded 32-bit integer field from the binary stream, - * or throws an error if the next field in the stream is not of the correct - * wire type. - * - * @return {number} The value of the signed 32-bit integer field. - * @export - */ -jspb.BinaryReader.prototype.readSint32 = function() { - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); - return this.decoder_.readZigzagVarint32(); -}; - - -/** - * Reads a signed zigzag-encoded 64-bit integer field from the binary stream, - * or throws an error if the next field in the stream is not of the correct - * wire type. - * - * @return {number} The value of the signed 64-bit integer field. - * @export - */ -jspb.BinaryReader.prototype.readSint64 = function() { - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); - return this.decoder_.readZigzagVarint64(); -}; - - -/** - * Reads a signed zigzag-encoded 64-bit integer field from the binary stream, - * or throws an error if the next field in the stream is not of the correct - * wire type. - * - * @return {string} The value of the signed 64-bit integer field as a decimal - * string. - * @export - */ -jspb.BinaryReader.prototype.readSint64String = function() { - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); - return this.decoder_.readZigzagVarint64String(); -}; - - -/** - * Reads an unsigned 32-bit fixed-length integer fiield from the binary stream, - * or throws an error if the next field in the stream is not of the correct - * wire type. - * - * @return {number} The value of the double field. - * @export - */ -jspb.BinaryReader.prototype.readFixed32 = function() { - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED32); - return this.decoder_.readUint32(); -}; - - -/** - * Reads an unsigned 64-bit fixed-length integer fiield from the binary stream, - * or throws an error if the next field in the stream is not of the correct - * wire type. - * - * @return {number} The value of the float field. - * @export - */ -jspb.BinaryReader.prototype.readFixed64 = function() { - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64); - return this.decoder_.readUint64(); -}; - - -/** - * Reads a signed 64-bit integer field from the binary stream as a string, or - * throws an error if the next field in the stream is not of the correct wire - * type. - * - * Returns the value as a string. - * - * @return {string} The value of the unsigned 64-bit integer field as a decimal - * string. - * @export - */ -jspb.BinaryReader.prototype.readFixed64String = function() { - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64); - return this.decoder_.readUint64String(); -}; - - -/** - * Reads a signed 32-bit fixed-length integer fiield from the binary stream, or - * throws an error if the next field in the stream is not of the correct wire - * type. - * - * @return {number} The value of the signed 32-bit integer field. - * @export - */ -jspb.BinaryReader.prototype.readSfixed32 = function() { - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED32); - return this.decoder_.readInt32(); -}; - - -/** - * Reads a signed 32-bit fixed-length integer fiield from the binary stream, or - * throws an error if the next field in the stream is not of the correct wire - * type. - * - * @return {string} The value of the signed 32-bit integer field as a decimal - * string. - * @export - */ -jspb.BinaryReader.prototype.readSfixed32String = function() { - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED32); - return this.decoder_.readInt32().toString(); -}; - - -/** - * Reads a signed 64-bit fixed-length integer fiield from the binary stream, or - * throws an error if the next field in the stream is not of the correct wire - * type. - * - * @return {number} The value of the sfixed64 field. - * @export - */ -jspb.BinaryReader.prototype.readSfixed64 = function() { - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64); - return this.decoder_.readInt64(); -}; - - -/** - * Reads a signed 64-bit fixed-length integer fiield from the binary stream, or - * throws an error if the next field in the stream is not of the correct wire - * type. - * - * Returns the value as a string. - * - * @return {string} The value of the sfixed64 field as a decimal string. - * @export - */ -jspb.BinaryReader.prototype.readSfixed64String = function() { - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64); - return this.decoder_.readInt64String(); -}; - - -/** - * Reads a 32-bit floating-point field from the binary stream, or throws an - * error if the next field in the stream is not of the correct wire type. - * - * @return {number} The value of the float field. - * @export - */ -jspb.BinaryReader.prototype.readFloat = function() { - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED32); - return this.decoder_.readFloat(); -}; - - -/** - * Reads a 64-bit floating-point field from the binary stream, or throws an - * error if the next field in the stream is not of the correct wire type. - * - * @return {number} The value of the double field. - * @export - */ -jspb.BinaryReader.prototype.readDouble = function() { - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64); - return this.decoder_.readDouble(); -}; -/** - * Reads a boolean field from the binary stream, or throws an error if the next - * field in the stream is not of the correct wire type. - * - * @return {boolean} The value of the boolean field. - * @export - */ -jspb.BinaryReader.prototype.readBool = function() { - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); - return !!this.decoder_.readUnsignedVarint32(); -}; - - -/** - * Reads an enum field from the binary stream, or throws an error if the next - * field in the stream is not of the correct wire type. - * - * @return {number} The value of the enum field. - * @export - */ -jspb.BinaryReader.prototype.readEnum = function() { - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); - return this.decoder_.readSignedVarint64(); -}; - - -/** - * Reads a string field from the binary stream, or throws an error if the next - * field in the stream is not of the correct wire type. - * - * @return {string} The value of the string field. - * @export - */ -jspb.BinaryReader.prototype.readString = function() { - // delegate to the other reader so that inlining can eliminate this method - // in the common case. - if (UTF8_PARSING_ERRORS_ARE_FATAL) { - return this.readStringRequireUtf8(); + /** + * Reads a signed 64-bit fixed-length integer field from the binary stream, + * or throws an error if the next field in the stream is not of the correct + * wire type. + * + * Returns the value as a string. + * + * @return {string} The value of the sfixed64 field as a decimal string. + */ + readSfixed64String() { + asserts.assert(this.nextWireType_ == BinaryConstants.WireType.FIXED64); + return BinaryDecoder.readInt64String(this.decoder_); } - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED); - var length = this.decoder_.readUnsignedVarint32(); - return this.decoder_.readString(length, /*requireUtf8=*/ false); -}; - -/** - * Reads a string field from the binary stream, or throws an error if the next - * field in the stream is not of the correct wire type, or if the string is - * not valid utf8. - * - * @return {string} The value of the string field. - */ -jspb.BinaryReader.prototype.readStringRequireUtf8 = function () { - jspb.asserts.assert(this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED); - const length = this.decoder_.readUnsignedVarint32(); - return this.decoder_.readString(length, /*requireUtf8=*/ true); -}; - - -/** - * Reads a length-prefixed block of bytes from the binary stream, or returns - * null if the next field in the stream has an invalid length value. - * - * @return {!Uint8Array} The block of bytes. - * @export - */ -jspb.BinaryReader.prototype.readBytes = function() { - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED); - var length = this.decoder_.readUnsignedVarint32(); - return this.decoder_.readBytes(length); -}; - - -/** - * Reads a 64-bit varint or fixed64 field from the stream and returns it as an - * 8-character Unicode string for use as a hash table key, or throws an error - * if the next field in the stream is not of the correct wire type. - * - * @return {string} The hash value. - * @export - */ -jspb.BinaryReader.prototype.readVarintHash64 = function() { - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); - return this.decoder_.readVarintHash64(); -}; - - -/** - * Reads an sint64 field from the stream and returns it as an 8-character - * Unicode string for use as a hash table key, or throws an error if the next - * field in the stream is not of the correct wire type. - * - * @return {string} The hash value. - * @export - */ -jspb.BinaryReader.prototype.readSintHash64 = function() { - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); - return this.decoder_.readZigzagVarintHash64(); -}; + /** + * Reads a 32-bit floating-point field from the binary stream, or throws an + * error if the next field in the stream is not of the correct wire type. + * + * @return {number} The value of the float field. + */ + readFloat() { + asserts.assert(this.nextWireType_ == BinaryConstants.WireType.FIXED32); + return BinaryDecoder.readFloat(this.decoder_); + } -/** - * Reads a 64-bit varint field from the stream and invokes `convert` to produce - * the return value, or throws an error if the next field in the stream is not - * of the correct wire type. - * - * @param {function(number, number): T} convert Conversion function to produce - * the result value, takes parameters (lowBits, highBits). - * @return {T} - * @template T - * @export - */ -jspb.BinaryReader.prototype.readSplitVarint64 = function(convert) { - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); - return this.decoder_.readSplitVarint64(convert); -}; + /** + * Reads a 64-bit floating-point field from the binary stream, or throws an + * error if the next field in the stream is not of the correct wire type. + * + * @return {number} The value of the double field. + */ + readDouble() { + asserts.assert(this.nextWireType_ == BinaryConstants.WireType.FIXED64); + return BinaryDecoder.readDouble(this.decoder_); + } -/** - * Reads a 64-bit zig-zag varint field from the stream and invokes `convert` to - * produce the return value, or throws an error if the next field in the stream - * is not of the correct wire type. - * - * @param {function(number, number): T} convert Conversion function to produce - * the result value, takes parameters (lowBits, highBits). - * @return {T} - * @template T - * @export - */ -jspb.BinaryReader.prototype.readSplitZigzagVarint64 = function(convert) { - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); - return this.decoder_.readSplitVarint64(function(lowBits, highBits) { - return jspb.utils.fromZigzag64(lowBits, highBits, convert); - }); -}; + /** + * Reads a boolean field from the binary stream, or throws an error if the + * next field in the stream is not of the correct wire type. + * + * @return {boolean} The value of the boolean field. + */ + readBool() { + asserts.assert(this.nextWireType_ == BinaryConstants.WireType.VARINT); + return BinaryDecoder.readBool(this.decoder_); + } -/** - * Reads a 64-bit varint or fixed64 field from the stream and returns it as a - * 8-character Unicode string for use as a hash table key, or throws an error - * if the next field in the stream is not of the correct wire type. - * - * @return {string} The hash value. - * @export - */ -jspb.BinaryReader.prototype.readFixedHash64 = function() { - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64); - return this.decoder_.readFixedHash64(); -}; + /** + * Reads an enum field from the binary stream, or throws an error if the next + * field in the stream is not of the correct wire type. + * + * @return {number} The value of the enum field. + */ + readEnum() { + asserts.assert(this.nextWireType_ == BinaryConstants.WireType.VARINT); + return BinaryDecoder.readSignedVarint32(this.decoder_); + } -/** - * Reads a 64-bit fixed64 field from the stream and invokes `convert` - * to produce the return value, or throws an error if the next field in the - * stream is not of the correct wire type. - * - * @param {function(number, number): T} convert Conversion function to produce - * the result value, takes parameters (lowBits, highBits). - * @return {T} - * @template T - * @export - */ -jspb.BinaryReader.prototype.readSplitFixed64 = function(convert) { - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64); - return this.decoder_.readSplitFixed64(convert); -}; + /** + * Reads a string field from the binary stream, or throws an error if the next + * field in the stream is not of the correct wire type. + * + * @return {string} The value of the string field. + */ + readString() { + // delegate to the other reader so that inlining can eliminate this method + // in the common case. + if (UTF8_PARSING_ERRORS_ARE_FATAL) { + return this.readStringRequireUtf8(); + } + asserts.assert(this.nextWireType_ == BinaryConstants.WireType.DELIMITED); + const length = BinaryDecoder.readUnsignedVarint32(this.decoder_); + return this.decoder_.readString(length, /*parsingErrorsAreFatal=*/ false); + } + /** + * Reads a string field from the binary stream, or throws an error if the next + * field in the stream is not of the correct wire type, or if the string is + * not valid utf8. + * + * @return {string} The value of the string field. + */ + readStringRequireUtf8() { + asserts.assert(this.nextWireType_ == BinaryConstants.WireType.DELIMITED); + const length = BinaryDecoder.readUnsignedVarint32(this.decoder_); + return this.decoder_.readString(length, /*parsingErrorsAreFatal=*/ true); + } -/** - * Reads a packed scalar field using the supplied raw reader function. - * @param {function(this:jspb.BinaryDecoder)} decodeMethod - * @return {!Array} - * @private - */ -jspb.BinaryReader.prototype.readPackedField_ = function(decodeMethod) { - jspb.asserts.assert( - this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED); - var length = this.decoder_.readUnsignedVarint32(); - var end = this.decoder_.getCursor() + length; - var result = []; - while (this.decoder_.getCursor() < end) { - // TODO(aappleby): .call is slow - result.push(decodeMethod.call(this.decoder_)); - } - return result; -}; + /** + * Reads a length-prefixed block of bytes from the binary stream, or returns + * null if the next field in the stream has an invalid length value. + * + * @return {!Uint8Array} The block of bytes. + */ + readBytes() { + asserts.assert(this.nextWireType_ == BinaryConstants.WireType.DELIMITED); + const length = BinaryDecoder.readUnsignedVarint32(this.decoder_); + return this.decoder_.readBytes(length); + } + /** + * Reads a length-prefixed block of bytes from the binary stream, or returns + * null if the next field in the stream has an invalid length value. + * + * @return {!ByteString} The block of bytes. + */ + readByteString() { + asserts.assert(this.nextWireType_ == BinaryConstants.WireType.DELIMITED); + const length = BinaryDecoder.readUnsignedVarint32(this.decoder_); + return this.decoder_.readByteString(length); + } -/** - * Reads a packed int32 field, which consists of a length header and a list of - * signed varints. - * @return {!Array} - * @export - */ -jspb.BinaryReader.prototype.readPackedInt32 = function() { - return this.readPackedField_(this.decoder_.readSignedVarint32); -}; + /** + * Reads a 64-bit varint field from the stream and invokes `convert` to + * produce the return value, or throws an error if the next field in the + * stream is not of the correct wire type. + * + * @param {function(number, number): T} convert Conversion function to produce + * the result value, takes parameters (lowBits, highBits). + * @return {T} + * @template T + */ + readSplitVarint64(convert) { + asserts.assert(this.nextWireType_ == BinaryConstants.WireType.VARINT); + return BinaryDecoder.readSplitVarint64(this.decoder_, convert); + } -/** - * Reads a packed int32 field, which consists of a length header and a list of - * signed varints. Returns a list of strings. - * @return {!Array} - * @export - */ -jspb.BinaryReader.prototype.readPackedInt32String = function() { - return this.readPackedField_(this.decoder_.readSignedVarint32String); -}; + /** + * Reads a 64-bit zig-zag varint field from the stream and invokes `convert` + * to produce the return value, or throws an error if the next field in the + * stream is not of the correct wire type. + * + * @param {function(number, number): T} convert Conversion function to produce + * the result value, takes parameters (lowBits, highBits). + * @return {T} + * @template T + */ + readSplitZigzagVarint64(convert) { + asserts.assert(this.nextWireType_ == BinaryConstants.WireType.VARINT); + return BinaryDecoder.readSplitVarint64( + this.decoder_, + (lowBits, highBits) => utils.fromZigzag64(lowBits, highBits, convert)); + } -/** - * Reads a packed int64 field, which consists of a length header and a list of - * signed varints. - * @return {!Array} - * @export - */ -jspb.BinaryReader.prototype.readPackedInt64 = function() { - return this.readPackedField_(this.decoder_.readSignedVarint64); -}; + /** + * Reads a 64-bit fixed64 field from the stream and invokes `convert` + * to produce the return value, or throws an error if the next field in the + * stream is not of the correct wire type. + * + * @param {function(number, number): T} convert Conversion function to produce + * the result value, takes parameters (lowBits, highBits). + * @return {T} + * @template T + */ + readSplitFixed64(convert) { + asserts.assert(this.nextWireType_ == BinaryConstants.WireType.FIXED64); + return BinaryDecoder.readSplitFixed64(this.decoder_, convert); + } -/** - * Reads a packed int64 field, which consists of a length header and a list of - * signed varints. Returns a list of strings. - * @return {!Array} - * @export - */ -jspb.BinaryReader.prototype.readPackedInt64String = function() { - return this.readPackedField_(this.decoder_.readSignedVarint64String); -}; + /** + * Reads a packed scalar field using the supplied raw reader function. + * @param {function(!BinaryDecoder):T} decodeMethod + * @param {!Array} dst + * @template T + * @private + */ + readPackedFieldInto_(decodeMethod, dst) { + const length = this.readPackedFieldLength_(); + const end = this.decoder_.getCursor() + length; + while (this.decoder_.getCursor() < end) { + dst.push(decodeMethod(this.decoder_)); + } + } + /** + * Reads the length of a packed field. + * @return {number} + * @private + */ + readPackedFieldLength_() { + asserts.assert(this.nextWireType_ == BinaryConstants.WireType.DELIMITED); + return BinaryDecoder.readUnsignedVarint32(this.decoder_); + } -/** - * Reads a packed uint32 field, which consists of a length header and a list of - * unsigned varints. - * @return {!Array} - * @export - */ -jspb.BinaryReader.prototype.readPackedUint32 = function() { - return this.readPackedField_(this.decoder_.readUnsignedVarint32); -}; + /** + * Reads an int32 field that might be packed + * @param {!Array} dst + */ + readPackableInt32Into(dst) { + if (this.isDelimited()) { + this.readPackedFieldInto_(BinaryDecoder.readSignedVarint32, dst); + } else { + dst.push(this.readInt32()); + } + } + /** + * Reads an int64 field that might be packed + * @param {!Array}dst + */ + readPackableInt64Into(dst) { + if (this.isDelimited()) { + this.readPackedFieldInto_(BinaryDecoder.readSignedVarint64, dst); + } else { + dst.push(this.readInt64()); + } + } -/** - * Reads a packed uint32 field, which consists of a length header and a list of - * unsigned varints. Returns a list of strings. - * @return {!Array} - * @export - */ -jspb.BinaryReader.prototype.readPackedUint32String = function() { - return this.readPackedField_(this.decoder_.readUnsignedVarint32String); -}; + /** + * Reads an int64 field that might be packed + * @param {!Array} dst + */ + readPackableInt64StringInto(dst) { + if (this.isDelimited()) { + this.readPackedFieldInto_(BinaryDecoder.readSignedVarint64String, dst); + } else { + dst.push(this.readInt64String()); + } + } + /** + * Reads an int32 field that might be packed + * @param {!Array} dst + */ + readPackableUint32Into(dst) { + if (this.isDelimited()) { + this.readPackedFieldInto_(BinaryDecoder.readUnsignedVarint32, dst); + } else { + dst.push(this.readUint32()); + } + } -/** - * Reads a packed uint64 field, which consists of a length header and a list of - * unsigned varints. - * @return {!Array} - * @export - */ -jspb.BinaryReader.prototype.readPackedUint64 = function() { - return this.readPackedField_(this.decoder_.readUnsignedVarint64); -}; + /** + * Reads an uint64 field that might be packed + * @param {!Array} dst + */ + readPackableUint64Into(dst) { + if (this.isDelimited()) { + this.readPackedFieldInto_(BinaryDecoder.readUnsignedVarint64, dst); + } else { + dst.push(this.readUint64()); + } + } + /** + * Reads an uint64 field that might be packed + * @param {!Array} dst + */ + readPackableUint64StringInto(dst) { + if (this.isDelimited()) { + this.readPackedFieldInto_(BinaryDecoder.readUnsignedVarint64String, dst); + } else { + dst.push(this.readUint64String()); + } + } -/** - * Reads a packed uint64 field, which consists of a length header and a list of - * unsigned varints. Returns a list of strings. - * @return {!Array} - * @export - */ -jspb.BinaryReader.prototype.readPackedUint64String = function() { - return this.readPackedField_(this.decoder_.readUnsignedVarint64String); -}; + /** + * Reads a possibly packed sint32 field, + * @param {!Array} dst + */ + readPackableSint32Into(dst) { + if (this.isDelimited()) { + this.readPackedFieldInto_(BinaryDecoder.readZigzagVarint32, dst); + } else { + dst.push(this.readSint32()); + } + } + /** + * Reads a possibly packed sint64 field, + * @param {!Array} dst + */ + readPackableSint64Into(dst) { + if (this.isDelimited()) { + this.readPackedFieldInto_(BinaryDecoder.readZigzagVarint64, dst); + } else { + dst.push(this.readSint64()); + } + } -/** - * Reads a packed sint32 field, which consists of a length header and a list of - * zigzag varints. - * @return {!Array} - * @export - */ -jspb.BinaryReader.prototype.readPackedSint32 = function() { - return this.readPackedField_(this.decoder_.readZigzagVarint32); -}; + /** + * Reads a possibly packed sint64 field as an array of strings. + * @param {!Array} dst + */ + readPackableSint64StringInto(dst) { + if (this.isDelimited()) { + this.readPackedFieldInto_(BinaryDecoder.readZigzagVarint64String, dst); + } else { + dst.push(this.readSint64String()); + } + } + /** + * Reads a possibly packed fixed32 field. + * @param {!Array} dst + */ + readPackableFixed32Into(dst) { + if (this.isDelimited()) { + this.readPackedFieldInto_(BinaryDecoder.readUint32, dst); + } else { + dst.push(this.readFixed32()); + } + } -/** - * Reads a packed sint64 field, which consists of a length header and a list of - * zigzag varints. - * @return {!Array} - * @export - */ -jspb.BinaryReader.prototype.readPackedSint64 = function() { - return this.readPackedField_(this.decoder_.readZigzagVarint64); -}; + /** + * Reads a possibly packed fixed64 field. + * @param {!Array} dst + */ + readPackableFixed64Into(dst) { + if (this.isDelimited()) { + this.readPackedFieldInto_(BinaryDecoder.readUint64, dst); + } else { + dst.push(this.readFixed64()); + } + } + /** + * Reads a possibly packed fixed64 field as an array fo strings + * @param {!Array} dst + */ + readPackableFixed64StringInto(dst) { + if (this.isDelimited()) { + this.readPackedFieldInto_(BinaryDecoder.readUint64String, dst); + } else { + dst.push(this.readFixed64String()); + } + } -/** - * Reads a packed sint64 field, which consists of a length header and a list of - * zigzag varints. Returns a list of strings. - * @return {!Array} - * @export - */ -jspb.BinaryReader.prototype.readPackedSint64String = function() { - return this.readPackedField_(this.decoder_.readZigzagVarint64String); -}; + /** + * Reads a possibly packed sfixed32 + * @param {!Array} dst + */ + readPackableSfixed32Into(dst) { + if (this.isDelimited()) { + this.readPackedFieldInto_(BinaryDecoder.readInt32, dst); + } else { + dst.push(this.readSfixed32()); + } + } + /** + * Reads a possibly packed sfixed64 field. + * @param {!Array} dst + */ + readPackableSfixed64Into(dst) { + if (this.isDelimited()) { + this.readPackedFieldInto_(BinaryDecoder.readInt64, dst); + } else { + dst.push(this.readSfixed64()); + } + } -/** - * Reads a packed fixed32 field, which consists of a length header and a list - * of unsigned 32-bit ints. - * @return {!Array} - * @export - */ -jspb.BinaryReader.prototype.readPackedFixed32 = function() { - return this.readPackedField_(this.decoder_.readUint32); -}; + /** + * Reads a possibly packed sfixed64 field as an array of strings + * @param {!Array} dst + */ + readPackableSfixed64StringInto(dst) { + if (this.isDelimited()) { + this.readPackedFieldInto_(BinaryDecoder.readInt64String, dst); + } else { + dst.push(this.readSfixed64String()); + } + } + /** + * Reads a packed fixed32 field, which consists of a length header and a list + * of unsigned 32-bit ints. + * @return {!Array} + * @export + */ + readPackedFixed32() { + const values = []; + this.readPackableFixed32Into(values); + return values; + } -/** - * Reads a packed fixed64 field, which consists of a length header and a list - * of unsigned 64-bit ints. - * @return {!Array} - * @export - */ -jspb.BinaryReader.prototype.readPackedFixed64 = function() { - return this.readPackedField_(this.decoder_.readUint64); -}; + /** + * Reads a packed fixed64 field, which consists of a length header and a list + * of unsigned 64-bit ints. + * @return {!Array} + * @export + */ + readPackedFixed64() { + const values = []; + this.readPackableFixed64Into(values); + return values; + } -/** - * Reads a packed fixed64 field, which consists of a length header and a list - * of unsigned 64-bit ints. Returns a list of strings. - * @return {!Array} - * @export - */ -jspb.BinaryReader.prototype.readPackedFixed64String = function() { - return this.readPackedField_(this.decoder_.readUint64String); -}; + /** + * Reads a packed fixed64 field, which consists of a length header and a list + * of unsigned 64-bit ints. Returns a list of strings. + * @return {!Array} + * @export + */ + readPackedFixed64String() { + const values = []; + this.readPackableFixed64StringInto(values); + return values; + } -/** - * Reads a packed sfixed32 field, which consists of a length header and a list - * of 32-bit ints. - * @return {!Array} - * @export - */ -jspb.BinaryReader.prototype.readPackedSfixed32 = function() { - return this.readPackedField_(this.decoder_.readInt32); -}; + /** + * Reads a packed sfixed32 field, which consists of a length header and a list + * of 32-bit ints. + * @return {!Array} + * @export + */ + readPackedSfixed32() { + const values = []; + this.readPackableSfixed32Into(values); + return values; + } -/** - * Reads a packed sfixed64 field, which consists of a length header and a list - * of 64-bit ints. - * @return {!Array} - * @export - */ -jspb.BinaryReader.prototype.readPackedSfixed64 = function() { - return this.readPackedField_(this.decoder_.readInt64); -}; + /** + * Reads a packed sfixed64 field, which consists of a length header and a list + * of 64-bit ints. Returns a list of strings. + * @return {!Array} + * @export + */ + readPackedSfixed64String() { + const values = []; + this.readPackableSfixed64StringInto(values); + return values; + } -/** - * Reads a packed sfixed64 field, which consists of a length header and a list - * of 64-bit ints. Returns a list of strings. - * @return {!Array} - * @export - */ -jspb.BinaryReader.prototype.readPackedSfixed64String = function() { - return this.readPackedField_(this.decoder_.readInt64String); -}; + /** + * Reads a possibly packed float field + * @param {!Array} dst + */ + readPackableFloatInto(dst) { + if (this.isDelimited()) { + this.readPackedFieldInto_(BinaryDecoder.readFloat, dst); + } else { + dst.push(this.readFloat()); + } + } -/** - * Reads a packed float field, which consists of a length header and a list of - * floats. - * @return {!Array} - * @export - */ -jspb.BinaryReader.prototype.readPackedFloat = function() { - return this.readPackedField_(this.decoder_.readFloat); -}; + /** + * Reads a possibly packed double field and appends it to `dst`. + * @param {!Array} dst + */ + readPackableDoubleInto(dst) { + if (this.isDelimited()) { + this.decoder_.readDoubleArrayInto(this.readPackedFieldLength_() / 8, dst); + } else { + dst.push(this.readDouble()); + } + } + /** + * Reads a possibly packed bool field + * @param {!Array} dst + */ + readPackableBoolInto(dst) { + if (this.isDelimited()) { + this.readPackedFieldInto_(BinaryDecoder.readBool, dst); + } else { + dst.push(this.readBool()); + } + } -/** - * Reads a packed double field, which consists of a length header and a list of - * doubles. - * @return {!Array} - * @export - */ -jspb.BinaryReader.prototype.readPackedDouble = function() { - return this.readPackedField_(this.decoder_.readDouble); -}; + /** + * Reads a possibly packed enum field + * @param {!Array} dst + */ + readPackableEnumInto(dst) { + if (this.isDelimited()) { + this.readPackedFieldInto_(BinaryDecoder.readEnum, dst); + } else { + dst.push(this.readEnum()); + } + } -/** - * Reads a packed bool field, which consists of a length header and a list of - * unsigned varints. - * @return {!Array} - * @export - */ -jspb.BinaryReader.prototype.readPackedBool = function() { - return this.readPackedField_(this.decoder_.readBool); -}; + /** + * Visible for testing. + * @package + */ + static resetInstanceCache() { + BinaryReader.instanceCache_ = []; + } + /** + * Visible for testing. + * @return {!Array} + * @package + */ + static getInstanceCache() { + return BinaryReader.instanceCache_; + } +} /** - * Reads a packed enum field, which consists of a length header and a list of - * unsigned varints. - * @return {!Array} - * @export + * @param {number} tag + * @return {!BinaryConstants.WireType} */ -jspb.BinaryReader.prototype.readPackedEnum = function() { - return this.readPackedField_(this.decoder_.readEnum); -}; - +function parseWireType(tag) { + return /** @type {!BinaryConstants.WireType} */ (tag & 0x7); +} /** - * Reads a packed varint hash64 field, which consists of a length header and a - * list of varint hash64s. - * @return {!Array} - * @export + * @param {number} tag + * @return {number} */ -jspb.BinaryReader.prototype.readPackedVarintHash64 = function() { - return this.readPackedField_(this.decoder_.readVarintHash64); -}; - +function parseFieldNumber(tag) { + return tag >>> 3; +} /** - * Reads a packed fixed hash64 field, which consists of a length header and a - * list of fixed hash64s. - * @return {!Array} - * @export - */ -jspb.BinaryReader.prototype.readPackedFixedHash64 = function() { - return this.readPackedField_(this.decoder_.readFixedHash64); + * Global pool of BinaryReader instances. + * @private {!Array} + */ +BinaryReader.instanceCache_ = []; + +const /** number */ MESSAGE_SET_START_GROUP_TAG = utils.makeTag( + BinaryConstants.MESSAGE_SET_GROUP_NUMBER, + BinaryConstants.WireType.START_GROUP); +const /** number */ MESSAGE_SET_TYPE_ID_TAG = utils.makeTag( + BinaryConstants.MESSAGE_SET_TYPE_ID_FIELD_NUMBER, + BinaryConstants.WireType.VARINT); +const /** number */ MESSAGE_SET_MESSAGE_TAG = utils.makeTag( + BinaryConstants.MESSAGE_SET_MESSAGE_FIELD_NUMBER, + BinaryConstants.WireType.DELIMITED); +const /** number */ MESSAGE_SET_END_TAG = utils.makeTag( + BinaryConstants.MESSAGE_SET_GROUP_NUMBER, + BinaryConstants.WireType.END_GROUP); + +exports = { + BinaryReader, + BinaryReaderOptions, + UTF8_PARSING_ERRORS_ARE_FATAL, }; diff --git a/binary/reader_alias.js b/binary/reader_alias.js new file mode 100755 index 0000000..c19d104 --- /dev/null +++ b/binary/reader_alias.js @@ -0,0 +1,9 @@ +/** + * @fileoverview Legacy alias for the old namespace used by reader.js + */ +goog.module('jspb.BinaryReader'); +goog.module.declareLegacyNamespace(); + +const {BinaryReader} = goog.require('jspb.binary.reader'); + +exports = BinaryReader; diff --git a/binary/reader_test.js b/binary/reader_test.js old mode 100644 new mode 100755 index fcb32e2..5df6235 --- a/binary/reader_test.js +++ b/binary/reader_test.js @@ -42,82 +42,193 @@ */ goog.require('jspb.BinaryConstants'); -goog.require('jspb.BinaryDecoder'); +goog.require('jspb.binary.decoder'); +goog.require('jspb.binary.encoder'); goog.require('jspb.BinaryReader'); goog.require('jspb.BinaryWriter'); goog.require('jspb.utils'); -goog.requireType('jspb.BinaryMessage'); +const BinaryConstants = goog.module.get('jspb.BinaryConstants'); +const BinaryMessage = BinaryConstants.BinaryMessage; +const BinaryDecoder = goog.module.get('jspb.binary.decoder').BinaryDecoder; +const BinaryEncoder = goog.module.get('jspb.binary.encoder').BinaryEncoder; +const BinaryReader = goog.module.get('jspb.BinaryReader'); +const BinaryWriter = goog.module.get('jspb.BinaryWriter'); +const makeTag = goog.module.get('jspb.utils').makeTag; +const sliceUint8Array = goog.module.get('jspb.utils').sliceUint8Array; + +const test64BitIntSignedData = [ + '-9223372036854775808', + '-4611686018427387904', + 4294967296, + -2147483648, + -1, + 0, + 1, + 2147483648, + 4294967296, + '4611686018427387904', + '9223372036854775807', +]; + +const test64BitIntUnsignedData = [ + 0, + 1, + 2147483648, + 4294967296, + '4611686018427387904', + '9223372036854775808', + '18446744073709551615', +]; +/** + * @param {number|string|bigint} x + * @returns number + */ +function asNumberOrString(x) { + const num = Number(x); + return Number.isSafeInteger(num) ? num : (/** @type{number} */(String(x))); +} + +function doTest64BitIntField( + /** function(this:!BinaryReader): number */ readField, + /** function(this:!BinaryWriter, number, number) */writeField, + /** ReadonlyArray */testData, +) { + const writer = new BinaryWriter(); + + const inputValues = []; + + for (const cursor of testData) { + writeField.call(writer, 1, /** @type{number}*/(cursor)); + inputValues.push({ + fieldNumber: 1, + value: cursor, + }); + } + + const reader = BinaryReader.alloc(writer.getResultBuffer()); + + for (let i = 0; i < inputValues.length; i++) { + const expected = inputValues[i]; + reader.nextField(); + expect(reader.getFieldNumber()).toBe(expected.fieldNumber); + expect(readField.call(reader)).toBe(/** @type{number}*/(expected.value)); + } +} + +function doTestSigned64BitIntField( + /** function(this:!BinaryReader): number */ readField, + /** function(this:!BinaryWriter, number, number) */writeField +) { + doTest64BitIntField(readField, writeField, test64BitIntSignedData); + + // Encoding values outside should truncate. + const outOfRangeData = ['-36893488147419103230', '36893488147419103230']; + const writer = new BinaryWriter(); + + for (const value of outOfRangeData) { + writeField.call(writer, 1, /** @type{number} */(value)); + } + + const reader = BinaryReader.alloc(writer.getResultBuffer()); + for (const value of outOfRangeData) { + reader.nextField(); + expect(reader.getFieldNumber()).toBe(1); + expect(readField.call(reader)).toBe( + asNumberOrString(BigInt.asIntN(64, BigInt(value)).toString()), + ); + } +} + +function doTestUnsigned64BitIntField( + /** function(this:!BinaryReader): number */ readField, + /** function(this:!BinaryWriter, number, number) */writeField +) { + doTest64BitIntField(readField, writeField, test64BitIntUnsignedData); + + // Out of range numbers should assert. + const pastLowerLimit = -1; + const writer = new BinaryWriter(); + expect(() => void writeField.call(writer, 1, pastLowerLimit)).toThrow(); + + // Out of range strings should truncate. + const pastUpperLimit = '36893488147419103230'; + writeField.call(writer, 1, /** @type{number} */(pastUpperLimit)); + + const reader = BinaryReader.alloc(writer.getResultBuffer()); + reader.nextField(); + expect(reader.getFieldNumber()).toBe(1); + expect(readField.call(reader)).toBe( + asNumberOrString(BigInt.asUintN(64, BigInt(pastUpperLimit)).toString()), + ); +} describe('binaryReaderTest', () => { - /** - * Tests the reader instance cache. - */ - it('testInstanceCaches', /** @suppress {visibility} */ () => { - const writer = new jspb.BinaryWriter(); - const dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); - writer.writeMessage(1, dummyMessage, () => {}); - writer.writeMessage(2, dummyMessage, () => {}); + /** Tests the reader instance cache. */ + it('testInstanceCaches', () => { + const writer = new BinaryWriter(); + const dummyMessage = /** @type {!BinaryMessage} */ ({}); + writer.writeMessage(1, dummyMessage, () => { }); + writer.writeMessage(2, dummyMessage, () => { }); const buffer = writer.getResultBuffer(); // Empty the instance caches. - jspb.BinaryReader.clearInstanceCache(); + BinaryReader.resetInstanceCache(); // Allocating and then freeing three decoders should leave us with three in // the cache. - const decoder1 = jspb.BinaryDecoder.alloc(); - const decoder2 = jspb.BinaryDecoder.alloc(); - const decoder3 = jspb.BinaryDecoder.alloc(); + const decoder1 = BinaryDecoder.alloc(); + const decoder2 = BinaryDecoder.alloc(); + const decoder3 = BinaryDecoder.alloc(); decoder1.free(); decoder2.free(); decoder3.free(); - expect(jspb.BinaryDecoder.getInstanceCacheLength()).toEqual(3); - expect(jspb.BinaryReader.getInstanceCacheLength()).toEqual(0); + expect(BinaryDecoder.getInstanceCache().length).toEqual(3); + expect(BinaryReader.getInstanceCache().length).toEqual(0); // Allocating and then freeing a reader should remove one decoder from its // cache, but it should stay stuck to the reader afterwards since we can't // have a reader without a decoder. - jspb.BinaryReader.alloc().free(); + BinaryReader.alloc().free(); - expect(jspb.BinaryDecoder.getInstanceCacheLength()).toEqual(2); - expect(jspb.BinaryReader.getInstanceCacheLength()).toEqual(1); + expect(BinaryDecoder.getInstanceCache().length).toEqual(2); + expect(BinaryReader.getInstanceCache().length).toEqual(1); // Allocating a reader should remove a reader from the cache. - const reader = jspb.BinaryReader.alloc(buffer); + const reader = BinaryReader.alloc(buffer); - expect(jspb.BinaryDecoder.getInstanceCacheLength()).toEqual(2); - expect(jspb.BinaryReader.getInstanceCacheLength()).toEqual(0); + expect(BinaryDecoder.getInstanceCache().length).toEqual(2); + expect(BinaryReader.getInstanceCache().length).toEqual(0); // Processing the message reuses the current reader. reader.nextField(); expect(reader.getFieldNumber()).toEqual(1); reader.readMessage(dummyMessage, () => { - expect(jspb.BinaryReader.getInstanceCacheLength()).toEqual(0); - }); + expect(BinaryReader.getInstanceCache().length).toEqual(0); + }); reader.nextField(); expect(reader.getFieldNumber()).toEqual(2); reader.readMessage(dummyMessage, () => { - expect(jspb.BinaryReader.getInstanceCacheLength()).toEqual(0); - }); + expect(BinaryReader.getInstanceCache().length).toEqual(0); + }); expect(reader.nextField()).toEqual(false); - expect(jspb.BinaryDecoder.getInstanceCacheLength()).toEqual(2); - expect(jspb.BinaryReader.getInstanceCacheLength()).toEqual(0); + expect(BinaryDecoder.getInstanceCache().length).toEqual(2); + expect(BinaryReader.getInstanceCache().length).toEqual(0); // Freeing the reader should put it back into the cache. reader.free(); - expect(jspb.BinaryDecoder.getInstanceCacheLength()).toEqual(2); - expect(jspb.BinaryReader.getInstanceCacheLength()).toEqual(1); + expect(BinaryDecoder.getInstanceCache().length).toEqual(2); + expect(BinaryReader.getInstanceCache().length).toEqual(1); }); - /** * @param {number} x * @return {number} @@ -128,332 +239,273 @@ describe('binaryReaderTest', () => { return temp[0]; } + /** Verifies that misuse of the reader class triggers assertions. */ + it('testReadErrors', /** @suppress {checkTypes|visibility} */() => { + // Calling readMessage on a non-delimited field should trigger an + // assertion. + let reader = BinaryReader.alloc([8, 1]); + const dummyMessage = /** @type {!BinaryMessage} */ ({}); + reader.nextField(); + expect(() => { + reader.readMessage(dummyMessage, goog.nullFunction); + }).toThrowError(); - /** - * Verifies that misuse of the reader class triggers assertions. - */ - it('testReadErrors', /** @suppress {checkTypes|visibility} */ () => { - // Calling readMessage on a non-delimited field should trigger an - // assertion. - let reader = jspb.BinaryReader.alloc([8, 1]); - const dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); - reader.nextField(); - expect(() => { - reader.readMessage(dummyMessage, () => { }); - }).toThrow(); - - // Reading past the end of the stream should trigger an assertion. - reader = jspb.BinaryReader.alloc([9, 1]); - reader.nextField(); - expect(() => { - reader.readFixed64(); - }).toThrow(); + // Reading past the end of the stream should trigger an assertion. + reader = BinaryReader.alloc([9, 1]); + reader.nextField(); + expect(() => reader.readFixed64()).toThrowError(); - // Reading past the end of a submessage should trigger an assertion. - reader = jspb.BinaryReader.alloc([10, 4, 13, 1, 1, 1]); - reader.nextField(); + // Reading past the end of a submessage should trigger an assertion. + reader = BinaryReader.alloc([10, 4, 13, 1, 1, 1]); + reader.nextField(); + expect(() => { reader.readMessage(dummyMessage, () => { - reader.nextField(); - expect(() => { - reader.readFixed32(); - }).toThrow(); - }); - - // Skipping an invalid field should trigger an assertion. - reader = jspb.BinaryReader.alloc([12, 1]); - reader.nextWireType_ = 1000; - expect(() => { - reader.skipField(); - }).toThrow(); + reader.nextField(); + expect(() => reader.readFixed32()) + .toThrowError('Tried to read past the end of the data 7 > 6'); + }); + }) + .toThrowError( + 'Message parsing ended unexpectedly. Expected to read 4 bytes, instead read 5 bytes, either the data ended unexpectedly or the message misreported its own length'); - // Reading fields with the wrong wire type should assert. - reader = jspb.BinaryReader.alloc([9, 0, 0, 0, 0, 0, 0, 0, 0]); - reader.nextField(); - expect(() => { - reader.readInt32(); - }).toThrow(); - expect(function () { - reader.readInt32String(); - }).toThrow(); - expect(function () { - reader.readInt64(); - }).toThrow(); - expect(function () { - reader.readInt64String(); - }).toThrow(); - expect(function () { - reader.readUint32(); - }).toThrow(); - expect(function () { - reader.readUint32String(); - }).toThrow(); - expect(function () { - reader.readUint64(); - }).toThrow(); - expect(function () { - reader.readUint64String(); - }).toThrow(); - expect(function () { - reader.readSint32(); - }).toThrow(); - expect(function () { - reader.readBool(); - }).toThrow(); - expect(function () { - reader.readEnum(); - }).toThrow(); - - reader = jspb.BinaryReader.alloc([8, 1]); - reader.nextField(); - expect(function () { - reader.readFixed32(); - }).toThrow(); - expect(function () { - reader.readFixed64(); - }).toThrow(); - expect(function () { - reader.readSfixed32(); - }).toThrow(); - expect(function () { - reader.readSfixed64(); - }).toThrow(); - expect(function () { - reader.readFloat(); - }).toThrow(); - expect(function () { - reader.readDouble(); - }).toThrow(); - - expect(function () { - reader.readString(); - }).toThrow(); - expect(function () { - reader.readBytes(); - }).toThrow(); - }); + // Skipping an invalid field should trigger an assertion. + reader = BinaryReader.alloc([12, 1]); + reader.nextWireType_ = 1000; + expect(() => reader.skipField()).toThrowError(); + // Reading fields with the wrong wire type should assert. + reader = BinaryReader.alloc([9, 0, 0, 0, 0, 0, 0, 0, 0]); + reader.nextField(); + expect(() => reader.readInt32()).toThrowError(); + expect(() => reader.readInt32String()).toThrowError(); + expect(() => reader.readInt64()).toThrowError(); + expect(() => reader.readInt64String()).toThrowError(); + expect(() => reader.readUint32()).toThrowError(); + expect(() => reader.readUint32String()).toThrowError(); + expect(() => reader.readUint64()).toThrowError(); + expect(() => reader.readUint64String()).toThrowError(); + expect(() => reader.readSint32()).toThrowError(); + expect(() => reader.readBool()).toThrowError(); + expect(() => reader.readEnum()).toThrowError(); + + reader = BinaryReader.alloc([8, 1]); + reader.nextField(); + expect(() => reader.readFixed32()).toThrowError(); + expect(() => reader.readFixed64()).toThrowError(); + expect(() => reader.readSfixed32()).toThrowError(); + expect(() => reader.readSfixed64()).toThrowError(); + expect(() => reader.readFloat()).toThrowError(); + expect(() => reader.readDouble()).toThrowError(); + + expect(() => reader.readString()).toThrowError(); + expect(() => reader.readBytes()).toThrowError(); + }); /** * Tests encoding and decoding of unsigned field types. - * @param {Function} readField - * @param {Function} writeField + * @param {!Function} readField + * @param {!Function} writeField * @param {number} epsilon * @param {number} upperLimit - * @param {Function} filter - * @private - * @suppress {missingProperties} + * @param {!Function} filter + * @private @suppress {missingProperties} */ - const doTestUnsignedField_ = function( - readField, writeField, epsilon, upperLimit, filter) { - expect(readField).not.toBeNull(); - expect(writeField).not.toBeNull(); + const doTestUnsignedField = + (readField, writeField, epsilon, upperLimit, filter) => { + expect(readField).not.toBeNull(); + expect(writeField).not.toBeNull(); - const writer = new jspb.BinaryWriter(); + const writer = new BinaryWriter(); - // Encode zero and limits. - writeField.call(writer, 1, filter(0)); - writeField.call(writer, 2, filter(epsilon)); - writeField.call(writer, 3, filter(upperLimit)); + // Encode zero and limits. + writeField.call(writer, 1, filter(0)); + writeField.call(writer, 2, filter(epsilon)); + writeField.call(writer, 3, filter(upperLimit)); - // Encode positive values. - for (let cursor = epsilon; cursor < upperLimit; cursor *= 1.1) { - writeField.call(writer, 4, filter(cursor)); - } - - const reader = jspb.BinaryReader.alloc(writer.getResultBuffer()); + // Encode positive values. + for (let cursor = epsilon; cursor < upperLimit; cursor *= 1.1) { + writeField.call(writer, 4, filter(cursor)); + } - // Check zero and limits. - reader.nextField(); - expect(reader.getFieldNumber()).toEqual(1); - expect(readField.call(reader)).toEqual(filter(0)); + const reader = BinaryReader.alloc(writer.getResultBuffer()); - reader.nextField(); - expect(reader.getFieldNumber()).toEqual(2); - expect(readField.call(reader)).toEqual(filter(epsilon)); + // Check zero and limits. + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(1); + expect(readField.call(reader)).toEqual(filter(0)); - reader.nextField(); - expect(reader.getFieldNumber()).toEqual(3); - expect(readField.call(reader)).toEqual(filter(upperLimit)); + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(2); + expect(readField.call(reader)).toEqual(filter(epsilon)); - // Check positive values. - for (let cursor = epsilon; cursor < upperLimit; cursor *= 1.1) { reader.nextField(); - if (4 != reader.getFieldNumber()) throw 'fail!'; - if (filter(cursor) != readField.call(reader)) throw 'fail!'; - } - }; + expect(reader.getFieldNumber()).toEqual(3); + expect(readField.call(reader)).toEqual(filter(upperLimit)); + // Check positive values. + for (let cursor = epsilon; cursor < upperLimit; cursor *= 1.1) { + reader.nextField(); + if (4 != reader.getFieldNumber()) throw 'fail!'; + if (filter(cursor) != readField.call(reader)) throw 'fail!'; + } + }; /** * Tests encoding and decoding of signed field types. - * @param {Function} readField - * @param {Function} writeField + * @param {!Function} readField + * @param {!Function} writeField * @param {number} epsilon * @param {number} lowerLimit * @param {number} upperLimit - * @param {Function} filter - * @private - * @suppress {missingProperties} + * @param {!Function} filter + * @private @suppress {missingProperties} */ - const doTestSignedField_ = function( - readField, writeField, epsilon, lowerLimit, upperLimit, filter) { - const writer = new jspb.BinaryWriter(); - - // Encode zero and limits. - writeField.call(writer, 1, filter(lowerLimit)); - writeField.call(writer, 2, filter(-epsilon)); - writeField.call(writer, 3, filter(0)); - writeField.call(writer, 4, filter(epsilon)); - writeField.call(writer, 5, filter(upperLimit)); - - const inputValues = []; - - // Encode negative values. - for (let cursor = lowerLimit; cursor < -epsilon; cursor /= 1.1) { - const val = filter(cursor); - writeField.call(writer, 6, val); - inputValues.push({fieldNumber: 6, value: val}); - } - - // Encode positive values. - for (let cursor = epsilon; cursor < upperLimit; cursor *= 1.1) { - const val = filter(cursor); - writeField.call(writer, 7, val); - inputValues.push({fieldNumber: 7, value: val}); - } + const doTestSignedField = + (readField, writeField, epsilon, lowerLimit, upperLimit, filter) => { + const writer = new BinaryWriter(); + + // Encode zero and limits. + writeField.call(writer, 1, filter(lowerLimit)); + writeField.call(writer, 2, filter(-epsilon)); + writeField.call(writer, 3, filter(0)); + writeField.call(writer, 4, filter(epsilon)); + writeField.call(writer, 5, filter(upperLimit)); + + const inputValues = []; + + // Encode negative values. + for (let cursor = lowerLimit; cursor < -epsilon; cursor /= 1.1) { + const val = filter(cursor); + writeField.call(writer, 6, val); + inputValues.push({ + fieldNumber: 6, + value: val, + }); + } - const reader = jspb.BinaryReader.alloc(writer.getResultBuffer()); + // Encode positive values. + for (let cursor = epsilon; cursor < upperLimit; cursor *= 1.1) { + const val = filter(cursor); + writeField.call(writer, 7, val); + inputValues.push({ + fieldNumber: 7, + value: val, + }); + } - // Check zero and limits. - reader.nextField(); - expect(reader.getFieldNumber()).toEqual(1); - expect(readField.call(reader)).toEqual(filter(lowerLimit)); + const reader = BinaryReader.alloc(writer.getResultBuffer()); - reader.nextField(); - expect(reader.getFieldNumber()).toEqual(2); - expect(readField.call(reader)).toEqual(filter(-epsilon)); + // Check zero and limits. + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(1); + expect(readField.call(reader)).toEqual(filter(lowerLimit)); - reader.nextField(); - expect(reader.getFieldNumber()).toEqual(3); - expect(readField.call(reader)).toEqual(filter(0)); + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(2); + expect(readField.call(reader)).toEqual(filter(-epsilon)); - reader.nextField(); - expect(reader.getFieldNumber()).toEqual(4); - expect(readField.call(reader)).toEqual(filter(epsilon)); + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(3); + expect(readField.call(reader)).toEqual(filter(0)); - reader.nextField(); - expect(reader.getFieldNumber()).toEqual(5); - expect(readField.call(reader)).toEqual(filter(upperLimit)); + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(4); + expect(readField.call(reader)).toEqual(filter(epsilon)); - for (let i = 0; i < inputValues.length; i++) { - const expected = inputValues[i]; reader.nextField(); - expect(reader.getFieldNumber()).toEqual(expected.fieldNumber); - expect(readField.call(reader)).toEqual(expected.value); - } - }; + expect(reader.getFieldNumber()).toEqual(5); + expect(readField.call(reader)).toEqual(filter(upperLimit)); + for (let i = 0; i < inputValues.length; i++) { + const expected = inputValues[i]; + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(expected.fieldNumber); + expect(readField.call(reader)).toEqual(expected.value); + } + }; - /** - * Tests fields that use varint encoding. - */ + /** Tests fields that use varint encoding. */ it('testVarintFields', () => { - expect(jspb.BinaryReader.prototype.readUint32).not.toBeUndefined(); - expect(jspb.BinaryWriter.prototype.writeUint32).not.toBeUndefined(); - expect(jspb.BinaryReader.prototype.readUint64).not.toBeUndefined(); - expect(jspb.BinaryWriter.prototype.writeUint64).not.toBeUndefined(); - expect(jspb.BinaryReader.prototype.readBool).not.toBeUndefined(); - expect(jspb.BinaryWriter.prototype.writeBool).not.toBeUndefined(); - doTestUnsignedField_( - jspb.BinaryReader.prototype.readUint32, - jspb.BinaryWriter.prototype.writeUint32, 1, Math.pow(2, 32) - 1, - Math.round); - - doTestUnsignedField_( - jspb.BinaryReader.prototype.readUint64, - jspb.BinaryWriter.prototype.writeUint64, 1, Math.pow(2, 64) - 1025, - Math.round); - - doTestSignedField_( - jspb.BinaryReader.prototype.readInt32, - jspb.BinaryWriter.prototype.writeInt32, 1, -Math.pow(2, 31), - Math.pow(2, 31) - 1, Math.round); - - doTestSignedField_( - jspb.BinaryReader.prototype.readInt64, - jspb.BinaryWriter.prototype.writeInt64, 1, -Math.pow(2, 63), - Math.pow(2, 63) - 513, Math.round); - - doTestSignedField_( - jspb.BinaryReader.prototype.readEnum, - jspb.BinaryWriter.prototype.writeEnum, 1, -Math.pow(2, 31), - Math.pow(2, 31) - 1, Math.round); - - doTestUnsignedField_( - jspb.BinaryReader.prototype.readBool, - jspb.BinaryWriter.prototype.writeBool, 1, 1, function(x) { - return !!x; - }); + expect(BinaryReader.prototype.readUint32).toBeDefined(); + expect(BinaryWriter.prototype.writeUint32).toBeDefined(); + expect(BinaryReader.prototype.readUint64).toBeDefined(); + expect(BinaryWriter.prototype.writeUint64).toBeDefined(); + expect(BinaryReader.prototype.readBool).toBeDefined(); + expect(BinaryWriter.prototype.writeBool).toBeDefined(); + doTestUnsignedField( + BinaryReader.prototype.readUint32, BinaryWriter.prototype.writeUint32, + 1, Math.pow(2, 32) - 1, Math.round); + + doTestUnsigned64BitIntField( + BinaryReader.prototype.readUint64, BinaryWriter.prototype.writeUint64); + + doTestSignedField( + BinaryReader.prototype.readInt32, BinaryWriter.prototype.writeInt32, 1, + -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round); + + doTestSigned64BitIntField(BinaryReader.prototype.readInt64, BinaryWriter.prototype.writeInt64); + + doTestSignedField( + BinaryReader.prototype.readEnum, BinaryWriter.prototype.writeEnum, 1, + -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round); + + doTestUnsignedField( + BinaryReader.prototype.readBool, BinaryWriter.prototype.writeBool, 1, 1, + (x) => !!x); }); - /** * Tests reading a field from hexadecimal string (format: '08 BE EF'). - * @param {Function} readField + * @param {!Function} readField * @param {number} expected * @param {string} hexString */ - function doTestHexStringVarint_(readField, expected, hexString) { + function doTestHexStringVarint(readField, expected, hexString) { const bytesCount = (hexString.length + 1) / 3; const bytes = new Uint8Array(bytesCount); for (let i = 0; i < bytesCount; i++) { bytes[i] = parseInt(hexString.substring(i * 3, i * 3 + 2), 16); } - const reader = jspb.BinaryReader.alloc(bytes); + const reader = BinaryReader.alloc(bytes); reader.nextField(); expect(readField.call(reader)).toEqual(expected); } - - /** - * Tests non-canonical redundant varint decoding. - */ + /** Tests non-canonical redundant varint decoding. */ it('testRedundantVarintFields', () => { - expect(jspb.BinaryReader.prototype.readUint32).not.toBeNull(); - expect(jspb.BinaryReader.prototype.readUint64).not.toBeNull(); - expect(jspb.BinaryReader.prototype.readSint32).not.toBeNull(); - expect(jspb.BinaryReader.prototype.readSint64).not.toBeNull(); + expect(BinaryReader.prototype.readUint32).toBeDefined(); + expect(BinaryReader.prototype.readUint64).toBeDefined(); + expect(BinaryReader.prototype.readSint32).toBeDefined(); + expect(BinaryReader.prototype.readSint64).toBeDefined(); // uint32 and sint32 take no more than 5 bytes // 08 - field prefix (type = 0 means varint) - doTestHexStringVarint_( - jspb.BinaryReader.prototype.readUint32, 12, '08 8C 80 80 80 00'); + doTestHexStringVarint( + BinaryReader.prototype.readUint32, 12, '08 8C 80 80 80 00'); // 11 stands for -6 in zigzag encoding - doTestHexStringVarint_( - jspb.BinaryReader.prototype.readSint32, -6, '08 8B 80 80 80 00'); + doTestHexStringVarint( + BinaryReader.prototype.readSint32, -6, '08 8B 80 80 80 00'); // uint64 and sint64 take no more than 10 bytes // 08 - field prefix (type = 0 means varint) - doTestHexStringVarint_( - jspb.BinaryReader.prototype.readUint64, 12, - '08 8C 80 80 80 80 80 80 80 80 00'); + doTestHexStringVarint( + BinaryReader.prototype.readUint64, 12, + '08 8C 80 80 80 80 80 80 80 80 00'); // 11 stands for -6 in zigzag encoding - doTestHexStringVarint_( - jspb.BinaryReader.prototype.readSint64, -6, - '08 8B 80 80 80 80 80 80 80 80 00'); + doTestHexStringVarint( + BinaryReader.prototype.readSint64, -6, + '08 8B 80 80 80 80 80 80 80 80 00'); }); - /** - * Tests reading 64-bit integers as split values. - */ + /** Tests reading 64-bit integers as split values. */ it('handles split 64 fields', () => { - const writer = new jspb.BinaryWriter(); + const writer = new BinaryWriter(); writer.writeInt64String(1, '4294967296'); writer.writeSfixed64String(2, '4294967298'); writer.writeInt64String(3, '3'); // 3 is the zig-zag encoding of -2. - const reader = jspb.BinaryReader.alloc(writer.getResultBuffer()); + const reader = BinaryReader.alloc(writer.getResultBuffer()); function rejoin(lowBits, highBits) { return highBits * 2 ** 32 + (lowBits >>> 0); @@ -471,23 +523,33 @@ describe('binaryReaderTest', () => { expect(reader.readSplitZigzagVarint64(rejoin)).toEqual(-2); }); - /** - * Tests 64-bit fields that are handled as strings. - */ + /** Tests 64-bit fields that are handled as strings. */ it('testStringInt64Fields', () => { - const writer = new jspb.BinaryWriter(); + const writer = new BinaryWriter(); const testSignedData = [ - '2730538252207801776', '-2688470994844604560', '3398529779486536359', - '3568577411627971000', '272477188847484900', '-6649058714086158188', - '-7695254765712060806', '-4525541438037104029', '-4993706538836508568', - '4990160321893729138' + '2730538252207801776', + '-2688470994844604560', + '3398529779486536359', + '3568577411627971000', + '272477188847484900', + '-6649058714086158188', + '-7695254765712060806', + '-4525541438037104029', + '-4993706538836508568', + '4990160321893729138', ]; const testUnsignedData = [ - '7822732630241694882', '6753602971916687352', '2399935075244442116', - '8724292567325338867', '16948784802625696584', '4136275908516066934', - '3575388346793700364', '5167142028379259461', '1557573948689737699', - '17100725280812548567' + '7822732630241694882', + '6753602971916687352', + '2399935075244442116', + '8724292567325338867', + '16948784802625696584', + '4136275908516066934', + '3575388346793700364', + '5167142028379259461', + '1557573948689737699', + '17100725280812548567', ]; for (let i = 0; i < testSignedData.length; i++) { @@ -495,100 +557,67 @@ describe('binaryReaderTest', () => { writer.writeUint64String(2 * i + 2, testUnsignedData[i]); } - const reader = jspb.BinaryReader.alloc(writer.getResultBuffer()); + const reader = BinaryReader.alloc(writer.getResultBuffer()); for (let i = 0; i < testSignedData.length; i++) { reader.nextField(); expect(reader.getFieldNumber()).toEqual(2 * i + 1); - expect(testSignedData[i]).toEqual(reader.readInt64String()); + expect(reader.readInt64String()).toEqual(testSignedData[i]); reader.nextField(); expect(reader.getFieldNumber()).toEqual(2 * i + 2); - expect(testUnsignedData[i]).toEqual(reader.readUint64String()); + expect(reader.readUint64String()).toEqual(testUnsignedData[i]); } }); - - /** - * Tests fields that use zigzag encoding. - */ + /** Tests fields that use zigzag encoding. */ it('testZigzagFields', () => { - doTestSignedField_( - jspb.BinaryReader.prototype.readSint32, - jspb.BinaryWriter.prototype.writeSint32, 1, -Math.pow(2, 31), - Math.pow(2, 31) - 1, Math.round); - - doTestSignedField_( - jspb.BinaryReader.prototype.readSint64, - jspb.BinaryWriter.prototype.writeSint64, 1, -Math.pow(2, 63), - Math.pow(2, 63) - 513, Math.round); - - doTestSignedField_( - jspb.BinaryReader.prototype.readSintHash64, - jspb.BinaryWriter.prototype.writeSintHash64, 1, -Math.pow(2, 63), - Math.pow(2, 63) - 513, jspb.utils.numberToHash64); - }); + doTestSignedField( + BinaryReader.prototype.readSint32, BinaryWriter.prototype.writeSint32, + 1, -Math.pow(2, 31), Math.pow(2, 31) - 1, Math.round); + doTestSigned64BitIntField(BinaryReader.prototype.readSint64, BinaryWriter.prototype.writeSint64); + }); - /** - * Tests fields that use fixed-length encoding. - */ + /** Tests fields that use fixed-length encoding. */ it('testFixedFields', () => { - doTestUnsignedField_( - jspb.BinaryReader.prototype.readFixed32, - jspb.BinaryWriter.prototype.writeFixed32, 1, Math.pow(2, 32) - 1, - Math.round); - - doTestUnsignedField_( - jspb.BinaryReader.prototype.readFixed64, - jspb.BinaryWriter.prototype.writeFixed64, 1, Math.pow(2, 64) - 1025, - Math.round); - - doTestSignedField_( - jspb.BinaryReader.prototype.readSfixed32, - jspb.BinaryWriter.prototype.writeSfixed32, 1, -Math.pow(2, 31), - Math.pow(2, 31) - 1, Math.round); - - doTestSignedField_( - jspb.BinaryReader.prototype.readSfixed64, - jspb.BinaryWriter.prototype.writeSfixed64, 1, -Math.pow(2, 63), - Math.pow(2, 63) - 513, Math.round); - }); + doTestUnsignedField( + BinaryReader.prototype.readFixed32, BinaryWriter.prototype.writeFixed32, + 1, Math.pow(2, 32) - 1, Math.round); + doTestUnsigned64BitIntField(BinaryReader.prototype.readFixed64, BinaryWriter.prototype.writeFixed64); - /** - * Tests floating point fields. - */ - it('testFloatFields', () => { - doTestSignedField_( - jspb.BinaryReader.prototype.readFloat, - jspb.BinaryWriter.prototype.writeFloat, - jspb.BinaryConstants.FLOAT32_MIN, -jspb.BinaryConstants.FLOAT32_MAX, - jspb.BinaryConstants.FLOAT32_MAX, truncate); - - doTestSignedField_( - jspb.BinaryReader.prototype.readDouble, - jspb.BinaryWriter.prototype.writeDouble, - jspb.BinaryConstants.FLOAT64_EPS * 10, - -jspb.BinaryConstants.FLOAT64_MIN, jspb.BinaryConstants.FLOAT64_MIN, - function(x) { - return x; - }); + doTestSignedField( + BinaryReader.prototype.readSfixed32, + BinaryWriter.prototype.writeSfixed32, 1, -Math.pow(2, 31), + Math.pow(2, 31) - 1, Math.round); + + doTestSigned64BitIntField(BinaryReader.prototype.readSfixed64, BinaryWriter.prototype.writeSfixed64); }); + /** Tests floating point fields. */ + it('testFloatFields', () => { + doTestSignedField( + BinaryReader.prototype.readFloat, BinaryWriter.prototype.writeFloat, + BinaryConstants.FLOAT32_MIN, -BinaryConstants.FLOAT32_MAX, + BinaryConstants.FLOAT32_MAX, truncate); + + doTestSignedField( + BinaryReader.prototype.readDouble, BinaryWriter.prototype.writeDouble, + BinaryConstants.FLOAT64_EPS * 10, -BinaryConstants.FLOAT64_MIN, + BinaryConstants.FLOAT64_MIN, (x) => x); + }); - /** - * Tests length-delimited string fields. - */ + /** Tests length-delimited string fields. */ it('testStringFields', () => { const s1 = 'The quick brown fox jumps over the lazy dog.'; const s2 = '人人生而自由,在尊嚴和權利上一律平等。'; - const writer = new jspb.BinaryWriter(); + const writer = new BinaryWriter(); writer.writeString(1, s1); writer.writeString(2, s2); - const reader = jspb.BinaryReader.alloc(writer.getResultBuffer()); + const reader = BinaryReader.alloc(writer.getResultBuffer()); reader.nextField(); expect(reader.getFieldNumber()).toEqual(1); @@ -599,17 +628,12 @@ describe('binaryReaderTest', () => { expect(reader.readString()).toEqual(s2); }); - - /** - * Tests length-delimited byte fields. - */ + /** Tests length-delimited byte fields. */ it('testByteFields', () => { - const message = []; const lowerLimit = 1; const upperLimit = 256; - const scale = 1.1; - const writer = new jspb.BinaryWriter(); + const writer = new BinaryWriter(); for (let cursor = lowerLimit; cursor < upperLimit; cursor *= 1.1) { const len = Math.round(cursor); @@ -619,7 +643,7 @@ describe('binaryReaderTest', () => { writer.writeBytes(len, bytes); } - const reader = jspb.BinaryReader.alloc(writer.getResultBuffer()); + const reader = BinaryReader.alloc(writer.getResultBuffer()); for (let cursor = lowerLimit; reader.nextField(); cursor *= 1.1) { const len = Math.round(cursor); @@ -631,15 +655,13 @@ describe('binaryReaderTest', () => { if (i % 256 != bytes[i]) throw 'fail!'; } } + expect().nothing(); // suppress 'no expectations' warning }); - - /** - * Tests nested messages. - */ + /** Tests nested messages. */ it('testNesting', () => { - const writer = new jspb.BinaryWriter(); - const dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); + const writer = new BinaryWriter(); + const dummyMessage = /** @type {!BinaryMessage} */ ({}); writer.writeInt32(1, 100); @@ -651,17 +673,17 @@ describe('binaryReaderTest', () => { }); // Add one empty message. - writer.writeMessage(6, dummyMessage, () => {}); + writer.writeMessage(6, dummyMessage, () => { }); writer.writeInt32(7, 700); - const reader = jspb.BinaryReader.alloc(writer.getResultBuffer()); + const reader = BinaryReader.alloc(writer.getResultBuffer()); // Validate outermost message. reader.nextField(); expect(reader.getFieldNumber()).toEqual(1); - expect(100).toEqual(reader.readInt32()); + expect(reader.readInt32()).toEqual(100); reader.nextField(); expect(reader.getFieldNumber()).toEqual(2); @@ -669,15 +691,15 @@ describe('binaryReaderTest', () => { // Validate embedded message 1. reader.nextField(); expect(reader.getFieldNumber()).toEqual(3); - expect(300).toEqual(reader.readInt32()); + expect(reader.readInt32()).toEqual(300); reader.nextField(); expect(reader.getFieldNumber()).toEqual(4); - expect(400).toEqual(reader.readInt32()); + expect(reader.readInt32()).toEqual(400); reader.nextField(); expect(reader.getFieldNumber()).toEqual(5); - expect(500).toEqual(reader.readInt32()); + expect(reader.readInt32()).toEqual(500); expect(reader.nextField()).toEqual(false); }); @@ -692,7 +714,7 @@ describe('binaryReaderTest', () => { reader.nextField(); expect(reader.getFieldNumber()).toEqual(7); - expect(700).toEqual(reader.readInt32()); + expect(reader.readInt32()).toEqual(700); expect(reader.nextField()).toEqual(false); }); @@ -702,7 +724,7 @@ describe('binaryReaderTest', () => { * values and skipping everything that's not a sentinel. */ it('testSkipField', () => { - const writer = new jspb.BinaryWriter(); + const writer = new BinaryWriter(); const sentinel = 123456789; @@ -732,7 +754,7 @@ describe('binaryReaderTest', () => { // Write a group with a nested group inside. writer.writeInt32(5, sentinel); - const dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); + const dummyMessage = /** @type {!BinaryMessage} */ ({}); writer.writeGroup(5, dummyMessage, () => { // Previously the skipGroup implementation was wrong, which only consume // the decoder by nextField. This case is for making the previous @@ -751,18 +773,18 @@ describe('binaryReaderTest', () => { writer.writeInt64(84, 42); writer.writeInt64(84, 44); writer.writeBytes( - 43, [255, 255, 255, 255, 255, 255, 255, 255, 255, 255]); + 43, [255, 255, 255, 255, 255, 255, 255, 255, 255, 255]); }); }); // Write final sentinel. writer.writeInt32(6, sentinel); - const reader = jspb.BinaryReader.alloc(writer.getResultBuffer()); + const reader = BinaryReader.alloc(writer.getResultBuffer()); function skip(field, count) { for (let i = 0; i < count; i++) { - reader.nextField(); + expect(reader.nextField()).toBe(true); if (field != reader.getFieldNumber()) throw 'fail!'; reader.skipField(); } @@ -770,40 +792,37 @@ describe('binaryReaderTest', () => { reader.nextField(); expect(reader.getFieldNumber()).toEqual(1); - expect(sentinel).toEqual(reader.readInt32()); + expect(reader.readInt32()).toEqual(sentinel); skip(1, 4); reader.nextField(); expect(reader.getFieldNumber()).toEqual(2); - expect(sentinel).toEqual(reader.readInt32()); + expect(reader.readInt32()).toEqual(sentinel); skip(2, 3); reader.nextField(); expect(reader.getFieldNumber()).toEqual(3); - expect(sentinel).toEqual(reader.readInt32()); + expect(reader.readInt32()).toEqual(sentinel); skip(3, 3); reader.nextField(); expect(reader.getFieldNumber()).toEqual(4); - expect(sentinel).toEqual(reader.readInt32()); + expect(reader.readInt32()).toEqual(sentinel); skip(4, 2); reader.nextField(); expect(reader.getFieldNumber()).toEqual(5); - expect(sentinel).toEqual(reader.readInt32()); + expect(reader.readInt32()).toEqual(sentinel); skip(5, 1); reader.nextField(); expect(reader.getFieldNumber()).toEqual(6); - expect(sentinel).toEqual(reader.readInt32()); + expect(reader.readInt32()).toEqual(sentinel); }); - - /** - * Tests packed fields. - */ - it('testPackedFields', () => { - const writer = new jspb.BinaryWriter(); + /** Tests Packable fields. */ + it('testPackableFields', () => { + const writer = new BinaryWriter(); const sentinel = 123456789; @@ -836,58 +855,85 @@ describe('binaryReaderTest', () => { writer.writeInt32(3, sentinel); - const reader = jspb.BinaryReader.alloc(writer.getResultBuffer()); + const reader = BinaryReader.alloc(writer.getResultBuffer()); reader.nextField(); - expect(sentinel).toEqual(reader.readInt32()); + expect(reader.readInt32()).toEqual(sentinel); reader.nextField(); - expect(signedData).toEqual(reader.readPackedInt32()); + const array = []; + reader.readPackableInt32Into(array); + expect(array).toEqual(signedData); reader.nextField(); - expect(signedData).toEqual(reader.readPackedInt64()); + array.length = 0; + reader.readPackableInt64Into(array); + expect(array).toEqual(signedData); reader.nextField(); - expect(unsignedData).toEqual(reader.readPackedUint32()); + array.length = 0; + reader.readPackableUint32Into(array); + expect(array).toEqual(unsignedData); reader.nextField(); - expect(unsignedData).toEqual(reader.readPackedUint64()); + array.length = 0; + reader.readPackableUint64Into(array); + expect(array).toEqual(unsignedData); reader.nextField(); - expect(signedData).toEqual(reader.readPackedSint32()); + array.length = 0; + reader.readPackableSint32Into(array); + expect(array).toEqual(signedData); reader.nextField(); - expect(signedData).toEqual(reader.readPackedSint64()); + array.length = 0; + reader.readPackableSint64Into(array); + expect(array).toEqual(signedData); reader.nextField(); - expect(unsignedData).toEqual(reader.readPackedFixed32()); + array.length = 0; + reader.readPackableFixed32Into(array); + expect(array).toEqual(unsignedData); reader.nextField(); - expect(unsignedData).toEqual(reader.readPackedFixed64()); + array.length = 0; + reader.readPackableFixed64Into(array); + expect(array).toEqual(unsignedData); reader.nextField(); - expect(signedData).toEqual(reader.readPackedSfixed32()); + array.length = 0; + reader.readPackableSfixed32Into(array); + expect(array).toEqual(signedData); reader.nextField(); - expect(signedData).toEqual(reader.readPackedSfixed64()); + array.length = 0; + reader.readPackableSfixed64Into(array); + expect(array).toEqual(signedData); reader.nextField(); - expect(floatData).toEqual(reader.readPackedFloat()); + array.length = 0; + reader.readPackableFloatInto(array); + expect(array).toEqual(floatData); reader.nextField(); - expect(doubleData).toEqual(reader.readPackedDouble()); + array.length = 0; + reader.readPackableDoubleInto(array); + expect(array).toEqual(doubleData); reader.nextField(); - expect(boolData).toEqual(reader.readPackedBool()); + array.length = 0; + reader.readPackableBoolInto(array); + expect(array).toEqual(boolData); reader.nextField(); - expect(unsignedData).toEqual(reader.readPackedEnum()); + array.length = 0; + reader.readPackableEnumInto(array); + expect(array).toEqual(unsignedData); reader.nextField(); - expect(sentinel).toEqual(reader.readInt32()); + expect(reader.readInt32()).toEqual(sentinel); }); - /** * Byte blobs inside nested messages should always have their byte offset set * relative to the start of the outermost blob, not the start of their parent @@ -897,10 +943,10 @@ describe('binaryReaderTest', () => { // Create a proto consisting of two nested messages, with the inner one // containing a blob of bytes. - const fieldTag = (1 << 3) | /* jspb.BinaryConstants.WireType.DELIMITED = */ 2; + const fieldTag = (1 << 3) | BinaryConstants.WireType.DELIMITED; const blob = [1, 2, 3, 4, 5]; - const writer = new jspb.BinaryWriter(); - const dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); + const writer = new BinaryWriter(); + const dummyMessage = /** @type {!BinaryMessage} */ ({}); writer.writeMessage(1, dummyMessage, () => { writer.writeMessage(1, dummyMessage, () => { @@ -911,30 +957,33 @@ describe('binaryReaderTest', () => { // Peel off the outer two message layers. Each layer should have two bytes // of overhead, one for the field tag and one for the length of the inner // blob. - - const decoder1 = new jspb.BinaryDecoder(writer.getResultBuffer()); - expect(fieldTag).toEqual(decoder1.readUnsignedVarint32()); - expect(blob.length + 4).toEqual(decoder1.readUnsignedVarint32()); - - const decoder2 = - new jspb.BinaryDecoder(decoder1.readBytes(blob.length + 4)); - expect(fieldTag).toEqual(decoder2.readUnsignedVarint32()); - expect(blob.length + 2).toEqual(decoder2.readUnsignedVarint32()); - - expect(fieldTag).toEqual(decoder2.readUnsignedVarint32()); - expect(blob.length).toEqual(decoder2.readUnsignedVarint32()); + const buf = writer.getResultBuffer(); + const decoder1 = new BinaryDecoder(buf); + expect(BinaryDecoder.readUnsignedVarint32(decoder1)).toEqual(fieldTag); + expect(BinaryDecoder.readUnsignedVarint32(decoder1)) + .toEqual(blob.length + 4); + + const decoder2 = new BinaryDecoder(decoder1.readBytes(blob.length + 4)); + expect(BinaryDecoder.readUnsignedVarint32(decoder2)).toEqual(fieldTag); + expect(BinaryDecoder.readUnsignedVarint32(decoder2)) + .toEqual(blob.length + 2); + + expect(BinaryDecoder.readUnsignedVarint32(decoder2)).toEqual(fieldTag); + expect(BinaryDecoder.readUnsignedVarint32(decoder2)).toEqual(blob.length); const bytes = decoder2.readBytes(blob.length); - expect(Uint8Array.from(blob)).toEqual(bytes); + // Mutating the input buffer shouldn't matter here because it will have been + // copied. + buf.fill(0); + + // toEqual doesn't support uint8array, so convert to arrays. + expect(Array.from(bytes)).toEqual(Array.from(blob)); }); - - /** - * Tests read callbacks. - */ - it('testReadCallbacks', () => { - const writer = new jspb.BinaryWriter(); - const dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); + /** Tests read callbacks. */ + it('test read message', () => { + const writer = new BinaryWriter(); + const dummyMessage = /** @type {!BinaryMessage} */ ({}); // Add an int, a submessage, and another int. writer.writeInt32(1, 100); @@ -947,47 +996,125 @@ describe('binaryReaderTest', () => { writer.writeInt32(7, 700); - // Create the reader and register a custom read callback. - const reader = jspb.BinaryReader.alloc(writer.getResultBuffer()); + const reader = BinaryReader.alloc(writer.getResultBuffer()); + + // Read the container message. + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(1); + expect(reader.readInt32()).toEqual(100); - /** - * @param {!jspb.BinaryReader} reader - * @return {*} - */ - function readCallback(reader) { + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(2); + reader.readMessage(dummyMessage, () => { reader.nextField(); expect(reader.getFieldNumber()).toEqual(3); - expect(300).toEqual(reader.readInt32()); + expect(reader.readInt32()).toEqual(300); reader.nextField(); expect(reader.getFieldNumber()).toEqual(4); - expect(400).toEqual(reader.readInt32()); + expect(reader.readInt32()).toEqual(400); reader.nextField(); expect(reader.getFieldNumber()).toEqual(5); - expect(500).toEqual(reader.readInt32()); + expect(reader.readInt32()).toEqual(500); expect(reader.nextField()).toEqual(false); - }; - - reader.registerReadCallback('readCallback', readCallback); + }); - // Read the container message. reader.nextField(); - expect(reader.getFieldNumber()).toEqual(1); - expect(100).toEqual(reader.readInt32()); + expect(reader.getFieldNumber()).toEqual(7); + expect(reader.readInt32()).toEqual(700); + expect(reader.nextField()).toEqual(false); + }); + it('test group ends early when reading', () => { + const writer = new BinaryWriter(); + writer.writeGroup(1, {}, (msg, writer) => { + writer.writeString(1, 'hello'); + }); + const reader = BinaryReader.alloc(writer.getResultBuffer()); + // Normal reading works fine + expect(reader.nextField()).toBe(true); + reader.readGroup(1, {}, (msg, reader) => { + expect(reader.nextField()).toBe(true); + expect(reader.readString()).toBe('hello'); + expect(reader.nextField()).toBe(true); + }); + reader.reset(); + expect(reader.nextField()).toBe(true); + // If the reader callback returns early then an error will be thrown + expect(() => { + reader.readGroup(1, {}, (msg, reader) => { + expect(reader.nextField()).toBe(true); + expect(reader.readString()).toBe('hello'); + }); + }).toThrowError('Group submessage did not end with an END_GROUP tag'); + }); + it('test group ends with wrong tag when reading', () => { + const writer = new BinaryWriter(); + writer.writeGroup(1, {}, (msg, writer) => { + writer.writeString(1, 'hello'); + }); + const bytes = writer.getResultBuffer(); + // make the end tag at the end correspond to the wrong field number + bytes[bytes.length - 1] = makeTag(2, BinaryConstants.WireType.END_GROUP); + // slice the endgroup tag off + const reader = BinaryReader.alloc(bytes); reader.nextField(); - expect(reader.getFieldNumber()).toEqual(2); - reader.readMessage(dummyMessage, () => { - // Decode the embedded message using the registered callback. - reader.runReadCallback('readCallback'); + expect(() => reader.readGroup(1, {}, (msg, reader) => { + expect(reader.nextField()).toBe(true); + expect(reader.readString()).toBe('hello'); + expect(reader.nextField()).toBe(true); + })).toThrowError('Unmatched end-group tag'); + }); + it('test group ends early when skipping', () => { + const writer = new BinaryWriter(); + writer.writeGroup(1, {}, (msg, writer) => { + writer.writeString(1, 'hello'); + }); + // slice the endgroup tag off + const reader = + BinaryReader.alloc(sliceUint8Array(writer.getResultBuffer(), 0, -1)); + reader.nextField(); + expect(() => reader.skipField()) + .toThrowError('Unmatched start-group tag: stream EOF'); + }); + + it('test group ends with wrong end tag when skipping', () => { + const writer = new BinaryWriter(); + writer.writeGroup(1, {}, (msg, writer) => { + writer.writeString(1, 'hello'); }); + const bytes = writer.getResultBuffer(); + // make the end tag at the end correspond to the wrong field number + bytes[bytes.length - 1] = makeTag(2, BinaryConstants.WireType.END_GROUP); + const reader = BinaryReader.alloc(bytes); + reader.nextField(); + expect(() => reader.skipField()).toThrowError('Unmatched end-group tag'); + }); + + it('throws when stop group appears first', () => { + const misplacedEndGroupEncoder = new BinaryEncoder(); + const fieldNumber = 1; + misplacedEndGroupEncoder.writeUnsignedVarint32( + (fieldNumber << 3) + BinaryConstants.WireType.END_GROUP); + const misplacedEndGroupData = misplacedEndGroupEncoder.end(); + const reader = BinaryReader.alloc(misplacedEndGroupData); reader.nextField(); - expect(reader.getFieldNumber()).toEqual(7); - expect(700).toEqual(reader.readInt32()); - expect(reader.nextField()).toEqual(false); + expect(() => reader.skipField()) + .toThrowError('Invalid wire type: 4 (at position 0)'); + }); + + it('throws on invalid wire types', () => { + const badWireTypeEncoder = new BinaryEncoder(); + const fieldNumber = 1; + badWireTypeEncoder.writeUnsignedVarint32( + (fieldNumber << 3) + /* max wiretype + 1 */6); + const badWireTypeData = badWireTypeEncoder.end(); + const reader = BinaryReader.alloc(badWireTypeData); + expect(() => reader.nextField()) + .toThrowError('Invalid wire type: 6 (at position 0)'); }); }); diff --git a/binary/repeated_field_type.js b/binary/repeated_field_type.js new file mode 100755 index 0000000..d6fc561 --- /dev/null +++ b/binary/repeated_field_type.js @@ -0,0 +1,11 @@ +goog.module('jspb.binary.repeated_field_type'); + +const {ScalarFieldType} = goog.requireType('jspb.binary.scalar_field_type'); + +/** + * A repeated field is an array of scalars, blobs, or messages. + * @typedef {!Array|!Array} + */ +let RepeatedFieldType; + +exports = {RepeatedFieldType}; diff --git a/binary/scalar_field_type.js b/binary/scalar_field_type.js new file mode 100755 index 0000000..c7cadb4 --- /dev/null +++ b/binary/scalar_field_type.js @@ -0,0 +1,9 @@ +goog.module('jspb.binary.scalar_field_type'); + +/** + * A scalar field can be a boolean, number, or string. + * @typedef {boolean|number|string} + */ +let ScalarFieldType; + +exports = {ScalarFieldType}; diff --git a/binary/test_utils.js b/binary/test_utils.js new file mode 100755 index 0000000..3302736 --- /dev/null +++ b/binary/test_utils.js @@ -0,0 +1,51 @@ +/** @fileoverview Utilities for testing binary protobuf code. */ +goog.module('jspb.binary.test_utils'); +goog.module.declareLegacyNamespace(); + + +const {BinaryReader} = goog.require('jspb.binary.reader'); +const {assertNumber} = goog.require('goog.asserts'); + +/** + * Converts a Uint8Array into a string of hex with two characters per byte. + * @param {!Uint8Array} u8array + * @return {string} + */ +function toHexString(u8array) { + return Array + .from( + u8array, (b) => (assertNumber(b) < 0x10 ? '0' : '') + b.toString(16)) + .join(''); +} +exports.toHexString = toHexString; + +/** + * Splits an encoded protocol buffer message into separate hex strings for each + * field number. + * + * Allows comparison of serialized protos without regard to field number + * ordering, which is not guaranteed to be stable. + * See https://developers.google.com/protocol-buffers/docs/encoding#order + * + * Contains all bytes relevant to the field, including the header with field + * number and type. Repeated fields are one long string including all headers. + * + * @param {!Uint8Array} u8array + * @return {!Object} + */ +function toHexFields(u8array) { + const /** !Object */ fields = {}; + const reader = new BinaryReader(u8array); + let startCursor = 0; + while (reader.nextField()) { + const fieldNumber = reader.getFieldNumber(); + const existingString = fields[fieldNumber] || ''; + reader.skipField(); + const endCursor = reader.getCursor(); + fields[fieldNumber] = + existingString + toHexString(u8array.subarray(startCursor, endCursor)); + startCursor = endCursor; + } + return fields; +} +exports.toHexFields = toHexFields; diff --git a/binary/utf8.js b/binary/utf8.js old mode 100644 new mode 100755 index 371982d..b25fff9 --- a/binary/utf8.js +++ b/binary/utf8.js @@ -1,26 +1,30 @@ /** * @fileoverview UTF8 encoding and decoding routines + * */ -goog.provide('jspb.binary.utf8'); +goog.module('jspb.binary.utf8'); +goog.module.declareLegacyNamespace(); -goog.require('jspb.asserts'); +const {assert, assertString} = goog.require('goog.asserts'); /** * Whether to use the browser based `TextEncoder` and `TextDecoder` APIs for * handling utf8. * - *

Enabled by default for `goog.FEATURESET_YEAR >= 2020`. The code also - * performs feature detection for this API and will always use it if available, - * this variable enables us to not ship the polyfill. - * - *

See http://go/jscompiler-flags#browser-featureset-year-options for the - * behavior here. + *

If enabled and `goog.FEATURESET_YEAR >= 2020`, `TextEncoder` and + * `TextDecoder` are used unconditionally without feature detection (and the + * code crashes if they are not available); this is best for code size. If + * enabled and `goog.FEATURESET_YEAR < 2020`, `TextEncoder` and `TextDecoder` + * are feature-detected, used if available, and the JS implementation is used + * if they're not. If disabled, the slower JS implementation is always used; + * this is appropriate for non-Web environments that don't have `TextEncoder` + * and `TextDecoder`. * * @define {boolean} */ -const USE_TEXT_ENCODING = - goog.define('jspb.binary.USE_TEXTENCODING', goog.FEATURESET_YEAR >= 2020); +const USE_TEXT_ENCODING = goog.define('jspb.binary.USE_TEXTENCODING', true); +const ASSUME_TEXT_ENCODING_AVAILABLE = goog.FEATURESET_YEAR >= 2020; const /** number */ MIN_SURROGATE = 0xD800; const /** number */ MIN_HIGH_SURROGATE = MIN_SURROGATE; @@ -75,7 +79,7 @@ function codeUnitsToString( * * @return {string} */ -jspb.binary.utf8.polyfillDecodeUtf8 = function ( +function polyfillDecodeUtf8( /** !Uint8Array */ bytes, /** number */ offset, /** number */ length, /** boolean */ parsingErrorsAreFatal) { let cursor = offset; @@ -112,7 +116,7 @@ jspb.binary.utf8.polyfillDecodeUtf8 = function ( const codeUnit = ((c1 & 0x1F) << 6) | (c2 & 0x3F); // Consistency check that the computed code is in range for a 2 byte // sequence. - jspb.asserts.assert(codeUnit >= 0x80 && codeUnit <= 0x07FF); + assert(codeUnit >= 0x80 && codeUnit <= 0x07FF); codeUnits.push(codeUnit); } } @@ -122,15 +126,15 @@ jspb.binary.utf8.polyfillDecodeUtf8 = function ( } else { c2 = bytes[cursor++]; if (isNotTrailingByte(c2) || - // These checks were taken from - // java/com/google/protobuf/Utf8.java - // overlong? 5 most significant bits must not all be zero - (c1 === 0xE0 && c2 < 0xA0) - // check for illegal surrogate codepoints - || (c1 === 0xED && c2 >= 0xA0) || - // We delay reading c3 until now so than an error in c2 or c1 will - // preserve c3 for the next loop iteration - isNotTrailingByte(c3 = bytes[cursor++])) { + // These checks were taken from + // java/com/google/protobuf/Utf8.java + // overlong? 5 most significant bits must not all be zero + (c1 === 0xE0 && c2 < 0xA0) + // check for illegal surrogate codepoints + || (c1 === 0xED && c2 >= 0xA0) || + // We delay reading c3 until now so than an error in c2 or c1 will + // preserve c3 for the next loop iteration + isNotTrailingByte(c3 = bytes[cursor++])) { cursor--; // push back c2 or c3, depending on how far we made it invalid(parsingErrorsAreFatal, codeUnits); } else { @@ -138,11 +142,11 @@ jspb.binary.utf8.polyfillDecodeUtf8 = function ( // 6 bits from each of the two lower bytes // == 16 bits total const codeUnit = - ((c1 & 0xF) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F); + ((c1 & 0xF) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F); // Consistency check, this is the valid range for a 3 byte character - jspb.asserts.assert(codeUnit >= 0x800 && codeUnit <= 0xFFFF); + assert(codeUnit >= 0x800 && codeUnit <= 0xFFFF); // And that Utf16 surrogates are disallowed - jspb.asserts.assert(codeUnit < MIN_SURROGATE || codeUnit > MAX_SURROGATE); + assert(codeUnit < MIN_SURROGATE || codeUnit > MAX_SURROGATE); codeUnits.push(codeUnit); } } @@ -154,20 +158,20 @@ jspb.binary.utf8.polyfillDecodeUtf8 = function ( } else { c2 = bytes[cursor++]; if (isNotTrailingByte(c2) || - // This check was inspired by - // java/com/google/protobuf/Utf8.java - // Tricky optimized form of: - // valid 4-byte leading byte? - // if (byte1 > (byte) 0xF4 || - // overlong? 4 most significant bits must not all be zero - // byte1 == (byte) 0xF0 && byte2 < (byte) 0x90 || - // codepoint larger than the highest code point (U+10FFFF)? - // byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F) - (((c1 << 28) + (c2 - 0x90)) >> 30) !== 0 || - // We delay reading c3 and c4 until now so than an error in c2 or c1 - // will preserve them for the next loop iteration. - isNotTrailingByte(c3 = bytes[cursor++]) || - isNotTrailingByte(c4 = bytes[cursor++])) { + // This check was inspired by + // java/com/google/protobuf/Utf8.java + // Tricky optimized form of: + // valid 4-byte leading byte? + // if (byte1 > (byte) 0xF4 || + // overlong? 4 most significant bits must not all be zero + // byte1 == (byte) 0xF0 && byte2 < (byte) 0x90 || + // codepoint larger than the highest code point (U+10FFFF)? + // byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F) + (((c1 << 28) + (c2 - 0x90)) >> 30) !== 0 || + // We delay reading c3 and c4 until now so than an error in c2 or c1 + // will preserve them for the next loop iteration. + isNotTrailingByte(c3 = bytes[cursor++]) || + isNotTrailingByte(c4 = bytes[cursor++])) { cursor--; // push back c2, c3 or c4 depending on how far we made it invalid(parsingErrorsAreFatal, codeUnits); } else { @@ -177,9 +181,9 @@ jspb.binary.utf8.polyfillDecodeUtf8 = function ( // bytes. This is 21 bits which is too big for a 16 bit utf16 code // unit so we use surrogates. let codepoint = ((c1 & 0x7) << 18) | ((c2 & 0x3F) << 12) | - ((c3 & 0x3F) << 6) | (c4 & 0x3F); + ((c3 & 0x3F) << 6) | (c4 & 0x3F); // Consistency check, this is the valid range for a 4 byte character. - jspb.asserts.assert(codepoint >= 0x10000 && codepoint <= 0x10FFFF); + assert(codepoint >= 0x10000 && codepoint <= 0x10FFFF); // Surrogates formula from wikipedia. // 1. Subtract 0x10000 from codepoint codepoint -= 0x10000; @@ -203,15 +207,15 @@ jspb.binary.utf8.polyfillDecodeUtf8 = function ( } } // ensure we don't overflow or underflow - jspb.asserts.assert(cursor === end, `expected ${cursor} === ${end}`); + assert(cursor === end, `expected ${cursor} === ${end}`); return codeUnitsToString(result, codeUnits); } /** @type {boolean|undefined} */ let isFatalTextDecoderCachableAfterThrowing_ = - // chrome version >= 2020 are not subject to https://crbug.com/910292 - goog.FEATURESET_YEAR >= 2020 ? true : undefined; + // chrome version >= 2020 are not subject to https://crbug.com/910292 + goog.FEATURESET_YEAR >= 2020 ? true : undefined; /** @return {boolean} */ function isFatalTextDecoderCachableAfterThrowing(/** !TextDecoder */ decoder) { @@ -250,7 +254,7 @@ let fatalDecoderInstance; function getFatalDecoderInstance() { let instance = fatalDecoderInstance; if (!instance) { - instance = fatalDecoderInstance = new TextDecoder('utf-8', { fatal: true }); + instance = fatalDecoderInstance = new TextDecoder('utf-8', {fatal: true}); } return instance; } @@ -263,7 +267,7 @@ function getNonFatalDecoderInstance() { let instance = nonFatalDecoderInstance; if (!instance) { instance = nonFatalDecoderInstance = - new TextDecoder('utf-8', { fatal: false }); + new TextDecoder('utf-8', {fatal: false}); } return instance; } @@ -277,25 +281,25 @@ function getNonFatalDecoderInstance() { function subarray( /** !Uint8Array*/ bytes, /** number */ offset, /** number */ end) { return offset === 0 && end === bytes.length ? bytes : - bytes.subarray(offset, end); + bytes.subarray(offset, end); } /** * @return {string} */ -jspb.binary.utf8.textDecoderDecodeUtf8 = function ( +function textDecoderDecodeUtf8( /** !Uint8Array*/ bytes, /** number */ offset, /** number */ length, /** boolean*/ parsingErrorsAreFatal) { const /** !TextDecoder */ decoder = parsingErrorsAreFatal ? - getFatalDecoderInstance() : - getNonFatalDecoderInstance(); + getFatalDecoderInstance() : + getNonFatalDecoderInstance(); bytes = subarray(bytes, offset, offset + length); try { return decoder.decode(bytes); } catch (e) { if (parsingErrorsAreFatal && - !isFatalTextDecoderCachableAfterThrowing(decoder)) { + !isFatalTextDecoderCachableAfterThrowing(decoder)) { fatalDecoderInstance = undefined; } throw e; @@ -303,60 +307,57 @@ jspb.binary.utf8.textDecoderDecodeUtf8 = function ( } /** @const {boolean} */ -const useTextDecoderDecode = - USE_TEXT_ENCODING || typeof TextDecoder !== 'undefined'; +const useTextDecoderDecode = USE_TEXT_ENCODING && + (ASSUME_TEXT_ENCODING_AVAILABLE || typeof TextDecoder !== 'undefined'); /** * A utf8 decoding routine either based upon TextDecoder if available or using * our polyfill implementation * @return {string} */ -jspb.binary.utf8.decodeUtf8 = function ( +function decodeUtf8( /** !Uint8Array*/ bytes, /** number */ offset, /** number */ length, /** boolean*/ parsingErrorsAreFatal) { return useTextDecoderDecode ? - jspb.binary.utf8.textDecoderDecodeUtf8(bytes, offset, length, parsingErrorsAreFatal) : - jspb.binary.utf8.polyfillDecodeUtf8(bytes, offset, length, parsingErrorsAreFatal); + textDecoderDecodeUtf8(bytes, offset, length, parsingErrorsAreFatal) : + polyfillDecodeUtf8(bytes, offset, length, parsingErrorsAreFatal); } /** @type {!TextEncoder|undefined} */ let textEncoderInstance; /** @return {!Uint8Array} */ -jspb.binary.utf8.textEncoderEncode = function ( +function textEncoderEncode( /** string */ s, /** boolean */ rejectUnpairedSurrogates) { if (rejectUnpairedSurrogates) { - jspb.binary.utf8.checkWellFormed(s); - } - - if (!textEncoderInstance) { - textEncoderInstance = new TextEncoder(); + checkWellFormed(s); } - return textEncoderInstance.encode(s); + return (textEncoderInstance ||= new TextEncoder()).encode(s); } +// No externs on isWellFormed until the JSCompiler implements a polyfill. +const /** string */ IS_WELL_FORMED = 'isWellFormed'; + // isWellFormed landed in major browsers in early 2023 so it will only be // definitely available in 2024 See // http://go/mdn/JavaScript/Reference/Global_Objects/String/isWellFormed const /** boolean */ HAS_WELL_FORMED_METHOD = goog.FEATURESET_YEAR > 2023 || - typeof String.prototype.isWellFormed === 'function'; + typeof String.prototype[IS_WELL_FORMED] === 'function'; -jspb.binary.utf8.checkWellFormed = function (/** string */ text) { +function checkWellFormed(/** string */ text) { if (HAS_WELL_FORMED_METHOD ? - // Externs don't contain the definition of this function yet. - // http://go/mdn/JavaScript/Reference/Global_Objects/String/isWellFormed - !(/** @type{{isWellFormed:function():boolean}}*/ ( - /** @type {?} */ (text)) - .isWellFormed()) : - /(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])/ - .test(text)) { + // Externs don't contain the definition of this function yet. + // http://go/mdn/JavaScript/Reference/Global_Objects/String/isWellFormed + !(/** @type {?} */ (text)[IS_WELL_FORMED]()) : + /(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])/ + .test(text)) { throw new Error('Found an unpaired surrogate'); } } /** @return {!Uint8Array} */ -jspb.binary.utf8.polyfillEncode = function ( +function polyfillEncode( /** string */ s, /** boolean */ rejectUnpairedSurrogates) { let bi = 0; // The worse case is that every character requires 3 output bytes, so we @@ -371,7 +372,7 @@ jspb.binary.utf8.polyfillEncode = function ( buffer[bi++] = (c >> 6) | 0xC0; buffer[bi++] = (c & 63) | 0x80; } else { - jspb.asserts.assert(c < 65536); + assert(c < 65536); // Look for surrogates // First check if it is surrogate range if (c >= MIN_SURROGATE && c <= MAX_SURROGATE) { @@ -381,7 +382,7 @@ jspb.binary.utf8.polyfillEncode = function ( if (c2 >= MIN_LOW_SURROGATE && c2 <= MAX_LOW_SURROGATE) { // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae const codePoint = - (c - MIN_SURROGATE) * 0x400 + c2 - MIN_LOW_SURROGATE + 0x10000; + (c - MIN_SURROGATE) * 0x400 + c2 - MIN_LOW_SURROGATE + 0x10000; buffer[bi++] = (codePoint >> 18) | 0xF0; buffer[bi++] = ((codePoint >> 12) & 63) | 0x80; buffer[bi++] = ((codePoint >> 6) & 63) | 0x80; @@ -408,18 +409,30 @@ jspb.binary.utf8.polyfillEncode = function ( } /** @const {boolean} */ -const useTextEncoderEncode = - (USE_TEXT_ENCODING || typeof TextEncoder !== 'undefined'); +const useTextEncoderEncode = USE_TEXT_ENCODING && + (ASSUME_TEXT_ENCODING_AVAILABLE || typeof TextEncoder !== 'undefined'); /** * A utf8 encoding routine either based upon TextEncoder if available or using * our polyfill implementation * @return {!Uint8Array} */ -jspb.binary.utf8.encodeUtf8 = function ( +function encodeUtf8( /**string*/ string, /** boolean=*/ rejectUnpairedSurrogates = false) { - jspb.asserts.assertString(string); + assertString(string); return useTextEncoderEncode ? - jspb.binary.utf8.textEncoderEncode(string, rejectUnpairedSurrogates) : - jspb.binary.utf8.polyfillEncode(string, rejectUnpairedSurrogates); + textEncoderEncode(string, rejectUnpairedSurrogates) : + polyfillEncode(string, rejectUnpairedSurrogates); } + + +exports = { + decodeUtf8, + encodeUtf8, + checkWellFormed, + // The following are exposed directly for testing/benchmarking purposes only. + textDecoderDecodeUtf8, + polyfillDecodeUtf8, + textEncoderEncode, + polyfillEncode, +}; diff --git a/binary/utils.js b/binary/utils.js old mode 100644 new mode 100755 index 037386a..6664fe2 --- a/binary/utils.js +++ b/binary/utils.js @@ -1,50 +1,56 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://protobuf.dev/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - /** - * @fileoverview This file contains helper code used by jspb.BinaryReader + * @fileoverview This file contains helper code used by BinaryReader * and BinaryWriter. * - * @suppress {missingRequire} TODO(b/152540451): this shouldn't be needed + * * @author aappleby@google.com (Austin Appleby) */ -goog.provide('jspb.utils'); +goog.module('jspb.utils'); +goog.module.declareLegacyNamespace(); -goog.require('goog.crypt'); -goog.require('goog.crypt.base64'); -goog.require('goog.string'); +const BinaryConstants = goog.require('jspb.BinaryConstants'); +const { assert } = goog.require('goog.asserts'); +const { isBigIntAvailable } = goog.require('jspb.internal_options'); +const { ByteString } = goog.require('jspb.bytestring'); +const { decodeStringToUint8Array } = goog.require('goog.crypt.base64'); +const { unsafeUint8ArrayFromByteString } = goog.require('jspb.unsafe_bytestring'); + +/** + * Flag for browser support of Uint8Array slicing. + * + * This isn't available in every browser that supports Uint8Array + * + * See https://caniuse.com/mdn-javascript_builtins_typedarray_slice and + * go/jscompiler-flags#browser-featureset-year-options + * @const {boolean} + */ +const SUPPORTS_UINT8ARRAY_SLICING = goog.FEATURESET_YEAR >= 2018 || + (typeof Uint8Array.prototype.slice === 'function'); -goog.require('jspb.asserts'); -goog.require('jspb.BinaryConstants'); +/** @const {number} */ +const MAX_SCRATCHPAD_BYTES = 8; + +/** + * Returns a copy of a slice of a Uint8Array. + * + * @param {!Uint8Array} arr the input array to slice. + * @param {number} startIdx The starting index of the slice. + * @param {number} endIdx The ending index of the slice. + * @return {!Uint8Array} the array slice. + */ +function sliceUint8Array(arr, startIdx, endIdx) { + // See https://jsbench.me/ysl0kb8y54/1 + // This test is significantly faster than native slice performance for an + // empty slice, and empty slices are not uncommon. + if (startIdx === endIdx) { + return new Uint8Array(0); + } + return SUPPORTS_UINT8ARRAY_SLICING ? + arr.slice(startIdx, endIdx) : + new Uint8Array(arr.subarray(startIdx, endIdx)); +} /** * Javascript can't natively handle 64-bit data types, so to manipulate them we @@ -56,102 +62,70 @@ goog.require('jspb.BinaryConstants'); * integer, this temporary value will contain the low 32 bits of that integer. * If the original value was a double, this temporary value will contain the * low 32 bits of the binary representation of that double, etcetera. + * + * This value may be signed or unsigned for the same bit pattern. Coerce to a + * specific interpretation before use if needed. * @type {number} - * @private */ -jspb.utils.split64Low = 0; +let split64Low = 0; /** * And correspondingly, this temporary variable will contain the high 32 bits * of whatever value was split. * @type {number} - * @private */ -jspb.utils.split64High = 0; - - -/** - * @return {number} - * @export - */ -jspb.utils.getSplit64Low = function() { - return jspb.utils.split64Low; -} - -/** - * @return {number} - * @export - */ -jspb.utils.getSplit64High = function() { - return jspb.utils.split64High; -} +let split64High = 0; +/** @type {!DataView|undefined} */ +let scratchpad; /** * Splits an unsigned Javascript integer into two 32-bit halves and stores it * in the temp values above. * @param {number} value The number to split. - * @export */ -jspb.utils.splitUint64 = function(value) { +function splitUint64(value) { // Extract low 32 bits and high 32 bits as unsigned integers. - var lowBits = value >>> 0; - var highBits = - Math.floor((value - lowBits) / jspb.BinaryConstants.TWO_TO_32) >>> 0; - - jspb.utils.split64Low = lowBits; - jspb.utils.split64High = highBits; -}; + const lowBits = value >>> 0; + const highBits = ((value - lowBits) / BinaryConstants.TWO_TO_32) >>> 0; + split64Low = lowBits; + split64High = highBits; +} /** * Splits a signed Javascript integer into two 32-bit halves and stores it in * the temp values above. * @param {number} value The number to split. - * @export */ -jspb.utils.splitInt64 = function(value) { - // Convert to sign-magnitude representation. - var sign = (value < 0); - value = Math.abs(value); - - // Extract low 32 bits and high 32 bits as unsigned integers. - var lowBits = value >>> 0; - var highBits = Math.floor((value - lowBits) / jspb.BinaryConstants.TWO_TO_32); - highBits = highBits >>> 0; - +function splitInt64(value) { // Perform two's complement conversion if the sign bit was set. - if (sign) { - highBits = ~highBits >>> 0; - lowBits = ~lowBits >>> 0; - lowBits += 1; - if (lowBits > 0xFFFFFFFF) { - lowBits = 0; - highBits++; - if (highBits > 0xFFFFFFFF) highBits = 0; - } + if (value < 0) { + // Convert to sign-magnitude representation. + splitUint64(0 - value); + const [negLow, negHigh] = negate(split64Low, split64High); + split64Low = negLow >>> 0; + split64High = negHigh >>> 0; + } else { + splitUint64(value); } - - jspb.utils.split64Low = lowBits; - jspb.utils.split64High = highBits; -}; +} /** * Converts a signed Javascript integer into zigzag format, splits it into two * 32-bit halves, and stores it in the temp values above. * @param {number} value The number to split. - * @export */ -jspb.utils.splitZigzag64 = function(value) { +function splitZigzag64(value) { // Convert to sign-magnitude and scale by 2 before we split the value. - var sign = (value < 0); + const sign = (value < 0); value = Math.abs(value) * 2; - jspb.utils.splitUint64(value); - var lowBits = jspb.utils.split64Low; - var highBits = jspb.utils.split64High; + splitUint64(value); + let lowBits = split64Low; + let highBits = split64High; // If the value is negative, subtract 1 from the split representation so we // don't lose the sign bit due to precision issues. @@ -169,196 +143,90 @@ jspb.utils.splitZigzag64 = function(value) { } } - jspb.utils.split64Low = lowBits; - jspb.utils.split64High = highBits; -}; + split64Low = lowBits; + split64High = highBits; +} +/** + * Initialize the scratchpad `DataView` to the given number of bytes and + * returns scratchpad. + * @param {number} numBytes + * @return {!DataView} + */ +function getScratchpad(numBytes) { + assert(numBytes <= MAX_SCRATCHPAD_BYTES); + return scratchpad || + (scratchpad = new DataView(new ArrayBuffer(MAX_SCRATCHPAD_BYTES))); +} /** * Converts a floating-point number into 32-bit IEEE representation and stores * it in the temp values above. - * @param {number} value - * @export - */ -jspb.utils.splitFloat32 = function(value) { - var sign = (value < 0) ? 1 : 0; - value = sign ? -value : value; - var exp; - var mant; - - // Handle zeros. - if (value === 0) { - if ((1 / value) > 0) { - // Positive zero. - jspb.utils.split64High = 0; - jspb.utils.split64Low = 0x00000000; - } else { - // Negative zero. - jspb.utils.split64High = 0; - jspb.utils.split64Low = 0x80000000; - } - return; - } - - // Handle nans. - if (isNaN(value)) { - jspb.utils.split64High = 0; - jspb.utils.split64Low = 0x7FFFFFFF; - return; - } - - // Handle infinities. - if (value > jspb.BinaryConstants.FLOAT32_MAX) { - jspb.utils.split64High = 0; - jspb.utils.split64Low = ((sign << 31) | (0x7F800000)) >>> 0; - return; - } - - // Handle denormals. - if (value < jspb.BinaryConstants.FLOAT32_MIN) { - // Number is a denormal. - mant = Math.round(value / Math.pow(2, -149)); - jspb.utils.split64High = 0; - jspb.utils.split64Low = ((sign << 31) | mant) >>> 0; - return; - } - - exp = Math.floor(Math.log(value) / Math.LN2); - mant = value * Math.pow(2, -exp); - mant = Math.round(mant * jspb.BinaryConstants.TWO_TO_23); - if (mant >= 0x1000000) { - ++exp; - } - mant = mant & 0x7FFFFF; - - jspb.utils.split64High = 0; - jspb.utils.split64Low = ((sign << 31) | ((exp + 127) << 23) | mant) >>> 0; -}; + * @param {number|string} value to split. Accepts 'Infinity'/'-Infinity'/'NaN' + * for JSPB wire format compatibility. + */ +function splitFloat32(value) { + const scratch = getScratchpad(/* numBytes= */ 4); + // See go/proto-encoding#cheat-sheet re: little endian. + scratch.setFloat32(0, +value, /* littleEndian= */ true); + split64High = 0; + split64Low = scratch.getUint32(0, /* littleEndian = */ true); +} /** * Converts a floating-point number into 64-bit IEEE representation and stores * it in the temp values above. - * @param {number} value - * @export - */ -jspb.utils.splitFloat64 = function(value) { - var sign = (value < 0) ? 1 : 0; - value = sign ? -value : value; - - // Handle zeros. - if (value === 0) { - if ((1 / value) > 0) { - // Positive zero. - jspb.utils.split64High = 0x00000000; - jspb.utils.split64Low = 0x00000000; - } else { - // Negative zero. - jspb.utils.split64High = 0x80000000; - jspb.utils.split64Low = 0x00000000; - } - return; - } - - // Handle nans. - if (isNaN(value)) { - jspb.utils.split64High = 0x7FFFFFFF; - jspb.utils.split64Low = 0xFFFFFFFF; - return; - } - - // Handle infinities. - if (value > jspb.BinaryConstants.FLOAT64_MAX) { - jspb.utils.split64High = ((sign << 31) | (0x7FF00000)) >>> 0; - jspb.utils.split64Low = 0; - return; - } - - // Handle denormals. - if (value < jspb.BinaryConstants.FLOAT64_MIN) { - // Number is a denormal. - var mant = value / Math.pow(2, -1074); - var mantHigh = (mant / jspb.BinaryConstants.TWO_TO_32); - jspb.utils.split64High = ((sign << 31) | mantHigh) >>> 0; - jspb.utils.split64Low = (mant >>> 0); - return; - } - - // Compute the least significant exponent needed to represent the magnitude of - // the value by repeadly dividing/multiplying by 2 until the magnitude - // crosses 2. While tempting to use log math to find the exponent, at the - // boundaries of precision, the result can be off by one. - var maxDoubleExponent = 1023; - var minDoubleExponent = -1022; - var x = value; - var exp = 0; - if (x >= 2) { - while (x >= 2 && exp < maxDoubleExponent) { - exp++; - x = x / 2; - } - } else { - while (x < 1 && exp > minDoubleExponent) { - x = x * 2; - exp--; - } - } - var mant = value * Math.pow(2, -exp); - - var mantHigh = (mant * jspb.BinaryConstants.TWO_TO_20) & 0xFFFFF; - var mantLow = (mant * jspb.BinaryConstants.TWO_TO_52) >>> 0; - - jspb.utils.split64High = - ((sign << 31) | ((exp + 1023) << 20) | mantHigh) >>> 0; - jspb.utils.split64Low = mantLow; -}; + * @param {number|string} value to split. Accepts 'Infinity'/'-Infinity'/'NaN' + * for JSPB wire format compatibility. + */ +function splitFloat64(value) { + const scratch = getScratchpad(/* numBytes= */ 8); + // See go/proto-encoding#cheat-sheet re: little endian. + scratch.setFloat64(0, +value, /* littleEndian= */ true); + split64Low = scratch.getUint32(0, /* littleEndian = */ true); + split64High = scratch.getUint32(4, /* littleEndian = */ true); +} /** - * Converts an 8-character hash string into two 32-bit numbers and stores them - * in the temp values above. - * @param {string} hash - * @export + * Converts an 8-byte array into two 32-bit numbers and stores them in the temp + * values above. + * @param {!Array} bytes */ -jspb.utils.splitHash64 = function(hash) { - var a = hash.charCodeAt(0); - var b = hash.charCodeAt(1); - var c = hash.charCodeAt(2); - var d = hash.charCodeAt(3); - var e = hash.charCodeAt(4); - var f = hash.charCodeAt(5); - var g = hash.charCodeAt(6); - var h = hash.charCodeAt(7); - - jspb.utils.split64Low = (a + (b << 8) + (c << 16) + (d << 24)) >>> 0; - jspb.utils.split64High = (e + (f << 8) + (g << 16) + (h << 24)) >>> 0; -}; +function splitBytes64(bytes) { + const [a, b, c, d, e, f, g, h] = bytes; + + split64Low = (a + (b << 8) + (c << 16) + (d << 24)) >>> 0; + split64High = (e + (f << 8) + (g << 16) + (h << 24)) >>> 0; +} /** - * Joins two 32-bit values into a 64-bit unsigned integer. Precision will be - * lost if the result is greater than 2^52. + * Joins two 32-bit values into a 64-bit unsigned integer. Value will be + * returned as a string if it is greater than 2^52 to avoid precision loss. * @param {number} bitsLow * @param {number} bitsHigh * @return {number} - * @export */ -jspb.utils.joinUint64 = function(bitsLow, bitsHigh) { - return bitsHigh * jspb.BinaryConstants.TWO_TO_32 + (bitsLow >>> 0); -}; - +function joinUint64(bitsLow, bitsHigh) { + const maybeUnsafeValue = + bitsHigh * BinaryConstants.TWO_TO_32 + (bitsLow >>> 0); + return Number.isSafeInteger(maybeUnsafeValue) ? + maybeUnsafeValue : /** @type {number} */ + (/** @type {*} */ (joinUnsignedDecimalString(bitsLow, bitsHigh))); +} /** - * Joins two 32-bit values into a 64-bit signed integer. Precision will be lost - * if the result is greater than 2^52. + * Joins two 32-bit values into a 64-bit signed integer. Value will be + * returned as a string if it outside of the safe integer range. * @param {number} bitsLow * @param {number} bitsHigh * @return {number} - * @export */ -jspb.utils.joinInt64 = function(bitsLow, bitsHigh) { +function joinInt64(bitsLow, bitsHigh) { // If the high bit is set, do a manual two's complement conversion. - var sign = (bitsHigh & 0x80000000); + const sign = (bitsHigh & 0x80000000); if (sign) { bitsLow = (~bitsLow + 1) >>> 0; bitsHigh = ~bitsHigh >>> 0; @@ -367,9 +235,25 @@ jspb.utils.joinInt64 = function(bitsLow, bitsHigh) { } } - var result = jspb.utils.joinUint64(bitsLow, bitsHigh); - return sign ? -result : result; -}; + const result = joinUint64(bitsLow, bitsHigh); + if (typeof result === 'number') { + return sign ? -result : result; + } + + return sign ? /** @type {number} */ (/** @type {*} */ ('-' + result)) : + result; +} + +/** + * Converts 32-bit values from standard two's complement encoding to zig-zag + * encoding. + * + * @param {number} value + * @return {number} + */ +function toZigzag32(value) { + return ((value << 1) ^ (value >> 31)) >>> 0; +} /** * Converts split 64-bit values from standard two's complement encoding to @@ -381,9 +265,8 @@ jspb.utils.joinInt64 = function(bitsLow, bitsHigh) { * the result value, takes parameters (lowBits, highBits). * @return {T} * @template T - * @export */ -jspb.utils.toZigzag64 = function(bitsLow, bitsHigh, convert) { +function toZigzag64(bitsLow, bitsHigh, convert) { // See // https://engdoc.corp.google.com/eng/howto/protocolbuffers/developerguide/encoding.shtml?cl=head#types // 64-bit math is: (n << 1) ^ (n >> 63) @@ -393,11 +276,11 @@ jspb.utils.toZigzag64 = function(bitsLow, bitsHigh, convert) { // Then we can operate on each word individually, with the addition of the // "carry" to get the most significant bit from the low word into the high // word. - var signFlipMask = bitsHigh >> 31; + const signFlipMask = bitsHigh >> 31; bitsHigh = (bitsHigh << 1 | bitsLow >>> 31) ^ signFlipMask; bitsLow = (bitsLow << 1) ^ signFlipMask; return convert(bitsLow, bitsHigh); -}; +} /** @@ -406,12 +289,21 @@ jspb.utils.toZigzag64 = function(bitsLow, bitsHigh, convert) { * @param {number} bitsLow * @param {number} bitsHigh * @return {number} - * @export */ -jspb.utils.joinZigzag64 = function(bitsLow, bitsHigh) { - return jspb.utils.fromZigzag64(bitsLow, bitsHigh, jspb.utils.joinInt64); -}; +function joinZigzag64(bitsLow, bitsHigh) { + return fromZigzag64(bitsLow, bitsHigh, joinInt64); +} +/** + * Converts 32-bit value from zigzag encoding to standard two's + * complement encoding. + * @param {number} zigzag + * @return {number} + */ +function fromZigzag32(zigzag) { + const signFlipMask = -(zigzag & 1); + return (zigzag >>> 1) ^ signFlipMask; +} /** * Converts split 64-bit values from zigzag encoding to standard two's @@ -423,9 +315,8 @@ jspb.utils.joinZigzag64 = function(bitsLow, bitsHigh) { * the result value, takes parameters (lowBits, highBits). * @return {T} * @template T - * @export */ -jspb.utils.fromZigzag64 = function(bitsLow, bitsHigh, convert) { +function fromZigzag64(bitsLow, bitsHigh, convert) { // 64 bit math is: // signmask = (zigzag & 1) ? -1 : 0; // twosComplement = (zigzag >> 1) ^ signmask; @@ -433,11 +324,11 @@ jspb.utils.fromZigzag64 = function(bitsLow, bitsHigh, convert) { // To work with 32 bit, we can operate on both but "carry" the lowest bit // from the high word by shifting it up 31 bits to be the most significant bit // of the low word. - var signFlipMask = -(bitsLow & 1); + const signFlipMask = -(bitsLow & 1); bitsLow = ((bitsLow >>> 1) | (bitsHigh << 31)) ^ signFlipMask; bitsHigh = (bitsHigh >>> 1) ^ signFlipMask; return convert(bitsLow, bitsHigh); -}; +} /** @@ -446,12 +337,11 @@ jspb.utils.fromZigzag64 = function(bitsLow, bitsHigh, convert) { * @param {number} bitsLow The low 32 bits of the binary number; * @param {number} bitsHigh The high 32 bits of the binary number. * @return {number} - * @export */ -jspb.utils.joinFloat32 = function(bitsLow, bitsHigh) { - var sign = ((bitsLow >> 31) * 2 + 1); - var exp = (bitsLow >>> 23) & 0xFF; - var mant = bitsLow & 0x7FFFFF; +function joinFloat32(bitsLow, bitsHigh) { + const sign = ((bitsLow >> 31) * 2 + 1); + const exp = (bitsLow >>> 23) & 0xFF; + const mant = bitsLow & 0x7FFFFF; if (exp == 0xFF) { if (mant) { @@ -467,7 +357,7 @@ jspb.utils.joinFloat32 = function(bitsLow, bitsHigh) { } else { return sign * Math.pow(2, exp - 150) * (mant + Math.pow(2, 23)); } -}; +} /** @@ -476,12 +366,11 @@ jspb.utils.joinFloat32 = function(bitsLow, bitsHigh) { * @param {number} bitsLow The low 32 bits of the binary number; * @param {number} bitsHigh The high 32 bits of the binary number. * @return {number} - * @export */ -jspb.utils.joinFloat64 = function(bitsLow, bitsHigh) { - var sign = ((bitsHigh >> 31) * 2 + 1); - var exp = (bitsHigh >>> 20) & 0x7FF; - var mant = jspb.BinaryConstants.TWO_TO_32 * (bitsHigh & 0xFFFFF) + bitsLow; +function joinFloat64(bitsLow, bitsHigh) { + const sign = ((bitsHigh >> 31) * 2 + 1); + const exp = (bitsHigh >>> 20) & 0x7FF; + const mant = BinaryConstants.TWO_TO_32 * (bitsHigh & 0xFFFFF) + bitsLow; if (exp == 0x7FF) { if (mant) { @@ -495,46 +384,9 @@ jspb.utils.joinFloat64 = function(bitsLow, bitsHigh) { // Denormal. return sign * Math.pow(2, -1074) * mant; } else { - return sign * Math.pow(2, exp - 1075) * - (mant + jspb.BinaryConstants.TWO_TO_52); + return sign * Math.pow(2, exp - 1075) * (mant + BinaryConstants.TWO_TO_52); } -}; - - -/** - * Joins two 32-bit values into an 8-character hash string. - * @param {number} bitsLow - * @param {number} bitsHigh - * @return {string} - * @export - */ -jspb.utils.joinHash64 = function(bitsLow, bitsHigh) { - var a = (bitsLow >>> 0) & 0xFF; - var b = (bitsLow >>> 8) & 0xFF; - var c = (bitsLow >>> 16) & 0xFF; - var d = (bitsLow >>> 24) & 0xFF; - var e = (bitsHigh >>> 0) & 0xFF; - var f = (bitsHigh >>> 8) & 0xFF; - var g = (bitsHigh >>> 16) & 0xFF; - var h = (bitsHigh >>> 24) & 0xFF; - - return String.fromCharCode(a, b, c, d, e, f, g, h); -}; - -/** - * Individual digits for number->string conversion. - * @const {!Array} - * @export - */ -jspb.utils.DIGITS = [ - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' -]; - -/** @const @private {number} '0' */ -jspb.utils.ZERO_CHAR_CODE_ = 48; - -/** @const @private {number} 'a' */ -jspb.utils.A_CHAR_CODE_ = 97; +} /** * Losslessly converts a 64-bit unsigned integer in 32:32 split representation @@ -542,65 +394,88 @@ jspb.utils.A_CHAR_CODE_ = 97; * @param {number} bitsLow The low 32 bits of the binary number; * @param {number} bitsHigh The high 32 bits of the binary number. * @return {string} The binary number represented as a string. - * @export */ -jspb.utils.joinUnsignedDecimalString = function(bitsLow, bitsHigh) { +function joinUnsignedDecimalString(bitsLow, bitsHigh) { + // Must ensure the values are handled as unsigned, any bitwise operations + // on the input arguments would have turned them into signed values (e.g. + // zigzag decoding). + bitsHigh = bitsHigh >>> 0; + bitsLow = bitsLow >>> 0; // Skip the expensive conversion if the number is small enough to use the // built-in conversions. + // Number.MAX_SAFE_INTEGER = 0x001FFFFF FFFFFFFF, thus any number with + // bitsHigh <= 0x1FFFFF can be safely expressed with a double and retain + // integer precision. + // Proven by: Number.isSafeInteger(0x1FFFFF * 2**32 + 0xFFFFFFFF) == true. + // Even when BigInt is supported, it's faster to avoid the conversion to + // bigint and back. if (bitsHigh <= 0x1FFFFF) { - return '' + jspb.utils.joinUint64(bitsLow, bitsHigh); + return '' + (BinaryConstants.TWO_TO_32 * bitsHigh + bitsLow); + } else if (isBigIntAvailable()) { + return '' + (BigInt(bitsHigh) << BigInt(32) | BigInt(bitsLow)); } + return joinUnsignedDecimalStringFallback(bitsLow, bitsHigh); +} +/** + * Losslessly converts a 64-bit unsigned integer in 32:32 split representation + * into a decimal string without using BigInt. + * @param {number} bitsLow The unsigned low 32 bits of the binary number; + * @param {number} bitsHigh The unsigned high 32 bits of the binary number. + * @return {string} The binary number represented as a string. + * @package For Testing only. + */ +function joinUnsignedDecimalStringFallback(bitsLow, bitsHigh) { // What this code is doing is essentially converting the input number from // base-2 to base-1e7, which allows us to represent the 64-bit range with // only 3 (very large) digits. Those digits are then trivial to convert to // a base-10 string. - // The magic numbers used here are - - // 2^24 = 16777216 = (1,6777216) in base-1e7. - // 2^48 = 281474976710656 = (2,8147497,6710656) in base-1e7. - // Split 32:32 representation into 16:24:24 representation so our // intermediate digits don't overflow. - var low = bitsLow & 0xFFFFFF; - var mid = (((bitsLow >>> 24) | (bitsHigh << 8)) >>> 0) & 0xFFFFFF; - var high = (bitsHigh >> 16) & 0xFFFF; + const low = bitsLow & LOW_24_BITS; + const mid = ((bitsLow >>> 24) | (bitsHigh << 8)) & LOW_24_BITS; + const high = (bitsHigh >> 16) & LOW_16_BITS; // Assemble our three base-1e7 digits, ignoring carries. The maximum // value in a digit at this step is representable as a 48-bit integer, which // can be stored in a 64-bit floating point number. - var digitA = low + (mid * 6777216) + (high * 6710656); - var digitB = mid + (high * 8147497); - var digitC = (high * 2); + + // The magic numbers used here are - + // 2^24 = 16777216 = (1,6777216) in base-1e7. + // 2^48 = 281474976710656 = (2,8147497,6710656) in base-1e7. + let digitA = low + (mid * 6777216) + (high * 6710656); + let digitB = mid + (high * 8147497); + let digitC = (high * 2); // Apply carries from A to B and from B to C. - var base = 10000000; + const base = 10000000; if (digitA >= base) { - digitB += Math.floor(digitA / base); + digitB += (digitA / base) >>> 0; digitA %= base; } if (digitB >= base) { - digitC += Math.floor(digitB / base); + digitC += (digitB / base) >>> 0; digitB %= base; } - // Convert base-1e7 digits to base-10, with optional leading zeroes. - function decimalFrom1e7(digit1e7, needLeadingZeros) { - var partial = digit1e7 ? String(digit1e7) : ''; - if (needLeadingZeros) { - return '0000000'.slice(partial.length) + partial; - } - return partial; - } - - return decimalFrom1e7(digitC, /*needLeadingZeros=*/ 0) + - decimalFrom1e7(digitB, /*needLeadingZeros=*/ digitC) + - // If the final 1e7 digit didn't need leading zeros, we would have - // returned via the trivial code path at the top. - decimalFrom1e7(digitA, /*needLeadingZeros=*/ 1); -}; + // If digitC is 0, then we should have returned in the trivial code path + // at the top for non-safe integers. Given this, we can assume both digitB + // and digitA need leading zeros. + assert(digitC); + return digitC + decimalFrom1e7WithLeadingZeros(digitB) + + decimalFrom1e7WithLeadingZeros(digitA); +} +/** + * @param {number} digit1e7 Number < 1e7 + * @return {string} Decimal representation of digit1e7 with leading zeros. + */ +function decimalFrom1e7WithLeadingZeros(digit1e7) { + const partial = String(digit1e7); + return '0000000'.slice(partial.length) + partial; +} /** * Losslessly converts a 64-bit signed integer in 32:32 split representation @@ -608,218 +483,156 @@ jspb.utils.joinUnsignedDecimalString = function(bitsLow, bitsHigh) { * @param {number} bitsLow The low 32 bits of the binary number; * @param {number} bitsHigh The high 32 bits of the binary number. * @return {string} The binary number represented as a string. - * @export */ -jspb.utils.joinSignedDecimalString = function(bitsLow, bitsHigh) { - // If we're treating the input as a signed value and the high bit is set, do - // a manual two's complement conversion before the decimal conversion. - var negative = (bitsHigh & 0x80000000); +function joinSignedDecimalString(bitsLow, bitsHigh) { + const negative = (bitsHigh & 0x80000000); if (negative) { - bitsLow = (~bitsLow + 1) >>> 0; - var carry = (bitsLow == 0) ? 1 : 0; - bitsHigh = (~bitsHigh + carry) >>> 0; + if (isBigIntAvailable()) { + return '' + + ((BigInt(bitsHigh | 0) << BigInt(32)) | BigInt(bitsLow >>> 0)); + } + return joinNegativeDecimalStringFallback(bitsLow, bitsHigh); + } else { + return joinUnsignedDecimalString(bitsLow, bitsHigh); } - - var result = jspb.utils.joinUnsignedDecimalString(bitsLow, bitsHigh); - return negative ? '-' + result : result; -}; - +} /** - * Convert an 8-character hash string representing either a signed or unsigned - * 64-bit integer into its decimal representation without losing accuracy. - * @param {string} hash The hash string to convert. - * @param {boolean} signed True if we should treat the hash string as encoding - * a signed integer. - * @return {string} - * @export + * Losslessly converts a 64-bit signed integer in 32:32 split representation + * into a number or decimal string, using a number when the value is between + * [Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER], or decimal string + * otherwise. + * + * @param {number} bitsLow The low 32 bits of the binary number; + * @param {number} bitsHigh The high 32 bits of the binary number. + * @return {number|string} The number represented as a number or string. */ -jspb.utils.hash64ToDecimalString = function(hash, signed) { - jspb.utils.splitHash64(hash); - var bitsLow = jspb.utils.split64Low; - var bitsHigh = jspb.utils.split64High; - return signed ? jspb.utils.joinSignedDecimalString(bitsLow, bitsHigh) : - jspb.utils.joinUnsignedDecimalString(bitsLow, bitsHigh); -}; - +function joinSignedNumberOrDecimalString(bitsLow, bitsHigh) { + const possiblyUnsafe = joinInt64(bitsLow, bitsHigh); + if (Number.isSafeInteger(possiblyUnsafe)) { + return possiblyUnsafe; + } + return joinSignedDecimalString(bitsLow, bitsHigh); +} /** - * Converts an array of 8-character hash strings into their decimal - * representations. - * @param {!Array} hashes The array of hash strings to convert. - * @param {boolean} signed True if we should treat the hash string as encoding - * a signed integer. - * @return {!Array} - * @export + * Losslessly converts a 64-bit unsigned integer in 32:32 split representation + * into a number or decimal string, using a number when the value is between + * [0, Number.MAX_SAFE_INTEGER], or decimal string otherwise. + * + * @param {number} bitsLow The low 32 bits of the binary number; + * @param {number} bitsHigh The high 32 bits of the binary number. + * @return {number|string} The number represented as a number or string. */ -jspb.utils.hash64ArrayToDecimalStrings = function(hashes, signed) { - var result = new Array(hashes.length); - for (var i = 0; i < hashes.length; i++) { - result[i] = jspb.utils.hash64ToDecimalString(hashes[i], signed); +function joinUnsignedNumberOrDecimalString(bitsLow, bitsHigh) { + bitsHigh >>>= 0; + const possiblyUnsafe = joinUint64(bitsLow, bitsHigh); + if (Number.isSafeInteger(possiblyUnsafe)) { + return possiblyUnsafe; } - return result; -}; - + return joinUnsignedDecimalString(bitsLow, bitsHigh); +} /** - * Converts a signed or unsigned decimal string into its hash string - * representation. - * @param {string} dec - * @return {string} - * @export + * Losslessly converts a 64-bit signed integer in 32:32 split representation + * into a decimal string. + * @param {number} bitsLow The low 32 bits of the binary number; + * @param {number} bitsHigh The high 32 bits of the binary number. + * @return {string} The binary number represented as a string. + * @package For Testing only. */ -jspb.utils.decimalStringToHash64 = function(dec) { - jspb.asserts.assert(dec.length > 0); - - // Check for minus sign. - var minus = false; - if (dec[0] === '-') { - minus = true; - dec = dec.slice(1); - } - - // Store result as a byte array. - var resultBytes = [0, 0, 0, 0, 0, 0, 0, 0]; - - // Set result to m*result + c. - function muladd(m, c) { - for (var i = 0; i < 8 && (m !== 1 || c > 0); i++) { - var r = m * resultBytes[i] + c; - resultBytes[i] = r & 0xFF; - c = r >>> 8; - } - } - - // Negate the result bits. - function neg() { - for (var i = 0; i < 8; i++) { - resultBytes[i] = (~resultBytes[i]) & 0xFF; - } - } - - // For each decimal digit, set result to 10*result + digit. - for (var i = 0; i < dec.length; i++) { - muladd(10, dec.charCodeAt(i) - jspb.utils.ZERO_CHAR_CODE_); - } - - // If there's a minus sign, convert into two's complement. - if (minus) { - neg(); - muladd(1, 1); - } - - return goog.crypt.byteArrayToString(resultBytes); -}; +function joinNegativeDecimalStringFallback(bitsLow, bitsHigh) { + // Do a manual two's complement conversion before the decimal conversion. + const [negLow, negHigh] = negate(bitsLow, bitsHigh); + bitsLow = negLow; + bitsHigh = negHigh; + return '-' + joinUnsignedDecimalString(bitsLow, bitsHigh); +} /** * Converts a signed or unsigned decimal string into two 32-bit halves, and - * stores them in the temp variables listed above. + * stores them in the temp variables listed above. Only the lower 64 bits of the + * value are kept. * @param {string} value The decimal string to convert. - * @export */ -jspb.utils.splitDecimalString = function(value) { - jspb.utils.splitHash64(jspb.utils.decimalStringToHash64(value)); -}; +function splitDecimalString(value) { + assert(value.length > 0); -/** - * @param {number} nibble A 4-bit integer. - * @return {string} - * @private - */ -jspb.utils.toHexDigit_ = function(nibble) { - return String.fromCharCode( - nibble < 10 ? jspb.utils.ZERO_CHAR_CODE_ + nibble : - jspb.utils.A_CHAR_CODE_ - 10 + nibble); -}; - -/** - * @param {number} hexCharCode - * @return {number} - * @private - */ -jspb.utils.fromHexCharCode_ = function(hexCharCode) { - if (hexCharCode >= jspb.utils.A_CHAR_CODE_) { - return hexCharCode - jspb.utils.A_CHAR_CODE_ + 10; + // Strings that are shorter than MAX_SAFE_INTEGER are sure to be safe + // to parse directly to a double for conversion with Int64.fromNumber. + if (value.length < MAX_SAFE_INTEGER_DECIMAL_LENGTH) { + splitInt64(Number(value)); + return; } - return hexCharCode - jspb.utils.ZERO_CHAR_CODE_; -}; -/** - * Converts an 8-character hash string into its hexadecimal representation. - * @param {string} hash - * @return {string} - * @export - */ -jspb.utils.hash64ToHexString = function(hash) { - var temp = new Array(18); - temp[0] = '0'; - temp[1] = 'x'; - - for (var i = 0; i < 8; i++) { - var c = hash.charCodeAt(7 - i); - temp[i * 2 + 2] = jspb.utils.toHexDigit_(c >> 4); - temp[i * 2 + 3] = jspb.utils.toHexDigit_(c & 0xF); + if (isBigIntAvailable()) { + const bigInt = BigInt(value); + split64Low = Number(bigInt & BigInt(ALL_32_BITS)) >>> 0; + split64High = Number((bigInt >> BigInt(32)) & BigInt(ALL_32_BITS)); + } else { + splitDecimalStringFallback(value); } - - var result = temp.join(''); - return result; -}; - +} /** - * Converts a '0x<16 digits>' hex string into its hash string representation. - * @param {string} hex - * @return {string} - * @export + * Converts a signed or unsigned decimal string into two 32-bit halves, and + * stores them in the temp variables listed above. Only the lower 64 bits of the + * value are kept. + * @param {string} value The decimal string to convert. + * @package For Testing only. */ -jspb.utils.hexStringToHash64 = function(hex) { - hex = hex.toLowerCase(); - jspb.asserts.assert(hex.length == 18); - jspb.asserts.assert(hex[0] == '0'); - jspb.asserts.assert(hex[1] == 'x'); - - var result = ''; - for (var i = 0; i < 8; i++) { - var hi = jspb.utils.fromHexCharCode_(hex.charCodeAt(i * 2 + 2)); - var lo = jspb.utils.fromHexCharCode_(hex.charCodeAt(i * 2 + 3)); - result = String.fromCharCode(hi * 16 + lo) + result; +function splitDecimalStringFallback(value) { + assert(value.length > 0); + // Check for minus sign. + const firstDigitIndex = +(value[0] === '-'); + split64Low = 0; + split64High = 0; + const end = value.length; + // Work 6 decimal digits at a time, acting like we're converting base 1e6 + // digits to binary. This is safe to do with floating point math because + // Number.isSafeInteger(ALL_32_BITS * 1e6) == true. + const base = 1e6; + for (let sliceStart = 0 + firstDigitIndex, + sliceEnd = (end - firstDigitIndex) % 6 + firstDigitIndex; + sliceEnd <= end; sliceStart = sliceEnd, sliceEnd += 6) { + const digit1e6 = Number(value.slice(sliceStart, sliceEnd)); + split64High *= base; + split64Low = split64Low * base + digit1e6; + // Carry bits from split64Low to + if (split64Low >= BinaryConstants.TWO_TO_32) { + split64High += Math.trunc(split64Low / BinaryConstants.TWO_TO_32); + // Drop any bits higher than 64 as we accumulate + split64High = split64High >>> 0; + split64Low = split64Low >>> 0; + } } - return result; -}; - - -/** - * Convert an 8-character hash string representing either a signed or unsigned - * 64-bit integer into a Javascript number. Will lose accuracy if the result is - * larger than 2^52. - * @param {string} hash The hash string to convert. - * @param {boolean} signed True if the has should be interpreted as a signed - * number. - * @return {number} - * @export - */ -jspb.utils.hash64ToNumber = function(hash, signed) { - jspb.utils.splitHash64(hash); - var bitsLow = jspb.utils.split64Low; - var bitsHigh = jspb.utils.split64High; - return signed ? jspb.utils.joinInt64(bitsLow, bitsHigh) : - jspb.utils.joinUint64(bitsLow, bitsHigh); -}; - + if (firstDigitIndex /* != 0 */) { + const [negLow, negHigh] = negate(split64Low, split64High); + split64Low = negLow; + split64High = negHigh; + } +} /** - * Convert a Javascript number into an 8-character hash string. Will lose - * precision if the value is non-integral or greater than 2^64. - * @param {number} value The integer to convert. - * @return {string} - * @export + * @param {number} lowBits + * @param {number} highBits + * @return {!Array} [low, high] words of the result. + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators#Signed_32-bit_integers */ -jspb.utils.numberToHash64 = function(value) { - jspb.utils.splitInt64(value); - return jspb.utils.joinHash64(jspb.utils.split64Low, jspb.utils.split64High); -}; +function negate(lowBits, highBits) { + highBits = ~highBits; + if (lowBits) { + lowBits = ~lowBits + 1; + } else { + // If lowBits is 0, then bitwise-not is 0xFFFFFFFF, + // adding 1 to that, results in 0x100000000, which leaves + // the low bits 0x0 and simply adds one to the high bits. + highBits += 1; + } + return [lowBits, highBits]; +} /** @@ -828,12 +641,11 @@ jspb.utils.numberToHash64 = function(value) { * @param {number} start The starting point in the buffer to scan. * @param {number} end The end point in the buffer to scan. * @return {number} The number of varints in the buffer. - * @export */ -jspb.utils.countVarints = function(buffer, start, end) { +function countVarints(buffer, start, end) { // Count how many high bits of each byte were set in the buffer. - var count = 0; - for (var i = start; i < end; i++) { + let count = 0; + for (let i = start; i < end; i++) { count += buffer[i] >> 7; } @@ -841,7 +653,7 @@ jspb.utils.countVarints = function(buffer, start, end) { // the number of non-terminal bytes in the buffer (those with the high bit // set). return (end - start) - count; -}; +} /** @@ -852,12 +664,11 @@ jspb.utils.countVarints = function(buffer, start, end) { * @param {number} end The end point in the buffer to scan. * @param {number} field The field number to count. * @return {number} The number of matching fields in the buffer. - * @export */ -jspb.utils.countVarintFields = function(buffer, start, end, field) { - var count = 0; - var cursor = start; - var tag = field * 8 + jspb.BinaryConstants.WireType.VARINT; +function countVarintFields(buffer, start, end, field) { + let count = 0; + let cursor = start; + const tag = field * 8 + BinaryConstants.WireType.VARINT; if (tag < 128) { // Single-byte field tag, we can use a slightly quicker count. @@ -870,14 +681,14 @@ jspb.utils.countVarintFields = function(buffer, start, end, field) { // Skip the varint. while (1) { - var x = buffer[cursor++]; + const x = buffer[cursor++]; if ((x & 0x80) == 0) break; } } } else { while (cursor < end) { // Skip the field tag, or exit if we find a non-matching tag. - var temp = tag; + let temp = tag; while (temp > 128) { if (buffer[cursor] != ((temp & 0x7F) | 0x80)) return count; cursor++; @@ -890,13 +701,13 @@ jspb.utils.countVarintFields = function(buffer, start, end, field) { // Skip the varint. while (1) { - var x = buffer[cursor++]; + const x = buffer[cursor++]; if ((x & 0x80) == 0) break; } } } return count; -}; +} /** @@ -910,9 +721,9 @@ jspb.utils.countVarintFields = function(buffer, start, end, field) { * @return {number} The number of fields with a matching tag in the buffer. * @private */ -jspb.utils.countFixedFields_ = function(buffer, start, end, tag, stride) { - var count = 0; - var cursor = start; +function countFixedFields_(buffer, start, end, tag, stride) { + let count = 0; + let cursor = start; if (tag < 128) { // Single-byte field tag, we can use a slightly quicker count. @@ -929,7 +740,7 @@ jspb.utils.countFixedFields_ = function(buffer, start, end, tag, stride) { } else { while (cursor < end) { // Skip the field tag, or exit if we find a non-matching tag. - var temp = tag; + let temp = tag; while (temp > 128) { if (buffer[cursor++] != ((temp & 0x7F) | 0x80)) return count; temp >>= 7; @@ -944,7 +755,7 @@ jspb.utils.countFixedFields_ = function(buffer, start, end, tag, stride) { } } return count; -}; +} /** @@ -955,12 +766,11 @@ jspb.utils.countFixedFields_ = function(buffer, start, end, tag, stride) { * @param {number} end The end point in the buffer to scan. * @param {number} field The field number to count. * @return {number} The number of matching fields in the buffer. - * @export */ -jspb.utils.countFixed32Fields = function(buffer, start, end, field) { - var tag = field * 8 + jspb.BinaryConstants.WireType.FIXED32; - return jspb.utils.countFixedFields_(buffer, start, end, tag, 4); -}; +function countFixed32Fields(buffer, start, end, field) { + const tag = field * 8 + BinaryConstants.WireType.FIXED32; + return countFixedFields_(buffer, start, end, tag, 4); +} /** @@ -971,12 +781,11 @@ jspb.utils.countFixed32Fields = function(buffer, start, end, field) { * @param {number} end The end point in the buffer to scan. * @param {number} field The field number to count * @return {number} The number of matching fields in the buffer. - * @export */ -jspb.utils.countFixed64Fields = function(buffer, start, end, field) { - var tag = field * 8 + jspb.BinaryConstants.WireType.FIXED64; - return jspb.utils.countFixedFields_(buffer, start, end, tag, 8); -}; +function countFixed64Fields(buffer, start, end, field) { + const tag = field * 8 + BinaryConstants.WireType.FIXED64; + return countFixedFields_(buffer, start, end, tag, 8); +} /** @@ -987,16 +796,15 @@ jspb.utils.countFixed64Fields = function(buffer, start, end, field) { * @param {number} end The end point in the buffer to scan. * @param {number} field The field number to count. * @return {number} The number of matching fields in the buffer. - * @export */ -jspb.utils.countDelimitedFields = function(buffer, start, end, field) { - var count = 0; - var cursor = start; - var tag = field * 8 + jspb.BinaryConstants.WireType.DELIMITED; +function countDelimitedFields(buffer, start, end, field) { + let count = 0; + let cursor = start; + const tag = field * 8 + BinaryConstants.WireType.DELIMITED; while (cursor < end) { // Skip the field tag, or exit if we find a non-matching tag. - var temp = tag; + let temp = tag; while (temp > 128) { if (buffer[cursor++] != ((temp & 0x7F) | 0x80)) return count; temp >>= 7; @@ -1007,8 +815,8 @@ jspb.utils.countDelimitedFields = function(buffer, start, end, field) { count++; // Decode the length prefix. - var length = 0; - var shift = 1; + let length = 0; + let shift = 1; while (1) { temp = buffer[cursor++]; length += (temp & 0x7f) * shift; @@ -1020,77 +828,19 @@ jspb.utils.countDelimitedFields = function(buffer, start, end, field) { cursor += length; } return count; -}; - - -/** - * String-ify bytes for text format. Should be optimized away in non-debug. - * The returned string uses \xXX escapes for all values and is itself quoted. - * [1, 31] serializes to '"\x01\x1f"'. - * @param {jspb.ByteSource} byteSource The bytes to serialize. - * @return {string} Stringified bytes for text format. - * @export - */ -jspb.utils.debugBytesToTextFormat = function(byteSource) { - var s = '"'; - if (byteSource) { - var bytes = jspb.utils.byteSourceToUint8Array(byteSource); - for (var i = 0; i < bytes.length; i++) { - s += '\\x'; - if (bytes[i] < 16) s += '0'; - s += bytes[i].toString(16); - } - } - return s + '"'; -}; - - -/** - * String-ify a scalar for text format. Should be optimized away in non-debug. - * @param {string|number|boolean} scalar The scalar to stringify. - * @return {string} Stringified scalar for text format. - * @export - */ -jspb.utils.debugScalarToTextFormat = function(scalar) { - if (typeof scalar === 'string') { - return goog.string.quote(scalar); - } else { - return scalar.toString(); - } -}; - - -/** - * Utility function: convert a string with codepoints 0--255 inclusive to a - * Uint8Array. If any codepoints greater than 255 exist in the string, throws an - * exception. - * @param {string} str - * @return {!Uint8Array} - * @export - */ -jspb.utils.stringToByteArray = function(str) { - var arr = new Uint8Array(str.length); - for (var i = 0; i < str.length; i++) { - var codepoint = str.charCodeAt(i); - if (codepoint > 255) { - throw new Error( - 'Conversion error: string contains codepoint ' + - 'outside of byte range'); - } - arr[i] = codepoint; - } - return arr; -}; - +} /** - * Converts any type defined in jspb.ByteSource into a Uint8Array. - * @param {!jspb.ByteSource} data + * Converts any type defined in ByteSource into a Uint8Array. + * @param {!ByteSource|!ByteString} data + * @param {boolean=} copyByteString whether to make a copy of ByteString + * internal data * @return {!Uint8Array} * @suppress {invalidCasts} - * @export */ -jspb.utils.byteSourceToUint8Array = function(data) { +function byteSourceToUint8Array(data, copyByteString) { + // Comparing a property is much faster than the instanceof test below, so + // prefer this. if (data.constructor === Uint8Array) { return /** @type {!Uint8Array} */ (data); } @@ -1107,18 +857,95 @@ jspb.utils.byteSourceToUint8Array = function(data) { if (data.constructor === String) { data = /** @type {string} */ (data); - return goog.crypt.base64.decodeStringToUint8Array(data); + return decodeStringToUint8Array(data); + } + + if (data.constructor === ByteString) { + data = /** @type {!ByteString} */ (data); + if (!copyByteString) { + return unsafeUint8ArrayFromByteString(data); + } + return data.asUint8Array(); } if (data instanceof Uint8Array) { - // Support types like nodejs Buffer and other subclasses of Uint8Array. + // Support types like nodejs Buffer (a subclass of Uint8Array). data = /** @type {!Uint8Array} */ (data); - // Make a shallow copy to ensure we only ever deal with Uint8Array + // Make a shallow copy to ensure jspb code only ever deals with Uint8Array // exactly to ensure monomorphism. return /** @type {!Uint8Array} */ ( - new Uint8Array(data.buffer, data.byteOffset, data.byteLength)); + new Uint8Array(data.buffer, data.byteOffset, data.byteLength)); } + throw new Error( + 'Type not convertible to a Uint8Array, expected a Uint8Array, an ' + + 'ArrayBuffer, a base64 encoded string, or Array of numbers'); +} + +/** @return {number} */ +function getSplit64Low() { + return split64Low; +} +/** @return {number} */ +function getSplit64High() { + return split64High; +} + +/** + * Makes a wire tag + * @return {number} + */ +function makeTag( + /** number */ fieldNumber, + /** !BinaryConstants.WireType */ wireType) { + // N.B. can't use << 3 because that enforces 2s complement 32 bit math and we + // want unsigned math. Consider that `(2**29 -1) << 3 === -8` but + // `(2**29 -1) * 8 === 4294967288` + return fieldNumber * 8 + wireType; +} - jspb.asserts.fail('Type not convertible to Uint8Array.'); - return /** @type {!Uint8Array} */ (new Uint8Array(0)); +/** @const {number} */ +const LOW_16_BITS = 0xFFFF; + +/** @const {number} */ +const LOW_24_BITS = 0xFFFFFF; + +/** @const {number} */ +const ALL_32_BITS = 0xFFFFFFFF; + +/** @const {number} String(Number.MAX_SAFE_INTEGER).length */ +const MAX_SAFE_INTEGER_DECIMAL_LENGTH = 16; + +exports = { + byteSourceToUint8Array, + countDelimitedFields, + countFixed32Fields, + countFixed64Fields, + countVarintFields, + countVarints, + fromZigzag32, + fromZigzag64, + getSplit64High, + getSplit64Low, + joinFloat32, + joinFloat64, + joinInt64, + joinNegativeDecimalStringFallback, + joinSignedDecimalString, + joinSignedNumberOrDecimalString, + joinUint64, + joinUnsignedDecimalString, + joinUnsignedDecimalStringFallback, + joinUnsignedNumberOrDecimalString, + joinZigzag64, + makeTag, + sliceUint8Array, + splitDecimalString, + splitDecimalStringFallback, + splitFloat32, + splitFloat64, + splitInt64, + splitUint64, + splitZigzag64, + toZigzag32, + toZigzag64, }; diff --git a/binary/utils_test.js b/binary/utils_test.js old mode 100644 new mode 100755 index 5a46905..9f0624b --- a/binary/utils_test.js +++ b/binary/utils_test.js @@ -42,6 +42,35 @@ goog.require('jspb.BinaryConstants'); goog.require('jspb.BinaryWriter'); goog.require('jspb.utils'); +const BinaryWriter = goog.module.get('jspb.BinaryWriter'); +const BinaryMessage = goog.module.get('jspb.BinaryConstants').BinaryMessage; +const FLOAT32_EPS = goog.module.get('jspb.BinaryConstants').FLOAT32_EPS; +const FLOAT32_MAX = goog.module.get('jspb.BinaryConstants').FLOAT32_MAX; +const FLOAT32_MIN = goog.module.get('jspb.BinaryConstants').FLOAT32_MIN; +const FLOAT64_EPS = goog.module.get('jspb.BinaryConstants').FLOAT64_EPS; +const FLOAT64_MAX = goog.module.get('jspb.BinaryConstants').FLOAT64_MAX; +const FLOAT64_MIN = goog.module.get('jspb.BinaryConstants').FLOAT64_MIN; +const byteArrayToString = goog.module.get('goog.crypt').byteArrayToString; +const encodeByteArray = goog.module.get('goog.crypt.base64').encodeByteArray; +const byteSourceToUint8Array = goog.module.get('jspb.utils').byteSourceToUint8Array; +const countDelimitedFields = goog.module.get('jspb.utils').countDelimitedFields; +const countFixed32Fields = goog.module.get('jspb.utils').countFixed32Fields; +const countFixed64Fields = goog.module.get('jspb.utils').countFixed64Fields; +const countVarintFields = goog.module.get('jspb.utils').countVarintFields; +const countVarints = goog.module.get('jspb.utils').countVarints; +const fromZigzag64 = goog.module.get('jspb.utils').fromZigzag64; +const getSplit64High = goog.module.get('jspb.utils').getSplit64High; +const getSplit64Low = goog.module.get('jspb.utils').getSplit64Low; +const hash64ArrayToDecimalStrings = goog.module.get('jspb.utils').hash64ArrayToDecimalStrings; +const hexStringToHash64 = goog.module.get('jspb.utils').hexStringToHash64; +const joinFloat32 = goog.module.get('jspb.utils').joinFloat32; +const joinFloat64 = goog.module.get('jspb.utils').joinFloat64; +const joinUnsignedDecimalString = goog.module.get('jspb.utils').joinUnsignedDecimalString; +const splitDecimalString = goog.module.get('jspb.utils').splitDecimalString; +const splitFloat32 = goog.module.get('jspb.utils').splitFloat32; +const splitFloat64 = goog.module.get('jspb.utils').splitFloat64; +const toZigzag64 = goog.module.get('jspb.utils').toZigzag64; + /** * @param {number} x @@ -63,9 +92,9 @@ function truncate(x) { */ function toHashString(bitsLow, bitsHigh) { return String.fromCharCode( - (bitsLow >>> 0) & 0xFF, (bitsLow >>> 8) & 0xFF, (bitsLow >>> 16) & 0xFF, - (bitsLow >>> 24) & 0xFF, (bitsHigh >>> 0) & 0xFF, (bitsHigh >>> 8) & 0xFF, - (bitsHigh >>> 16) & 0xFF, (bitsHigh >>> 24) & 0xFF); + (bitsLow >>> 0) & 0xFF, (bitsLow >>> 8) & 0xFF, (bitsLow >>> 16) & 0xFF, + (bitsLow >>> 24) & 0xFF, (bitsHigh >>> 0) & 0xFF, (bitsHigh >>> 8) & 0xFF, + (bitsHigh >>> 16) & 0xFF, (bitsHigh >>> 24) & 0xFF); } @@ -75,36 +104,36 @@ describe('binaryUtilsTest', () => { */ it('testDecimalConversion', () => { // Check some magic numbers. - let result = jspb.utils.joinUnsignedDecimalString(0x89e80001, 0x8ac72304); + let result = joinUnsignedDecimalString(0x89e80001, 0x8ac72304); expect(result).toEqual('10000000000000000001'); - result = jspb.utils.joinUnsignedDecimalString(0xacd05f15, 0x1b69b4b); + result = joinUnsignedDecimalString(0xacd05f15, 0x1b69b4b); expect(result).toEqual('123456789123456789'); - result = jspb.utils.joinUnsignedDecimalString(0xeb1f0ad2, 0xab54a98c); + result = joinUnsignedDecimalString(0xeb1f0ad2, 0xab54a98c); expect(result).toEqual('12345678901234567890'); - result = jspb.utils.joinUnsignedDecimalString(0xe3b70cb1, 0x891087b8); + result = joinUnsignedDecimalString(0xe3b70cb1, 0x891087b8); expect(result).toEqual('9876543210987654321'); // Check limits. - result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00000000); + result = joinUnsignedDecimalString(0x00000000, 0x00000000); expect(result).toEqual('0'); - result = jspb.utils.joinUnsignedDecimalString(0xFFFFFFFF, 0xFFFFFFFF); + result = joinUnsignedDecimalString(0xFFFFFFFF, 0xFFFFFFFF); expect(result).toEqual('18446744073709551615'); // Check each bit of the low dword. for (let i = 0; i < 32; i++) { const low = (1 << i) >>> 0; - result = jspb.utils.joinUnsignedDecimalString(low, 0); + result = joinUnsignedDecimalString(low, 0); expect(result).toEqual('' + Math.pow(2, i)); } // Check the first 20 bits of the high dword. for (let i = 0; i < 20; i++) { const high = (1 << i) >>> 0; - result = jspb.utils.joinUnsignedDecimalString(0, high); + result = joinUnsignedDecimalString(0, high); expect(result).toEqual('' + Math.pow(2, 32 + i)); } @@ -112,201 +141,43 @@ describe('binaryUtilsTest', () => { // 2^52, even if they're representable integers - check the rest of the bits // manually against the correct string representations of 2^N. - result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00100000); + result = joinUnsignedDecimalString(0x00000000, 0x00100000); expect(result).toEqual('4503599627370496'); - result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00200000); + result = joinUnsignedDecimalString(0x00000000, 0x00200000); expect(result).toEqual('9007199254740992'); - result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00400000); + result = joinUnsignedDecimalString(0x00000000, 0x00400000); expect(result).toEqual('18014398509481984'); - result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x00800000); + result = joinUnsignedDecimalString(0x00000000, 0x00800000); expect(result).toEqual('36028797018963968'); - result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x01000000); + result = joinUnsignedDecimalString(0x00000000, 0x01000000); expect(result).toEqual('72057594037927936'); - result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x02000000); + result = joinUnsignedDecimalString(0x00000000, 0x02000000); expect(result).toEqual('144115188075855872'); - result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x04000000); + result = joinUnsignedDecimalString(0x00000000, 0x04000000); expect(result).toEqual('288230376151711744'); - result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x08000000); + result = joinUnsignedDecimalString(0x00000000, 0x08000000); expect(result).toEqual('576460752303423488'); - result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x10000000); + result = joinUnsignedDecimalString(0x00000000, 0x10000000); expect(result).toEqual('1152921504606846976'); - result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x20000000); + result = joinUnsignedDecimalString(0x00000000, 0x20000000); expect(result).toEqual('2305843009213693952'); - result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x40000000); + result = joinUnsignedDecimalString(0x00000000, 0x40000000); expect(result).toEqual('4611686018427387904'); - result = jspb.utils.joinUnsignedDecimalString(0x00000000, 0x80000000); - expect(result).toEqual('9223372036854775808'); - }); - - - /** - * Going from hash strings to decimal strings should also be lossless. - */ - it('testHashToDecimalConversion', () => { - let result; - const convert = jspb.utils.hash64ToDecimalString; - - result = convert(toHashString(0x00000000, 0x00000000), false); - expect(result).toEqual('0'); - - result = convert(toHashString(0x00000000, 0x00000000), true); - expect(result).toEqual('0'); - - result = convert(toHashString(0xFFFFFFFF, 0xFFFFFFFF), false); - expect(result).toEqual('18446744073709551615'); - - result = convert(toHashString(0xFFFFFFFF, 0xFFFFFFFF), true); - expect(result).toEqual('-1'); - - result = convert(toHashString(0x00000000, 0x80000000), false); + result = joinUnsignedDecimalString(0x00000000, 0x80000000); expect(result).toEqual('9223372036854775808'); - - result = convert(toHashString(0x00000000, 0x80000000), true); - expect(result).toEqual('-9223372036854775808'); - - result = convert(toHashString(0xacd05f15, 0x01b69b4b), false); - expect(result).toEqual('123456789123456789'); - - result = convert(toHashString(~0xacd05f15 + 1, ~0x01b69b4b), true); - expect(result).toEqual('-123456789123456789'); - - // And converting arrays of hashes should work the same way. - result = jspb.utils.hash64ArrayToDecimalStrings( - [ - toHashString(0xFFFFFFFF, 0xFFFFFFFF), - toHashString(0x00000000, 0x80000000), - toHashString(0xacd05f15, 0x01b69b4b) - ], - false); - expect(result.length).toEqual(3); - expect(result[0]).toEqual('18446744073709551615'); - expect(result[1]).toEqual('9223372036854775808'); - expect(result[2]).toEqual('123456789123456789'); - }); - - /* - * Going from decimal strings to hash strings should be lossless. - */ - it('testDecimalToHashConversion', () => { - let result; - const convert = jspb.utils.decimalStringToHash64; - - result = convert('0'); - expect(result).toEqual(goog.crypt.byteArrayToString( - [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])); - - result = convert('-1'); - expect(result).toEqual(goog.crypt.byteArrayToString( - [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])); - - result = convert('18446744073709551615'); - expect(result).toEqual(goog.crypt.byteArrayToString( - [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])); - - result = convert('9223372036854775808'); - expect(result).toEqual(goog.crypt.byteArrayToString( - [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80])); - - result = convert('-9223372036854775808'); - expect(result).toEqual(goog.crypt.byteArrayToString( - [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80])); - - result = convert('123456789123456789'); - expect(result).toEqual(goog.crypt.byteArrayToString( - [0x15, 0x5F, 0xD0, 0xAC, 0x4B, 0x9B, 0xB6, 0x01])); - - result = convert('-123456789123456789'); - expect(result).toEqual(goog.crypt.byteArrayToString( - [0xEB, 0xA0, 0x2F, 0x53, 0xB4, 0x64, 0x49, 0xFE])); - }); - - /** - * Going from hash strings to hex strings should be lossless. - */ - it('testHashToHexConversion', () => { - let result; - const convert = jspb.utils.hash64ToHexString; - - result = convert(toHashString(0x00000000, 0x00000000)); - expect(result).toEqual('0x0000000000000000'); - - result = convert(toHashString(0xFFFFFFFF, 0xFFFFFFFF)); - expect(result).toEqual('0xffffffffffffffff'); - - result = convert(toHashString(0x12345678, 0x9ABCDEF0)); - expect(result).toEqual('0x9abcdef012345678'); - }); - - - /** - * Going from hex strings to hash strings should be lossless. - */ - it('testHexToHashConversion', () => { - let result; - const convert = jspb.utils.hexStringToHash64; - - result = convert('0x0000000000000000'); - expect(result).toEqual(goog.crypt.byteArrayToString( - [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])); - - result = convert('0xffffffffffffffff'); - expect(result).toEqual(goog.crypt.byteArrayToString( - [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])); - - // Hex string is big-endian, hash string is little-endian. - result = convert('0x123456789ABCDEF0'); - expect(result).toEqual(goog.crypt.byteArrayToString( - [0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12])); - - // Capitalization should not matter. - result = convert('0x0000abcdefABCDEF'); - expect(result).toEqual(goog.crypt.byteArrayToString( - [0xEF, 0xCD, 0xAB, 0xEF, 0xCD, 0xAB, 0x00, 0x00])); - }); - - - /** - * Going from numbers to hash strings should be lossless for up to 53 bits of - * precision. - */ - it('testNumberToHashConversion', () => { - let result; - const convert = jspb.utils.numberToHash64; - - result = convert(0x0000000000000); - expect(jspb.utils.hash64ToHexString(result)).toEqual('0x0000000000000000'); - - result = convert(0xFFFFFFFFFFFFF); - expect(jspb.utils.hash64ToHexString(result)).toEqual('0x000fffffffffffff'); - - result = convert(0x123456789ABCD); - expect(jspb.utils.hash64ToHexString(result)).toEqual('0x000123456789abcd'); - - result = convert(0xDCBA987654321); - expect(jspb.utils.hash64ToHexString(result)).toEqual('0x000dcba987654321'); - - // 53 bits of precision should not be truncated. - result = convert(0x10000000000001); - expect(jspb.utils.hash64ToHexString(result)).toEqual('0x0010000000000001'); - - // 54 bits of precision should be truncated. - result = convert(0x20000000000001); - expect(jspb.utils.hash64ToHexString(result)) - .not.toEqual('0x0020000000000001'); }); - /** * Sanity check the behavior of Javascript's strings when doing funny things * with unicode characters. @@ -336,30 +207,24 @@ describe('binaryUtilsTest', () => { * Tests conversion from 32-bit floating point numbers to split64 numbers. */ it('testFloat32ToSplit64', () => { - const f32_eps = jspb.BinaryConstants.FLOAT32_EPS; - const f32_min = jspb.BinaryConstants.FLOAT32_MIN; - const f32_max = jspb.BinaryConstants.FLOAT32_MAX; - const f32_max_safe_int = jspb.utils.joinFloat32(0x4b7fffff, 0); + const f32_max_safe_int = joinFloat32(0x4b7fffff, 0); const f32_pi = Math.fround(Math.PI); // NaN. - jspb.utils.splitFloat32(NaN); - expect(isNaN(jspb.utils.joinFloat32( - jspb.utils.getSplit64Low(), jspb.utils.getSplit64High()))) - .toEqual(true); + splitFloat32(NaN); + expect(isNaN(joinFloat32(getSplit64Low(), getSplit64High()))).toEqual(true); /** * @param {number} x * @param {number=} opt_bits */ function test(x, opt_bits) { - jspb.utils.splitFloat32(x); + splitFloat32(x); if (opt_bits !== undefined) { - if (opt_bits != jspb.utils.getSplit64Low()) throw 'fail!'; + if (opt_bits != getSplit64Low()) throw 'fail!'; } expect(truncate(x)) - .toEqual(jspb.utils.joinFloat32( - jspb.utils.getSplit64Low(), jspb.utils.getSplit64High())); + .toEqual(joinFloat32(getSplit64Low(), getSplit64High())); } // Positive and negative infinity. @@ -371,16 +236,16 @@ describe('binaryUtilsTest', () => { test(-0, 0x80000000); // Positive and negative epsilon. - test(f32_eps, 0x00000001); - test(-f32_eps, 0x80000001); + test(FLOAT32_EPS, 0x00000001); + test(-FLOAT32_EPS, 0x80000001); // Positive and negative min. - test(f32_min, 0x00800000); - test(-f32_min, 0x80800000); + test(FLOAT32_MIN, 0x00800000); + test(-FLOAT32_MIN, 0x80800000); // Positive and negative max. - test(f32_max, 0x7F7FFFFF); - test(-f32_max, 0xFF7FFFFF); + test(FLOAT32_MAX, 0x7F7FFFFF); + test(-FLOAT32_MAX, 0xFF7FFFFF); // Positive and negative max_safe_int. test(f32_max_safe_int, 0x4B7FFFFF); @@ -395,14 +260,14 @@ describe('binaryUtilsTest', () => { test(Math.sin(30 * Math.PI / 180), 0x3f000000); // sin(30 degrees) // Various positive values. - let cursor = f32_eps * 10; + let cursor = FLOAT32_EPS * 10; while (cursor != Infinity) { test(cursor); cursor *= 1.1; } // Various negative values. - cursor = -f32_eps * 10; + cursor = -FLOAT32_EPS * 10; while (cursor != -Infinity) { test(cursor); cursor *= 1.1; @@ -414,15 +279,9 @@ describe('binaryUtilsTest', () => { * Tests conversion from 64-bit floating point numbers to split64 numbers. */ it('testFloat64ToSplit64', () => { - const f64_eps = jspb.BinaryConstants.FLOAT64_EPS; - const f64_min = jspb.BinaryConstants.FLOAT64_MIN; - const f64_max = jspb.BinaryConstants.FLOAT64_MAX; - // NaN. - jspb.utils.splitFloat64(NaN); - expect(isNaN(jspb.utils.joinFloat64( - jspb.utils.split64Low, jspb.utils.split64High))) - .toEqual(true); + splitFloat64(NaN); + expect(isNaN(joinFloat64(getSplit64Low(), getSplit64High()))).toEqual(true); /** * @param {number} x @@ -430,18 +289,16 @@ describe('binaryUtilsTest', () => { * @param {number=} opt_lowBits */ function test(x, opt_highBits, opt_lowBits) { - jspb.utils.splitFloat64(x); + splitFloat64(x); if (opt_highBits !== undefined) { - const split64High = jspb.utils.getSplit64High(); + const split64High = getSplit64High(); expect(opt_highBits.toString(16)).toEqual(split64High.toString(16)); } if (opt_lowBits !== undefined) { - const split64Low = jspb.utils.getSplit64Low(); + const split64Low = getSplit64Low(); expect(opt_lowBits.toString(16)).toEqual(split64Low.toString(16)); } - expect( - jspb.utils.joinFloat64(jspb.utils.getSplit64Low(), jspb.utils.getSplit64High())) - .toEqual(x); + expect(joinFloat64(getSplit64Low(), getSplit64High())).toEqual(x); } // Positive and negative infinity. @@ -456,16 +313,16 @@ describe('binaryUtilsTest', () => { test(2, 0x40000000, 0x00000000); // Positive and negative epsilon. - test(f64_eps, 0x00000000, 0x00000001); - test(-f64_eps, 0x80000000, 0x00000001); + test(FLOAT64_EPS, 0x00000000, 0x00000001); + test(-FLOAT64_EPS, 0x80000000, 0x00000001); // Positive and negative min. - test(f64_min, 0x00100000, 0x00000000); - test(-f64_min, 0x80100000, 0x00000000); + test(FLOAT64_MIN, 0x00100000, 0x00000000); + test(-FLOAT64_MIN, 0x80100000, 0x00000000); // Positive and negative max. - test(f64_max, 0x7FEFFFFF, 0xFFFFFFFF); - test(-f64_max, 0xFFEFFFFF, 0xFFFFFFFF); + test(FLOAT64_MAX, 0x7FEFFFFF, 0xFFFFFFFF); + test(-FLOAT64_MAX, 0xFFEFFFFF, 0xFFFFFFFF); test(Number.MAX_SAFE_INTEGER, 0x433FFFFF, 0xFFFFFFFF); test(Number.MIN_SAFE_INTEGER, 0xC33FFFFF, 0xFFFFFFFF); @@ -478,17 +335,17 @@ describe('binaryUtilsTest', () => { test(1.9999999999999998, 0x3FFFFFFF, 0xFFFFFFFF); test(2.225073858507201e-308, 0x000FFFFF, 0xFFFFFFFF); test(Math.PI, 0x400921fb, 0x54442d18); - test(jspb.BinaryConstants.FLOAT32_MIN, 0x38100000, 0x00000000); + test(FLOAT32_MIN, 0x38100000, 0x00000000); // Various positive values. - let cursor = f64_eps * 10; + let cursor = FLOAT64_EPS * 10; while (cursor != Infinity) { test(cursor); cursor *= 1.1; } // Various negative values. - cursor = -f64_eps * 10; + cursor = -FLOAT64_EPS * 10; while (cursor != -Infinity) { test(cursor); cursor *= 1.1; @@ -500,22 +357,19 @@ describe('binaryUtilsTest', () => { */ it('can encode and decode zigzag 64', () => { function stringToHiLoPair(str) { - jspb.utils.splitDecimalString(str); - return { - lo: jspb.utils.getSplit64Low() >>> 0, - hi: jspb.utils.getSplit64High() >>> 0 - }; + splitDecimalString(str); + return { lo: getSplit64Low() >>> 0, hi: getSplit64High() >>> 0 }; } function makeHiLoPair(lo, hi) { - return {lo: lo >>> 0, hi: hi >>> 0}; + return { lo: lo >>> 0, hi: hi >>> 0 }; } // Test cases directly from the protobuf dev guide. // https://engdoc.corp.google.com/eng/howto/protocolbuffers/developerguide/encoding.shtml?cl=head#types const testCases = [ - {original: stringToHiLoPair('0'), zigzag: stringToHiLoPair('0')}, - {original: stringToHiLoPair('-1'), zigzag: stringToHiLoPair('1')}, - {original: stringToHiLoPair('1'), zigzag: stringToHiLoPair('2')}, - {original: stringToHiLoPair('-2'), zigzag: stringToHiLoPair('3')}, + { original: stringToHiLoPair('0'), zigzag: stringToHiLoPair('0') }, + { original: stringToHiLoPair('-1'), zigzag: stringToHiLoPair('1') }, + { original: stringToHiLoPair('1'), zigzag: stringToHiLoPair('2') }, + { original: stringToHiLoPair('-2'), zigzag: stringToHiLoPair('3') }, { original: stringToHiLoPair('2147483647'), zigzag: stringToHiLoPair('4294967294') @@ -535,10 +389,10 @@ describe('binaryUtilsTest', () => { }, ]; for (const c of testCases) { - expect(jspb.utils.toZigzag64(c.original.lo, c.original.hi, makeHiLoPair)) - .toEqual(c.zigzag); - expect(jspb.utils.fromZigzag64(c.zigzag.lo, c.zigzag.hi, makeHiLoPair)) - .toEqual(c.original); + expect(toZigzag64(c.original.lo, c.original.hi, makeHiLoPair)) + .toEqual(c.zigzag); + expect(fromZigzag64(c.zigzag.lo, c.zigzag.hi, makeHiLoPair)) + .toEqual(c.original); } }); @@ -552,15 +406,14 @@ describe('binaryUtilsTest', () => { values.push(Math.floor(i)); } - const writer = new jspb.BinaryWriter(); + const writer = new BinaryWriter(); writer.writePackedUint64(1, values); const buffer = new Uint8Array(writer.getResultBuffer()); // We should have two more varints than we started with - one for the field // tag, one for the packed length. - expect(jspb.utils.countVarints(buffer, 0, buffer.length)) - .toEqual(values.length + 2); + expect(countVarints(buffer, 0, buffer.length)).toEqual(values.length + 2); }); @@ -568,7 +421,7 @@ describe('binaryUtilsTest', () => { * Tests counting matching varint fields. */ it('testCountVarintFields', () => { - let writer = new jspb.BinaryWriter(); + let writer = new BinaryWriter(); let count = 0; for (let i = 1; i < 1000000000; i *= 1.1) { @@ -578,10 +431,9 @@ describe('binaryUtilsTest', () => { writer.writeString(2, 'terminator'); let buffer = new Uint8Array(writer.getResultBuffer()); - expect(jspb.utils.countVarintFields(buffer, 0, buffer.length, 1)) - .toEqual(count); + expect(countVarintFields(buffer, 0, buffer.length, 1)).toEqual(count); - writer = new jspb.BinaryWriter(); + writer = new BinaryWriter(); count = 0; for (let i = 1; i < 1000000000; i *= 1.1) { @@ -591,8 +443,7 @@ describe('binaryUtilsTest', () => { writer.writeString(2, 'terminator'); buffer = new Uint8Array(writer.getResultBuffer()); - expect(jspb.utils.countVarintFields(buffer, 0, buffer.length, 123456789)) - .toEqual(count); + expect(countVarintFields(buffer, 0, buffer.length, 123456789)).toEqual(count); }); @@ -600,7 +451,7 @@ describe('binaryUtilsTest', () => { * Tests counting matching fixed32 fields. */ it('testCountFixed32Fields', () => { - let writer = new jspb.BinaryWriter(); + let writer = new BinaryWriter(); let count = 0; for (let i = 1; i < 1000000000; i *= 1.1) { @@ -610,10 +461,9 @@ describe('binaryUtilsTest', () => { writer.writeString(2, 'terminator'); let buffer = new Uint8Array(writer.getResultBuffer()); - expect(jspb.utils.countFixed32Fields(buffer, 0, buffer.length, 1)) - .toEqual(count); + expect(countFixed32Fields(buffer, 0, buffer.length, 1)).toEqual(count); - writer = new jspb.BinaryWriter(); + writer = new BinaryWriter(); count = 0; for (let i = 1; i < 1000000000; i *= 1.1) { @@ -623,8 +473,7 @@ describe('binaryUtilsTest', () => { writer.writeString(2, 'terminator'); buffer = new Uint8Array(writer.getResultBuffer()); - expect(jspb.utils.countFixed32Fields(buffer, 0, buffer.length, 123456789)) - .toEqual(count); + expect(countFixed32Fields(buffer, 0, buffer.length, 123456789)).toEqual(count); }); @@ -632,7 +481,7 @@ describe('binaryUtilsTest', () => { * Tests counting matching fixed64 fields. */ it('testCountFixed64Fields', () => { - let writer = new jspb.BinaryWriter(); + let writer = new BinaryWriter(); let count = 0; for (let i = 1; i < 1000000000; i *= 1.1) { @@ -642,10 +491,9 @@ describe('binaryUtilsTest', () => { writer.writeString(2, 'terminator'); let buffer = new Uint8Array(writer.getResultBuffer()); - expect(jspb.utils.countFixed64Fields(buffer, 0, buffer.length, 1)) - .toEqual(count); + expect(countFixed64Fields(buffer, 0, buffer.length, 1)).toEqual(count); - writer = new jspb.BinaryWriter(); + writer = new BinaryWriter(); count = 0; for (let i = 1; i < 1000000000; i *= 1.1) { @@ -655,8 +503,7 @@ describe('binaryUtilsTest', () => { writer.writeString(2, 'terminator'); buffer = new Uint8Array(writer.getResultBuffer()); - expect(jspb.utils.countFixed64Fields(buffer, 0, buffer.length, 123456789)) - .toEqual(count); + expect(countFixed64Fields(buffer, 0, buffer.length, 123456789)).toEqual(count); }); @@ -664,7 +511,7 @@ describe('binaryUtilsTest', () => { * Tests counting matching delimited fields. */ it('testCountDelimitedFields', () => { - let writer = new jspb.BinaryWriter(); + let writer = new BinaryWriter(); let count = 0; for (let i = 1; i < 1000; i *= 1.1) { @@ -674,10 +521,9 @@ describe('binaryUtilsTest', () => { writer.writeString(2, 'terminator'); let buffer = new Uint8Array(writer.getResultBuffer()); - expect(jspb.utils.countDelimitedFields(buffer, 0, buffer.length, 1)) - .toEqual(count); + expect(countDelimitedFields(buffer, 0, buffer.length, 1)).toEqual(count); - writer = new jspb.BinaryWriter(); + writer = new BinaryWriter(); count = 0; for (let i = 1; i < 1000; i *= 1.1) { @@ -687,27 +533,15 @@ describe('binaryUtilsTest', () => { writer.writeString(2, 'terminator'); buffer = new Uint8Array(writer.getResultBuffer()); - expect(jspb.utils.countDelimitedFields(buffer, 0, buffer.length, 123456789)) - .toEqual(count); + expect(countDelimitedFields(buffer, 0, buffer.length, 123456789)) + .toEqual(count); }); - - /** - * Tests byte format for debug strings. - */ - it('testDebugBytesToTextFormat', () => { - expect(jspb.utils.debugBytesToTextFormat(null)).toEqual('""'); - expect(jspb.utils.debugBytesToTextFormat([ - 0, 16, 255 - ])).toEqual('"\\x00\\x10\\xff"'); - }); - - /** * Tests converting byte blob sources into byte blobs. */ it('testByteSourceToUint8Array', () => { - const convert = jspb.utils.byteSourceToUint8Array; + const convert = byteSourceToUint8Array; const sourceData = []; for (let i = 0; i < 256; i++) { @@ -716,7 +550,7 @@ describe('binaryUtilsTest', () => { const sourceBytes = new Uint8Array(sourceData); const sourceBuffer = sourceBytes.buffer; - const sourceBase64 = goog.crypt.base64.encodeByteArray(sourceData); + const sourceBase64 = encodeByteArray(sourceData); function check(result) { expect(result.constructor).toEqual(Uint8Array); diff --git a/binary/writer.js b/binary/writer.js old mode 100644 new mode 100755 index c1876b1..e3874de --- a/binary/writer.js +++ b/binary/writer.js @@ -1,33 +1,3 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// https://protobuf.dev/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - /** * @fileoverview This file contains utilities for encoding Javascript objects * into binary, wire-format protocol buffers (in the form of Uint8Arrays) that @@ -52,1887 +22,1698 @@ * Major caveat 3 - This class uses typed arrays and must not be used on older * browsers that do not support them. * - * @suppress {missingRequire} TODO(b/152540451): this shouldn't be needed * @author aappleby@google.com (Austin Appleby) */ -goog.provide('jspb.BinaryWriter'); - -goog.require('goog.crypt.base64'); - -goog.require('jspb.asserts'); -goog.require('jspb.BinaryConstants'); -goog.require('jspb.BinaryEncoder'); -goog.require('jspb.arith.Int64'); -goog.require('jspb.arith.UInt64'); -goog.require('jspb.utils'); - - +goog.module('jspb.binary.writer'); +goog.module.declareLegacyNamespace(); + +const { Alphabet, encodeByteArray: encodeByteArraySlow } = goog.require('goog.crypt.base64'); +const { AnyFieldType } = goog.requireType('jspb.binary.any_field_type'); +const { BinaryEncoder } = goog.require('jspb.binary.encoder'); +const { ByteSource } = goog.requireType('jspb.binary.bytesource'); +const { ByteString } = goog.require('jspb.bytestring'); +const { FieldType, TWO_TO_31, TWO_TO_32, TWO_TO_63, TWO_TO_64, WireType } = goog.require('jspb.BinaryConstants'); +const { Int64, UInt64 } = goog.require('jspb.arith'); +const { assert, fail } = goog.require('goog.asserts'); +const { bufferFromSource } = goog.require('jspb.binary.internal_buffer'); +const { encodeByteArray } = goog.require('jspb.internal_bytes'); +const { encodeUtf8 } = goog.require('jspb.binary.utf8'); +const { makeTag } = goog.require('jspb.utils'); +const { unsafeByteStringFromUint8Array, unsafeUint8ArrayFromByteString } = goog.require('jspb.unsafe_bytestring'); +/** + * Whether to reject unpaired surrogates when encoding strings to utf8. + * + *

Currently set to `goog.DEBUG`, but can be disabled if needed. + * + * @define {boolean} + */ +const REJECT_UNPAIRED_SURROGATES = + goog.define('jspb.binary.REJECT_UNPAIRED_SURROGATES', goog.DEBUG); /** * BinaryWriter implements encoders for all the wire types specified in - * https://protobuf.dev/programming-guides/encoding/. - * - * @constructor - * @struct - * @export - */ -jspb.BinaryWriter = function() { - /** - * Blocks of serialized data that will be concatenated once all messages have - * been written. - * @private {!Array>} - */ - this.blocks_ = []; + * https://developers.google.com/protocol-buffers/docs/encoding. + */ +class BinaryWriter { + constructor() { + /** + * Blocks of serialized data that will be concatenated once all messages + * have been written. + * @private {!Array>} + */ + this.blocks_ = []; + + /** + * Total number of bytes in the blocks_ array. Does _not_ include bytes in + * the encoder below. + * @private {number} + */ + this.totalLength_ = 0; + + /** + * Binary encoder holding pieces of a message that we're still serializing. + * When we get to a stopping point (either the start of a new submessage, or + * when we need to append a raw Uint8Array), the encoder's buffer will be + * added to the block array above and the encoder will be reset. + * @private @const {!BinaryEncoder} + */ + this.encoder_ = new BinaryEncoder(); + } + + /** @private*/ + pushBlock(/** !Array|!Uint8Array */ buffer) { + // Repeated calls to appendUint8Arrays may produce empty arrays from the + // encoder, avoid storing these in our list of blocks. + if (buffer.length !== 0) { + this.blocks_.push(buffer); + this.totalLength_ += buffer.length; + } + } /** - * Total number of bytes in the blocks_ array. Does _not_ include bytes in - * the encoder below. - * @private {number} + * Append a typed array of bytes onto the buffer. + * + * @param {!Uint8Array} arr The byte array to append. + * @private */ - this.totalLength_ = 0; + appendUint8Array_(arr) { + this.pushBlock(this.encoder_.end()); + this.pushBlock(arr); + } /** - * Binary encoder holding pieces of a message that we're still serializing. - * When we get to a stopping point (either the start of a new submessage, or - * when we need to append a raw Uint8Array), the encoder's buffer will be - * added to the block array above and the encoder will be reset. - * @private {!jspb.BinaryEncoder} + * Begins a new message by writing the field header and returning a bookmark + * which we will use to patch in the message length to in endDelimited_ below. + * @param {number} field + * @return {!Array} + * @private */ - this.encoder_ = new jspb.BinaryEncoder(); + beginDelimited_(field) { + this.writeFieldHeader_(field, WireType.DELIMITED); + const bookmark = this.encoder_.end(); + this.pushBlock(bookmark); + bookmark.push( + this.totalLength_); // store the current length in the bookmark + return bookmark; + } /** - * A stack of bookmarks containing the parent blocks for each message started - * via beginSubMessage(), needed as bookkeeping for endSubMessage(). - * TODO(aappleby): Deprecated, users should be calling writeMessage(). - * @private {!Array>} + * Ends a message by encoding the _change_ in length of the buffer to the + * parent block and adds the number of bytes needed to encode that length to + * the total byte length. + * @param {!Array} bookmark + * @private */ - this.bookmarks_ = []; -}; - - -/** - * Append a typed array of bytes onto the buffer. - * - * @param {!Uint8Array} arr The byte array to append. - * @private - */ -jspb.BinaryWriter.prototype.appendUint8Array_ = function(arr) { - var temp = this.encoder_.end(); - this.blocks_.push(temp); - this.blocks_.push(arr); - this.totalLength_ += temp.length + arr.length; -}; - - -/** - * Begins a new message by writing the field header and returning a bookmark - * which we will use to patch in the message length to in endDelimited_ below. - * @param {number} field - * @return {!Array} - * @private - */ -jspb.BinaryWriter.prototype.beginDelimited_ = function(field) { - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); - var bookmark = this.encoder_.end(); - this.blocks_.push(bookmark); - this.totalLength_ += bookmark.length; - bookmark.push(this.totalLength_); - return bookmark; -}; - - -/** - * Ends a message by encoding the _change_ in length of the buffer to the - * parent block and adds the number of bytes needed to encode that length to - * the total byte length. - * @param {!Array} bookmark - * @private - */ -jspb.BinaryWriter.prototype.endDelimited_ = function(bookmark) { - var oldLength = bookmark.pop(); - var messageLength = this.totalLength_ + this.encoder_.length() - oldLength; - jspb.asserts.assert(messageLength >= 0); - - while (messageLength > 127) { - bookmark.push((messageLength & 0x7f) | 0x80); - messageLength = messageLength >>> 7; + endDelimited_(bookmark) { + const oldLength = bookmark.pop(); + let messageLength = this.totalLength_ + this.encoder_.length() - oldLength; + assert(messageLength >= 0); + + while (messageLength > 127) { + bookmark.push((messageLength & 0x7f) | 0x80); + messageLength = messageLength >>> 7; + this.totalLength_++; + } + + bookmark.push(messageLength); this.totalLength_++; } - bookmark.push(messageLength); - this.totalLength_++; -}; - - -/** - * Writes a pre-serialized message to the buffer. - * @param {!Uint8Array} bytes The array of bytes to write. - * @param {number} start The start of the range to write. - * @param {number} end The end of the range to write. - * @export - */ -jspb.BinaryWriter.prototype.writeSerializedMessage = function( - bytes, start, end) { - this.appendUint8Array_(bytes.subarray(start, end)); -}; - - -/** - * Writes a pre-serialized message to the buffer if the message and endpoints - * are non-null. - * @param {?Uint8Array} bytes The array of bytes to write. - * @param {?number} start The start of the range to write. - * @param {?number} end The end of the range to write. - * @export - */ -jspb.BinaryWriter.prototype.maybeWriteSerializedMessage = function( - bytes, start, end) { - if (bytes != null && start != null && end != null) { - this.writeSerializedMessage(bytes, start, end); + /** + * Writes unknown fields to the output if there are any. + */ + writeUnknownFields(/** !Array */ unknownFields) { + this.pushBlock(this.encoder_.end()); + for (let i = 0; i < unknownFields.length; i++) { + // Unsafe access is ok here since arrays added to our output are always + // copied before returning to the user. + this.pushBlock(unsafeUint8ArrayFromByteString(unknownFields[i])); + } } -}; - - -/** - * Resets the writer, throwing away any accumulated buffers. - * @export - */ -jspb.BinaryWriter.prototype.reset = function() { - this.blocks_ = []; - this.encoder_.end(); - this.totalLength_ = 0; - this.bookmarks_ = []; -}; - - -/** - * Converts the encoded data into a Uint8Array. - * @return {!Uint8Array} - * @export - */ -jspb.BinaryWriter.prototype.getResultBuffer = function() { - jspb.asserts.assert(this.bookmarks_.length == 0); - - var flat = new Uint8Array(this.totalLength_ + this.encoder_.length()); - var blocks = this.blocks_; - var blockCount = blocks.length; - var offset = 0; - - for (var i = 0; i < blockCount; i++) { - var block = blocks[i]; - flat.set(block, offset); - offset += block.length; + /** + * Writes a pre-serialized message to the buffer. + * @param {!Uint8Array} bytes The array of bytes to write. + * @param {number} start The start of the range to write. + * @param {number} end The end of the range to write. + */ + writeSerializedMessage(bytes, start, end) { + this.appendUint8Array_(bytes.subarray(start, end)); } - var tail = this.encoder_.end(); - flat.set(tail, offset); - offset += tail.length; - - // Post condition: `flattened` must have had every byte written. - jspb.asserts.assert(offset == flat.length); - - // Replace our block list with the flattened block, which lets GC reclaim - // the temp blocks sooner. - this.blocks_ = [flat]; - - return flat; -}; - - -/** - * Converts the encoded data into a base64-encoded string. - * @param {!goog.crypt.base64.Alphabet=} alphabet Which flavor of base64 to use. - * @return {string} - * @export - */ -jspb.BinaryWriter.prototype.getResultBase64String = function(alphabet) { - return goog.crypt.base64.encodeByteArray(this.getResultBuffer(), alphabet); -}; - - -/** - * Begins a new sub-message. The client must call endSubMessage() when they're - * done. - * TODO(aappleby): Deprecated. Move callers to writeMessage(). - * @param {number} field The field number of the sub-message. - * @export - */ -jspb.BinaryWriter.prototype.beginSubMessage = function(field) { - this.bookmarks_.push(this.beginDelimited_(field)); -}; - - -/** - * Finishes a sub-message and packs it into the parent messages' buffer. - * TODO(aappleby): Deprecated. Move callers to writeMessage(). - * @export - */ -jspb.BinaryWriter.prototype.endSubMessage = function() { - jspb.asserts.assert(this.bookmarks_.length >= 0); - this.endDelimited_(this.bookmarks_.pop()); -}; - - -/** - * Encodes a (field number, wire type) tuple into a wire-format field header - * and stores it in the buffer as a varint. - * @param {number} field The field number. - * @param {number} wireType The wire-type of the field, as specified in the - * protocol buffer documentation. - * @private - */ -jspb.BinaryWriter.prototype.writeFieldHeader_ = function(field, wireType) { - jspb.asserts.assert(field >= 1 && field == Math.floor(field)); - var x = field * 8 + wireType; - this.encoder_.writeUnsignedVarint32(x); -}; - - -/** - * Writes a field of any valid scalar type to the binary stream. - * @param {jspb.BinaryConstants.FieldType} fieldType - * @param {number} field - * @param {jspb.AnyFieldType} value - * @export - */ -jspb.BinaryWriter.prototype.writeAny = function(fieldType, field, value) { - var fieldTypes = jspb.BinaryConstants.FieldType; - switch (fieldType) { - case fieldTypes.DOUBLE: - this.writeDouble(field, /** @type {number} */ (value)); - return; - case fieldTypes.FLOAT: - this.writeFloat(field, /** @type {number} */ (value)); - return; - case fieldTypes.INT64: - this.writeInt64(field, /** @type {number} */ (value)); - return; - case fieldTypes.UINT64: - this.writeUint64(field, /** @type {number} */ (value)); - return; - case fieldTypes.INT32: - this.writeInt32(field, /** @type {number} */ (value)); - return; - case fieldTypes.FIXED64: - this.writeFixed64(field, /** @type {number} */ (value)); - return; - case fieldTypes.FIXED32: - this.writeFixed32(field, /** @type {number} */ (value)); - return; - case fieldTypes.BOOL: - this.writeBool(field, /** @type {boolean} */ (value)); - return; - case fieldTypes.STRING: - this.writeString(field, /** @type {string} */ (value)); - return; - case fieldTypes.GROUP: - jspb.asserts.fail('Group field type not supported in writeAny()'); - return; - case fieldTypes.MESSAGE: - jspb.asserts.fail('Message field type not supported in writeAny()'); - return; - case fieldTypes.BYTES: - this.writeBytes(field, /** @type {?Uint8Array} */ (value)); - return; - case fieldTypes.UINT32: - this.writeUint32(field, /** @type {number} */ (value)); - return; - case fieldTypes.ENUM: - this.writeEnum(field, /** @type {number} */ (value)); - return; - case fieldTypes.SFIXED32: - this.writeSfixed32(field, /** @type {number} */ (value)); - return; - case fieldTypes.SFIXED64: - this.writeSfixed64(field, /** @type {number} */ (value)); - return; - case fieldTypes.SINT32: - this.writeSint32(field, /** @type {number} */ (value)); - return; - case fieldTypes.SINT64: - this.writeSint64(field, /** @type {number} */ (value)); - return; - case fieldTypes.FHASH64: - this.writeFixedHash64(field, /** @type {string} */ (value)); - return; - case fieldTypes.VHASH64: - this.writeVarintHash64(field, /** @type {string} */ (value)); - return; - default: - jspb.asserts.fail('Invalid field type in writeAny()'); - return; - } -}; - - -/** - * Writes a varint field to the buffer without range checking. - * @param {number} field The field number. - * @param {number?} value The value to write. - * @private - */ -jspb.BinaryWriter.prototype.writeUnsignedVarint32_ = function(field, value) { - if (value == null) return; - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); - this.encoder_.writeUnsignedVarint32(value); -}; - - -/** - * Writes a varint field to the buffer without range checking. - * @param {number} field The field number. - * @param {number?} value The value to write. - * @private - */ -jspb.BinaryWriter.prototype.writeSignedVarint32_ = function(field, value) { - if (value == null) return; - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); - this.encoder_.writeSignedVarint32(value); -}; - - -/** - * Writes a varint field to the buffer without range checking. - * @param {number} field The field number. - * @param {number?} value The value to write. - * @private - */ -jspb.BinaryWriter.prototype.writeUnsignedVarint64_ = function(field, value) { - if (value == null) return; - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); - this.encoder_.writeUnsignedVarint64(value); -}; - - -/** - * Writes a varint field to the buffer without range checking. - * @param {number} field The field number. - * @param {number?} value The value to write. - * @private - */ -jspb.BinaryWriter.prototype.writeSignedVarint64_ = function(field, value) { - if (value == null) return; - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); - this.encoder_.writeSignedVarint64(value); -}; - - -/** - * Writes a zigzag varint field to the buffer without range checking. - * @param {number} field The field number. - * @param {number?} value The value to write. - * @private - */ -jspb.BinaryWriter.prototype.writeZigzagVarint32_ = function(field, value) { - if (value == null) return; - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); - this.encoder_.writeZigzagVarint32(value); -}; - - -/** - * Writes a zigzag varint field to the buffer without range checking. - * @param {number} field The field number. - * @param {number?} value The value to write. - * @private - */ -jspb.BinaryWriter.prototype.writeZigzagVarint64_ = function(field, value) { - if (value == null) return; - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); - this.encoder_.writeZigzagVarint64(value); -}; - - -/** - * Writes a zigzag varint field to the buffer without range checking. - * @param {number} field The field number. - * @param {string?} value The value to write. - * @private - */ -jspb.BinaryWriter.prototype.writeZigzagVarint64String_ = function( - field, value) { - if (value == null) return; - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); - this.encoder_.writeZigzagVarint64String(value); -}; - - -/** - * Writes a zigzag varint field to the buffer without range checking. - * @param {number} field The field number. - * @param {string?} value The value to write. - * @private - */ -jspb.BinaryWriter.prototype.writeZigzagVarintHash64_ = function(field, value) { - if (value == null) return; - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); - this.encoder_.writeZigzagVarintHash64(value); -}; - - -/** - * Writes an int32 field to the buffer. Numbers outside the range [-2^31,2^31) - * will be truncated. - * @param {number} field The field number. - * @param {number?} value The value to write. - * @export - */ -jspb.BinaryWriter.prototype.writeInt32 = function(field, value) { - if (value == null) return; - jspb.asserts.assert( - (value >= -jspb.BinaryConstants.TWO_TO_31) && - (value < jspb.BinaryConstants.TWO_TO_31)); - this.writeSignedVarint32_(field, value); -}; - - -/** - * Writes an int32 field represented as a string to the buffer. Numbers outside - * the range [-2^31,2^31) will be truncated. - * @param {number} field The field number. - * @param {string?} value The value to write. - * @export - */ -jspb.BinaryWriter.prototype.writeInt32String = function(field, value) { - if (value == null) return; - var intValue = /** {number} */ parseInt(value, 10); - jspb.asserts.assert( - (intValue >= -jspb.BinaryConstants.TWO_TO_31) && - (intValue < jspb.BinaryConstants.TWO_TO_31)); - this.writeSignedVarint32_(field, intValue); -}; - - -/** - * Writes an int64 field to the buffer. Numbers outside the range [-2^63,2^63) - * will be truncated. - * @param {number} field The field number. - * @param {number?} value The value to write. - * @export - */ -jspb.BinaryWriter.prototype.writeInt64 = function(field, value) { - if (value == null) return; - jspb.asserts.assert( - (value >= -jspb.BinaryConstants.TWO_TO_63) && - (value < jspb.BinaryConstants.TWO_TO_63)); - this.writeSignedVarint64_(field, value); -}; - - -/** - * Writes a int64 field (with value as a string) to the buffer. - * @param {number} field The field number. - * @param {string?} value The value to write. - * @export - */ -jspb.BinaryWriter.prototype.writeInt64String = function(field, value) { - if (value == null) return; - var num = jspb.arith.Int64.fromString(value); - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); - this.encoder_.writeSplitVarint64(num.lo, num.hi); -}; - - -/** - * Writes a uint32 field to the buffer. Numbers outside the range [0,2^32) - * will be truncated. - * @param {number} field The field number. - * @param {number?} value The value to write. - * @export - */ -jspb.BinaryWriter.prototype.writeUint32 = function(field, value) { - if (value == null) return; - jspb.asserts.assert( - (value >= 0) && (value < jspb.BinaryConstants.TWO_TO_32)); - this.writeUnsignedVarint32_(field, value); -}; - - -/** - * Writes a uint32 field represented as a string to the buffer. Numbers outside - * the range [0,2^32) will be truncated. - * @param {number} field The field number. - * @param {string?} value The value to write. - * @export - */ -jspb.BinaryWriter.prototype.writeUint32String = function(field, value) { - if (value == null) return; - var intValue = /** {number} */ parseInt(value, 10); - jspb.asserts.assert( - (intValue >= 0) && (intValue < jspb.BinaryConstants.TWO_TO_32)); - this.writeUnsignedVarint32_(field, intValue); -}; - - -/** - * Writes a uint64 field to the buffer. Numbers outside the range [0,2^64) - * will be truncated. - * @param {number} field The field number. - * @param {number?} value The value to write. - * @export - */ -jspb.BinaryWriter.prototype.writeUint64 = function(field, value) { - if (value == null) return; - jspb.asserts.assert( - (value >= 0) && (value < jspb.BinaryConstants.TWO_TO_64)); - this.writeUnsignedVarint64_(field, value); -}; - - -/** - * Writes a uint64 field (with value as a string) to the buffer. - * @param {number} field The field number. - * @param {string?} value The value to write. - * @export - */ -jspb.BinaryWriter.prototype.writeUint64String = function(field, value) { - if (value == null) return; - var num = jspb.arith.UInt64.fromString(value); - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); - this.encoder_.writeSplitVarint64(num.lo, num.hi); -}; - - -/** - * Writes an sint32 field to the buffer. Numbers outside the range [-2^31,2^31) - * will be truncated. - * @param {number} field The field number. - * @param {number?} value The value to write. - * @export - */ -jspb.BinaryWriter.prototype.writeSint32 = function(field, value) { - if (value == null) return; - jspb.asserts.assert( - (value >= -jspb.BinaryConstants.TWO_TO_31) && - (value < jspb.BinaryConstants.TWO_TO_31)); - this.writeZigzagVarint32_(field, value); -}; - - -/** - * Writes an sint64 field to the buffer. Numbers outside the range [-2^63,2^63) - * will be truncated. - * @param {number} field The field number. - * @param {number?} value The value to write. - * @export - */ -jspb.BinaryWriter.prototype.writeSint64 = function(field, value) { - if (value == null) return; - jspb.asserts.assert( - (value >= -jspb.BinaryConstants.TWO_TO_63) && - (value < jspb.BinaryConstants.TWO_TO_63)); - this.writeZigzagVarint64_(field, value); -}; - - -/** - * Writes an sint64 field to the buffer from a hash64 encoded value. Numbers - * outside the range [-2^63,2^63) will be truncated. - * @param {number} field The field number. - * @param {string?} value The hash64 string to write. - * @export - */ -jspb.BinaryWriter.prototype.writeSintHash64 = function(field, value) { - if (value == null) return; - this.writeZigzagVarintHash64_(field, value); -}; - - -/** - * Writes an sint64 field to the buffer. Numbers outside the range [-2^63,2^63) - * will be truncated. - * @param {number} field The field number. - * @param {string?} value The decimal string to write. - * @export - */ -jspb.BinaryWriter.prototype.writeSint64String = function(field, value) { - if (value == null) return; - this.writeZigzagVarint64String_(field, value); -}; - - -/** - * Writes a fixed32 field to the buffer. Numbers outside the range [0,2^32) - * will be truncated. - * @param {number} field The field number. - * @param {number?} value The value to write. - * @export - */ -jspb.BinaryWriter.prototype.writeFixed32 = function(field, value) { - if (value == null) return; - jspb.asserts.assert( - (value >= 0) && (value < jspb.BinaryConstants.TWO_TO_32)); - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED32); - this.encoder_.writeUint32(value); -}; - - -/** - * Writes a fixed64 field to the buffer. Numbers outside the range [0,2^64) - * will be truncated. - * @param {number} field The field number. - * @param {number?} value The value to write. - * @export - */ -jspb.BinaryWriter.prototype.writeFixed64 = function(field, value) { - if (value == null) return; - jspb.asserts.assert( - (value >= 0) && (value < jspb.BinaryConstants.TWO_TO_64)); - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); - this.encoder_.writeUint64(value); -}; - - -/** - * Writes a fixed64 field (with value as a string) to the buffer. - * @param {number} field The field number. - * @param {string?} value The value to write. - * @export - */ -jspb.BinaryWriter.prototype.writeFixed64String = function(field, value) { - if (value == null) return; - var num = jspb.arith.UInt64.fromString(value); - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); - this.encoder_.writeSplitFixed64(num.lo, num.hi); -}; - - -/** - * Writes a sfixed32 field to the buffer. Numbers outside the range - * [-2^31,2^31) will be truncated. - * @param {number} field The field number. - * @param {number?} value The value to write. - * @export - */ -jspb.BinaryWriter.prototype.writeSfixed32 = function(field, value) { - if (value == null) return; - jspb.asserts.assert( - (value >= -jspb.BinaryConstants.TWO_TO_31) && - (value < jspb.BinaryConstants.TWO_TO_31)); - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED32); - this.encoder_.writeInt32(value); -}; - - -/** - * Writes a sfixed64 field to the buffer. Numbers outside the range - * [-2^63,2^63) will be truncated. - * @param {number} field The field number. - * @param {number?} value The value to write. - * @export - */ -jspb.BinaryWriter.prototype.writeSfixed64 = function(field, value) { - if (value == null) return; - jspb.asserts.assert( - (value >= -jspb.BinaryConstants.TWO_TO_63) && - (value < jspb.BinaryConstants.TWO_TO_63)); - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); - this.encoder_.writeInt64(value); -}; - - -/** - * Writes a sfixed64 string field to the buffer. Numbers outside the range - * [-2^63,2^63) will be truncated. - * @param {number} field The field number. - * @param {string?} value The value to write. - * @export - */ -jspb.BinaryWriter.prototype.writeSfixed64String = function(field, value) { - if (value == null) return; - var num = jspb.arith.Int64.fromString(value); - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); - this.encoder_.writeSplitFixed64(num.lo, num.hi); -}; - - -/** - * Writes a single-precision floating point field to the buffer. Numbers - * requiring more than 32 bits of precision will be truncated. - * @param {number} field The field number. - * @param {number?} value The value to write. - * @export - */ -jspb.BinaryWriter.prototype.writeFloat = function(field, value) { - if (value == null) return; - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED32); - this.encoder_.writeFloat(value); -}; - - -/** - * Writes a double-precision floating point field to the buffer. As this is the - * native format used by JavaScript, no precision will be lost. - * @param {number} field The field number. - * @param {number?} value The value to write. - * @export - */ -jspb.BinaryWriter.prototype.writeDouble = function(field, value) { - if (value == null) return; - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); - this.encoder_.writeDouble(value); -}; - - -/** - * Writes a boolean field to the buffer. We allow numbers as input - * because the JSPB code generator uses 0/1 instead of true/false to save space - * in the string representation of the proto. - * @param {number} field The field number. - * @param {boolean?|number?} value The value to write. - * @export - */ -jspb.BinaryWriter.prototype.writeBool = function(field, value) { - if (value == null) return; - jspb.asserts.assert( - typeof value === 'boolean' || typeof value === 'number'); - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); - this.encoder_.writeBool(value); -}; - - -/** - * Writes an enum field to the buffer. - * @param {number} field The field number. - * @param {number?} value The value to write. - * @export - */ -jspb.BinaryWriter.prototype.writeEnum = function(field, value) { - if (value == null) return; - jspb.asserts.assert( - (value >= -jspb.BinaryConstants.TWO_TO_31) && - (value < jspb.BinaryConstants.TWO_TO_31)); - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); - this.encoder_.writeSignedVarint32(value); -}; - - -/** - * Writes a string field to the buffer. - * @param {number} field The field number. - * @param {string?} value The string to write. - * @export - */ -jspb.BinaryWriter.prototype.writeString = function(field, value) { - if (value == null) return; - var bookmark = this.beginDelimited_(field); - this.encoder_.writeString(value); - this.endDelimited_(bookmark); -}; - - -/** - * Writes an arbitrary byte field to the buffer. Note - to match the behavior - * of the C++ implementation, empty byte arrays _are_ serialized. - * @param {number} field The field number. - * @param {?jspb.ByteSource} value The array of bytes to write. - * @export - */ -jspb.BinaryWriter.prototype.writeBytes = function(field, value) { - if (value == null) return; - var bytes = jspb.utils.byteSourceToUint8Array(value); - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); - this.encoder_.writeUnsignedVarint32(bytes.length); - this.appendUint8Array_(bytes); -}; - - -/** - * Writes a message to the buffer. - * @param {number} field The field number. - * @param {?MessageType} value The message to write. - * @param {function(MessageTypeNonNull, !jspb.BinaryWriter)} writerCallback - * Will be invoked with the value to write and the writer to write it with. - * @template MessageType - * Use go/closure-ttl to declare a non-nullable version of MessageType. Replace - * the null in blah|null with none. This is necessary because the compiler will - * infer MessageType to be nullable if the value parameter is nullable. - * @template MessageTypeNonNull := - * cond(isUnknown(MessageType), unknown(), - * mapunion(MessageType, (X) => - * cond(eq(X, 'null'), none(), X))) - * =: - * @export - */ -jspb.BinaryWriter.prototype.writeMessage = function( - field, value, writerCallback) { - if (value == null) return; - var bookmark = this.beginDelimited_(field); - writerCallback(value, this); - this.endDelimited_(bookmark); -}; - - -/** - * Writes a message set extension to the buffer. - * @param {number} field The field number for the extension. - * @param {?MessageType} value The extension message object to write. Note that - * message set can only have extensions with type of optional message. - * @param {function(!MessageTypeNonNull, !jspb.BinaryWriter)} writerCallback - * Will be invoked with the value to write and the writer to write it with. - * @template MessageType - * Use go/closure-ttl to declare a non-nullable version of MessageType. Replace - * the null in blah|null with none. This is necessary because the compiler will - * infer MessageType to be nullable if the value parameter is nullable. - * @template MessageTypeNonNull := - * cond(isUnknown(MessageType), unknown(), - * mapunion(MessageType, (X) => - * cond(eq(X, 'null'), none(), X))) - * =: - * @export - */ -jspb.BinaryWriter.prototype.writeMessageSet = function( - field, value, writerCallback) { - if (value == null) return; - // The wire format for a message set is defined by - // google3/net/proto/message_set.proto - this.writeFieldHeader_(1, jspb.BinaryConstants.WireType.START_GROUP); - this.writeFieldHeader_(2, jspb.BinaryConstants.WireType.VARINT); - this.encoder_.writeSignedVarint32(field); - var bookmark = this.beginDelimited_(3); - writerCallback(value, this); - this.endDelimited_(bookmark); - this.writeFieldHeader_(1, jspb.BinaryConstants.WireType.END_GROUP); -}; - - -/** - * Writes a group message to the buffer. - * - * @param {number} field The field number. - * @param {?MessageType} value The message to write, wrapped with START_GROUP / - * END_GROUP tags. Will be a no-op if 'value' is null. - * @param {function(MessageTypeNonNull, !jspb.BinaryWriter)} writerCallback - * Will be invoked with the value to write and the writer to write it with. - * @template MessageType - * Use go/closure-ttl to declare a non-nullable version of MessageType. Replace - * the null in blah|null with none. This is necessary because the compiler will - * infer MessageType to be nullable if the value parameter is nullable. - * @template MessageTypeNonNull := - * cond(isUnknown(MessageType), unknown(), - * mapunion(MessageType, (X) => - * cond(eq(X, 'null'), none(), X))) - * =: - * @export - */ -jspb.BinaryWriter.prototype.writeGroup = function( - field, value, writerCallback) { - if (value == null) return; - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.START_GROUP); - writerCallback(value, this); - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.END_GROUP); -}; - - -/** - * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to - * the buffer. - * @param {number} field The field number. - * @param {string?} value The hash string. - * @export - */ -jspb.BinaryWriter.prototype.writeFixedHash64 = function(field, value) { - if (value == null) return; - jspb.asserts.assert(value.length == 8); - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); - this.encoder_.writeFixedHash64(value); -}; - - -/** - * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to - * the buffer. - * @param {number} field The field number. - * @param {string?} value The hash string. - * @export - */ -jspb.BinaryWriter.prototype.writeVarintHash64 = function(field, value) { - if (value == null) return; - jspb.asserts.assert(value.length == 8); - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); - this.encoder_.writeVarintHash64(value); -}; - - -/** - * Writes a 64-bit field to the buffer as a fixed64. - * @param {number} field The field number. - * @param {number} lowBits The low 32 bits. - * @param {number} highBits The high 32 bits. - * @export - */ -jspb.BinaryWriter.prototype.writeSplitFixed64 = function( - field, lowBits, highBits) { - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); - this.encoder_.writeSplitFixed64(lowBits, highBits); -}; - - -/** - * Writes a 64-bit field to the buffer as a varint. - * @param {number} field The field number. - * @param {number} lowBits The low 32 bits. - * @param {number} highBits The high 32 bits. - * @export - */ -jspb.BinaryWriter.prototype.writeSplitVarint64 = function( - field, lowBits, highBits) { - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); - this.encoder_.writeSplitVarint64(lowBits, highBits); -}; - - -/** - * Writes a 64-bit field to the buffer as a zigzag encoded varint. - * @param {number} field The field number. - * @param {number} lowBits The low 32 bits. - * @param {number} highBits The high 32 bits. - * @export - */ -jspb.BinaryWriter.prototype.writeSplitZigzagVarint64 = function( - field, lowBits, highBits) { - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); - var encoder = this.encoder_; - jspb.utils.toZigzag64(lowBits, highBits, function(lowBits, highBits) { - encoder.writeSplitVarint64(lowBits >>> 0, highBits >>> 0); - }); -}; - - -/** - * Writes an array of numbers to the buffer as a repeated 32-bit int field. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export - */ -jspb.BinaryWriter.prototype.writeRepeatedInt32 = function(field, value) { - if (value == null) return; - for (var i = 0; i < value.length; i++) { - this.writeSignedVarint32_(field, value[i]); + /** + * Writes a pre-serialized message to the buffer if the message and endpoints + * are non-null. + * @param {?Uint8Array} bytes The array of bytes to write. + * @param {?number} start The start of the range to write. + * @param {?number} end The end of the range to write. + */ + maybeWriteSerializedMessage(bytes, start, end) { + if (bytes != null && start != null && end != null) { + this.writeSerializedMessage(bytes, start, end); + } } -}; - -/** - * Writes an array of numbers formatted as strings to the buffer as a repeated - * 32-bit int field. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export - */ -jspb.BinaryWriter.prototype.writeRepeatedInt32String = function(field, value) { - if (value == null) return; - for (var i = 0; i < value.length; i++) { - this.writeInt32String(field, value[i]); + /** + * Resets the writer, throwing away any accumulated buffers. + */ + reset() { + this.blocks_ = []; + this.encoder_.end(); + this.totalLength_ = 0; } -}; - -/** - * Writes an array of numbers to the buffer as a repeated 64-bit int field. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export - */ -jspb.BinaryWriter.prototype.writeRepeatedInt64 = function(field, value) { - if (value == null) return; - for (var i = 0; i < value.length; i++) { - this.writeSignedVarint64_(field, value[i]); + /** + * Converts the encoded data into a Uint8Array. + * @return {!Uint8Array} + */ + getResultBuffer() { + // flush the encoder to avoid a special case below. + this.pushBlock(this.encoder_.end()); + const resultLength = this.totalLength_; + // NOTE: some of the Uint8Arrays stored in blocks_ are backing stores for + // ByteString objects and so we should be careful not to leak references to + // them from here. i.o.w. don't add an optimization that directly returns + // references to things in blocks. + const flat = new Uint8Array(resultLength); + const blocks = this.blocks_; + const blockCount = blocks.length; + let offset = 0; + + for (let i = 0; i < blockCount; i++) { + const block = blocks[i]; + flat.set(block, offset); + offset += block.length; + } + + // Post condition: `flattened` must have had every byte written. + assert(offset == flat.length); + + // Replace our block list with the flattened block, which lets GC reclaim + // the temp blocks sooner. + this.blocks_ = [flat]; + + return flat; } -}; - -/** - * Writes an array of 64-bit values to the buffer as a fixed64. - * @param {number} field The field number. - * @param {?Array} value The value. - * @param {function(T): number} lo Function to get low bits. - * @param {function(T): number} hi Function to get high bits. - * @template T - * @export - */ -jspb.BinaryWriter.prototype.writeRepeatedSplitFixed64 = function( - field, value, lo, hi) { - if (value == null) return; - for (var i = 0; i < value.length; i++) { - this.writeSplitFixed64(field, lo(value[i]), hi(value[i])); + /** + * Converts the encoded data into a ByteString. + * @return {!ByteString} + */ + getResultBufferAsByteString() { + // Note that this is safe because we never leak or mutate the Uint8Array + // returned by getResultBuffer even though it's stored in `blocks_`. + return unsafeByteStringFromUint8Array(this.getResultBuffer()); } -}; - -/** - * Writes an array of 64-bit values to the buffer as a varint. - * @param {number} field The field number. - * @param {?Array} value The value. - * @param {function(T): number} lo Function to get low bits. - * @param {function(T): number} hi Function to get high bits. - * @template T - * @export - */ -jspb.BinaryWriter.prototype.writeRepeatedSplitVarint64 = function( - field, value, lo, hi) { - if (value == null) return; - for (var i = 0; i < value.length; i++) { - this.writeSplitVarint64(field, lo(value[i]), hi(value[i])); + /** + * Converts the encoded data into a base64-encoded string. + * @param {!Alphabet=} alphabet Which flavor of base64 to + * use. + * @return {string} + */ + getResultBase64String(alphabet) { + if (alphabet === undefined) { + return encodeByteArray(this.getResultBuffer()); + } else { + return encodeByteArraySlow(this.getResultBuffer(), alphabet); + } } -}; - -/** - * Writes an array of 64-bit values to the buffer as a zigzag varint. - * @param {number} field The field number. - * @param {?Array} value The value. - * @param {function(T): number} lo Function to get low bits. - * @param {function(T): number} hi Function to get high bits. - * @template T - * @export - */ -jspb.BinaryWriter.prototype.writeRepeatedSplitZigzagVarint64 = function( - field, value, lo, hi) { - if (value == null) return; - for (var i = 0; i < value.length; i++) { - this.writeSplitZigzagVarint64(field, lo(value[i]), hi(value[i])); + /** + * Encodes a (field number, wire type) tuple into a wire-format field header + * and stores it in the buffer as a varint. + * @param {number} field The field number. + * @param {!WireType} wireType The wire-type of the field, as specified in the + * protocol buffer documentation. + * @private + */ + writeFieldHeader_(field, wireType) { + assert(field >= 1 && field == Math.floor(field)); + this.encoder_.writeUnsignedVarint32(makeTag(field, wireType)); } -}; - -/** - * Writes an array of numbers formatted as strings to the buffer as a repeated - * 64-bit int field. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export - */ -jspb.BinaryWriter.prototype.writeRepeatedInt64String = function(field, value) { - if (value == null) return; - for (var i = 0; i < value.length; i++) { - this.writeInt64String(field, value[i]); + // TODO(b/221101646): Maybe update AnyFieldType to include ByteString. + /** + * Writes a field of any valid scalar type to the binary stream. + * @param {!FieldType} fieldType + * @param {number} field + * @param {!AnyFieldType|!ByteString} value + */ + writeAny(fieldType, field, value) { + switch (fieldType) { + case FieldType.DOUBLE: + this.writeDouble(field, /** @type {number} */(value)); + return; + case FieldType.FLOAT: + this.writeFloat(field, /** @type {number} */(value)); + return; + case FieldType.INT64: + this.writeInt64(field, /** @type {number} */(value)); + return; + case FieldType.UINT64: + this.writeUint64(field, /** @type {number} */(value)); + return; + case FieldType.INT32: + this.writeInt32(field, /** @type {number} */(value)); + return; + case FieldType.FIXED64: + this.writeFixed64(field, /** @type {number} */(value)); + return; + case FieldType.FIXED32: + this.writeFixed32(field, /** @type {number} */(value)); + return; + case FieldType.BOOL: + this.writeBool(field, /** @type {boolean} */(value)); + return; + case FieldType.STRING: + this.writeString(field, /** @type {string} */(value)); + return; + case FieldType.GROUP: + fail('Group field type not supported in writeAny()'); + return; + case FieldType.MESSAGE: + fail('Message field type not supported in writeAny()'); + return; + case FieldType.BYTES: + this.writeBytes(field, /** @type {?ByteSource|?ByteString} */(value)); + return; + case FieldType.UINT32: + this.writeUint32(field, /** @type {number} */(value)); + return; + case FieldType.ENUM: + this.writeEnum(field, /** @type {number} */(value)); + return; + case FieldType.SFIXED32: + this.writeSfixed32(field, /** @type {number} */(value)); + return; + case FieldType.SFIXED64: + this.writeSfixed64(field, /** @type {number} */(value)); + return; + case FieldType.SINT32: + this.writeSint32(field, /** @type {number} */(value)); + return; + case FieldType.SINT64: + this.writeSint64(field, /** @type {number} */(value)); + return; + default: + fail('Invalid field type in writeAny()'); + return; + } } -}; - -/** - * Writes an array numbers to the buffer as a repeated unsigned 32-bit int - * field. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export - */ -jspb.BinaryWriter.prototype.writeRepeatedUint32 = function(field, value) { - if (value == null) return; - for (var i = 0; i < value.length; i++) { - this.writeUnsignedVarint32_(field, value[i]); + /** + * Writes a varint field to the buffer without range checking. + * @param {number} field The field number. + * @param {number|null|undefined} value The value to write. + * @private + */ + writeUnsignedVarint32_(field, value) { + if (value == null) return; + this.writeFieldHeader_(field, WireType.VARINT); + this.encoder_.writeUnsignedVarint32(value); } -}; - -/** - * Writes an array of numbers formatted as strings to the buffer as a repeated - * unsigned 32-bit int field. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export - */ -jspb.BinaryWriter.prototype.writeRepeatedUint32String = function(field, value) { - if (value == null) return; - for (var i = 0; i < value.length; i++) { - this.writeUint32String(field, value[i]); + /** + * Writes a varint field to the buffer without range checking. + * @param {number} field The field number. + * @param {number|null|undefined} value The value to write. + * @private + */ + writeSignedVarint32_(field, value) { + if (value == null) return; + assertSignedInteger(field, value); + this.writeFieldHeader_(field, WireType.VARINT); + this.encoder_.writeSignedVarint32(value); } -}; - -/** - * Writes an array numbers to the buffer as a repeated unsigned 64-bit int - * field. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export - */ -jspb.BinaryWriter.prototype.writeRepeatedUint64 = function(field, value) { - if (value == null) return; - for (var i = 0; i < value.length; i++) { - this.writeUnsignedVarint64_(field, value[i]); + /** + * Writes a varint field to the buffer without range checking. + * @param {number} field The field number. + * @param {number|string|!bigint|null|undefined} value The value to write. + * @private + */ + writeUnsignedVarint64_(field, value) { + if (value == null) return; + this.writeFieldHeader_(field, WireType.VARINT); + switch (typeof value) { + case 'number': + this.encoder_.writeUnsignedVarint64(value); + break; + + case 'bigint': { + const num = UInt64.fromBigInt(/** @type {bigint} */(value)); + this.encoder_.writeSplitVarint64(num.lo, num.hi); + break; + } + + default: { + const num = UInt64.fromString(/** @type {string} */(value)); + this.encoder_.writeSplitVarint64(num.lo, num.hi); + break; + } + } } -}; - -/** - * Writes an array of numbers formatted as strings to the buffer as a repeated - * unsigned 64-bit int field. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export - */ -jspb.BinaryWriter.prototype.writeRepeatedUint64String = function(field, value) { - if (value == null) return; - for (var i = 0; i < value.length; i++) { - this.writeUint64String(field, value[i]); + /** + * Writes a varint field to the buffer without range checking. + * @param {number} field The field number. + * @param {number|string?|!bigint|null|undefined} value The value to write. + * @private + */ + writeSignedVarint64_(field, value) { + if (value == null) return; + this.writeFieldHeader_(field, WireType.VARINT); + switch (typeof value) { + case 'number': + this.encoder_.writeSignedVarint64(value); + break; + + case 'bigint': { + const num = Int64.fromBigInt(/** @type {bigint} */(value)); + this.encoder_.writeSplitVarint64(num.lo, num.hi); + break; + } + + default: { + const num = Int64.fromString(/** @type {string} */(value)); + this.encoder_.writeSplitVarint64(num.lo, num.hi); + break; + } + } } -}; - -/** - * Writes an array numbers to the buffer as a repeated signed 32-bit int field. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export - */ -jspb.BinaryWriter.prototype.writeRepeatedSint32 = function(field, value) { - if (value == null) return; - for (var i = 0; i < value.length; i++) { - this.writeZigzagVarint32_(field, value[i]); + /** + * Writes a zigzag varint field to the buffer without range checking. + * @param {number} field The field number. + * @param {number|null|undefined} value The value to write. + * @private + */ + writeZigzagVarint32_(field, value) { + if (value == null) return; + this.writeFieldHeader_(field, WireType.VARINT); + this.encoder_.writeZigzagVarint32(value); } -}; - -/** - * Writes an array numbers to the buffer as a repeated signed 64-bit int field. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export - */ -jspb.BinaryWriter.prototype.writeRepeatedSint64 = function(field, value) { - if (value == null) return; - for (var i = 0; i < value.length; i++) { - this.writeZigzagVarint64_(field, value[i]); + /** + * Writes a zigzag varint field to the buffer without range checking. + * @param {number} field The field number. + * @param {number|string|!bigint|null|undefined} value The value to write. + * @private + */ + writeZigzagVarint64_(field, value) { + if (value == null) return; + this.writeFieldHeader_(field, WireType.VARINT); + switch (typeof value) { + case 'number': + this.encoder_.writeZigzagVarint64(/** @type {number} */(value)); + break; + + case 'bigint': + this.encoder_.writeZigzagVarint64BigInt(/** @type {bigint} */(value)); + break; + + default: + this.encoder_.writeZigzagVarint64String(/** @type {string} */(value)); + break; + } } -}; - -/** - * Writes an array numbers to the buffer as a repeated signed 64-bit int field. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export - */ -jspb.BinaryWriter.prototype.writeRepeatedSint64String = function(field, value) { - if (value == null) return; - for (var i = 0; i < value.length; i++) { - this.writeZigzagVarint64String_(field, value[i]); + /** + * Writes an int32 field to the buffer. Numbers outside the range [-2^31,2^31) + * will be truncated. + * @param {number} field The field number. + * @param {number|null|undefined} value The value to write. + */ + writeInt32(field, value) { + if (value == null) return; + assertThat(field, value, (value >= -TWO_TO_31) && (value < TWO_TO_31)); + this.writeSignedVarint32_(field, value); } -}; - -/** - * Writes an array of hash64 strings to the buffer as a repeated signed 64-bit - * int field. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export - */ -jspb.BinaryWriter.prototype.writeRepeatedSintHash64 = function(field, value) { - if (value == null) return; - for (var i = 0; i < value.length; i++) { - this.writeZigzagVarintHash64_(field, value[i]); + /** + * Writes an int64 field to the buffer. Numbers outside the range [-2^63,2^63) + * will be truncated. + * @param {number} field The field number. + * @param {number|string|!bigint|null|undefined} value The value to write. + */ + writeInt64(field, value) { + if (value == null) return; + assertSignedInt64(field, value); + this.writeSignedVarint64_(field, value); } -}; + /** + * Writes a int64 field (with value as a string) to the buffer. + * @param {number} field The field number. + * @param {string|null|undefined} value The value to write. + * @deprecated Use writeInt64() + */ + writeInt64String(field, value) { + this.writeInt64(field, value); + } -/** - * Writes an array of numbers to the buffer as a repeated fixed32 field. This - * works for both signed and unsigned fixed32s. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export - */ -jspb.BinaryWriter.prototype.writeRepeatedFixed32 = function(field, value) { - if (value == null) return; - for (var i = 0; i < value.length; i++) { - this.writeFixed32(field, value[i]); + /** + * Writes a uint32 field to the buffer. Numbers outside the range [0,2^32) + * will be truncated. + * @param {number} field The field number. + * @param {number|null|undefined} value The value to write. + */ + writeUint32(field, value) { + if (value == null) return; + assertThat(field, value, (value >= 0) && (value < TWO_TO_32)); + this.writeUnsignedVarint32_(field, value); } -}; -/** - * Writes an array of numbers to the buffer as a repeated fixed64 field. This - * works for both signed and unsigned fixed64s. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export - */ -jspb.BinaryWriter.prototype.writeRepeatedFixed64 = function(field, value) { - if (value == null) return; - for (var i = 0; i < value.length; i++) { - this.writeFixed64(field, value[i]); + /** + * Writes a uint64 field to the buffer. Numbers outside the range [0,2^64) + * will be truncated. + * @param {number} field The field number. + * @param {number|string|!bigint|null|undefined} value The value to write. + */ + writeUint64(field, value) { + if (value == null) return; + assertUnsignedInt64(field, value); + this.writeUnsignedVarint64_(field, value); } -}; + /** + * Writes a uint64 field (with value as a string) to the buffer. + * @param {number} field The field number. + * @param {string|null|undefined} value The value to write. + * @deprecated Use writeUint64() + */ + writeUint64String(field, value) { + this.writeUint64(field, value); + } -/** - * Writes an array of numbers to the buffer as a repeated fixed64 field. This - * works for both signed and unsigned fixed64s. - * @param {number} field The field number. - * @param {?Array} value The array of decimal strings to write. - * @export - */ -jspb.BinaryWriter.prototype.writeRepeatedFixed64String = function( - field, value) { - if (value == null) return; - for (var i = 0; i < value.length; i++) { - this.writeFixed64String(field, value[i]); + /** + * Writes an sint32 field to the buffer. Numbers outside the range + * [-2^31,2^31) will be truncated. + * @param {number} field The field number. + * @param {number|null|undefined} value The value to write. + */ + writeSint32(field, value) { + if (value == null) return; + assertThat(field, value, (value >= -TWO_TO_31) && (value < TWO_TO_31)); + this.writeZigzagVarint32_(field, value); } -}; + /** + * Writes an sint64 field to the buffer. Numbers outside the range + * [-2^63,2^63) will be truncated. + * @param {number} field The field number. + * @param {number|string|!bigint|null|undefined} value The value to write. + */ + writeSint64(field, value) { + if (value == null) return; + assertSignedInt64(field, value); + this.writeZigzagVarint64_(field, value); + } -/** - * Writes an array of numbers to the buffer as a repeated sfixed32 field. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export - */ -jspb.BinaryWriter.prototype.writeRepeatedSfixed32 = function(field, value) { - if (value == null) return; - for (var i = 0; i < value.length; i++) { - this.writeSfixed32(field, value[i]); + /** + * Writes an sint64 field to the buffer. Numbers outside the range + * [-2^63,2^63) will be truncated. + * @param {number} field The field number. + * @param {string|null|undefined} value The decimal string to write. + * @deprecated Use writeSint64(); + */ + writeSint64String(field, value) { + this.writeSint64(field, value); } -}; + /** + * Writes a fixed32 field to the buffer. Numbers outside the range [0,2^32) + * will be truncated. + * @param {number} field The field number. + * @param {number|null|undefined} value The value to write. + */ + writeFixed32(field, value) { + if (value == null) return; + assertThat(field, value, (value >= 0) && (value < TWO_TO_32)); + this.writeFieldHeader_(field, WireType.FIXED32); + this.encoder_.writeUint32(value); + } -/** - * Writes an array of numbers to the buffer as a repeated sfixed64 field. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export - */ -jspb.BinaryWriter.prototype.writeRepeatedSfixed64 = function(field, value) { - if (value == null) return; - for (var i = 0; i < value.length; i++) { - this.writeSfixed64(field, value[i]); + /** + * Writes a fixed64 field to the buffer. Numbers outside the range [0,2^64) + * will be truncated. + * @param {number} field The field number. + * @param {number|string|!bigint|null|undefined} value The value to write. + */ + writeFixed64(field, value) { + if (value == null) return; + assertUnsignedInt64(field, value); + this.writeFieldHeader_(field, WireType.FIXED64); + switch (typeof value) { + case 'number': + this.encoder_.writeUint64(value); + break; + case 'bigint': { + const num = UInt64.fromBigInt(/** @type {bigint} */(value)); + this.encoder_.writeSplitFixed64(num.lo, num.hi); + break; + } + default: { + const num = UInt64.fromString(/** @type {string} */(value)); + this.encoder_.writeSplitFixed64(num.lo, num.hi); + break; + } + } } -}; + /** + * Writes a fixed64 field (with value as a string) to the buffer. + * @param {number} field The field number. + * @param {string|null|undefined} value The value to write. + * @deprecated Use writeFixed64(). + */ + writeFixed64String(field, value) { + this.writeFixed64(field, value); + } -/** - * Writes an array of decimal strings to the buffer as a repeated sfixed64 - * field. - * @param {number} field The field number. - * @param {?Array} value The array of decimal strings to write. - * @export - */ -jspb.BinaryWriter.prototype.writeRepeatedSfixed64String = function( - field, value) { - if (value == null) return; - for (var i = 0; i < value.length; i++) { - this.writeSfixed64String(field, value[i]); + /** + * Writes a sfixed32 field to the buffer. Numbers outside the range + * [-2^31,2^31) will be truncated. + * @param {number} field The field number. + * @param {number|null|undefined} value The value to write. + */ + writeSfixed32(field, value) { + if (value == null) return; + assertThat(field, value, (value >= -TWO_TO_31) && (value < TWO_TO_31)); + this.writeFieldHeader_(field, WireType.FIXED32); + this.encoder_.writeInt32(value); } -}; + /** + * Writes a sfixed64 field to the buffer. Numbers outside the range + * [-2^63,2^63) will be truncated. + * @param {number} field The field number. + * @param {number|string|!bigint|null|undefined} value The value to write. + */ + writeSfixed64(field, value) { + if (value == null) return; + assertSignedInt64(field, value); + this.writeFieldHeader_(field, WireType.FIXED64); + switch (typeof value) { + case 'number': + this.encoder_.writeInt64(value); + break; + case 'bigint': + const int64Big = Int64.fromBigInt(/** @type {bigint} */(value)); + this.encoder_.writeSplitFixed64(int64Big.lo, int64Big.hi); + break; + default: + const int64Str = Int64.fromString(/** @type {string} */(value)); + this.encoder_.writeSplitFixed64(int64Str.lo, int64Str.hi); + break; + } + } -/** - * Writes an array of numbers to the buffer as a repeated float field. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export - */ -jspb.BinaryWriter.prototype.writeRepeatedFloat = function(field, value) { - if (value == null) return; - for (var i = 0; i < value.length; i++) { - this.writeFloat(field, value[i]); + /** + * Writes a sfixed64 string field to the buffer. Numbers outside the range + * [-2^63,2^63) will be truncated. + * @param {number} field The field number. + * @param {string|null|undefined} value The value to write. + * @deprecated Use writeSfixed64(). + */ + writeSfixed64String(field, value) { + this.writeSfixed64(field, value); } -}; + /** + * Writes a single-precision floating point field to the buffer. Numbers + * requiring more than 32 bits of precision will be truncated. + * @param {number} field The field number. + * @param {number?|string|null|undefined} value The value to write, accepts + * 'Infinity'/'-Infinity'/'NaN' for JSPB wire format compatibility. + */ + writeFloat(field, value) { + if (value == null) return; + this.writeFieldHeader_(field, WireType.FIXED32); + this.encoder_.writeFloat(value); + } -/** - * Writes an array of numbers to the buffer as a repeated double field. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export - */ -jspb.BinaryWriter.prototype.writeRepeatedDouble = function(field, value) { - if (value == null) return; - for (var i = 0; i < value.length; i++) { - this.writeDouble(field, value[i]); + /** + * Writes a double-precision floating point field to the buffer. As this is + * the native format used by JavaScript, no precision will be lost. + * @param {number} field The field number. + * @param {number?|string|null|undefined} value The value to write, accepts + * 'Infinity'/'-Infinity'/'NaN' for JSPB wire format compatibility. + */ + writeDouble(field, value) { + if (value == null) return; + this.writeFieldHeader_(field, WireType.FIXED64); + this.encoder_.writeDouble(value); } -}; + /** + * Writes a boolean field to the buffer. We allow numbers as input + * because the JSPB code generator uses 0/1 instead of true/false to save + * space in the string representation of the proto. + * @param {number} field The field number. + * @param {boolean?|number|null|undefined} value The value to write. + */ + writeBool(field, value) { + if (value == null) return; + assertThat( + field, value, typeof value === 'boolean' || typeof value === 'number'); + this.writeFieldHeader_(field, WireType.VARINT); + this.encoder_.writeBool(value); + } -/** - * Writes an array of booleans to the buffer as a repeated bool field. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export - */ -jspb.BinaryWriter.prototype.writeRepeatedBool = function(field, value) { - if (value == null) return; - for (var i = 0; i < value.length; i++) { - this.writeBool(field, value[i]); + /** + * Writes an enum field to the buffer. + * @param {number} field The field number. + * @param {number|null|undefined} value The value to write. + */ + writeEnum(field, value) { + if (value == null) return; + // Converting since value might be object typed integer here. + const intValue = /** number */ parseInt(value, 10); + assertSignedInteger(field, intValue); + this.writeFieldHeader_(field, WireType.VARINT); + this.encoder_.writeSignedVarint32(intValue); } -}; + /** + * Writes a string field to the buffer. + * @param {number} field The field number. + * @param {string|null|undefined} value The string to write. + */ + writeString(field, value) { + if (value == null) return; + this.writeUint8Array( + field, + encodeUtf8( + value, /** rejectUnpairedSurrogates=*/ REJECT_UNPAIRED_SURROGATES)); + } -/** - * Writes an array of enums to the buffer as a repeated enum field. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export - */ -jspb.BinaryWriter.prototype.writeRepeatedEnum = function(field, value) { - if (value == null) return; - for (var i = 0; i < value.length; i++) { - this.writeEnum(field, value[i]); + /** + * Writes an arbitrary byte field to the buffer. Note - to match the behavior + * of the C++ implementation, empty byte arrays _are_ serialized. + * @param {number} field The field number. + * @param {?ByteSource|?ByteString|undefined} value The array of bytes to + * write. + */ + writeBytes(field, value) { + if (value == null) return; + this.writeUint8Array( + field, + bufferFromSource(value, /* treatNewDataAsImmutable= */ true).buffer); } -}; + /** + * @param {number} field The field number. + * @param {!Uint8Array} value The array of bytes to write. + * @private + */ + writeUint8Array(field, value) { + this.writeFieldHeader_(field, WireType.DELIMITED); + this.encoder_.writeUnsignedVarint32(value.length); + this.appendUint8Array_(value); + } -/** - * Writes an array of strings to the buffer as a repeated string field. - * @param {number} field The field number. - * @param {?Array} value The array of strings to write. - * @export - */ -jspb.BinaryWriter.prototype.writeRepeatedString = function(field, value) { - if (value == null) return; - for (var i = 0; i < value.length; i++) { - this.writeString(field, value[i]); + /** + * Writes a message to the buffer. + * @param {number} field The field number. + * @param {?MessageType|undefined} value The message to write. + * @param {function(MessageTypeNonNull, !BinaryWriter)} writerCallback + * Will be invoked with the value to write and the writer to write it + * with. + * @template MessageType + * Use go/closure-ttl to declare a non-nullable version of MessageType. + * Replace the null in blah|null with none. This is necessary because the + * compiler will infer MessageType to be nullable if the value parameter is + * nullable. + * @template MessageTypeNonNull := + * cond(isUnknown(MessageType), unknown(), + * mapunion(MessageType, (X) => + * cond(eq(X, 'undefined'), none(), cond(eq(X, 'null'), none(), X)))) + * =: + */ + writeMessage(field, value, writerCallback) { + if (value == null) return; + const bookmark = this.beginDelimited_(field); + writerCallback(value, this); + this.endDelimited_(bookmark); } -}; + /** + * Writes a message set extension to the buffer. + * @param {number} field The field number for the extension. + * @param {?MessageType|undefined} value The extension message object to + * write. Note that message set can only have extensions with type of + * optional message. + * @param {function(!MessageTypeNonNull, !BinaryWriter)} writerCallback + * Will be invoked with the value to write and the writer to write it + * with. + * @template MessageType + * Use go/closure-ttl to declare a non-nullable version of MessageType. + * Replace the null in blah|null with none. This is necessary because the + * compiler will infer MessageType to be nullable if the value parameter is + * nullable. + * @template MessageTypeNonNull := + * cond(isUnknown(MessageType), unknown(), + * mapunion(MessageType, (X) => + * cond(eq(X, 'undefined'), none(), cond(eq(X, 'null'), none(), X)))) + * =: + */ + writeMessageSet(field, value, writerCallback) { + if (value == null) return; + // The wire format for a message set is defined by + // google3/net/proto/message_set.proto + this.writeFieldHeader_(1, WireType.START_GROUP); + this.writeFieldHeader_(2, WireType.VARINT); + this.encoder_.writeSignedVarint32(field); + const bookmark = this.beginDelimited_(3); + writerCallback(value, this); + this.endDelimited_(bookmark); + this.writeFieldHeader_(1, WireType.END_GROUP); + } -/** - * Writes an array of arbitrary byte fields to the buffer. - * @param {number} field The field number. - * @param {?Array} value The arrays of arrays of bytes to - * write. - * @export - */ -jspb.BinaryWriter.prototype.writeRepeatedBytes = function(field, value) { - if (value == null) return; - for (var i = 0; i < value.length; i++) { - this.writeBytes(field, value[i]); + /** + * Writes a group message to the buffer. + * + * @param {number} field The field number. + * @param {?MessageType|undefined} value The message to write, wrapped with + * START_GROUP / END_GROUP tags. Will be a no-op if 'value' is null. + * @param {function(MessageTypeNonNull, !BinaryWriter)} writerCallback + * Will be invoked with the value to write and the writer to write it + * with. + * @template MessageType + * Use go/closure-ttl to declare a non-nullable version of MessageType. + * Replace the null in blah|null with none. This is necessary because the + * compiler will infer MessageType to be nullable if the value parameter is + * nullable. + * @template MessageTypeNonNull := + * cond(isUnknown(MessageType), unknown(), + * mapunion(MessageType, (X) => + * cond(eq(X, 'undefined'), none(), cond(eq(X, 'null'), none(), X)))) + * =: + */ + writeGroup(field, value, writerCallback) { + if (value == null) return; + this.writeFieldHeader_(field, WireType.START_GROUP); + writerCallback(value, this); + this.writeFieldHeader_(field, WireType.END_GROUP); } -}; + /** + * Writes a 64-bit field to the buffer as a fixed64. + * @param {number} field The field number. + * @param {number} lowBits The low 32 bits. + * @param {number} highBits The high 32 bits. + */ + writeSplitFixed64(field, lowBits, highBits) { + this.writeFieldHeader_(field, WireType.FIXED64); + this.encoder_.writeSplitFixed64(lowBits, highBits); + } -/** - * Writes an array of messages to the buffer. - * @template MessageType - * @param {number} field The field number. - * @param {?Array} value The array of messages to - * write. - * @param {function(MessageType, !jspb.BinaryWriter)} writerCallback - * Will be invoked with the value to write and the writer to write it with. - * @export - */ -jspb.BinaryWriter.prototype.writeRepeatedMessage = function( - field, value, writerCallback) { - if (value == null) return; - for (var i = 0; i < value.length; i++) { - var bookmark = this.beginDelimited_(field); - writerCallback(value[i], this); - this.endDelimited_(bookmark); + /** + * Writes a 64-bit field to the buffer as a varint. + * @param {number} field The field number. + * @param {number} lowBits The low 32 bits. + * @param {number} highBits The high 32 bits. + */ + writeSplitVarint64(field, lowBits, highBits) { + this.writeFieldHeader_(field, WireType.VARINT); + this.encoder_.writeSplitVarint64(lowBits, highBits); } -}; + /** + * Writes a 64-bit field to the buffer as a zigzag encoded varint. + * @param {number} field The field number. + * @param {number} lowBits The low 32 bits. + * @param {number} highBits The high 32 bits. + */ + writeSplitZigzagVarint64(field, lowBits, highBits) { + this.writeFieldHeader_(field, WireType.VARINT); + this.encoder_.writeSplitZigzagVarint64(lowBits >>> 0, highBits >>> 0); + } -/** - * Writes an array of group messages to the buffer. - * @template MessageType - * @param {number} field The field number. - * @param {?Array} value The array of messages to - * write. - * @param {function(MessageType, !jspb.BinaryWriter)} writerCallback - * Will be invoked with the value to write and the writer to write it with. - * @export - */ -jspb.BinaryWriter.prototype.writeRepeatedGroup = function( - field, value, writerCallback) { - if (value == null) return; - for (var i = 0; i < value.length; i++) { - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.START_GROUP); - writerCallback(value[i], this); - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.END_GROUP); + /** + * Writes an array of numbers to the buffer as a repeated 32-bit int field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of ints to write. + */ + writeRepeatedInt32(field, value) { + if (value == null) return; + for (let i = 0; i < value.length; i++) { + this.writeSignedVarint32_(field, value[i]); + } } -}; -/** - * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to - * the buffer. - * @param {number} field The field number. - * @param {?Array} value The array of hashes to write. - * @export - */ -jspb.BinaryWriter.prototype.writeRepeatedFixedHash64 = function(field, value) { - if (value == null) return; - for (var i = 0; i < value.length; i++) { - this.writeFixedHash64(field, value[i]); + /** + * Writes an array of numbers to the buffer as a repeated 64-bit int field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of ints + * to write. + */ + writeRepeatedInt64(field, value) { + if (value == null) return; + for (let i = 0; i < value.length; i++) { + this.writeSignedVarint64_(field, value[i]); + } } -}; + /** + * Writes an array of 64-bit values to the buffer as a fixed64. + * @param {number} field The field number. + * @param {?Array|undefined} value The value. + * @param {function(T): number} lo Function to get low bits. + * @param {function(T): number} hi Function to get high bits. + * @template T + */ + writeRepeatedSplitFixed64(field, value, lo, hi) { + if (value == null) return; + for (let i = 0; i < value.length; i++) { + this.writeSplitFixed64(field, lo(value[i]), hi(value[i])); + } + } -/** - * Writes a repeated 64-bit hash string field (8 characters @ 8 bits of data - * each) to the buffer. - * @param {number} field The field number. - * @param {?Array} value The array of hashes to write. - * @export - */ -jspb.BinaryWriter.prototype.writeRepeatedVarintHash64 = function(field, value) { - if (value == null) return; - for (var i = 0; i < value.length; i++) { - this.writeVarintHash64(field, value[i]); + /** + * Writes an array of 64-bit values to the buffer as a varint. + * @param {number} field The field number. + * @param {?Array|undefined} value The value. + * @param {function(T): number} lo Function to get low bits. + * @param {function(T): number} hi Function to get high bits. + * @template T + */ + writeRepeatedSplitVarint64(field, value, lo, hi) { + if (value == null) return; + for (let i = 0; i < value.length; i++) { + this.writeSplitVarint64(field, lo(value[i]), hi(value[i])); + } } -}; + /** + * Writes an array of 64-bit values to the buffer as a zigzag varint. + * @param {number} field The field number. + * @param {?Array|undefined} value The value. + * @param {function(T): number} lo Function to get low bits. + * @param {function(T): number} hi Function to get high bits. + * @template T + */ + writeRepeatedSplitZigzagVarint64(field, value, lo, hi) { + if (value == null) return; + for (let i = 0; i < value.length; i++) { + this.writeSplitZigzagVarint64(field, lo(value[i]), hi(value[i])); + } + } -/** - * Writes an array of numbers to the buffer as a packed 32-bit int field. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export - */ -jspb.BinaryWriter.prototype.writePackedInt32 = function(field, value) { - if (value == null || !value.length) return; - var bookmark = this.beginDelimited_(field); - for (var i = 0; i < value.length; i++) { - this.encoder_.writeSignedVarint32(value[i]); + /** + * Writes an array of numbers formatted as strings to the buffer as a repeated + * 64-bit int field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of ints to write. + * @deprecated use writeRepeatedInt64(). + */ + writeRepeatedInt64String(field, value) { + this.writeRepeatedInt64(field, value); } - this.endDelimited_(bookmark); -}; + /** + * Writes an array numbers to the buffer as a repeated unsigned 32-bit int + * field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of ints to write. + */ + writeRepeatedUint32(field, value) { + if (value == null) return; + for (let i = 0; i < value.length; i++) { + this.writeUnsignedVarint32_(field, value[i]); + } + } -/** - * Writes an array of numbers represented as strings to the buffer as a packed - * 32-bit int field. - * @param {number} field - * @param {?Array} value - * @export - */ -jspb.BinaryWriter.prototype.writePackedInt32String = function(field, value) { - if (value == null || !value.length) return; - var bookmark = this.beginDelimited_(field); - for (var i = 0; i < value.length; i++) { - this.encoder_.writeSignedVarint32(parseInt(value[i], 10)); + /** + * Writes an array numbers or decimal strings to the buffer as a repeated + * unsigned 64-bit int field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of ints + * to write. + */ + writeRepeatedUint64(field, value) { + if (value == null) return; + for (let i = 0; i < value.length; i++) { + this.writeUnsignedVarint64_(field, value[i]); + } } - this.endDelimited_(bookmark); -}; + /** + * Writes an array of numbers formatted as strings to the buffer as a repeated + * unsigned 64-bit int field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of ints to write. + * @deprecated Use writeRepeatedUint64(). + */ + writeRepeatedUint64String(field, value) { + this.writeRepeatedUint64(field, value); + } -/** - * Writes an array of numbers to the buffer as a packed 64-bit int field. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export - */ -jspb.BinaryWriter.prototype.writePackedInt64 = function(field, value) { - if (value == null || !value.length) return; - var bookmark = this.beginDelimited_(field); - for (var i = 0; i < value.length; i++) { - this.encoder_.writeSignedVarint64(value[i]); + /** + * Writes an array numbers to the buffer as a repeated signed 32-bit int + * field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of ints to write. + */ + writeRepeatedSint32(field, value) { + if (value == null) return; + for (let i = 0; i < value.length; i++) { + this.writeZigzagVarint32_(field, value[i]); + } } - this.endDelimited_(bookmark); -}; + /** + * Writes an array numbers or decimal strings to the buffer as a repeated + * signed 64-bit int field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of ints + * to write. + */ + writeRepeatedSint64(field, value) { + if (value == null) return; + for (let i = 0; i < value.length; i++) { + this.writeZigzagVarint64_(field, value[i]); + } + } -/** - * Writes an array of 64-bit values to the buffer as a fixed64. - * @param {number} field The field number. - * @param {?Array} value The value. - * @param {function(T): number} lo Function to get low bits. - * @param {function(T): number} hi Function to get high bits. - * @template T - * @export - */ -jspb.BinaryWriter.prototype.writePackedSplitFixed64 = function( - field, value, lo, hi) { - if (value == null) return; - var bookmark = this.beginDelimited_(field); - for (var i = 0; i < value.length; i++) { - this.encoder_.writeSplitFixed64(lo(value[i]), hi(value[i])); + /** + * Writes an array numbers to the buffer as a repeated signed 64-bit int + * field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of ints to write. + * @deprecated Use writeRepeatedSint64(). + */ + writeRepeatedSint64String(field, value) { + this.writeRepeatedSint64(field, value); } - this.endDelimited_(bookmark); -}; + /** + * Writes an array of numbers to the buffer as a repeated fixed32 field. This + * works for both signed and unsigned fixed32s. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of ints to write. + */ + writeRepeatedFixed32(field, value) { + if (value == null) return; + for (let i = 0; i < value.length; i++) { + this.writeFixed32(field, value[i]); + } + } -/** - * Writes an array of 64-bit values to the buffer as a varint. - * @param {number} field The field number. - * @param {?Array} value The value. - * @param {function(T): number} lo Function to get low bits. - * @param {function(T): number} hi Function to get high bits. - * @template T - * @export - */ -jspb.BinaryWriter.prototype.writePackedSplitVarint64 = function( - field, value, lo, hi) { - if (value == null) return; - var bookmark = this.beginDelimited_(field); - for (var i = 0; i < value.length; i++) { - this.encoder_.writeSplitVarint64(lo(value[i]), hi(value[i])); + /** + * Writes an array of numbers or decimal strings to the buffer as a repeated + * fixed64 field. This works for both signed and unsigned fixed64s. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of ints + * to write. + */ + writeRepeatedFixed64(field, value) { + if (value == null) return; + for (let i = 0; i < value.length; i++) { + this.writeFixed64(field, value[i]); + } } - this.endDelimited_(bookmark); -}; + /** + * Writes an array of numbers to the buffer as a repeated fixed64 field. This + * works for both signed and unsigned fixed64s. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of decimal strings to + * write. + * @deprecated Use writeRepeatedFixed64(). + */ + writeRepeatedFixed64String(field, value) { + this.writeRepeatedFixed64(field, value); + } -/** - * Writes an array of 64-bit values to the buffer as a zigzag varint. - * @param {number} field The field number. - * @param {?Array} value The value. - * @param {function(T): number} lo Function to get low bits. - * @param {function(T): number} hi Function to get high bits. - * @template T - * @export - */ -jspb.BinaryWriter.prototype.writePackedSplitZigzagVarint64 = function( - field, value, lo, hi) { - if (value == null) return; - var bookmark = this.beginDelimited_(field); - var encoder = this.encoder_; - for (var i = 0; i < value.length; i++) { - jspb.utils.toZigzag64( - lo(value[i]), hi(value[i]), function(bitsLow, bitsHigh) { - encoder.writeSplitVarint64(bitsLow >>> 0, bitsHigh >>> 0); - }); + /** + * Writes an array of numbers to the buffer as a repeated sfixed32 field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of ints to write. + */ + writeRepeatedSfixed32(field, value) { + if (value == null) return; + for (let i = 0; i < value.length; i++) { + this.writeSfixed32(field, value[i]); + } } - this.endDelimited_(bookmark); -}; + /** + * Writes an array of numbers or decimal strings to the buffer as a repeated + * sfixed64 field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of ints to write. + */ + writeRepeatedSfixed64(field, value) { + if (value == null) return; + for (let i = 0; i < value.length; i++) { + this.writeSfixed64(field, value[i]); + } + } -/** - * Writes an array of numbers represented as strings to the buffer as a packed - * 64-bit int field. - * @param {number} field - * @param {?Array} value - * @export - */ -jspb.BinaryWriter.prototype.writePackedInt64String = function(field, value) { - if (value == null || !value.length) return; - var bookmark = this.beginDelimited_(field); - for (var i = 0; i < value.length; i++) { - var num = jspb.arith.Int64.fromString(value[i]); - this.encoder_.writeSplitVarint64(num.lo, num.hi); + /** + * Writes an array of decimal strings to the buffer as a repeated sfixed64 + * field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of decimal strings to + * write. + * @deprecated Use writeRepeatedSfixed64(). + */ + writeRepeatedSfixed64String(field, value) { + this.writeRepeatedSfixed64(field, value); } - this.endDelimited_(bookmark); -}; + /** + * Writes an array of numbers to the buffer as a repeated float field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of floats to + * write, accepts 'Infinity'/'-Infinity'/'NaN' for JSPB wire format + * compatibility. + */ + writeRepeatedFloat(field, value) { + if (value == null) return; + for (let i = 0; i < value.length; i++) { + this.writeFloat(field, value[i]); + } + } -/** - * Writes an array numbers to the buffer as a packed unsigned 32-bit int field. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export - */ -jspb.BinaryWriter.prototype.writePackedUint32 = function(field, value) { - if (value == null || !value.length) return; - var bookmark = this.beginDelimited_(field); - for (var i = 0; i < value.length; i++) { - this.encoder_.writeUnsignedVarint32(value[i]); + /** + * Writes an array of numbers to the buffer as a repeated double field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of doubles to + * write, accepts 'Infinity'/'-Infinity'/'NaN' for JSPB wire format + * compatibility. + */ + writeRepeatedDouble(field, value) { + if (value == null) return; + for (let i = 0; i < value.length; i++) { + this.writeDouble(field, value[i]); + } } - this.endDelimited_(bookmark); -}; + /** + * Writes an array of booleans to the buffer as a repeated bool field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of booleans to + * write. + */ + writeRepeatedBool(field, value) { + if (value == null) return; + for (let i = 0; i < value.length; i++) { + this.writeBool(field, value[i]); + } + } -/** - * Writes an array of numbers represented as strings to the buffer as a packed - * unsigned 32-bit int field. - * @param {number} field - * @param {?Array} value - * @export - */ -jspb.BinaryWriter.prototype.writePackedUint32String = function(field, value) { - if (value == null || !value.length) return; - var bookmark = this.beginDelimited_(field); - for (var i = 0; i < value.length; i++) { - this.encoder_.writeUnsignedVarint32(parseInt(value[i], 10)); + /** + * Writes an array of enums to the buffer as a repeated enum field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of ints to write. + */ + writeRepeatedEnum(field, value) { + if (value == null) return; + for (let i = 0; i < value.length; i++) { + this.writeEnum(field, value[i]); + } } - this.endDelimited_(bookmark); -}; + /** + * Writes an array of strings to the buffer as a repeated string field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of strings to write. + */ + writeRepeatedString(field, value) { + if (value == null) return; + for (let i = 0; i < value.length; i++) { + this.writeString(field, value[i]); + } + } -/** - * Writes an array numbers to the buffer as a packed unsigned 64-bit int field. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export - */ -jspb.BinaryWriter.prototype.writePackedUint64 = function(field, value) { - if (value == null || !value.length) return; - var bookmark = this.beginDelimited_(field); - for (var i = 0; i < value.length; i++) { - this.encoder_.writeUnsignedVarint64(value[i]); + /** + * Writes an array of arbitrary byte fields to the buffer. + * @param {number} field The field number. + * @param {?Array|undefined} value The arrays of + * arrays of bytes to write. + */ + writeRepeatedBytes(field, value) { + if (value == null) return; + for (let i = 0; i < value.length; i++) { + this.writeBytes(field, value[i]); + } } - this.endDelimited_(bookmark); -}; + /** + * Writes an array of messages to the buffer. + * @template MessageType + * @param {number} field The field number. + * @param {?Array|undefined} value The array of messages to + * write. + * @param {function(MessageType, !BinaryWriter)} writerCallback + * Will be invoked with the value to write and the writer to write it + * with. + */ + writeRepeatedMessage(field, value, writerCallback) { + if (value == null) return; + for (let i = 0; i < value.length; i++) { + const bookmark = this.beginDelimited_(field); + writerCallback(value[i], this); + this.endDelimited_(bookmark); + } + } -/** - * Writes an array of numbers represented as strings to the buffer as a packed - * unsigned 64-bit int field. - * @param {number} field - * @param {?Array} value - * @export - */ -jspb.BinaryWriter.prototype.writePackedUint64String = function(field, value) { - if (value == null || !value.length) return; - var bookmark = this.beginDelimited_(field); - for (var i = 0; i < value.length; i++) { - var num = jspb.arith.UInt64.fromString(value[i]); - this.encoder_.writeSplitVarint64(num.lo, num.hi); + /** + * Writes an array of group messages to the buffer. + * @template MessageType + * @param {number} field The field number. + * @param {?Array|undefined} value The array of messages to + * write. + * @param {function(MessageType, !BinaryWriter)} writerCallback + * Will be invoked with the value to write and the writer to write it + * with. + */ + writeRepeatedGroup(field, value, writerCallback) { + if (value == null) return; + for (let i = 0; i < value.length; i++) { + this.writeFieldHeader_(field, WireType.START_GROUP); + writerCallback(value[i], this); + this.writeFieldHeader_(field, WireType.END_GROUP); + } } - this.endDelimited_(bookmark); -}; + /** + * Writes an array of numbers to the buffer as a packed 32-bit int field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of ints to write. + */ + writePackedInt32(field, value) { + if (value == null || !value.length) return; + const bookmark = this.beginDelimited_(field); + for (let i = 0; i < value.length; i++) { + assertSignedInteger(field, value[i]); + this.encoder_.writeSignedVarint32(value[i]); + } + this.endDelimited_(bookmark); + } -/** - * Writes an array numbers to the buffer as a packed signed 32-bit int field. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export - */ -jspb.BinaryWriter.prototype.writePackedSint32 = function(field, value) { - if (value == null || !value.length) return; - var bookmark = this.beginDelimited_(field); - for (var i = 0; i < value.length; i++) { - this.encoder_.writeZigzagVarint32(value[i]); + /** + * Writes an array of numbers represented as strings to the buffer as a packed + * 32-bit int field. + * @param {number} field + * @param {?Array|undefined} value + */ + writePackedInt32String(field, value) { + if (value == null || !value.length) return; + const bookmark = this.beginDelimited_(field); + for (let i = 0; i < value.length; i++) { + const intValue = parseInt(value[i], 10); + assertSignedInteger(field, intValue); + this.encoder_.writeSignedVarint32(intValue); + } + this.endDelimited_(bookmark); } - this.endDelimited_(bookmark); -}; + /** + * Writes an array of numbers or decimal strings to the buffer as a packed + * 64-bit int field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of ints + * to write. + */ + writePackedInt64(field, value) { + if (value == null || !value.length) return; + const bookmark = this.beginDelimited_(field); + for (let i = 0; i < value.length; i++) { + const v = value[i]; + switch (typeof v) { + case 'number': + this.encoder_.writeSignedVarint64(v); + break; + + case 'bigint': { + const num = Int64.fromBigInt(/** @type {bigint} */(v)); + this.encoder_.writeSplitVarint64(num.lo, num.hi); + break; + } + + default: { + const num = Int64.fromString(/** @type {string} */(v)); + this.encoder_.writeSplitVarint64(num.lo, num.hi); + break; + } + } + } + this.endDelimited_(bookmark); + } -/** - * Writes an array of numbers to the buffer as a packed signed 64-bit int field. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export - */ -jspb.BinaryWriter.prototype.writePackedSint64 = function(field, value) { - if (value == null || !value.length) return; - var bookmark = this.beginDelimited_(field); - for (var i = 0; i < value.length; i++) { - this.encoder_.writeZigzagVarint64(value[i]); + /** + * Writes an array of 64-bit values to the buffer as a fixed64. + * @param {number} field The field number. + * @param {?Array|undefined} value The value. + * @param {function(T): number} lo Function to get low bits. + * @param {function(T): number} hi Function to get high bits. + * @template T + */ + writePackedSplitFixed64(field, value, lo, hi) { + if (value == null) return; + const bookmark = this.beginDelimited_(field); + for (let i = 0; i < value.length; i++) { + this.encoder_.writeSplitFixed64(lo(value[i]), hi(value[i])); + } + this.endDelimited_(bookmark); } - this.endDelimited_(bookmark); -}; + /** + * Writes an array of 64-bit values to the buffer as a varint. + * @param {number} field The field number. + * @param {?Array|undefined} value The value. + * @param {function(T): number} lo Function to get low bits. + * @param {function(T): number} hi Function to get high bits. + * @template T + */ + writePackedSplitVarint64(field, value, lo, hi) { + if (value == null) return; + const bookmark = this.beginDelimited_(field); + for (let i = 0; i < value.length; i++) { + this.encoder_.writeSplitVarint64(lo(value[i]), hi(value[i])); + } + this.endDelimited_(bookmark); + } -/** - * Writes an array of decimal strings to the buffer as a packed signed 64-bit - * int field. - * @param {number} field The field number. - * @param {?Array} value The array of decimal strings to write. - * @export - */ -jspb.BinaryWriter.prototype.writePackedSint64String = function(field, value) { - if (value == null || !value.length) return; - var bookmark = this.beginDelimited_(field); - for (var i = 0; i < value.length; i++) { - this.encoder_.writeZigzagVarintHash64( - jspb.utils.decimalStringToHash64(value[i])); + /** + * Writes an array of 64-bit values to the buffer as a zigzag varint. + * @param {number} field The field number. + * @param {?Array|undefined} value The value. + * @param {function(T): number} lo Function to get low bits. + * @param {function(T): number} hi Function to get high bits. + * @template T + */ + writePackedSplitZigzagVarint64(field, value, lo, hi) { + if (value == null) return; + const bookmark = this.beginDelimited_(field); + const encoder = this.encoder_; + for (let i = 0; i < value.length; i++) { + encoder.writeSplitZigzagVarint64(lo(value[i]), hi(value[i])); + } + this.endDelimited_(bookmark); } - this.endDelimited_(bookmark); -}; + /** + * Writes an array of numbers represented as strings to the buffer as a packed + * 64-bit int field. + * @param {number} field + * @param {?Array|undefined} value + * @deprecated Use writePackedInt64(). + */ + writePackedInt64String(field, value) { + this.writePackedInt64(field, value); + } -/** - * Writes an array of hash 64 strings to the buffer as a packed signed 64-bit - * int field. - * @param {number} field The field number. - * @param {?Array} value The array of decimal strings to write. - * @export - */ -jspb.BinaryWriter.prototype.writePackedSintHash64 = function(field, value) { - if (value == null || !value.length) return; - var bookmark = this.beginDelimited_(field); - for (var i = 0; i < value.length; i++) { - this.encoder_.writeZigzagVarintHash64(value[i]); + /** + * Writes an array numbers to the buffer as a packed unsigned 32-bit int + * field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of ints to write. + */ + writePackedUint32(field, value) { + if (value == null || !value.length) return; + const bookmark = this.beginDelimited_(field); + for (let i = 0; i < value.length; i++) { + this.encoder_.writeUnsignedVarint32(value[i]); + } + this.endDelimited_(bookmark); } - this.endDelimited_(bookmark); -}; + /** + * Writes an array numbers or decimal strings to the buffer as a packed + * unsigned 64-bit int field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of ints + * to write. + */ + writePackedUint64(field, value) { + if (value == null || !value.length) return; + const bookmark = this.beginDelimited_(field); + for (let i = 0; i < value.length; i++) { + const v = value[i]; + switch (typeof v) { + case 'number': + this.encoder_.writeUnsignedVarint64(v); + break; + + case 'bigint': + const n = Number(v); + if (Number.isSafeInteger(n)) { + this.encoder_.writeUnsignedVarint64(n); + } else { + const num = UInt64.fromBigInt(/** @type {bigint} */(v)); + this.encoder_.writeSplitVarint64(num.lo, num.hi); + } + break; + + default: + const num = UInt64.fromString(/** @type {string} */(v)); + this.encoder_.writeSplitVarint64(num.lo, num.hi); + break; + } + } + this.endDelimited_(bookmark); + } -/** - * Writes an array of numbers to the buffer as a packed fixed32 field. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export - */ -jspb.BinaryWriter.prototype.writePackedFixed32 = function(field, value) { - if (value == null || !value.length) return; - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); - this.encoder_.writeUnsignedVarint32(value.length * 4); - for (var i = 0; i < value.length; i++) { - this.encoder_.writeUint32(value[i]); + /** + * Writes an array of numbers represented as strings to the buffer as a packed + * unsigned 64-bit int field. + * @param {number} field + * @param {?Array|undefined} value + * @deprecated Use writePackedUint64() + */ + writePackedUint64String(field, value) { + this.writePackedUint64(field, value); } -}; + /** + * Writes an array numbers to the buffer as a packed signed 32-bit int field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of ints to write. + */ + writePackedSint32(field, value) { + if (value == null || !value.length) return; + const bookmark = this.beginDelimited_(field); + for (let i = 0; i < value.length; i++) { + this.encoder_.writeZigzagVarint32(value[i]); + } + this.endDelimited_(bookmark); + } -/** - * Writes an array of numbers to the buffer as a packed fixed64 field. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export - */ -jspb.BinaryWriter.prototype.writePackedFixed64 = function(field, value) { - if (value == null || !value.length) return; - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); - this.encoder_.writeUnsignedVarint32(value.length * 8); - for (var i = 0; i < value.length; i++) { - this.encoder_.writeUint64(value[i]); + /** + * Writes an array of numbers or decimal strings to the buffer as a packed + * signed 64-bit int field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of ints + * to write. + */ + writePackedSint64(field, value) { + if (value == null || !value.length) return; + const bookmark = this.beginDelimited_(field); + for (let i = 0; i < value.length; i++) { + const v = value[i]; + switch (typeof v) { + case 'number': + this.encoder_.writeZigzagVarint64(v); + break; + + case 'bigint': + this.encoder_.writeZigzagVarint64BigInt(/** @type {bigint} */(v)); + break; + + default: + this.encoder_.writeZigzagVarint64String(/** @type {string} */(v)); + break; + } + } + this.endDelimited_(bookmark); } -}; + /** + * Writes an array of decimal strings to the buffer as a packed signed 64-bit + * int field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of decimal strings to + * write. + * @deprecated Use writePackedSint64(). + */ + writePackedSint64String(field, value) { + this.writePackedSint64(field, value); + } -/** - * Writes an array of numbers represented as strings to the buffer as a packed - * fixed64 field. - * @param {number} field The field number. - * @param {?Array} value The array of strings to write. - * @export - */ -jspb.BinaryWriter.prototype.writePackedFixed64String = function(field, value) { - if (value == null || !value.length) return; - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); - this.encoder_.writeUnsignedVarint32(value.length * 8); - for (var i = 0; i < value.length; i++) { - var num = jspb.arith.UInt64.fromString(value[i]); - this.encoder_.writeSplitFixed64(num.lo, num.hi); + /** + * Writes an array of numbers to the buffer as a packed fixed32 field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of ints to write. + */ + writePackedFixed32(field, value) { + if (value == null || !value.length) return; + this.writeFieldHeader_(field, WireType.DELIMITED); + this.encoder_.writeUnsignedVarint32(value.length * 4); + for (let i = 0; i < value.length; i++) { + this.encoder_.writeUint32(value[i]); + } } -}; + /** + * Writes an array of numbers or decimal strings to the buffer as a packed + * fixed64 field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of ints + * to write. + */ + writePackedFixed64(field, value) { + if (value == null || !value.length) return; + this.writeFieldHeader_(field, WireType.DELIMITED); + this.encoder_.writeUnsignedVarint32(value.length * 8); + for (let i = 0; i < value.length; i++) { + const v = value[i]; + switch (typeof v) { + case 'number': + this.encoder_.writeUint64(/** @type {number} */(v)); + break; + + case 'bigint': + const fromBigint = UInt64.fromBigInt(/** @type {bigint} */(v)); + this.encoder_.writeSplitFixed64(fromBigint.lo, fromBigint.hi); + break; + + + default: + const fromString = UInt64.fromString(/** @type {string} */(v)); + this.encoder_.writeSplitFixed64(fromString.lo, fromString.hi); + break; + } + } + } -/** - * Writes an array of numbers to the buffer as a packed sfixed32 field. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export - */ -jspb.BinaryWriter.prototype.writePackedSfixed32 = function(field, value) { - if (value == null || !value.length) return; - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); - this.encoder_.writeUnsignedVarint32(value.length * 4); - for (var i = 0; i < value.length; i++) { - this.encoder_.writeInt32(value[i]); + /** + * Writes an array of numbers represented as strings to the buffer as a packed + * fixed64 field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of strings to write. + * @deprecated Use writePackedFixed64(). + */ + writePackedFixed64String(field, value) { + this.writePackedFixed64(field, value); } -}; + /** + * Writes an array of numbers to the buffer as a packed sfixed32 field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of ints to write. + */ + writePackedSfixed32(field, value) { + if (value == null || !value.length) return; + this.writeFieldHeader_(field, WireType.DELIMITED); + this.encoder_.writeUnsignedVarint32(value.length * 4); + for (let i = 0; i < value.length; i++) { + this.encoder_.writeInt32(value[i]); + } + } -/** - * Writes an array of numbers to the buffer as a packed sfixed64 field. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export - */ -jspb.BinaryWriter.prototype.writePackedSfixed64 = function(field, value) { - if (value == null || !value.length) return; - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); - this.encoder_.writeUnsignedVarint32(value.length * 8); - for (var i = 0; i < value.length; i++) { - this.encoder_.writeInt64(value[i]); + /** + * Writes an array of numbers or decimal strings to the buffer as a packed + * sfixed64 field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of ints + * to write. + */ + writePackedSfixed64(field, value) { + if (value == null || !value.length) return; + this.writeFieldHeader_(field, WireType.DELIMITED); + this.encoder_.writeUnsignedVarint32(value.length * 8); + for (let i = 0; i < value.length; i++) { + const v = value[i]; + switch (typeof v) { + case 'number': + this.encoder_.writeInt64(v); + break; + + case 'bigint': { + const num = Int64.fromBigInt(/** @type {bigint} */(v)); + this.encoder_.writeSplitFixed64(num.lo, num.hi); + break; + } + + default: { + const num = Int64.fromString(/** @type {string} */(v)); + this.encoder_.writeSplitFixed64(num.lo, num.hi); + break; + } + } + } } -}; + /** + * Writes an array of numbers or decimal strings to the buffer as a packed + * sfixed64 field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of ints to write. + * @deprecated Use writePackedSfixed64() + */ + writePackedSfixed64String(field, value) { + this.writePackedSfixed64(field, value); + } -/** - * Writes an array of numbers to the buffer as a packed sfixed64 field. - * @param {number} field The field number. - * @param {?Array} value The array of decimal strings to write. - * @export - */ -jspb.BinaryWriter.prototype.writePackedSfixed64String = function(field, value) { - if (value == null || !value.length) return; - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); - this.encoder_.writeUnsignedVarint32(value.length * 8); - for (var i = 0; i < value.length; i++) { - this.encoder_.writeInt64String(value[i]); + /** + * Writes an array of numbers to the buffer as a packed float field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of floats to + * write, accepts 'Infinity'/'-Infinity'/'NaN' for JSPB wire format + * compatibility. + */ + writePackedFloat(field, value) { + if (value == null || !value.length) return; + this.writeFieldHeader_(field, WireType.DELIMITED); + this.encoder_.writeUnsignedVarint32(value.length * 4); + for (let i = 0; i < value.length; i++) { + this.encoder_.writeFloat(value[i]); + } } -}; + /** + * Writes an array of numbers to the buffer as a packed double field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of doulbe to + * write, accepts 'Infinity'/'-Infinity'/'NaN' for JSPB wire format + * compatibility. + */ + writePackedDouble(field, value) { + if (value == null || !value.length) return; + this.writeFieldHeader_(field, WireType.DELIMITED); + this.encoder_.writeUnsignedVarint32(value.length * 8); + for (let i = 0; i < value.length; i++) { + this.encoder_.writeDouble(value[i]); + } + } -/** - * Writes an array of numbers to the buffer as a packed float field. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export - */ -jspb.BinaryWriter.prototype.writePackedFloat = function(field, value) { - if (value == null || !value.length) return; - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); - this.encoder_.writeUnsignedVarint32(value.length * 4); - for (var i = 0; i < value.length; i++) { - this.encoder_.writeFloat(value[i]); + /** + * Writes an array of booleans to the buffer as a packed bool field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of booleans to + * write. + */ + writePackedBool(field, value) { + if (value == null || !value.length) return; + this.writeFieldHeader_(field, WireType.DELIMITED); + this.encoder_.writeUnsignedVarint32(value.length); + for (let i = 0; i < value.length; i++) { + this.encoder_.writeBool(value[i]); + } } -}; + /** + * Writes an array of enums to the buffer as a packed enum field. + * @param {number} field The field number. + * @param {?Array|undefined} value The array of ints to write. + */ + writePackedEnum(field, value) { + if (value == null || !value.length) return; + const bookmark = this.beginDelimited_(field); + for (let i = 0; i < value.length; i++) { + this.encoder_.writeEnum(value[i]); + } + this.endDelimited_(bookmark); + } +} /** - * Writes an array of numbers to the buffer as a packed double field. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export + * Asserts that the value is signed 32-bit integer. + * @param {number} field + * @param {?} value */ -jspb.BinaryWriter.prototype.writePackedDouble = function(field, value) { - if (value == null || !value.length) return; - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); - this.encoder_.writeUnsignedVarint32(value.length * 8); - for (var i = 0; i < value.length; i++) { - this.encoder_.writeDouble(value[i]); - } -}; - +function assertSignedInteger(field, value) { + assertThat(field, value, value === Math.floor(value)); + assertThat(field, value, value >= -TWO_TO_31 && value < TWO_TO_31); +} /** - * Writes an array of booleans to the buffer as a packed bool field. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export - */ -jspb.BinaryWriter.prototype.writePackedBool = function(field, value) { - if (value == null || !value.length) return; - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); - this.encoder_.writeUnsignedVarint32(value.length); - for (var i = 0; i < value.length; i++) { - this.encoder_.writeBool(value[i]); + * Asserts that the value is an unsigned 64-bit integer. + * NOTE: does not yet validate the range of decimal strings, such a change + * would need to be tested before becoming more strict. + * @param {number} field + * @param {*} value + */ +function assertSignedInt64(field, value) { + const typeofValue = typeof value; + switch (typeofValue) { + case 'string': { + const valueStr = /** @type {string} */ (value); + assertThat(field, valueStr, Int64.fromString(valueStr)); + break; + } + + case 'number': { + const valueNum = /** @type {number} */ (value); + assertThat( + field, valueNum, valueNum >= -TWO_TO_63 && valueNum < TWO_TO_63); + break; + } + + default: { + const valueBig = /** @type {bigint} */ (value); + assertThat( + field, valueBig, + valueBig >= BigInt(-TWO_TO_63) && valueBig < BigInt(TWO_TO_63)); + break; + } } -}; - +} /** - * Writes an array of enums to the buffer as a packed enum field. - * @param {number} field The field number. - * @param {?Array} value The array of ints to write. - * @export - */ -jspb.BinaryWriter.prototype.writePackedEnum = function(field, value) { - if (value == null || !value.length) return; - var bookmark = this.beginDelimited_(field); - for (var i = 0; i < value.length; i++) { - this.encoder_.writeEnum(value[i]); + * Asserts that the value is signed 64-bit integer. + * NOTE: does not yet validate the range of decimal strings, such a change + * would need to be tested before becoming more strict. + * @param {number} field + * @param {*} value + */ +function assertUnsignedInt64(field, value) { + const typeofValue = typeof value; + switch (typeofValue) { + case 'string': { + const valueStr = /** @type {string} */ (value); + assertThat(field, valueStr, UInt64.fromString(valueStr)); + break; + } + + case 'number': { + const valueNum = /** @type {number} */ (value); + assertThat(field, valueNum, valueNum >= 0 && valueNum < TWO_TO_64); + break; + } + + default: { + const valueBig = /** @type {bigint} */ (value); + assertThat( + field, valueBig, + valueBig >= BigInt(0) && valueBig < BigInt(TWO_TO_64)); + break; + } } - this.endDelimited_(bookmark); -}; - +} /** - * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to - * the buffer. - * @param {number} field The field number. - * @param {?Array} value The array of hashes to write. - * @export - */ -jspb.BinaryWriter.prototype.writePackedFixedHash64 = function(field, value) { - if (value == null || !value.length) return; - this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); - this.encoder_.writeUnsignedVarint32(value.length * 8); - for (var i = 0; i < value.length; i++) { - this.encoder_.writeFixedHash64(value[i]); + * Asserts the condition. + * @param {number} field + * @param {?} value + * @param {?} condition + */ +function assertThat(field, value, condition) { + // Manual assertion here instead of asserts.assert(...) call for perf + // reasons, to avoid unnecessary string concatenations. + if (!condition) { + fail(`for [${value}] at [${field}]`); } -}; +} -/** - * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to - * the buffer. - * @param {number} field The field number. - * @param {?Array} value The array of hashes to write. - * @export - */ -jspb.BinaryWriter.prototype.writePackedVarintHash64 = function(field, value) { - if (value == null || !value.length) return; - var bookmark = this.beginDelimited_(field); - for (var i = 0; i < value.length; i++) { - this.encoder_.writeVarintHash64(value[i]); - } - this.endDelimited_(bookmark); -}; +exports = { BinaryWriter }; diff --git a/binary/writer_alias.js b/binary/writer_alias.js new file mode 100755 index 0000000..4f41188 --- /dev/null +++ b/binary/writer_alias.js @@ -0,0 +1,9 @@ +/** + * @fileoverview Legacy alias for the old namespace used by writer.js + */ +goog.module('jspb.BinaryWriter'); +goog.module.declareLegacyNamespace(); + +const {BinaryWriter} = goog.require('jspb.binary.writer'); + +exports = BinaryWriter; diff --git a/binary/writer_test.js b/binary/writer_test.js old mode 100644 new mode 100755 index a540934..2b6fc0c --- a/binary/writer_test.js +++ b/binary/writer_test.js @@ -38,16 +38,28 @@ * @author aappleby@google.com (Austin Appleby) */ -goog.require('goog.crypt'); -goog.require('goog.crypt.base64'); - goog.require('jspb.BinaryConstants'); goog.require('jspb.BinaryReader'); +goog.require('jspb.binary.test_utils'); goog.require('jspb.BinaryWriter'); +goog.require('jspb.bytestring'); goog.require('jspb.utils'); +goog.require('goog.crypt'); +goog.require('goog.crypt.base64'); -goog.requireType('jspb.BinaryMessage'); - +const BinaryMessage = goog.module.get('jspb.BinaryConstants').BinaryMessage; +const BinaryReader = goog.module.get('jspb.BinaryReader'); +const BinaryWriter = goog.module.get('jspb.BinaryWriter'); +const ByteString = goog.module.get('jspb.bytestring').ByteString; +const FLOAT32_MAX = goog.module.get('jspb.BinaryConstants').FLOAT32_MAX; +const FLOAT32_MIN = goog.module.get('jspb.BinaryConstants').FLOAT32_MIN; +const base64 = goog.module.get('goog.crypt.base64'); +const byteArrayToHex = goog.module.get('goog.crypt').byteArrayToHex; +const byteSourceToUint8Array = goog.module.get('jspb.utils').byteSourceToUint8Array; +const getSplit64High = goog.module.get('jspb.utils').getSplit64High; +const getSplit64Low = goog.module.get('jspb.utils').getSplit64Low; +const splitDecimalString = goog.module.get('jspb.utils').splitDecimalString; +const toHexFields = goog.module.get('jspb.binary.test_utils').toHexFields; describe('binaryWriterTest', () => { /** @@ -55,91 +67,91 @@ describe('binaryWriterTest', () => { */ it('testWriteErrors', () => { // Submessages with invalid field indices should assert. - let writer = new jspb.BinaryWriter(); - const dummyMessage = /** @type {!jspb.BinaryMessage} */ ({}); + let writer = new BinaryWriter(); + const dummyMessage = /** @type {!BinaryMessage} */ ({}); expect(() => { - writer.writeMessage(-1, dummyMessage, () => {}); - }).toThrow(); + writer.writeMessage(-1, dummyMessage, goog.nullFunction); + }).toThrowError(); // Writing invalid field indices should assert. - writer = new jspb.BinaryWriter(); + writer = new BinaryWriter(); expect(() => { writer.writeUint64(-1, 1); - }).toThrow(); + }).toThrowError(); // Writing out-of-range field values should assert. - writer = new jspb.BinaryWriter(); + writer = new BinaryWriter(); expect(() => { writer.writeInt32(1, -Infinity); - }).toThrow(); + }).toThrowError(); expect(() => { writer.writeInt32(1, Infinity); - }).toThrow(); + }).toThrowError(); expect(() => { writer.writeInt64(1, -Infinity); - }).toThrow(); + }).toThrowError(); expect(() => { writer.writeInt64(1, Infinity); - }).toThrow(); + }).toThrowError(); expect(() => { writer.writeUint32(1, -1); - }).toThrow(); + }).toThrowError(); expect(() => { writer.writeUint32(1, Infinity); - }).toThrow(); + }).toThrowError(); expect(() => { writer.writeUint64(1, -1); - }).toThrow(); + }).toThrowError(); expect(() => { writer.writeUint64(1, Infinity); - }).toThrow(); + }).toThrowError(); expect(() => { writer.writeSint32(1, -Infinity); - }).toThrow(); + }).toThrowError(); expect(() => { writer.writeSint32(1, Infinity); - }).toThrow(); + }).toThrowError(); expect(() => { writer.writeSint64(1, -Infinity); - }).toThrow(); + }).toThrowError(); expect(() => { writer.writeSint64(1, Infinity); - }).toThrow(); + }).toThrowError(); expect(() => { writer.writeFixed32(1, -1); - }).toThrow(); + }).toThrowError(); expect(() => { writer.writeFixed32(1, Infinity); - }).toThrow(); + }).toThrowError(); expect(() => { writer.writeFixed64(1, -1); - }).toThrow(); + }).toThrowError(); expect(() => { writer.writeFixed64(1, Infinity); - }).toThrow(); + }).toThrowError(); expect(() => { writer.writeSfixed32(1, -Infinity); - }).toThrow(); + }).toThrowError(); expect(() => { writer.writeSfixed32(1, Infinity); - }).toThrow(); + }).toThrowError(); expect(() => { writer.writeSfixed64(1, -Infinity); - }).toThrow(); + }).toThrowError(); expect(() => { writer.writeSfixed64(1, Infinity); - }).toThrow(); + }).toThrowError(); }); @@ -149,14 +161,14 @@ describe('binaryWriterTest', () => { it('testGetResultBuffer', () => { const expected = '0864120b48656c6c6f20776f726c641a0301020320c801'; - const writer = new jspb.BinaryWriter(); + const writer = new BinaryWriter(); writer.writeUint32(1, 100); writer.writeString(2, 'Hello world'); writer.writeBytes(3, new Uint8Array([1, 2, 3])); writer.writeUint32(4, 200); const buffer = writer.getResultBuffer(); - expect(goog.crypt.byteArrayToHex(buffer)).toEqual(expected); + expect(byteArrayToHex(buffer)).toEqual(expected); }); @@ -164,17 +176,17 @@ describe('binaryWriterTest', () => { * Tests websafe encodings for base64 strings. */ it('testWebSafeOption', () => { - const writer = new jspb.BinaryWriter(); + const writer = new BinaryWriter(); writer.writeBytes(1, new Uint8Array([127])); - expect('CgF/').toEqual(writer.getResultBase64String()); - expect('CgF/').toEqual( - writer.getResultBase64String(/* goog.crypt.base64.Alphabet.DEFAULT = */ 0)); - expect('CgF_').toEqual(writer.getResultBase64String( - /* goog.crypt.base64.Alphabet.WEBSAFE_NO_PADDING = */ 4)); + expect(writer.getResultBase64String()).toEqual('CgF/'); + expect(writer.getResultBase64String(base64.Alphabet.DEFAULT)) + .toEqual('CgF/'); + expect(writer.getResultBase64String(base64.Alphabet.WEBSAFE_NO_PADDING)) + .toEqual('CgF_'); }); it('writes split 64 fields', () => { - const writer = new jspb.BinaryWriter(); + const writer = new BinaryWriter(); writer.writeSplitVarint64(1, 0x1, 0x2); writer.writeSplitVarint64(1, 0xFFFFFFFF, 0xFFFFFFFF); writer.writeSplitFixed64(2, 0x1, 0x2); @@ -190,10 +202,7 @@ describe('binaryWriterTest', () => { writer.writePackedSplitVarint64(5, [0, 1, 2], lo, hi); writer.writePackedSplitFixed64(6, [0, 1, 2], lo, hi); - function bitsAsArray(lowBits, highBits) { - return [lowBits >>> 0, highBits >>> 0]; - } - const reader = jspb.BinaryReader.alloc(writer.getResultBuffer()); + const reader = BinaryReader.alloc(writer.getResultBuffer()); reader.nextField(); expect(reader.getFieldNumber()).toEqual(1); expect(reader.readSplitVarint64(bitsAsArray)).toEqual([0x1, 0x2]); @@ -201,7 +210,8 @@ describe('binaryWriterTest', () => { reader.nextField(); expect(reader.getFieldNumber()).toEqual(1); expect(reader.readSplitVarint64(bitsAsArray)).toEqual([ - 0xFFFFFFFF, 0xFFFFFFFF + 0xFFFFFFFF, + 0xFFFFFFFF, ]); reader.nextField(); @@ -211,7 +221,8 @@ describe('binaryWriterTest', () => { reader.nextField(); expect(reader.getFieldNumber()).toEqual(2); expect(reader.readSplitFixed64(bitsAsArray)).toEqual([ - 0xFFFFFFF0, 0xFFFFFFFF + 0xFFFFFFF0, + 0xFFFFFFFF, ]); for (let i = 0; i < 3; i++) { @@ -228,7 +239,8 @@ describe('binaryWriterTest', () => { reader.nextField(); expect(reader.getFieldNumber()).toEqual(5); - expect(reader.readPackedInt64String()).toEqual([ + const a = []; + expect((reader.readPackableInt64StringInto(a), a)).toEqual([ String(2 * 2 ** 32 + 1), String(3 * 2 ** 32 + 2), String(4 * 2 ** 32 + 3), @@ -236,15 +248,88 @@ describe('binaryWriterTest', () => { reader.nextField(); expect(reader.getFieldNumber()).toEqual(6); - expect(reader.readPackedFixed64String()).toEqual([ + expect((a.length = 0, reader.readPackableFixed64StringInto(a), a)).toEqual([ String(2 * 2 ** 32 + 1), String(3 * 2 ** 32 + 2), String(4 * 2 ** 32 + 3), ]); }); + it('writes packed 64bit string fields', () => { + const MAX_UINT64 = '18446744073709551615'; // 0xFFFFFFFFFFFFFFFF + const MAX_INT64 = '9223372036854775807'; // 0x7FFFFFFFFFFFFFFF + const MIN_INT64 = '-9223372036854775808'; // 0x8000000000000000 + const signedValues = ['0', '-1', MAX_INT64, MIN_INT64]; + const unsignedValues = ['0', '1', MAX_UINT64]; + const writer = new BinaryWriter(); + writer.writePackedSfixed64String(1, signedValues); + writer.writePackedInt64String(2, signedValues); + writer.writePackedSint64String(3, signedValues); + + writer.writePackedFixed64String(4, unsignedValues); + writer.writePackedUint64String(5, unsignedValues); + + const resultBuffer = writer.getResultBuffer(); + expect(toHexFields(resultBuffer)).toEqual({ + 1: '0a20' + + '0000000000000000' + // 0 + 'ffffffffffffffff' + // -1 + 'ffffffffffffff7f' + // MAX_INT64 + '0000000000000080', // MIN_INT64 + 2: '121e' + + '00' + // 0 + 'ffffffffffffffffff01' + // -1 + 'ffffffffffffffff7f' + // MAX_INT64 + '80808080808080808001', // MIN_INT64 + 3: '1a16' + + '00' + // 0 + '01' + // -1 + 'feffffffffffffffff01' + // MAX_INT64 + 'ffffffffffffffffff01', // MIN_INT64 + 4: '2218' + + '0000000000000000' + // 0 + '0100000000000000' + // 1 + 'ffffffffffffffff', // MAX_UINT64 + 5: '2a0c' + + '00' + // 0 + '01' + // 1 + 'ffffffffffffffffff01', // MAX_UINT64 + }); + const reader = BinaryReader.alloc(resultBuffer); + + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(1); + const /** !Array */ results1 = []; + reader.readPackableSfixed64StringInto(results1); + expect(results1).toEqual(signedValues); + + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(2); + const /** !Array */ results2 = []; + reader.readPackableInt64StringInto(results2); + expect(results2).toEqual(signedValues); + + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(3); + const /** !Array */ results3 = []; + reader.readPackableSint64StringInto(results3); + expect(results3).toEqual(signedValues); + + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(4); + const /** !Array */ results4 = []; + reader.readPackableFixed64StringInto(results4); + expect(results4).toEqual(unsignedValues); + + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(5); + const /** !Array */ results5 = []; + reader.readPackableUint64StringInto(results5); + expect(results5).toEqual(unsignedValues); + }); + it('writes zigzag 64 fields', () => { - // Test cases directly from the protobuf dev guide. + // Test cases direcly from the protobuf dev guide. // https://engdoc.corp.google.com/eng/howto/protocolbuffers/developerguide/encoding.shtml?cl=head#types const testCases = [ {original: '0', zigzag: '0'}, @@ -258,58 +343,35 @@ describe('binaryWriterTest', () => { {original: '-9223372036854775808', zigzag: '18446744073709551615'}, ]; function decimalToLowBits(v) { - jspb.utils.splitDecimalString(v); - return jspb.utils.getSplit64Low() >>> 0; + splitDecimalString(v); + return getSplit64Low() >>> 0; } function decimalToHighBits(v) { - jspb.utils.splitDecimalString(v); - return jspb.utils.getSplit64High() >>> 0; + splitDecimalString(v); + return getSplit64High() >>> 0; } - const writer = new jspb.BinaryWriter(); - testCases.forEach(function(c) { + const writer = new BinaryWriter(); + testCases.forEach(c => { writer.writeSint64String(1, c.original); - writer.writeSintHash64(1, jspb.utils.decimalStringToHash64(c.original)); - jspb.utils.splitDecimalString(c.original); - writer.writeSplitZigzagVarint64( - 1, jspb.utils.getSplit64Low(), jspb.utils.getSplit64High()); + splitDecimalString(c.original); + writer.writeSplitZigzagVarint64(1, getSplit64Low(), getSplit64High()); }); - writer.writeRepeatedSint64String(2, testCases.map(function(c) { - return c.original; - })); - - writer.writeRepeatedSintHash64(3, testCases.map(function(c) { - return jspb.utils.decimalStringToHash64(c.original); - })); + writer.writeRepeatedSint64String(2, testCases.map(c => c.original)); writer.writeRepeatedSplitZigzagVarint64( - 4, testCases.map(function(c) { - return c.original; - }), - decimalToLowBits, decimalToHighBits); + 4, testCases.map(c => c.original), decimalToLowBits, decimalToHighBits); - writer.writePackedSint64String(5, testCases.map(function(c) { - return c.original; - })); - - writer.writePackedSintHash64(6, testCases.map(function(c) { - return jspb.utils.decimalStringToHash64(c.original); - })); + writer.writePackedSint64String(5, testCases.map(c => c.original)); writer.writePackedSplitZigzagVarint64( - 7, testCases.map(function(c) { - return c.original; - }), - decimalToLowBits, decimalToHighBits); + 7, testCases.map(c => c.original), decimalToLowBits, decimalToHighBits); // Verify by reading the stream as normal int64 fields and checking with // the canonical zigzag encoding of each value. - const reader = jspb.BinaryReader.alloc(writer.getResultBuffer()); - testCases.forEach(function(c) { - reader.nextField(); - expect(reader.getFieldNumber()).toEqual(1); - expect(reader.readUint64String()).toEqual(c.zigzag); + const reader = BinaryReader.alloc(writer.getResultBuffer()); + testCases.forEach(c => { reader.nextField(); expect(reader.getFieldNumber()).toEqual(1); expect(reader.readUint64String()).toEqual(c.zigzag); @@ -318,19 +380,13 @@ describe('binaryWriterTest', () => { expect(reader.readUint64String()).toEqual(c.zigzag); }); - testCases.forEach(function(c) { + testCases.forEach(c => { reader.nextField(); expect(reader.getFieldNumber()).toEqual(2); expect(reader.readUint64String()).toEqual(c.zigzag); }); - testCases.forEach(function(c) { - reader.nextField(); - expect(reader.getFieldNumber()).toEqual(3); - expect(reader.readUint64String()).toEqual(c.zigzag); - }); - - testCases.forEach(function(c) { + testCases.forEach(c => { reader.nextField(); expect(reader.getFieldNumber()).toEqual(4); expect(reader.readUint64String()).toEqual(c.zigzag); @@ -338,36 +394,36 @@ describe('binaryWriterTest', () => { reader.nextField(); expect(reader.getFieldNumber()).toEqual(5); - expect(reader.readPackedUint64String()).toEqual(testCases.map(function(c) { - return c.zigzag; - })); - - reader.nextField(); - expect(reader.getFieldNumber()).toEqual(6); - expect(reader.readPackedUint64String()).toEqual(testCases.map(function(c) { - return c.zigzag; - })); + const a = []; + expect((reader.readPackableUint64StringInto(a), a)) + .toEqual(testCases.map(c => c.zigzag)); reader.nextField(); expect(reader.getFieldNumber()).toEqual(7); - expect(reader.readPackedUint64String()).toEqual(testCases.map(function(c) { - return c.zigzag; - })); + expect((a.length = 0, reader.readPackableUint64StringInto(a), a)) + .toEqual(testCases.map(c => c.zigzag)); }); it('writes float32 fields', () => { const testCases = [ - 0, 1, -1, jspb.BinaryConstants.FLOAT32_MIN, - -jspb.BinaryConstants.FLOAT32_MIN, jspb.BinaryConstants.FLOAT32_MAX, - -jspb.BinaryConstants.FLOAT32_MAX, 3.1415927410125732, Infinity, - -Infinity, NaN + 0, + 1, + -1, + FLOAT32_MIN, + -FLOAT32_MIN, + FLOAT32_MAX, + -FLOAT32_MAX, + 3.1415927410125732, + Infinity, + -Infinity, + NaN, ]; - const writer = new jspb.BinaryWriter(); - testCases.forEach(function(f) { + const writer = new BinaryWriter(); + testCases.forEach(f => { writer.writeFloat(1, f); }); - const reader = jspb.BinaryReader.alloc(writer.getResultBuffer()); - testCases.forEach(function(f) { + const reader = BinaryReader.alloc(writer.getResultBuffer()); + testCases.forEach(f => { reader.nextField(); expect(reader.getFieldNumber()).toEqual(1); if (isNaN(f)) { @@ -380,17 +436,28 @@ describe('binaryWriterTest', () => { it('writes double fields', () => { const testCases = [ - 0, 1, -1, Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER, - Number.MAX_VALUE, Number.MIN_VALUE, jspb.BinaryConstants.FLOAT32_MIN, - -jspb.BinaryConstants.FLOAT32_MIN, jspb.BinaryConstants.FLOAT32_MAX, - -jspb.BinaryConstants.FLOAT32_MAX, Math.PI, Infinity, -Infinity, NaN + 0, + 1, + -1, + Number.MAX_SAFE_INTEGER, + Number.MIN_SAFE_INTEGER, + Number.MAX_VALUE, + Number.MIN_VALUE, + FLOAT32_MIN, + -FLOAT32_MIN, + FLOAT32_MAX, + -FLOAT32_MAX, + Math.PI, + Infinity, + -Infinity, + NaN, ]; - const writer = new jspb.BinaryWriter(); - testCases.forEach(function(f) { + const writer = new BinaryWriter(); + testCases.forEach(f => { writer.writeDouble(1, f); }); - const reader = jspb.BinaryReader.alloc(writer.getResultBuffer()); - testCases.forEach(function(f) { + const reader = BinaryReader.alloc(writer.getResultBuffer()); + testCases.forEach(f => { reader.nextField(); expect(reader.getFieldNumber()).toEqual(1); if (isNaN(f)) { @@ -400,4 +467,34 @@ describe('binaryWriterTest', () => { } }); }); + + it('writes binary fields', () => { + const testCases = [ + new Uint8Array([1, 2, 3]), + // Test that we don't stackoverflow with large blocks. + new Uint8Array(new Array(1000000).fill(1)), + '1234', + ByteString.fromBase64('5678'), + ByteString.fromUint8Array(new Uint8Array([9, 10])), + ]; + const writer = new BinaryWriter(); + testCases.forEach((f) => { + writer.writeBytes(1, f); + }); + const reader = BinaryReader.alloc(writer.getResultBuffer()); + testCases.forEach(f => { + reader.nextField(); + expect(reader.getFieldNumber()).toEqual(1); + expect(reader.readBytes()).toEqual(byteSourceToUint8Array(f)); + }); + }); }); + +/** + * @param {number} lowBits + * @param {number} highBits + * @return {!Array} + */ +function bitsAsArray(lowBits, highBits) { + return [lowBits >>> 0, highBits >>> 0]; +} diff --git a/bytestring.js b/bytestring.js new file mode 100644 index 0000000..0efdecd --- /dev/null +++ b/bytestring.js @@ -0,0 +1,257 @@ +/** + * @fileoverview ByteString class for encapsulating bytes fields. + */ + +goog.module('jspb.bytestring'); +goog.module.declareLegacyNamespace(); + +const { I_AM_INTERNAL, dataAsU8, encodeByteArray, uint8ArrayEquals } = goog.require('jspb.internal_bytes'); +const {assert, assertExists, assertInstanceof, assertNumber, assertString} = goog.require('goog.asserts'); +const {decodeUtf8, encodeUtf8} = goog.require('jspb.binary.utf8'); + +/** + * Encapsulation of a bytes field. + * + * Use the factory methods below to construct a ByteString. + * + * @final + * @struct + */ +class ByteString { + + /** + * Constructs a ByteString instance from a base64 string, per RFC 4648 section + * 4. + * @return {!ByteString} + */ + static fromBase64(/** string */ value) { + assertString(value); + return value ? new ByteString(value, I_AM_INTERNAL) : ByteString.empty(); + } + + /** + * Constructs a ByteString from a Uint8Array or Array of numbers. + * + * Makes a copy of the parameter. + * + * When passed an array of numbers, values will be truncated to be integers + * and then their value mod 2^8 will be preserved. + * + * See https://tc39.es/ecma262/multipage/abstract-operations.html#sec-touint8 + * + * @return {!ByteString} + */ + static fromUint8Array(/** !Uint8Array|!Array */ value) { + assert(value instanceof Uint8Array || Array.isArray(value)); + return value.length ? new ByteString(new Uint8Array(value), I_AM_INTERNAL) : + ByteString.empty(); + } + + /** + * Encodes `text` into a sequence of UTF-8 bytes and returns the result as a + * `ByteString`. + * @return {!ByteString} + */ + static fromStringUtf8(/** string */ text) { + assertString(text); + return text.length ? + new ByteString( + encodeUtf8(text, /* rejectUnpairedSurrogates=*/ true), + I_AM_INTERNAL) : + ByteString.empty(); + } + + /** + * Constructs a ByteString from a Blob. + * + * It is async because Blob does not provide sync access to its data. + * + * BROWSER COMPATIBILITY WARNING: + * This method uses Blob.arrayBuffer() to access Blob's content and therefore + * is compatible with browsers supporting this API, which is any release 2021 + * and later. See http://go/mdn/API/Blob/arrayBuffer for the full + * compatibility list. + * @return {!Promise} + */ + static async fromBlob(/** !Blob */ blob) { + assertInstanceof(blob, Blob); + if (blob.size === 0) return ByteString.empty(); + const data = await blob.arrayBuffer(); + return new ByteString(new Uint8Array(data), I_AM_INTERNAL); + } + + /** + * Returns the empty ByteString. + * @return {!ByteString} + */ + static empty() { + return emptyByteString || + (emptyByteString = new ByteString(null, I_AM_INTERNAL)); + } + + /** + * Returns this ByteString as a base64 encoded string, per RFC 4648 section 4. + * @return {string} + */ + asBase64() { + const value = this.value_; + if (value == null) { + return ''; + } + if (typeof value === 'string') { + return value; + } + return this.value_ = encodeByteArray(value); + } + + /** + * Returns this ByteString as a Uint8Array. This makes a copy and returns a + * new Uint8Array. + * @return {!Uint8Array} + */ + asUint8Array() { + return new Uint8Array(this.internalBytesUnsafe(I_AM_INTERNAL) || 0); + } + + /** + * Returns true if the ByteString is empty. + * @return {boolean} + */ + isEmpty() { + return this.value_ == null; + } + + /** + * Returns the size of the byte string in bytes. + * + * If you are only interested in whether or not the ByteString is empty, call + * `isEmpty` which is always faster. + * + * @return {number} + */ + sizeBytes() { + const bytes = this.internalBytesUnsafe(I_AM_INTERNAL); + return bytes ? bytes.length : 0; + } + + /** + * Returns the numeric value of the _unsigned_ byte at the given index. + * @return {number} + */ + unsignedByteAt(/** number */ index) { + assertNumber(index); + assert(index >= 0, 'index %s should be non-negative', index); + const bytes = this.internalBytesUnsafe(I_AM_INTERNAL); + assert( + index < bytes.length, 'index %s must be less than %s', index, + bytes.length); + return bytes[index]; + } + + /** + * Returns the numeric value of the byte at the given index as a _signed_ byte + * value in the range [-128,127] + * @return {number} + */ + signedByteAt(/** number */ index) { + const unsignedByte = this.unsignedByteAt(index); + // Bit operators are 'signed 32 bit' operators by default. + // First left shift so the sign-bit if it exists is in the 32 bit signed + // location + // Then, right shift back into the lower 8 bits to recover the now signed + // value. + return (unsignedByte << 24) >> 24; + } + + /** + * Returns a string by decoding the bytes as UTF-8. + * @param {{parsingErrorsAreFatal:boolean}=} opts an options bag. The + * `parsingErrorsAreFatal` option controls if invalid utf8 bytes should be + * a runtime error (if `true`) or if they should be replaced with the + * replacement character `\ufffd` (if `false`), the default is to throw. + * @return {string} + */ + asStringUtf8({parsingErrorsAreFatal = true} = {}) { + const bytes = this.internalBytesUnsafe(I_AM_INTERNAL); + return bytes ? decodeUtf8(bytes, 0, bytes.length, parsingErrorsAreFatal) : + ''; + } + + /** + * Returns the field as a Blob. This is a copy of the internal data. + * + * @param {?BlobPropertyBag=} options An object which may specify Blob + * properties. + * @return {!Blob} + */ + asBlob(options) { + const bytes = this.internalBytesUnsafe(I_AM_INTERNAL); + return bytes ? new Blob([bytes], options) : new Blob([], options); + } + + /** + * Internal only for access to the bytes in a zero copy fashion. + * + * See `unsafe_bytestring.js` for how to access this API. + * @param {*} areYouInternal + * @return {?Uint8Array} + * @package + */ + internalBytesUnsafe(areYouInternal) { + checkAllowedCaller(areYouInternal); + const u8 = dataAsU8(this.value_); + return (u8 == null) ? u8 : (this.value_ = u8); + } + + /** + * Internal only for access to the internals state of the bytestring, in a + * zero copy fashion. + * + * See `unsafe_bytestring.js` for how to access this API. + * @param {*} areYouInternal + * @return {string|!Uint8Array} + * @package + */ + internalUnwrap(areYouInternal) { + checkAllowedCaller(areYouInternal); + return this.value_ || ''; + } + + /** + * INTERNAL USE ONLY: Clients should use the factory functions above. + * @param {!Uint8Array|string|null} value Base64 string or Uint8Array. If + * null, this is an empty array. + * @param {*} areYouInternal + * @package + */ + constructor(value, areYouInternal) { + checkAllowedCaller(areYouInternal); + + /** + * This value is either a Uint8Array or a string, or else `null` for an + * empty byte string. + * + * @private {!Uint8Array|string|null} + */ + this.value_ = value; + + if (value != null && value.length === 0) { + throw new Error('ByteString should be constructed with non-empty values'); + } + } +} + + +/** @type {!ByteString|undefined} */ +let emptyByteString; + +/** + * @param {*} areYouInternal + */ +function checkAllowedCaller(areYouInternal) { + if (areYouInternal !== I_AM_INTERNAL) { + throw new Error('illegal external caller'); + } +} + +exports = {ByteString}; diff --git a/commonjs/export.js b/commonjs/export.js index 986a481..61e5390 100644 --- a/commonjs/export.js +++ b/commonjs/export.js @@ -14,6 +14,7 @@ goog.require('jspb.BinaryReader'); goog.require('jspb.BinaryWriter'); goog.require('jspb.ExtensionFieldBinaryInfo'); goog.require('jspb.ExtensionFieldInfo'); +goog.require('jspb.internal.public_for_gencode'); goog.require('jspb.Message'); goog.require('jspb.Map'); @@ -27,6 +28,8 @@ if (typeof exports === 'object') { exports['BinaryWriter'] = jspb.BinaryWriter; exports['ExtensionFieldInfo'] = jspb.ExtensionFieldInfo; exports['ExtensionFieldBinaryInfo'] = jspb.ExtensionFieldBinaryInfo; + exports['internal'] = { public_for_gencode: jspb.internal.public_for_gencode }; + // These are used by generated code but should not be used directly by clients. exports['exportSymbol'] = goog.exportSymbol; diff --git a/commonjs/export_testdeps.js b/commonjs/export_testdeps.js index 7bb5690..8c2b4a8 100644 --- a/commonjs/export_testdeps.js +++ b/commonjs/export_testdeps.js @@ -12,13 +12,18 @@ goog.provide('jspb.ExportTestDeps'); goog.require('goog.crypt.base64'); goog.require('goog.testing.PropertyReplacer'); +goog.require('jspb.arith'); goog.require('jspb.debug'); goog.require('jspb.BinaryReader'); goog.require('jspb.BinaryWriter'); +goog.require('jspb.BinaryConstants'); goog.require('jspb.ExtensionFieldBinaryInfo'); goog.require('jspb.ExtensionFieldInfo'); goog.require('jspb.Message'); goog.require('jspb.Map'); +goog.require('jspb.utils'); +goog.require('jspb.binary.utf8'); +goog.require('jspb.binary.test_utils'); if (typeof exports === 'object') { exports['goog'] = { @@ -46,6 +51,50 @@ if (typeof exports === 'object') { }; exports['jspb'] = { + 'arith': { + 'Int64': jspb.arith.Int64, + 'UInt64': jspb.arith.UInt64, + }, + 'binary': { + 'decoder': { + 'BinaryDecoder': jspb.binary.decoder.BinaryDecoder, + }, + 'encoder': { + 'BinaryEncoder': jspb.binary.encoder.BinaryEncoder, + }, + 'utf8': { + 'encodeUtf8': jspb.binary.utf8.encodeUtf8, + }, + 'test_utils': { + 'toHexFields': jspb.binary.test_utils.toHexFields, + }, + }, + 'bytestring': { + 'ByteString': jspb.bytestring.ByteString, + }, + 'utils': { + 'makeTag': jspb.utils.makeTag, + 'countFixed32Fields': jspb.utils.countFixed32Fields, + 'countFixed64Fields': jspb.utils.countFixed64Fields, + 'splitDecimalString': jspb.utils.splitDecimalString, + 'byteSourceToUint8Array': jspb.utils.byteSourceToUint8Array, + 'getSplit64Low': jspb.utils.getSplit64Low, + 'getSplit64High': jspb.utils.getSplit64High, + 'countVarintFields': jspb.utils.countVarintFields, + 'countDelimitedFields': jspb.utils.countDelimitedFields, + 'countVarints': jspb.utils.countVarints, + 'toZigzag64': jspb.utils.toZigzag64, + 'fromZigzag64': jspb.utils.fromZigzag64, + 'splitFloat64': jspb.utils.splitFloat64, + 'joinFloat64': jspb.utils.joinFloat64, + 'joinFloat32': jspb.utils.joinFloat32, + 'splitFloat32': jspb.utils.splitFloat32, + 'joinUnsignedDecimalString': jspb.utils.joinUnsignedDecimalString, + 'sliceUint8Array': jspb.utils.sliceUint8Array, + 'joinSignedDecimalString': jspb.utils.joinSignedDecimalString, + }, + 'BinaryConstants': jspb.BinaryConstants, + 'debug': jspb.debug, 'BinaryReader': jspb.BinaryReader, 'BinaryWriter': jspb.BinaryWriter, diff --git a/commonjs/rewrite_tests_for_commonjs.js b/commonjs/rewrite_tests_for_commonjs.js index 4487c42..8b13c28 100644 --- a/commonjs/rewrite_tests_for_commonjs.js +++ b/commonjs/rewrite_tests_for_commonjs.js @@ -71,7 +71,13 @@ console.log("global.goog = testdeps.goog;"); console.log("global.jspb = googleProtobuf.jspb;"); console.log(""); -lineReader.on('line', function(line) { +lineReader.on('line', function (line) { + const isModuleGet = line.match(/(.*)goog\.module\.get\('([^']*)'\)([^;]*);/); + if (isModuleGet) { + const fullSym = isModuleGet[2]; + console.log(isModuleGet[1] + "testdeps." + fullSym + isModuleGet[3]); + return; + } var isRequire = line.match(/goog\.require\('([^']*)'\)/); var isLoadFromFile = line.match(/CommonJS-LoadFromFile: (\S*) (.*)/); var isSetTestOnly = line.match(/goog.setTestOnly()/); diff --git a/conformance/LICENSE.md b/conformance/LICENSE.md new file mode 100644 index 0000000..0890b3f --- /dev/null +++ b/conformance/LICENSE.md @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2022, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/conformance/failing_tests.txt b/conformance/failing_tests.txt new file mode 100644 index 0000000..91b9dfd --- /dev/null +++ b/conformance/failing_tests.txt @@ -0,0 +1,48 @@ +Recommended.Editions_Proto2.ProtobufInput.ValidDataOneofBinary.MESSAGE.Merge.ProtobufOutput # Output was not equivalent to reference message: Expect: \202\007\014\022\012\010\001\020\001\310\005\001\310\005\001, but got: \ +Recommended.Editions_Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.Merge.ProtobufOutput # Output was not equivalent to reference message: Expect: \202\007\014\022\012\010\001\020\001\310\005\001\310\005\001, but got: \ +Recommended.Proto2.ProtobufInput.ValidDataOneofBinary.MESSAGE.Merge.ProtobufOutput # Output was not equivalent to reference message: Expect: \202\007\014\022\012\010\001\020\001\310\005\001\310\005\001, but got: \ +Recommended.Proto2.ProtobufInput.ValidMessageSetEncoding.SubmessageEncoding.NotUnknown.ProtobufOutput # Output was not equivalent to reference message: added: message_set_correct.(protobuf_test_messages.proto2.TestAllTypesProto2.Ext +Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.Merge.ProtobufOutput # Output was not equivalent to reference message: Expect: \202\007\014\022\012\010\001\020\001\310\005\001\310\005\001, but got: \ +Required.Editions.ProtobufInput.ValidDelimitedExtension.GroupLike.ProtobufOutput # Failed to parse input or produce output. +Required.Editions.ProtobufInput.ValidDelimitedExtension.NotGroupLike.ProtobufOutput # Failed to parse input or produce output. +Required.Editions.ProtobufInput.ValidDelimitedField.GroupLike.ProtobufOutput # Output was not equivalent to reference message: added: delimited_field: { group_int32: 99 } +Required.Editions.ProtobufInput.ValidDelimitedField.NotGroupLike.ProtobufOutput # Output was not equivalent to reference message: added: groupliketype: { group_int32: 99 } +Required.Editions_Proto2.ProtobufInput.RepeatedScalarMessageMerge.ProtobufOutput # Output was not equivalent to reference message: deleted: optional_nested_message.corecursive.optional_int64: 1234modified: optio +Required.Editions_Proto2.ProtobufInput.UnknownOrdering.ProtobufOutput # Unknown field mismatch +Required.Editions_Proto2.ProtobufInput.UnknownVarint.ProtobufOutput # Output was not equivalent to reference message: Expect: \250\037\001, but got: +Required.Editions_Proto2.ProtobufInput.UnmatchedEndGroup # Should have failed to parse, but didn't. +Required.Editions_Proto2.ProtobufInput.UnmatchedEndGroupNestedLen # Should have failed to parse, but didn't. +Required.Editions_Proto2.ProtobufInput.UnmatchedEndGroupUnknown # Should have failed to parse, but didn't. +Required.Editions_Proto2.ProtobufInput.UnmatchedEndGroupWithData # Should have failed to parse, but didn't. +Required.Editions_Proto2.ProtobufInput.UnmatchedEndGroupWrongType # Should have failed to parse, but didn't. +Required.Editions_Proto2.ProtobufInput.ValidDataOneof.MESSAGE.Merge.ProtobufOutput # Output was not equivalent to reference message: deleted: oneof_nested_message.corecursive.optional_int32: 1deleted: oneof_nested +Required.Editions_Proto3.ProtobufInput.RepeatedScalarMessageMerge.ProtobufOutput # Output was not equivalent to reference message: deleted: optional_nested_message.corecursive.optional_int64: 1234modified: optio +Required.Editions_Proto3.ProtobufInput.UnknownOrdering.ProtobufOutput # Unknown field mismatch +Required.Editions_Proto3.ProtobufInput.UnknownVarint.ProtobufOutput # Output was not equivalent to reference message: Expect: \250\037\001, but got: +Required.Editions_Proto3.ProtobufInput.UnmatchedEndGroup # Should have failed to parse, but didn't. +Required.Editions_Proto3.ProtobufInput.UnmatchedEndGroupNestedLen # Should have failed to parse, but didn't. +Required.Editions_Proto3.ProtobufInput.UnmatchedEndGroupUnknown # Should have failed to parse, but didn't. +Required.Editions_Proto3.ProtobufInput.UnmatchedEndGroupWithData # Should have failed to parse, but didn't. +Required.Editions_Proto3.ProtobufInput.UnmatchedEndGroupWrongType # Should have failed to parse, but didn't. +Required.Editions_Proto3.ProtobufInput.ValidDataOneof.MESSAGE.Merge.ProtobufOutput # Output was not equivalent to reference message: deleted: oneof_nested_message.corecursive.optional_int32: 1deleted: oneof_nested +Required.Proto2.ProtobufInput.MessageSetEncoding.UnknownExtension.ProtobufOutput # Output was not equivalent to reference message: deleted: message_set_correct.4135300[0]: "\000c" +Required.Proto2.ProtobufInput.RepeatedScalarMessageMerge.ProtobufOutput # Output was not equivalent to reference message: deleted: optional_nested_message.corecursive.optional_int64: 1234modified: optio +Required.Proto2.ProtobufInput.UnknownOrdering.ProtobufOutput # Unknown field mismatch +Required.Proto2.ProtobufInput.UnknownVarint.ProtobufOutput # Output was not equivalent to reference message: Expect: \250\037\001, but got: +Required.Proto2.ProtobufInput.UnmatchedEndGroup # Should have failed to parse, but didn't. +Required.Proto2.ProtobufInput.UnmatchedEndGroupNestedLen # Should have failed to parse, but didn't. +Required.Proto2.ProtobufInput.UnmatchedEndGroupUnknown # Should have failed to parse, but didn't. +Required.Proto2.ProtobufInput.UnmatchedEndGroupWithData # Should have failed to parse, but didn't. +Required.Proto2.ProtobufInput.UnmatchedEndGroupWrongType # Should have failed to parse, but didn't. +Required.Proto2.ProtobufInput.ValidDataOneof.MESSAGE.Merge.ProtobufOutput # Output was not equivalent to reference message: deleted: oneof_nested_message.corecursive.optional_int32: 1deleted: oneof_nested +Required.Proto2.ProtobufInput.ValidMessageSetEncoding.OutOfOrderGroupsEntries.ProtobufOutput # Output was not equivalent to reference message: deleted: message_set_correct.(protobuf_test_messages.proto2.TestAllTypesProto2.M +Required.Proto2.ProtobufInput.ValidMessageSetEncoding.ProtobufOutput # Output was not equivalent to reference message: deleted: message_set_correct.(protobuf_test_messages.proto2.TestAllTypesProto2.M +Required.Proto3.ProtobufInput.RepeatedScalarMessageMerge.ProtobufOutput # Output was not equivalent to reference message: deleted: optional_nested_message.corecursive.optional_int64: 1234modified: optio +Required.Proto3.ProtobufInput.UnknownOrdering.ProtobufOutput # Unknown field mismatch +Required.Proto3.ProtobufInput.UnknownVarint.ProtobufOutput # Output was not equivalent to reference message: Expect: \250\037\001, but got: +Required.Proto3.ProtobufInput.UnmatchedEndGroup # Should have failed to parse, but didn't. +Required.Proto3.ProtobufInput.UnmatchedEndGroupNestedLen # Should have failed to parse, but didn't. +Required.Proto3.ProtobufInput.UnmatchedEndGroupUnknown # Should have failed to parse, but didn't. +Required.Proto3.ProtobufInput.UnmatchedEndGroupWithData # Should have failed to parse, but didn't. +Required.Proto3.ProtobufInput.UnmatchedEndGroupWrongType # Should have failed to parse, but didn't. +Required.Proto3.ProtobufInput.ValidDataOneof.MESSAGE.Merge.ProtobufOutput # Output was not equivalent to reference message: deleted: oneof_nested_message.corecursive.optional_int32: 1deleted: oneof_nested diff --git a/conformance/package.json b/conformance/package.json new file mode 100644 index 0000000..5a68739 --- /dev/null +++ b/conformance/package.json @@ -0,0 +1,18 @@ +{ + "name": "google-protobuf-conformance", + "private": true, + "version": "0.0.1", + "description": "Conformance test runner for google-protobuf", + "main": "runner.js", + "files": [ + "runner.js", + "protos/*.proto", + "package.json", + "LICENSE.md" + ], + "dependencies": { + "google-protobuf": "file:../google-protobuf-3.21.4.tgz" + }, + "author": "Google Protocol Buffers Team", + "license": "BSD-3-Clause" +} diff --git a/conformance/protos/conformance.proto b/conformance/protos/conformance.proto new file mode 100644 index 0000000..e3298f0 --- /dev/null +++ b/conformance/protos/conformance.proto @@ -0,0 +1,172 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd + +syntax = "proto3"; + +package conformance; + +option java_package = "com.google.protobuf.conformance"; +option objc_class_prefix = "Conformance"; + +// This defines the conformance testing protocol. This protocol exists between +// the conformance test suite itself and the code being tested. For each test, +// the suite will send a ConformanceRequest message and expect a +// ConformanceResponse message. +// +// You can either run the tests in two different ways: +// +// 1. in-process (using the interface in conformance_test.h). +// +// 2. as a sub-process communicating over a pipe. Information about how to +// do this is in conformance_test_runner.cc. +// +// Pros/cons of the two approaches: +// +// - running as a sub-process is much simpler for languages other than C/C++. +// +// - running as a sub-process may be more tricky in unusual environments like +// iOS apps, where fork/stdin/stdout are not available. + +enum WireFormat { + UNSPECIFIED = 0; + PROTOBUF = 1; + JSON = 2; + JSPB = 3; // Only used inside Google. Opensource testees just skip it. + TEXT_FORMAT = 4; +} + +enum TestCategory { + UNSPECIFIED_TEST = 0; + BINARY_TEST = 1; // Test binary wire format. + JSON_TEST = 2; // Test json wire format. + // Similar to JSON_TEST. However, during parsing json, testee should ignore + // unknown fields. This feature is optional. Each implementation can decide + // whether to support it. See + // https://developers.google.com/protocol-buffers/docs/proto3#json_options + // for more detail. + JSON_IGNORE_UNKNOWN_PARSING_TEST = 3; + // Test jspb wire format. Only used inside Google. Opensource testees just + // skip it. + JSPB_TEST = 4; + // Test text format. For cpp, java and python, testees can already deal with + // this type. Testees of other languages can simply skip it. + TEXT_FORMAT_TEST = 5; +} + +// Meant to encapsulate all types of tests: successes, skips, failures, etc. +// Therefore, this may or may not have a failure message. Failure messages +// may be truncated for our failure lists. +message TestStatus { + string name = 1; + string failure_message = 2; + // What an actual test name matched to in a failure list. Can be wildcarded or + // an exact match without wildcards. + string matched_name = 3; +} + +// The conformance runner will request a list of failures as the first request. +// This will be known by message_type == "conformance.FailureSet", a conformance +// test should return a serialized FailureSet in protobuf_payload. +message FailureSet { + repeated TestStatus test = 2; + reserved 1; +} + +// Represents a single test case's input. The testee should: +// +// 1. parse this proto (which should always succeed) +// 2. parse the protobuf or JSON payload in "payload" (which may fail) +// 3. if the parse succeeded, serialize the message in the requested format. +message ConformanceRequest { + // The payload (whether protobuf of JSON) is always for a + // protobuf_test_messages.proto3.TestAllTypes proto (as defined in + // src/google/protobuf/proto3_test_messages.proto). + oneof payload { + bytes protobuf_payload = 1; + string json_payload = 2; + // Only used inside Google. Opensource testees just skip it. + string jspb_payload = 7; + string text_payload = 8; + } + + // Which format should the testee serialize its message to? + WireFormat requested_output_format = 3; + + // The full name for the test message to use; for the moment, either: + // protobuf_test_messages.proto3.TestAllTypesProto3 or + // protobuf_test_messages.proto2.TestAllTypesProto2 or + // protobuf_test_messages.editions.proto2.TestAllTypesProto2 or + // protobuf_test_messages.editions.proto3.TestAllTypesProto3 or + // protobuf_test_messages.editions.TestAllTypesEdition2023. + string message_type = 4; + + // Each test is given a specific test category. Some category may need + // specific support in testee programs. Refer to the definition of + // TestCategory for more information. + TestCategory test_category = 5; + + // Specify details for how to encode jspb. + JspbEncodingConfig jspb_encoding_options = 6; + + // This can be used in json and text format. If true, testee should print + // unknown fields instead of ignore. This feature is optional. + bool print_unknown_fields = 9; +} + +// Represents a single test case's output. +message ConformanceResponse { + oneof result { + // This string should be set to indicate parsing failed. The string can + // provide more information about the parse error if it is available. + // + // Setting this string does not necessarily mean the testee failed the + // test. Some of the test cases are intentionally invalid input. + string parse_error = 1; + + // If the input was successfully parsed but errors occurred when + // serializing it to the requested output format, set the error message in + // this field. + string serialize_error = 6; + + // This should be set if the test program timed out. The string should + // provide more information about what the child process was doing when it + // was killed. + string timeout_error = 9; + + // This should be set if some other error occurred. This will always + // indicate that the test failed. The string can provide more information + // about the failure. + string runtime_error = 2; + + // If the input was successfully parsed and the requested output was + // protobuf, serialize it to protobuf and set it in this field. + bytes protobuf_payload = 3; + + // If the input was successfully parsed and the requested output was JSON, + // serialize to JSON and set it in this field. + string json_payload = 4; + + // For when the testee skipped the test, likely because a certain feature + // wasn't supported, like JSON input/output. + string skipped = 5; + + // If the input was successfully parsed and the requested output was JSPB, + // serialize to JSPB and set it in this field. JSPB is only used inside + // Google. Opensource testees can just skip it. + string jspb_payload = 7; + + // If the input was successfully parsed and the requested output was + // TEXT_FORMAT, serialize to TEXT_FORMAT and set it in this field. + string text_payload = 8; + } +} + +// Encoding options for jspb format. +message JspbEncodingConfig { + // Encode the value field of Any as jspb array if true, otherwise binary. + bool use_jspb_array_any_format = 1; +} diff --git a/conformance/protos/test_messages_edition2023.proto b/conformance/protos/test_messages_edition2023.proto new file mode 100644 index 0000000..7affff6 --- /dev/null +++ b/conformance/protos/test_messages_edition2023.proto @@ -0,0 +1,217 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2024 Google Inc. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd + +edition = "2023"; + +package protobuf_test_messages.editions; + +option features.message_encoding = DELIMITED; +option java_package = "com.google.protobuf_test_messages.edition2023"; +option java_multiple_files = true; +option objc_class_prefix = "Editions"; + +message ComplexMessage { + int32 d = 1; +} + +message TestAllTypesEdition2023 { + message NestedMessage { + int32 a = 1; + TestAllTypesEdition2023 corecursive = 2 + [features.message_encoding = LENGTH_PREFIXED]; + } + + enum NestedEnum { + FOO = 0; + BAR = 1; + BAZ = 2; + NEG = -1; // Intentionally negative. + } + + // Singular + int32 optional_int32 = 1; + int64 optional_int64 = 2; + uint32 optional_uint32 = 3; + uint64 optional_uint64 = 4; + sint32 optional_sint32 = 5; + sint64 optional_sint64 = 6; + fixed32 optional_fixed32 = 7; + fixed64 optional_fixed64 = 8; + sfixed32 optional_sfixed32 = 9; + sfixed64 optional_sfixed64 = 10; + float optional_float = 11; + double optional_double = 12; + bool optional_bool = 13; + string optional_string = 14; + bytes optional_bytes = 15; + + NestedMessage optional_nested_message = 18 + [features.message_encoding = LENGTH_PREFIXED]; + ForeignMessageEdition2023 optional_foreign_message = 19 + [features.message_encoding = LENGTH_PREFIXED]; + + NestedEnum optional_nested_enum = 21; + ForeignEnumEdition2023 optional_foreign_enum = 22; + + string optional_string_piece = 24 [ctype = STRING_PIECE]; + string optional_cord = 25 [ctype = CORD]; + + TestAllTypesEdition2023 recursive_message = 27 + [features.message_encoding = LENGTH_PREFIXED]; + + // Repeated + repeated int32 repeated_int32 = 31; + repeated int64 repeated_int64 = 32; + repeated uint32 repeated_uint32 = 33; + repeated uint64 repeated_uint64 = 34; + repeated sint32 repeated_sint32 = 35; + repeated sint64 repeated_sint64 = 36; + repeated fixed32 repeated_fixed32 = 37; + repeated fixed64 repeated_fixed64 = 38; + repeated sfixed32 repeated_sfixed32 = 39; + repeated sfixed64 repeated_sfixed64 = 40; + repeated float repeated_float = 41; + repeated double repeated_double = 42; + repeated bool repeated_bool = 43; + repeated string repeated_string = 44; + repeated bytes repeated_bytes = 45; + + repeated NestedMessage repeated_nested_message = 48 + [features.message_encoding = LENGTH_PREFIXED]; + repeated ForeignMessageEdition2023 repeated_foreign_message = 49 + [features.message_encoding = LENGTH_PREFIXED]; + + repeated NestedEnum repeated_nested_enum = 51; + repeated ForeignEnumEdition2023 repeated_foreign_enum = 52; + + repeated string repeated_string_piece = 54 [ctype = STRING_PIECE]; + repeated string repeated_cord = 55 [ctype = CORD]; + + // Packed + repeated int32 packed_int32 = 75 [features.repeated_field_encoding = PACKED]; + repeated int64 packed_int64 = 76 [features.repeated_field_encoding = PACKED]; + repeated uint32 packed_uint32 = 77 + [features.repeated_field_encoding = PACKED]; + repeated uint64 packed_uint64 = 78 + [features.repeated_field_encoding = PACKED]; + repeated sint32 packed_sint32 = 79 + [features.repeated_field_encoding = PACKED]; + repeated sint64 packed_sint64 = 80 + [features.repeated_field_encoding = PACKED]; + repeated fixed32 packed_fixed32 = 81 + [features.repeated_field_encoding = PACKED]; + repeated fixed64 packed_fixed64 = 82 + [features.repeated_field_encoding = PACKED]; + repeated sfixed32 packed_sfixed32 = 83 + [features.repeated_field_encoding = PACKED]; + repeated sfixed64 packed_sfixed64 = 84 + [features.repeated_field_encoding = PACKED]; + repeated float packed_float = 85 [features.repeated_field_encoding = PACKED]; + repeated double packed_double = 86 + [features.repeated_field_encoding = PACKED]; + repeated bool packed_bool = 87 [features.repeated_field_encoding = PACKED]; + repeated NestedEnum packed_nested_enum = 88 + [features.repeated_field_encoding = PACKED]; + + // Unpacked + repeated int32 unpacked_int32 = 89 + [features.repeated_field_encoding = EXPANDED]; + repeated int64 unpacked_int64 = 90 + [features.repeated_field_encoding = EXPANDED]; + repeated uint32 unpacked_uint32 = 91 + [features.repeated_field_encoding = EXPANDED]; + repeated uint64 unpacked_uint64 = 92 + [features.repeated_field_encoding = EXPANDED]; + repeated sint32 unpacked_sint32 = 93 + [features.repeated_field_encoding = EXPANDED]; + repeated sint64 unpacked_sint64 = 94 + [features.repeated_field_encoding = EXPANDED]; + repeated fixed32 unpacked_fixed32 = 95 + [features.repeated_field_encoding = EXPANDED]; + repeated fixed64 unpacked_fixed64 = 96 + [features.repeated_field_encoding = EXPANDED]; + repeated sfixed32 unpacked_sfixed32 = 97 + [features.repeated_field_encoding = EXPANDED]; + repeated sfixed64 unpacked_sfixed64 = 98 + [features.repeated_field_encoding = EXPANDED]; + repeated float unpacked_float = 99 + [features.repeated_field_encoding = EXPANDED]; + repeated double unpacked_double = 100 + [features.repeated_field_encoding = EXPANDED]; + repeated bool unpacked_bool = 101 + [features.repeated_field_encoding = EXPANDED]; + repeated NestedEnum unpacked_nested_enum = 102 + [features.repeated_field_encoding = EXPANDED]; + + // Map + map map_int32_int32 = 56; + map map_int64_int64 = 57; + map map_uint32_uint32 = 58; + map map_uint64_uint64 = 59; + map map_sint32_sint32 = 60; + map map_sint64_sint64 = 61; + map map_fixed32_fixed32 = 62; + map map_fixed64_fixed64 = 63; + map map_sfixed32_sfixed32 = 64; + map map_sfixed64_sfixed64 = 65; + map map_int32_float = 66; + map map_int32_double = 67; + map map_bool_bool = 68; + map map_string_string = 69; + map map_string_bytes = 70; + map map_string_nested_message = 71; + map map_string_foreign_message = 72; + map map_string_nested_enum = 73; + map map_string_foreign_enum = 74; + + oneof oneof_field { + uint32 oneof_uint32 = 111; + NestedMessage oneof_nested_message = 112 + [features.message_encoding = LENGTH_PREFIXED]; + string oneof_string = 113; + bytes oneof_bytes = 114; + bool oneof_bool = 115; + uint64 oneof_uint64 = 116; + float oneof_float = 117; + double oneof_double = 118; + NestedEnum oneof_enum = 119; + } + + // extensions + extensions 120 to 200; + + // groups + message GroupLikeType { + int32 group_int32 = 202; + uint32 group_uint32 = 203; + } + GroupLikeType groupliketype = 201; + GroupLikeType delimited_field = 202; +} + +message ForeignMessageEdition2023 { + int32 c = 1; +} + +enum ForeignEnumEdition2023 { + FOREIGN_FOO = 0; + FOREIGN_BAR = 1; + FOREIGN_BAZ = 2; +} + +extend TestAllTypesEdition2023 { + int32 extension_int32 = 120; +} + +message GroupLikeType { + int32 c = 1; +} + +extend TestAllTypesEdition2023 { + GroupLikeType groupliketype = 121; + GroupLikeType delimited_ext = 122; +} diff --git a/conformance/protos/test_messages_proto2.proto b/conformance/protos/test_messages_proto2.proto new file mode 100644 index 0000000..097e812 --- /dev/null +++ b/conformance/protos/test_messages_proto2.proto @@ -0,0 +1,416 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd +// +// Test schema for proto2 messages. This test schema is used by: +// +// - conformance tests +// + +// LINT: ALLOW_GROUPS + +syntax = "proto2"; + +package protobuf_test_messages.proto2; + +option java_package = "com.google.protobuf_test_messages.proto2"; +option objc_class_prefix = "Proto2"; + +// This is the default, but we specify it here explicitly. +option optimize_for = SPEED; + +option cc_enable_arenas = true; + + +// This proto includes every type of field in both singular and repeated +// forms. +// +// Also, crucially, all messages and enums in this file are eventually +// submessages of this message. So for example, a fuzz test of TestAllTypes +// could trigger bugs that occur in any message type in this file. We verify +// this stays true in a unit test. +message TestAllTypesProto2 { + message NestedMessage { + optional int32 a = 1; + optional TestAllTypesProto2 corecursive = 2; + } + + enum NestedEnum { + FOO = 0; + BAR = 1; + BAZ = 2; + NEG = -1; // Intentionally negative. + } + + // Singular + optional int32 optional_int32 = 1; + optional int64 optional_int64 = 2; + optional uint32 optional_uint32 = 3; + optional uint64 optional_uint64 = 4; + optional sint32 optional_sint32 = 5; + optional sint64 optional_sint64 = 6; + optional fixed32 optional_fixed32 = 7; + optional fixed64 optional_fixed64 = 8; + optional sfixed32 optional_sfixed32 = 9; + optional sfixed64 optional_sfixed64 = 10; + optional float optional_float = 11; + optional double optional_double = 12; + optional bool optional_bool = 13; + optional string optional_string = 14; + optional bytes optional_bytes = 15; + + optional NestedMessage optional_nested_message = 18; + optional ForeignMessageProto2 optional_foreign_message = 19; + + optional NestedEnum optional_nested_enum = 21; + optional ForeignEnumProto2 optional_foreign_enum = 22; + + optional string optional_string_piece = 24 [ctype = STRING_PIECE]; + optional string optional_cord = 25 [ctype = CORD]; + + optional TestAllTypesProto2 recursive_message = 27; + + // Repeated + repeated int32 repeated_int32 = 31; + repeated int64 repeated_int64 = 32; + repeated uint32 repeated_uint32 = 33; + repeated uint64 repeated_uint64 = 34; + repeated sint32 repeated_sint32 = 35; + repeated sint64 repeated_sint64 = 36; + repeated fixed32 repeated_fixed32 = 37; + repeated fixed64 repeated_fixed64 = 38; + repeated sfixed32 repeated_sfixed32 = 39; + repeated sfixed64 repeated_sfixed64 = 40; + repeated float repeated_float = 41; + repeated double repeated_double = 42; + repeated bool repeated_bool = 43; + repeated string repeated_string = 44; + repeated bytes repeated_bytes = 45; + + repeated NestedMessage repeated_nested_message = 48; + repeated ForeignMessageProto2 repeated_foreign_message = 49; + + repeated NestedEnum repeated_nested_enum = 51; + repeated ForeignEnumProto2 repeated_foreign_enum = 52; + + repeated string repeated_string_piece = 54 [ctype = STRING_PIECE]; + repeated string repeated_cord = 55 [ctype = CORD]; + + // Packed + repeated int32 packed_int32 = 75 [packed = true]; + repeated int64 packed_int64 = 76 [packed = true]; + repeated uint32 packed_uint32 = 77 [packed = true]; + repeated uint64 packed_uint64 = 78 [packed = true]; + repeated sint32 packed_sint32 = 79 [packed = true]; + repeated sint64 packed_sint64 = 80 [packed = true]; + repeated fixed32 packed_fixed32 = 81 [packed = true]; + repeated fixed64 packed_fixed64 = 82 [packed = true]; + repeated sfixed32 packed_sfixed32 = 83 [packed = true]; + repeated sfixed64 packed_sfixed64 = 84 [packed = true]; + repeated float packed_float = 85 [packed = true]; + repeated double packed_double = 86 [packed = true]; + repeated bool packed_bool = 87 [packed = true]; + repeated NestedEnum packed_nested_enum = 88 [packed = true]; + + // Unpacked + repeated int32 unpacked_int32 = 89 [packed = false]; + repeated int64 unpacked_int64 = 90 [packed = false]; + repeated uint32 unpacked_uint32 = 91 [packed = false]; + repeated uint64 unpacked_uint64 = 92 [packed = false]; + repeated sint32 unpacked_sint32 = 93 [packed = false]; + repeated sint64 unpacked_sint64 = 94 [packed = false]; + repeated fixed32 unpacked_fixed32 = 95 [packed = false]; + repeated fixed64 unpacked_fixed64 = 96 [packed = false]; + repeated sfixed32 unpacked_sfixed32 = 97 [packed = false]; + repeated sfixed64 unpacked_sfixed64 = 98 [packed = false]; + repeated float unpacked_float = 99 [packed = false]; + repeated double unpacked_double = 100 [packed = false]; + repeated bool unpacked_bool = 101 [packed = false]; + repeated NestedEnum unpacked_nested_enum = 102 [packed = false]; + + // Map + map map_int32_int32 = 56; + map map_int64_int64 = 57; + map map_uint32_uint32 = 58; + map map_uint64_uint64 = 59; + map map_sint32_sint32 = 60; + map map_sint64_sint64 = 61; + map map_fixed32_fixed32 = 62; + map map_fixed64_fixed64 = 63; + map map_sfixed32_sfixed32 = 64; + map map_sfixed64_sfixed64 = 65; + map map_int32_bool = 104; + map map_int32_float = 66; + map map_int32_double = 67; + map map_int32_nested_message = 103; + map map_bool_bool = 68; + map map_string_string = 69; + map map_string_bytes = 70; + map map_string_nested_message = 71; + map map_string_foreign_message = 72; + map map_string_nested_enum = 73; + map map_string_foreign_enum = 74; + + oneof oneof_field { + uint32 oneof_uint32 = 111; + NestedMessage oneof_nested_message = 112; + string oneof_string = 113; + bytes oneof_bytes = 114; + bool oneof_bool = 115; + uint64 oneof_uint64 = 116; + float oneof_float = 117; + double oneof_double = 118; + NestedEnum oneof_enum = 119; + } + + // extensions + extensions 120 to 200; + + // groups + optional group Data = 201 { + optional int32 group_int32 = 202; + optional uint32 group_uint32 = 203; + } + + optional group MultiWordGroupField = 204 { + optional int32 group_int32 = 205; + optional uint32 group_uint32 = 206; + } + + // default values + optional int32 default_int32 = 241 [default = -123456789]; + optional int64 default_int64 = 242 [default = -9123456789123456789]; + optional uint32 default_uint32 = 243 [default = 2123456789]; + optional uint64 default_uint64 = 244 [default = 10123456789123456789]; + optional sint32 default_sint32 = 245 [default = -123456789]; + optional sint64 default_sint64 = 246 [default = -9123456789123456789]; + optional fixed32 default_fixed32 = 247 [default = 2123456789]; + optional fixed64 default_fixed64 = 248 [default = 10123456789123456789]; + optional sfixed32 default_sfixed32 = 249 [default = -123456789]; + optional sfixed64 default_sfixed64 = 250 [default = -9123456789123456789]; + optional float default_float = 251 [default = 9e9]; + optional double default_double = 252 [default = 7e22]; + optional bool default_bool = 253 [default = true]; + optional string default_string = 254 [default = "Rosebud"]; + optional bytes default_bytes = 255 [default = "joshua"]; + + // Test field-name-to-JSON-name convention. + // (protobuf says names can be any valid C/C++ identifier.) + optional int32 fieldname1 = 401; + optional int32 field_name2 = 402; + optional int32 _field_name3 = 403; + optional int32 field__name4_ = 404; + optional int32 field0name5 = 405; + optional int32 field_0_name6 = 406; + optional int32 fieldName7 = 407; + optional int32 FieldName8 = 408; + optional int32 field_Name9 = 409; + optional int32 Field_Name10 = 410; + optional int32 FIELD_NAME11 = 411; + optional int32 FIELD_name12 = 412; + optional int32 __field_name13 = 413; + optional int32 __Field_name14 = 414; + optional int32 field__name15 = 415; + optional int32 field__Name16 = 416; + optional int32 field_name17__ = 417; + optional int32 Field_name18__ = 418; + + // Reserved for unknown fields test. + reserved 1000 to 9999; + + optional MessageSetCorrect message_set_correct = 500; + + // message_set test case. + message MessageSetCorrect { + option message_set_wire_format = true; + + extensions 4 to max; + } + + message MessageSetCorrectExtension1 { + extend MessageSetCorrect { + optional MessageSetCorrectExtension1 message_set_extension = 1547769; + } + optional string str = 25; + } + + message MessageSetCorrectExtension2 { + extend MessageSetCorrect { + optional MessageSetCorrectExtension2 message_set_extension = 4135312; + } + optional int32 i = 9; + } + + message ExtensionWithOneof { + oneof oneof_field { + int32 a = 1; + int32 b = 2; + } + extend MessageSetCorrect { + optional ExtensionWithOneof extension_with_oneof = 123456789; + } + } +} + +message ForeignMessageProto2 { + optional int32 c = 1; +} + +enum ForeignEnumProto2 { + FOREIGN_FOO = 0; + FOREIGN_BAR = 1; + FOREIGN_BAZ = 2; +} + +extend TestAllTypesProto2 { + optional int32 extension_int32 = 120; +} + +extend TestAllTypesProto2 { + optional group GroupField = 121 { + optional int32 group_int32 = 122; + optional uint32 group_uint32 = 123; + } +} + +message UnknownToTestAllTypes { + optional int32 optional_int32 = 1001; + optional string optional_string = 1002; + optional ForeignMessageProto2 nested_message = 1003; + optional group OptionalGroup = 1004 { + optional int32 a = 1; + } + optional bool optional_bool = 1006; + repeated int32 repeated_int32 = 1011; +} + +message NullHypothesisProto2 {} + +message EnumOnlyProto2 { + enum Bool { + kFalse = 0; + kTrue = 1; + } +} + +message OneStringProto2 { + optional string data = 1; +} + +message ProtoWithKeywords { + optional int32 inline = 1; + optional string concept = 2; + repeated string requires = 3; +} + +message TestAllRequiredTypesProto2 { + message NestedMessage { + required int32 a = 1; + required TestAllRequiredTypesProto2 corecursive = 2; + optional TestAllRequiredTypesProto2 optional_corecursive = 3; + } + + enum NestedEnum { + FOO = 0; + BAR = 1; + BAZ = 2; + NEG = -1; // Intentionally negative. + } + + // Singular + required int32 required_int32 = 1; + required int64 required_int64 = 2; + required uint32 required_uint32 = 3; + required uint64 required_uint64 = 4; + required sint32 required_sint32 = 5; + required sint64 required_sint64 = 6; + required fixed32 required_fixed32 = 7; + required fixed64 required_fixed64 = 8; + required sfixed32 required_sfixed32 = 9; + required sfixed64 required_sfixed64 = 10; + required float required_float = 11; + required double required_double = 12; + required bool required_bool = 13; + required string required_string = 14; + required bytes required_bytes = 15; + + required NestedMessage required_nested_message = 18; + required ForeignMessageProto2 required_foreign_message = 19; + + required NestedEnum required_nested_enum = 21; + required ForeignEnumProto2 required_foreign_enum = 22; + + required string required_string_piece = 24 [ctype = STRING_PIECE]; + required string required_cord = 25 [ctype = CORD]; + + required TestAllRequiredTypesProto2 recursive_message = 27; + optional TestAllRequiredTypesProto2 optional_recursive_message = 28; + + // extensions + extensions 120 to 200; + + // groups + required group Data = 201 { + required int32 group_int32 = 202; + required uint32 group_uint32 = 203; + } + + // default values + required int32 default_int32 = 241 [default = -123456789]; + required int64 default_int64 = 242 [default = -9123456789123456789]; + required uint32 default_uint32 = 243 [default = 2123456789]; + required uint64 default_uint64 = 244 [default = 10123456789123456789]; + required sint32 default_sint32 = 245 [default = -123456789]; + required sint64 default_sint64 = 246 [default = -9123456789123456789]; + required fixed32 default_fixed32 = 247 [default = 2123456789]; + required fixed64 default_fixed64 = 248 [default = 10123456789123456789]; + required sfixed32 default_sfixed32 = 249 [default = -123456789]; + required sfixed64 default_sfixed64 = 250 [default = -9123456789123456789]; + required float default_float = 251 [default = 9e9]; + required double default_double = 252 [default = 7e22]; + required bool default_bool = 253 [default = true]; + required string default_string = 254 [default = "Rosebud"]; + required bytes default_bytes = 255 [default = "joshua"]; + + // Reserved for unknown fields test. + reserved 1000 to 9999; + + // message_set test case. + message MessageSetCorrect { + option message_set_wire_format = true; + + extensions 4 to max; + } + + message MessageSetCorrectExtension1 { + extend MessageSetCorrect { + optional MessageSetCorrectExtension1 message_set_extension = 1547769; + } + required string str = 25; + } + + message MessageSetCorrectExtension2 { + extend MessageSetCorrect { + optional MessageSetCorrectExtension2 message_set_extension = 4135312; + } + required int32 i = 9; + } +} + +message TestLargeOneof { + message A1 {} + message A2 {} + message A3 {} + message A4 {} + message A5 {} + oneof large_oneof { + A1 a1 = 1; + A2 a2 = 2; + A3 a3 = 3; + A4 a4 = 4; + A5 a5 = 5; + } +} diff --git a/conformance/protos/test_messages_proto2_editions.proto b/conformance/protos/test_messages_proto2_editions.proto new file mode 100644 index 0000000..25de6c9 --- /dev/null +++ b/conformance/protos/test_messages_proto2_editions.proto @@ -0,0 +1,683 @@ +// clang-format off +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd +// +// Test schema for proto2 messages. This test schema is used by: +// +// - conformance tests + +// LINT: ALLOW_GROUPS + +edition = "2023"; + +package protobuf_test_messages.editions.proto2; + +option features.enum_type = CLOSED; +option features.repeated_field_encoding = EXPANDED; +option features.utf8_validation = NONE; +option java_package = "com.google.protobuf_test_messages.editions.proto2"; +option objc_class_prefix = "EditionsProto2"; + +// This is the default, but we specify it here explicitly. +option optimize_for = SPEED; +option cc_enable_arenas = true; + +// This proto includes every type of field in both singular and repeated +// forms. +// +// Also, crucially, all messages and enums in this file are eventually +// submessages of this message. So for example, a fuzz test of TestAllTypes +// could trigger bugs that occur in any message type in this file. We verify +// this stays true in a unit test. +message TestAllTypesProto2 { + message NestedMessage { + int32 a = 1; + TestAllTypesProto2 corecursive = 2; + } + + enum NestedEnum { + FOO = 0; + BAR = 1; + BAZ = 2; + NEG = -1; // Intentionally negative. + } + + // Singular + int32 optional_int32 = 1; + int64 optional_int64 = 2; + uint32 optional_uint32 = 3; + uint64 optional_uint64 = 4; + sint32 optional_sint32 = 5; + sint64 optional_sint64 = 6; + fixed32 optional_fixed32 = 7; + fixed64 optional_fixed64 = 8; + sfixed32 optional_sfixed32 = 9; + sfixed64 optional_sfixed64 = 10; + float optional_float = 11; + double optional_double = 12; + bool optional_bool = 13; + string optional_string = 14; + bytes optional_bytes = 15; + NestedMessage optional_nested_message = 18; + ForeignMessageProto2 optional_foreign_message = 19; + NestedEnum optional_nested_enum = 21; + ForeignEnumProto2 optional_foreign_enum = 22; + string optional_string_piece = 24 [ + ctype = STRING_PIECE + ]; + + string optional_cord = 25 [ + ctype = CORD + ]; + + TestAllTypesProto2 recursive_message = 27; + + // Repeated + repeated int32 repeated_int32 = 31; + repeated int64 repeated_int64 = 32; + repeated uint32 repeated_uint32 = 33; + repeated uint64 repeated_uint64 = 34; + repeated sint32 repeated_sint32 = 35; + repeated sint64 repeated_sint64 = 36; + repeated fixed32 repeated_fixed32 = 37; + repeated fixed64 repeated_fixed64 = 38; + repeated sfixed32 repeated_sfixed32 = 39; + repeated sfixed64 repeated_sfixed64 = 40; + repeated float repeated_float = 41; + repeated double repeated_double = 42; + repeated bool repeated_bool = 43; + repeated string repeated_string = 44; + repeated bytes repeated_bytes = 45; + repeated NestedMessage repeated_nested_message = 48; + repeated ForeignMessageProto2 repeated_foreign_message = 49; + repeated NestedEnum repeated_nested_enum = 51; + repeated ForeignEnumProto2 repeated_foreign_enum = 52; + repeated string repeated_string_piece = 54 [ + ctype = STRING_PIECE + ]; + + repeated string repeated_cord = 55 [ + ctype = CORD + ]; + + // Packed + repeated int32 packed_int32 = 75 [ + features.repeated_field_encoding = PACKED + ]; + + repeated int64 packed_int64 = 76 [ + features.repeated_field_encoding = PACKED + ]; + + repeated uint32 packed_uint32 = 77 [ + features.repeated_field_encoding = PACKED + ]; + + repeated uint64 packed_uint64 = 78 [ + features.repeated_field_encoding = PACKED + ]; + + repeated sint32 packed_sint32 = 79 [ + features.repeated_field_encoding = PACKED + ]; + + repeated sint64 packed_sint64 = 80 [ + features.repeated_field_encoding = PACKED + ]; + + repeated fixed32 packed_fixed32 = 81 [ + features.repeated_field_encoding = PACKED + ]; + + repeated fixed64 packed_fixed64 = 82 [ + features.repeated_field_encoding = PACKED + ]; + + repeated sfixed32 packed_sfixed32 = 83 [ + features.repeated_field_encoding = PACKED + ]; + + repeated sfixed64 packed_sfixed64 = 84 [ + features.repeated_field_encoding = PACKED + ]; + + repeated float packed_float = 85 [ + features.repeated_field_encoding = PACKED + ]; + + repeated double packed_double = 86 [ + features.repeated_field_encoding = PACKED + ]; + + repeated bool packed_bool = 87 [ + features.repeated_field_encoding = PACKED + ]; + + repeated NestedEnum packed_nested_enum = 88 [ + features.repeated_field_encoding = PACKED + ]; + + // Unpacked + repeated int32 unpacked_int32 = 89; + repeated int64 unpacked_int64 = 90; + repeated uint32 unpacked_uint32 = 91; + repeated uint64 unpacked_uint64 = 92; + repeated sint32 unpacked_sint32 = 93; + repeated sint64 unpacked_sint64 = 94; + repeated fixed32 unpacked_fixed32 = 95; + repeated fixed64 unpacked_fixed64 = 96; + repeated sfixed32 unpacked_sfixed32 = 97; + repeated sfixed64 unpacked_sfixed64 = 98; + repeated float unpacked_float = 99; + repeated double unpacked_double = 100; + repeated bool unpacked_bool = 101; + repeated NestedEnum unpacked_nested_enum = 102; + + // Map + map map_int32_int32 = 56; + map map_int64_int64 = 57; + map map_uint32_uint32 = 58; + map map_uint64_uint64 = 59; + map map_sint32_sint32 = 60; + map map_sint64_sint64 = 61; + map map_fixed32_fixed32 = 62; + map map_fixed64_fixed64 = 63; + map map_sfixed32_sfixed32 = 64; + map map_sfixed64_sfixed64 = 65; + map map_int32_bool = 104; + map map_int32_float = 66; + map map_int32_double = 67; + map map_int32_nested_message = 103; + map map_bool_bool = 68; + map map_string_string = 69; + map map_string_bytes = 70; + map map_string_nested_message = 71; + map map_string_foreign_message = 72; + map map_string_nested_enum = 73; + map map_string_foreign_enum = 74; + + oneof oneof_field { + uint32 oneof_uint32 = 111; + NestedMessage oneof_nested_message = 112; + string oneof_string = 113; + bytes oneof_bytes = 114; + bool oneof_bool = 115; + uint64 oneof_uint64 = 116; + float oneof_float = 117; + double oneof_double = 118; + NestedEnum oneof_enum = 119; + } + + // extensions + extensions 120 to 200; + + // groups + message Data { + int32 group_int32 = 202; + uint32 group_uint32 = 203; + } + + Data data = 201 [ + features.message_encoding = DELIMITED + ]; + + message MultiWordGroupField { + int32 group_int32 = 205; + uint32 group_uint32 = 206; + } + + MultiWordGroupField multiwordgroupfield = 204 [ + features.message_encoding = DELIMITED + ]; + + // default values + int32 default_int32 = 241 [ + default = -123456789 + ]; + + int64 default_int64 = 242 [ + default = -9123456789123456789 + ]; + + uint32 default_uint32 = 243 [ + default = 2123456789 + ]; + + uint64 default_uint64 = 244 [ + default = 10123456789123456789 + ]; + + sint32 default_sint32 = 245 [ + default = -123456789 + ]; + + sint64 default_sint64 = 246 [ + default = -9123456789123456789 + ]; + + fixed32 default_fixed32 = 247 [ + default = 2123456789 + ]; + + fixed64 default_fixed64 = 248 [ + default = 10123456789123456789 + ]; + + sfixed32 default_sfixed32 = 249 [ + default = -123456789 + ]; + + sfixed64 default_sfixed64 = 250 [ + default = -9123456789123456789 + ]; + + float default_float = 251 [ + default = 9e9 + ]; + + double default_double = 252 [ + default = 7e22 + ]; + + bool default_bool = 253 [ + default = true + ]; + + string default_string = 254 [ + default = "Rosebud" + ]; + + bytes default_bytes = 255 [ + default = "joshua" + ]; + + // Test field-name-to-JSON-name convention. + // (protobuf says names can be any valid C/C++ identifier.) + int32 fieldname1 = 401; + int32 field_name2 = 402; + int32 _field_name3 = 403; + int32 field__name4_ = 404; + int32 field0name5 = 405; + int32 field_0_name6 = 406; + int32 fieldName7 = 407; + int32 FieldName8 = 408; + int32 field_Name9 = 409; + int32 Field_Name10 = 410; + int32 FIELD_NAME11 = 411; + int32 FIELD_name12 = 412; + int32 __field_name13 = 413; + int32 __Field_name14 = 414; + int32 field__name15 = 415; + int32 field__Name16 = 416; + int32 field_name17__ = 417; + int32 Field_name18__ = 418; + + // Reserved for unknown fields test. + reserved 1000 to 9999; + + MessageSetCorrect message_set_correct = 500; + + // message_set test case. + message MessageSetCorrect { + option message_set_wire_format = true; + + extensions 4 to max; + } + + message MessageSetCorrectExtension1 { + extend MessageSetCorrect { + MessageSetCorrectExtension1 message_set_extension = 1547769; + } + + string str = 25; + } + + message MessageSetCorrectExtension2 { + extend MessageSetCorrect { + MessageSetCorrectExtension2 message_set_extension = 4135312; + } + + int32 i = 9; + } + + message ExtensionWithOneof { + oneof oneof_field { + int32 a = 1; + int32 b = 2; + } + + extend MessageSetCorrect { + ExtensionWithOneof extension_with_oneof = 123456789; + } + } +} + +message ForeignMessageProto2 { + int32 c = 1; +} + +enum ForeignEnumProto2 { + FOREIGN_FOO = 0; + FOREIGN_BAR = 1; + FOREIGN_BAZ = 2; +} + +extend TestAllTypesProto2 { + int32 extension_int32 = 120; +} + +extend TestAllTypesProto2 { + GroupField groupfield = 121 [ + features.message_encoding = DELIMITED + ]; +} + +message GroupField { + int32 group_int32 = 122; + uint32 group_uint32 = 123; +} + +message UnknownToTestAllTypes { + int32 optional_int32 = 1001; + string optional_string = 1002; + ForeignMessageProto2 nested_message = 1003; + + message OptionalGroup { + int32 a = 1; + } + + OptionalGroup optionalgroup = 1004 [ + features.message_encoding = DELIMITED + ]; + + bool optional_bool = 1006; + repeated int32 repeated_int32 = 1011; +} + +message NullHypothesisProto2 { +} + +message EnumOnlyProto2 { + enum Bool { + kFalse = 0; + kTrue = 1; + } +} + +message OneStringProto2 { + string data = 1; +} + +message ProtoWithKeywords { + int32 inline = 1; + string concept = 2; + repeated string requires = 3; +} + +message TestAllRequiredTypesProto2 { + message NestedMessage { + int32 a = 1 [ + features.field_presence = LEGACY_REQUIRED + ]; + + TestAllRequiredTypesProto2 corecursive = 2 [ + features.field_presence = LEGACY_REQUIRED + ]; + + TestAllRequiredTypesProto2 optional_corecursive = 3; + } + + enum NestedEnum { + FOO = 0; + BAR = 1; + BAZ = 2; + NEG = -1; // Intentionally negative. + } + + // Singular + int32 required_int32 = 1 [ + features.field_presence = LEGACY_REQUIRED + ]; + + int64 required_int64 = 2 [ + features.field_presence = LEGACY_REQUIRED + ]; + + uint32 required_uint32 = 3 [ + features.field_presence = LEGACY_REQUIRED + ]; + + uint64 required_uint64 = 4 [ + features.field_presence = LEGACY_REQUIRED + ]; + + sint32 required_sint32 = 5 [ + features.field_presence = LEGACY_REQUIRED + ]; + + sint64 required_sint64 = 6 [ + features.field_presence = LEGACY_REQUIRED + ]; + + fixed32 required_fixed32 = 7 [ + features.field_presence = LEGACY_REQUIRED + ]; + + fixed64 required_fixed64 = 8 [ + features.field_presence = LEGACY_REQUIRED + ]; + + sfixed32 required_sfixed32 = 9 [ + features.field_presence = LEGACY_REQUIRED + ]; + + sfixed64 required_sfixed64 = 10 [ + features.field_presence = LEGACY_REQUIRED + ]; + + float required_float = 11 [ + features.field_presence = LEGACY_REQUIRED + ]; + + double required_double = 12 [ + features.field_presence = LEGACY_REQUIRED + ]; + + bool required_bool = 13 [ + features.field_presence = LEGACY_REQUIRED + ]; + + string required_string = 14 [ + features.field_presence = LEGACY_REQUIRED + ]; + + bytes required_bytes = 15 [ + features.field_presence = LEGACY_REQUIRED + ]; + + NestedMessage required_nested_message = 18 [ + features.field_presence = LEGACY_REQUIRED + ]; + + ForeignMessageProto2 required_foreign_message = 19 [ + features.field_presence = LEGACY_REQUIRED + ]; + + NestedEnum required_nested_enum = 21 [ + features.field_presence = LEGACY_REQUIRED + ]; + + ForeignEnumProto2 required_foreign_enum = 22 [ + features.field_presence = LEGACY_REQUIRED + ]; + + string required_string_piece = 24 [ + features.field_presence = LEGACY_REQUIRED, + ctype = STRING_PIECE + ]; + + string required_cord = 25 [ + features.field_presence = LEGACY_REQUIRED, + ctype = CORD + ]; + + TestAllRequiredTypesProto2 recursive_message = 27 [ + features.field_presence = LEGACY_REQUIRED + ]; + + TestAllRequiredTypesProto2 optional_recursive_message = 28; + + // extensions + extensions 120 to 200; + + // groups + message Data { + int32 group_int32 = 202 [ + features.field_presence = LEGACY_REQUIRED + ]; + + uint32 group_uint32 = 203 [ + features.field_presence = LEGACY_REQUIRED + ]; + } + + Data data = 201 [ + features.field_presence = LEGACY_REQUIRED, + features.message_encoding = DELIMITED + ]; + + // default values + int32 default_int32 = 241 [ + features.field_presence = LEGACY_REQUIRED, + default = -123456789 + ]; + + int64 default_int64 = 242 [ + features.field_presence = LEGACY_REQUIRED, + default = -9123456789123456789 + ]; + + uint32 default_uint32 = 243 [ + features.field_presence = LEGACY_REQUIRED, + default = 2123456789 + ]; + + uint64 default_uint64 = 244 [ + features.field_presence = LEGACY_REQUIRED, + default = 10123456789123456789 + ]; + + sint32 default_sint32 = 245 [ + features.field_presence = LEGACY_REQUIRED, + default = -123456789 + ]; + + sint64 default_sint64 = 246 [ + features.field_presence = LEGACY_REQUIRED, + default = -9123456789123456789 + ]; + + fixed32 default_fixed32 = 247 [ + features.field_presence = LEGACY_REQUIRED, + default = 2123456789 + ]; + + fixed64 default_fixed64 = 248 [ + features.field_presence = LEGACY_REQUIRED, + default = 10123456789123456789 + ]; + + sfixed32 default_sfixed32 = 249 [ + features.field_presence = LEGACY_REQUIRED, + default = -123456789 + ]; + + sfixed64 default_sfixed64 = 250 [ + features.field_presence = LEGACY_REQUIRED, + default = -9123456789123456789 + ]; + + float default_float = 251 [ + features.field_presence = LEGACY_REQUIRED, + default = 9e9 + ]; + + double default_double = 252 [ + features.field_presence = LEGACY_REQUIRED, + default = 7e22 + ]; + + bool default_bool = 253 [ + features.field_presence = LEGACY_REQUIRED, + default = true + ]; + + string default_string = 254 [ + features.field_presence = LEGACY_REQUIRED, + default = "Rosebud" + ]; + + bytes default_bytes = 255 [ + features.field_presence = LEGACY_REQUIRED, + default = "joshua" + ]; + + // Reserved for unknown fields test. + reserved 1000 to 9999; + + // message_set test case. + message MessageSetCorrect { + option message_set_wire_format = true; + + extensions 4 to max; + } + + message MessageSetCorrectExtension1 { + extend MessageSetCorrect { + MessageSetCorrectExtension1 message_set_extension = 1547769; + } + + string str = 25 [ + features.field_presence = LEGACY_REQUIRED + ]; + } + + message MessageSetCorrectExtension2 { + extend MessageSetCorrect { + MessageSetCorrectExtension2 message_set_extension = 4135312; + } + + int32 i = 9 [ + features.field_presence = LEGACY_REQUIRED + ]; + } +} + +message TestLargeOneof { + message A1 { + } + + message A2 { + } + + message A3 { + } + + message A4 { + } + + message A5 { + } + + oneof large_oneof { + A1 a1 = 1; + A2 a2 = 2; + A3 a3 = 3; + A4 a4 = 4; + A5 a5 = 5; + } +} diff --git a/conformance/protos/test_messages_proto3.proto b/conformance/protos/test_messages_proto3.proto new file mode 100644 index 0000000..b78e631 --- /dev/null +++ b/conformance/protos/test_messages_proto3.proto @@ -0,0 +1,266 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd +// +// Test schema for proto3 messages. This test schema is used by: +// +// - benchmarks +// - fuzz tests +// - conformance tests +// + +syntax = "proto3"; + +package protobuf_test_messages.proto3; + +option java_package = "com.google.protobuf_test_messages.proto3"; +option objc_class_prefix = "Proto3"; + +// This is the default, but we specify it here explicitly. +option optimize_for = SPEED; + +import "google/protobuf/any.proto"; +import "google/protobuf/duration.proto"; +import "google/protobuf/field_mask.proto"; +import "google/protobuf/struct.proto"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/wrappers.proto"; + +option cc_enable_arenas = true; + +// This proto includes every type of field in both singular and repeated +// forms. +// +// Also, crucially, all messages and enums in this file are eventually +// submessages of this message. So for example, a fuzz test of TestAllTypes +// could trigger bugs that occur in any message type in this file. We verify +// this stays true in a unit test. +message TestAllTypesProto3 { + message NestedMessage { + int32 a = 1; + TestAllTypesProto3 corecursive = 2; + } + + enum NestedEnum { + FOO = 0; + BAR = 1; + BAZ = 2; + NEG = -1; // Intentionally negative. + } + + enum AliasedEnum { + option allow_alias = true; + + ALIAS_FOO = 0; + ALIAS_BAR = 1; + ALIAS_BAZ = 2; + MOO = 2; + moo = 2; + bAz = 2; + } + + // Singular + // test [kotlin] comment + int32 optional_int32 = 1; + int64 optional_int64 = 2; + uint32 optional_uint32 = 3; + uint64 optional_uint64 = 4; + sint32 optional_sint32 = 5; + sint64 optional_sint64 = 6; + fixed32 optional_fixed32 = 7; + fixed64 optional_fixed64 = 8; + sfixed32 optional_sfixed32 = 9; + sfixed64 optional_sfixed64 = 10; + float optional_float = 11; + double optional_double = 12; + bool optional_bool = 13; + string optional_string = 14; + bytes optional_bytes = 15; + + NestedMessage optional_nested_message = 18; + ForeignMessage optional_foreign_message = 19; + + NestedEnum optional_nested_enum = 21; + ForeignEnum optional_foreign_enum = 22; + AliasedEnum optional_aliased_enum = 23; + + string optional_string_piece = 24 [ctype = STRING_PIECE]; + string optional_cord = 25 [ctype = CORD]; + + TestAllTypesProto3 recursive_message = 27; + + // Repeated + repeated int32 repeated_int32 = 31; + repeated int64 repeated_int64 = 32; + repeated uint32 repeated_uint32 = 33; + repeated uint64 repeated_uint64 = 34; + repeated sint32 repeated_sint32 = 35; + repeated sint64 repeated_sint64 = 36; + repeated fixed32 repeated_fixed32 = 37; + repeated fixed64 repeated_fixed64 = 38; + repeated sfixed32 repeated_sfixed32 = 39; + repeated sfixed64 repeated_sfixed64 = 40; + repeated float repeated_float = 41; + repeated double repeated_double = 42; + repeated bool repeated_bool = 43; + repeated string repeated_string = 44; + repeated bytes repeated_bytes = 45; + + repeated NestedMessage repeated_nested_message = 48; + repeated ForeignMessage repeated_foreign_message = 49; + + repeated NestedEnum repeated_nested_enum = 51; + repeated ForeignEnum repeated_foreign_enum = 52; + + repeated string repeated_string_piece = 54 [ctype = STRING_PIECE]; + repeated string repeated_cord = 55 [ctype = CORD]; + + // Packed + repeated int32 packed_int32 = 75 [packed = true]; + repeated int64 packed_int64 = 76 [packed = true]; + repeated uint32 packed_uint32 = 77 [packed = true]; + repeated uint64 packed_uint64 = 78 [packed = true]; + repeated sint32 packed_sint32 = 79 [packed = true]; + repeated sint64 packed_sint64 = 80 [packed = true]; + repeated fixed32 packed_fixed32 = 81 [packed = true]; + repeated fixed64 packed_fixed64 = 82 [packed = true]; + repeated sfixed32 packed_sfixed32 = 83 [packed = true]; + repeated sfixed64 packed_sfixed64 = 84 [packed = true]; + repeated float packed_float = 85 [packed = true]; + repeated double packed_double = 86 [packed = true]; + repeated bool packed_bool = 87 [packed = true]; + repeated NestedEnum packed_nested_enum = 88 [packed = true]; + + // Unpacked + repeated int32 unpacked_int32 = 89 [packed = false]; + repeated int64 unpacked_int64 = 90 [packed = false]; + repeated uint32 unpacked_uint32 = 91 [packed = false]; + repeated uint64 unpacked_uint64 = 92 [packed = false]; + repeated sint32 unpacked_sint32 = 93 [packed = false]; + repeated sint64 unpacked_sint64 = 94 [packed = false]; + repeated fixed32 unpacked_fixed32 = 95 [packed = false]; + repeated fixed64 unpacked_fixed64 = 96 [packed = false]; + repeated sfixed32 unpacked_sfixed32 = 97 [packed = false]; + repeated sfixed64 unpacked_sfixed64 = 98 [packed = false]; + repeated float unpacked_float = 99 [packed = false]; + repeated double unpacked_double = 100 [packed = false]; + repeated bool unpacked_bool = 101 [packed = false]; + repeated NestedEnum unpacked_nested_enum = 102 [packed = false]; + + // Map + map map_int32_int32 = 56; + map map_int64_int64 = 57; + map map_uint32_uint32 = 58; + map map_uint64_uint64 = 59; + map map_sint32_sint32 = 60; + map map_sint64_sint64 = 61; + map map_fixed32_fixed32 = 62; + map map_fixed64_fixed64 = 63; + map map_sfixed32_sfixed32 = 64; + map map_sfixed64_sfixed64 = 65; + map map_int32_float = 66; + map map_int32_double = 67; + map map_bool_bool = 68; + map map_string_string = 69; + map map_string_bytes = 70; + map map_string_nested_message = 71; + map map_string_foreign_message = 72; + map map_string_nested_enum = 73; + map map_string_foreign_enum = 74; + + oneof oneof_field { + uint32 oneof_uint32 = 111; + NestedMessage oneof_nested_message = 112; + string oneof_string = 113; + bytes oneof_bytes = 114; + bool oneof_bool = 115; + uint64 oneof_uint64 = 116; + float oneof_float = 117; + double oneof_double = 118; + NestedEnum oneof_enum = 119; + google.protobuf.NullValue oneof_null_value = 120; + } + + // Well-known types + google.protobuf.BoolValue optional_bool_wrapper = 201; + google.protobuf.Int32Value optional_int32_wrapper = 202; + google.protobuf.Int64Value optional_int64_wrapper = 203; + google.protobuf.UInt32Value optional_uint32_wrapper = 204; + google.protobuf.UInt64Value optional_uint64_wrapper = 205; + google.protobuf.FloatValue optional_float_wrapper = 206; + google.protobuf.DoubleValue optional_double_wrapper = 207; + google.protobuf.StringValue optional_string_wrapper = 208; + google.protobuf.BytesValue optional_bytes_wrapper = 209; + + repeated google.protobuf.BoolValue repeated_bool_wrapper = 211; + repeated google.protobuf.Int32Value repeated_int32_wrapper = 212; + repeated google.protobuf.Int64Value repeated_int64_wrapper = 213; + repeated google.protobuf.UInt32Value repeated_uint32_wrapper = 214; + repeated google.protobuf.UInt64Value repeated_uint64_wrapper = 215; + repeated google.protobuf.FloatValue repeated_float_wrapper = 216; + repeated google.protobuf.DoubleValue repeated_double_wrapper = 217; + repeated google.protobuf.StringValue repeated_string_wrapper = 218; + repeated google.protobuf.BytesValue repeated_bytes_wrapper = 219; + + google.protobuf.Duration optional_duration = 301; + google.protobuf.Timestamp optional_timestamp = 302; + google.protobuf.FieldMask optional_field_mask = 303; + google.protobuf.Struct optional_struct = 304; + google.protobuf.Any optional_any = 305; + google.protobuf.Value optional_value = 306; + google.protobuf.NullValue optional_null_value = 307; + + repeated google.protobuf.Duration repeated_duration = 311; + repeated google.protobuf.Timestamp repeated_timestamp = 312; + repeated google.protobuf.FieldMask repeated_fieldmask = 313; + repeated google.protobuf.Struct repeated_struct = 324; + repeated google.protobuf.Any repeated_any = 315; + repeated google.protobuf.Value repeated_value = 316; + repeated google.protobuf.ListValue repeated_list_value = 317; + + // Test field-name-to-JSON-name convention. + // (protobuf says names can be any valid C/C++ identifier.) + int32 fieldname1 = 401; + int32 field_name2 = 402; + int32 _field_name3 = 403; + int32 field__name4_ = 404; + int32 field0name5 = 405; + int32 field_0_name6 = 406; + int32 fieldName7 = 407; + int32 FieldName8 = 408; + int32 field_Name9 = 409; + int32 Field_Name10 = 410; + int32 FIELD_NAME11 = 411; + int32 FIELD_name12 = 412; + int32 __field_name13 = 413; + int32 __Field_name14 = 414; + int32 field__name15 = 415; + int32 field__Name16 = 416; + int32 field_name17__ = 417; + int32 Field_name18__ = 418; + + // Reserved for testing unknown fields + reserved 501 to 510; +} + +message ForeignMessage { + int32 c = 1; +} + +enum ForeignEnum { + FOREIGN_FOO = 0; + FOREIGN_BAR = 1; + FOREIGN_BAZ = 2; +} + +message NullHypothesisProto3 {} + +message EnumOnlyProto3 { + enum Bool { + kFalse = 0; + kTrue = 1; + } +} diff --git a/conformance/protos/test_messages_proto3_editions.proto b/conformance/protos/test_messages_proto3_editions.proto new file mode 100644 index 0000000..dc2cd21 --- /dev/null +++ b/conformance/protos/test_messages_proto3_editions.proto @@ -0,0 +1,309 @@ +// clang-format off +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd +// +// Test schema for proto3 messages. This test schema is used by: +// +// - benchmarks +// - fuzz tests +// - conformance tests + +edition = "2023"; + +package protobuf_test_messages.editions.proto3; + +import "google/protobuf/any.proto"; +import "google/protobuf/duration.proto"; +import "google/protobuf/field_mask.proto"; +import "google/protobuf/struct.proto"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/wrappers.proto"; + +option features.field_presence = IMPLICIT; +option java_package = "com.google.protobuf_test_messages.editions.proto3"; +option objc_class_prefix = "EditionsProto3"; + +// This is the default, but we specify it here explicitly. +option optimize_for = SPEED; +option cc_enable_arenas = true; + +// This proto includes every type of field in both singular and repeated +// forms. +// +// Also, crucially, all messages and enums in this file are eventually +// submessages of this message. So for example, a fuzz test of TestAllTypes +// could trigger bugs that occur in any message type in this file. We verify +// this stays true in a unit test. +message TestAllTypesProto3 { + message NestedMessage { + int32 a = 1; + TestAllTypesProto3 corecursive = 2; + } + + enum NestedEnum { + FOO = 0; + BAR = 1; + BAZ = 2; + NEG = -1; // Intentionally negative. + } + + enum AliasedEnum { + option allow_alias = true; + + ALIAS_FOO = 0; + ALIAS_BAR = 1; + ALIAS_BAZ = 2; + MOO = 2; + moo = 2; + bAz = 2; + } + + // Singular + // test [kotlin] comment + int32 optional_int32 = 1; + int64 optional_int64 = 2; + uint32 optional_uint32 = 3; + uint64 optional_uint64 = 4; + sint32 optional_sint32 = 5; + sint64 optional_sint64 = 6; + fixed32 optional_fixed32 = 7; + fixed64 optional_fixed64 = 8; + sfixed32 optional_sfixed32 = 9; + sfixed64 optional_sfixed64 = 10; + float optional_float = 11; + double optional_double = 12; + bool optional_bool = 13; + string optional_string = 14; + bytes optional_bytes = 15; + NestedMessage optional_nested_message = 18; + ForeignMessage optional_foreign_message = 19; + NestedEnum optional_nested_enum = 21; + ForeignEnum optional_foreign_enum = 22; + AliasedEnum optional_aliased_enum = 23; + string optional_string_piece = 24 [ + ctype = STRING_PIECE + ]; + + string optional_cord = 25 [ + ctype = CORD + ]; + + TestAllTypesProto3 recursive_message = 27; + + // Repeated + repeated int32 repeated_int32 = 31; + repeated int64 repeated_int64 = 32; + repeated uint32 repeated_uint32 = 33; + repeated uint64 repeated_uint64 = 34; + repeated sint32 repeated_sint32 = 35; + repeated sint64 repeated_sint64 = 36; + repeated fixed32 repeated_fixed32 = 37; + repeated fixed64 repeated_fixed64 = 38; + repeated sfixed32 repeated_sfixed32 = 39; + repeated sfixed64 repeated_sfixed64 = 40; + repeated float repeated_float = 41; + repeated double repeated_double = 42; + repeated bool repeated_bool = 43; + repeated string repeated_string = 44; + repeated bytes repeated_bytes = 45; + repeated NestedMessage repeated_nested_message = 48; + repeated ForeignMessage repeated_foreign_message = 49; + repeated NestedEnum repeated_nested_enum = 51; + repeated ForeignEnum repeated_foreign_enum = 52; + repeated string repeated_string_piece = 54 [ + ctype = STRING_PIECE + ]; + + repeated string repeated_cord = 55 [ + ctype = CORD + ]; + + // Packed + repeated int32 packed_int32 = 75; + repeated int64 packed_int64 = 76; + repeated uint32 packed_uint32 = 77; + repeated uint64 packed_uint64 = 78; + repeated sint32 packed_sint32 = 79; + repeated sint64 packed_sint64 = 80; + repeated fixed32 packed_fixed32 = 81; + repeated fixed64 packed_fixed64 = 82; + repeated sfixed32 packed_sfixed32 = 83; + repeated sfixed64 packed_sfixed64 = 84; + repeated float packed_float = 85; + repeated double packed_double = 86; + repeated bool packed_bool = 87; + repeated NestedEnum packed_nested_enum = 88; + + // Unpacked + repeated int32 unpacked_int32 = 89 [ + features.repeated_field_encoding = EXPANDED + ]; + + repeated int64 unpacked_int64 = 90 [ + features.repeated_field_encoding = EXPANDED + ]; + + repeated uint32 unpacked_uint32 = 91 [ + features.repeated_field_encoding = EXPANDED + ]; + + repeated uint64 unpacked_uint64 = 92 [ + features.repeated_field_encoding = EXPANDED + ]; + + repeated sint32 unpacked_sint32 = 93 [ + features.repeated_field_encoding = EXPANDED + ]; + + repeated sint64 unpacked_sint64 = 94 [ + features.repeated_field_encoding = EXPANDED + ]; + + repeated fixed32 unpacked_fixed32 = 95 [ + features.repeated_field_encoding = EXPANDED + ]; + + repeated fixed64 unpacked_fixed64 = 96 [ + features.repeated_field_encoding = EXPANDED + ]; + + repeated sfixed32 unpacked_sfixed32 = 97 [ + features.repeated_field_encoding = EXPANDED + ]; + + repeated sfixed64 unpacked_sfixed64 = 98 [ + features.repeated_field_encoding = EXPANDED + ]; + + repeated float unpacked_float = 99 [ + features.repeated_field_encoding = EXPANDED + ]; + + repeated double unpacked_double = 100 [ + features.repeated_field_encoding = EXPANDED + ]; + + repeated bool unpacked_bool = 101 [ + features.repeated_field_encoding = EXPANDED + ]; + + repeated NestedEnum unpacked_nested_enum = 102 [ + features.repeated_field_encoding = EXPANDED + ]; + + // Map + map map_int32_int32 = 56; + map map_int64_int64 = 57; + map map_uint32_uint32 = 58; + map map_uint64_uint64 = 59; + map map_sint32_sint32 = 60; + map map_sint64_sint64 = 61; + map map_fixed32_fixed32 = 62; + map map_fixed64_fixed64 = 63; + map map_sfixed32_sfixed32 = 64; + map map_sfixed64_sfixed64 = 65; + map map_int32_float = 66; + map map_int32_double = 67; + map map_bool_bool = 68; + map map_string_string = 69; + map map_string_bytes = 70; + map map_string_nested_message = 71; + map map_string_foreign_message = 72; + map map_string_nested_enum = 73; + map map_string_foreign_enum = 74; + + oneof oneof_field { + uint32 oneof_uint32 = 111; + NestedMessage oneof_nested_message = 112; + string oneof_string = 113; + bytes oneof_bytes = 114; + bool oneof_bool = 115; + uint64 oneof_uint64 = 116; + float oneof_float = 117; + double oneof_double = 118; + NestedEnum oneof_enum = 119; + google.protobuf.NullValue oneof_null_value = 120; + } + + // Well-known types + google.protobuf.BoolValue optional_bool_wrapper = 201; + google.protobuf.Int32Value optional_int32_wrapper = 202; + google.protobuf.Int64Value optional_int64_wrapper = 203; + google.protobuf.UInt32Value optional_uint32_wrapper = 204; + google.protobuf.UInt64Value optional_uint64_wrapper = 205; + google.protobuf.FloatValue optional_float_wrapper = 206; + google.protobuf.DoubleValue optional_double_wrapper = 207; + google.protobuf.StringValue optional_string_wrapper = 208; + google.protobuf.BytesValue optional_bytes_wrapper = 209; + repeated google.protobuf.BoolValue repeated_bool_wrapper = 211; + repeated google.protobuf.Int32Value repeated_int32_wrapper = 212; + repeated google.protobuf.Int64Value repeated_int64_wrapper = 213; + repeated google.protobuf.UInt32Value repeated_uint32_wrapper = 214; + repeated google.protobuf.UInt64Value repeated_uint64_wrapper = 215; + repeated google.protobuf.FloatValue repeated_float_wrapper = 216; + repeated google.protobuf.DoubleValue repeated_double_wrapper = 217; + repeated google.protobuf.StringValue repeated_string_wrapper = 218; + repeated google.protobuf.BytesValue repeated_bytes_wrapper = 219; + google.protobuf.Duration optional_duration = 301; + google.protobuf.Timestamp optional_timestamp = 302; + google.protobuf.FieldMask optional_field_mask = 303; + google.protobuf.Struct optional_struct = 304; + google.protobuf.Any optional_any = 305; + google.protobuf.Value optional_value = 306; + google.protobuf.NullValue optional_null_value = 307; + repeated google.protobuf.Duration repeated_duration = 311; + repeated google.protobuf.Timestamp repeated_timestamp = 312; + repeated google.protobuf.FieldMask repeated_fieldmask = 313; + repeated google.protobuf.Struct repeated_struct = 324; + repeated google.protobuf.Any repeated_any = 315; + repeated google.protobuf.Value repeated_value = 316; + repeated google.protobuf.ListValue repeated_list_value = 317; + + // Test field-name-to-JSON-name convention. + // (protobuf says names can be any valid C/C++ identifier.) + int32 fieldname1 = 401; + int32 field_name2 = 402; + int32 _field_name3 = 403; + int32 field__name4_ = 404; + int32 field0name5 = 405; + int32 field_0_name6 = 406; + int32 fieldName7 = 407; + int32 FieldName8 = 408; + int32 field_Name9 = 409; + int32 Field_Name10 = 410; + int32 FIELD_NAME11 = 411; + int32 FIELD_name12 = 412; + int32 __field_name13 = 413; + int32 __Field_name14 = 414; + int32 field__name15 = 415; + int32 field__Name16 = 416; + int32 field_name17__ = 417; + int32 Field_name18__ = 418; + + // Reserved for testing unknown fields + reserved 501 to 510; +} + +message ForeignMessage { + int32 c = 1; +} + +enum ForeignEnum { + FOREIGN_FOO = 0; + FOREIGN_BAR = 1; + FOREIGN_BAZ = 2; +} + +message NullHypothesisProto3 { +} + +message EnumOnlyProto3 { + enum Bool { + kFalse = 0; + kTrue = 1; + } +} diff --git a/conformance/runner.js b/conformance/runner.js new file mode 100755 index 0000000..77161c3 --- /dev/null +++ b/conformance/runner.js @@ -0,0 +1,175 @@ +#!/usr/bin/env -S node + +const { ConformanceRequest, ConformanceResponse, WireFormat } = require('./protos/conformance_pb.js'); +const { TestAllTypesProto2 } = require('./protos/test_messages_proto2_pb.js'); +const { TestAllTypesProto3 } = require('./protos/test_messages_proto3_pb.js'); +const { TestAllTypesEdition2023 } = require('./protos/test_messages_edition2023_pb.js'); +const { TestAllTypesProto2: TestAllTypesProto2Edition2023 } = require('./protos/test_messages_proto2_editions_pb.js'); +const { TestAllTypesProto3: TestAllTypesProto3Edition2023 } = require('./protos/test_messages_proto3_editions_pb.js'); + +const fs = require('fs'); + +/** + * Creates a `proto.conformance.ConformanceResponse` response according to the + * `proto.conformance.ConformanceRequest` request. + * @param {!ConformanceRequest} request + * @return {!ConformanceResponse} response + */ +function doTest(request) { + const response = new ConformanceResponse(); + + if (request.getPayloadCase() === ConformanceRequest.PayloadCase.JSON_PAYLOAD) { + response.setSkipped('Json is not supported as input format.'); + return response; + } + + if (request.getPayloadCase() === ConformanceRequest.PayloadCase.TEXT_PAYLOAD) { + response.setSkipped('Text format is not supported as input format.'); + return response; + } + + if (request.getPayloadCase() === ConformanceRequest.PayloadCase.PAYLOAD_NOT_SET) { + response.setRuntimeError('Request didn\'t have payload.'); + return response; + } + + if (request.getPayloadCase() !== ConformanceRequest.PayloadCase.PROTOBUF_PAYLOAD) { + throw new Error('Request didn\'t have accepted input format.'); + } + + if (request.getRequestedOutputFormat() === WireFormat.JSON) { + response.setSkipped('Json is not supported as output format.'); + return response; + } + + if (request.getRequestedOutputFormat() === WireFormat.TEXT_FORMAT) { + response.setSkipped('Text format is not supported as output format.'); + return response; + } + + if (request.getRequestedOutputFormat() === WireFormat.TEXT_FORMAT) { + response.setRuntimeError('Unspecified output format'); + return response; + } + + if (request.getRequestedOutputFormat() !== WireFormat.PROTOBUF) { + throw new Error('Request didn\'t have accepted output format.'); + } + + if (request.getMessageType() === 'conformance.FailureSet') { + response.setProtobufPayload(new ArrayBuffer(0)); + } else if ( + request.getMessageType() === + 'protobuf_test_messages.proto2.TestAllTypesProto2') { + try { + const testMessage = + TestAllTypesProto2.deserializeBinary(request.getProtobufPayload()); + response.setProtobufPayload(testMessage.serializeBinary()); + } catch (err) { + response.setParseError(err.toString()); + } + } else if ( + request.getMessageType() === + 'protobuf_test_messages.proto3.TestAllTypesProto3') { + try { + const testMessage = + TestAllTypesProto3.deserializeBinary(request.getProtobufPayload()); + response.setProtobufPayload(testMessage.serializeBinary()); + } catch (err) { + response.setParseError(err.toString()); + } + } else if ( + request.getMessageType() === + 'protobuf_test_messages.editions.TestAllTypesEdition2023') { + try { + const testMessage = + TestAllTypesEdition2023.deserializeBinary(request.getProtobufPayload()); + response.setProtobufPayload(testMessage.serializeBinary()); + } catch (err) { + response.setParseError(err.toString()); + } + } else if ( + request.getMessageType() === + 'protobuf_test_messages.editions.proto2.TestAllTypesProto2') { + try { + const testMessage = + TestAllTypesProto2Edition2023.deserializeBinary(request.getProtobufPayload()); + response.setProtobufPayload(testMessage.serializeBinary()); + } catch (err) { + response.setParseError(err.toString()); + } + } else if ( + request.getMessageType() === + 'protobuf_test_messages.editions.proto3.TestAllTypesProto3') { + try { + const testMessage = + TestAllTypesProto3Edition2023.deserializeBinary(request.getProtobufPayload()); + response.setProtobufPayload(testMessage.serializeBinary()); + } catch (err) { + response.setParseError(err.toString()); + } + } else { + throw new Error( + `Payload message not supported: ${request.getMessageType()}.`); + } + + return response; +} + +/** + * Reads a buffer of N bytes. + * @param {number} bytes Number of bytes to read. + * @return {!Buffer} Buffer which contains data. + */ +function readBuffer(bytes) { + // Linux cannot use process.stdin.fd (which isn't set up as sync) + const buf = new Buffer.alloc(bytes); + const fd = fs.openSync('/dev/stdin', 'r'); + fs.readSync(fd, buf, 0, bytes); + fs.closeSync(fd); + return buf; +} + +/** + * Writes all data in buffer. + * @param {!Buffer} buffer Buffer which contains data. + */ +function writeBuffer(buffer) { + // Under linux, process.stdout.fd is async. Needs to open stdout in a synced + // way for sync write. + const fd = fs.openSync('/dev/stdout', 'w'); + fs.writeSync(fd, buffer, 0, buffer.length); + fs.closeSync(fd); +} + +/** + * Returns true if the test ran successfully, false on legitimate EOF. + * @return {boolean} Whether to continue test. + */ +function runConformanceTest() { + const requestLengthBuf = readBuffer(4); + const requestLength = requestLengthBuf.readInt32LE(0); + if (!requestLength) { + return false; + } + + const serializedRequest = readBuffer(requestLength); + const array = new Uint8Array(serializedRequest); + const request = ConformanceRequest.deserializeBinary(array.buffer); + const response = doTest(request); + + const serializedResponse = response.serializeBinary(); + + const responseLengthBuf = new Buffer.alloc(4); + responseLengthBuf.writeInt32LE(serializedResponse.byteLength, 0); + writeBuffer(responseLengthBuf); + writeBuffer(new Buffer.from(serializedResponse)); + + return true; +} + +while (true) { + if (!runConformanceTest()) { + break; + } +} diff --git a/experimental/runtime/kernel/conformance/conformance_request.js b/experimental/runtime/kernel/conformance/conformance_request.js deleted file mode 100644 index 2d4f106..0000000 --- a/experimental/runtime/kernel/conformance/conformance_request.js +++ /dev/null @@ -1,91 +0,0 @@ -/** - * @fileoverview Handwritten code of ConformanceRequest. - */ -goog.module('proto.conformance.ConformanceRequest'); - -const Kernel = goog.require('protobuf.runtime.Kernel'); -const WireFormat = goog.require('proto.conformance.WireFormat'); - -/** - * Handwritten code of conformance.ConformanceRequest. - * This is used to send request from the conformance test runner to the testee. - * Check //third_party/protobuf/testing/protobuf/conformance/conformance.proto - * for more details. - * @final - */ -class ConformanceRequest { - /** - * @param {!ArrayBuffer} bytes - * @private - */ - constructor(bytes) { - /** @private @const {!Kernel} */ - this.accessor_ = Kernel.fromArrayBuffer(bytes); - } - - /** - * Create a request instance with the given bytes data. - * @param {!ArrayBuffer} bytes - * @return {!ConformanceRequest} - */ - static deserialize(bytes) { - return new ConformanceRequest(bytes); - } - - /** - * Gets the protobuf_payload. - * @return {!ArrayBuffer} - */ - getProtobufPayload() { - return this.accessor_.getBytesWithDefault(1).toArrayBuffer(); - } - - /** - * Gets the requested_output_format. - * @return {!WireFormat} - */ - getRequestedOutputFormat() { - return /** @type {!WireFormat} */ (this.accessor_.getInt32WithDefault(3)); - } - - /** - * Gets the message_type. - * @return {string} - */ - getMessageType() { - return this.accessor_.getStringWithDefault(4); - } - - /** - * Gets the oneof case for payload field. - * This implementation assumes only one field in a oneof group is set. - * @return {!ConformanceRequest.PayloadCase} - */ - getPayloadCase() { - if (this.accessor_.hasFieldNumber(1)) { - return /** @type {!ConformanceRequest.PayloadCase} */ ( - ConformanceRequest.PayloadCase.PROTOBUF_PAYLOAD); - } else if (this.accessor_.hasFieldNumber(2)) { - return /** @type {!ConformanceRequest.PayloadCase} */ ( - ConformanceRequest.PayloadCase.JSON_PAYLOAD); - } else if (this.accessor_.hasFieldNumber(8)) { - return /** @type {!ConformanceRequest.PayloadCase} */ ( - ConformanceRequest.PayloadCase.TEXT_PAYLOAD); - } else { - return /** @type {!ConformanceRequest.PayloadCase} */ ( - ConformanceRequest.PayloadCase.PAYLOAD_NOT_SET); - } - } -} - -/** - * @enum {number} - */ -ConformanceRequest.PayloadCase = { - PAYLOAD_NOT_SET: 0, - PROTOBUF_PAYLOAD: 1, - JSON_PAYLOAD: 2, - TEXT_PAYLOAD: 8, -}; - -exports = ConformanceRequest; diff --git a/experimental/runtime/kernel/conformance/conformance_response.js b/experimental/runtime/kernel/conformance/conformance_response.js deleted file mode 100644 index 482f31b..0000000 --- a/experimental/runtime/kernel/conformance/conformance_response.js +++ /dev/null @@ -1,76 +0,0 @@ -/** - * @fileoverview Handwritten code of ConformanceResponse. - */ -goog.module('proto.conformance.ConformanceResponse'); - -const ByteString = goog.require('protobuf.ByteString'); -const Kernel = goog.require('protobuf.runtime.Kernel'); - -/** - * Handwritten code of conformance.ConformanceResponse. - * This is used to send response from the conformance testee to the test runner. - * Check //third_party/protobuf/testing/protobuf/conformance/conformance.proto - * for more details. - * @final - */ -class ConformanceResponse { - /** - * @param {!ArrayBuffer} bytes - * @private - */ - constructor(bytes) { - /** @private @const {!Kernel} */ - this.accessor_ = Kernel.fromArrayBuffer(bytes); - } - - /** - * Create an empty response instance. - * @return {!ConformanceResponse} - */ - static createEmpty() { - return new ConformanceResponse(new ArrayBuffer(0)); - } - - /** - * Sets parse_error field. - * @param {string} value - */ - setParseError(value) { - this.accessor_.setString(1, value); - } - - /** - * Sets runtime_error field. - * @param {string} value - */ - setRuntimeError(value) { - this.accessor_.setString(2, value); - } - - /** - * Sets protobuf_payload field. - * @param {!ArrayBuffer} value - */ - setProtobufPayload(value) { - const bytesString = ByteString.fromArrayBuffer(value); - this.accessor_.setBytes(3, bytesString); - } - - /** - * Sets skipped field. - * @param {string} value - */ - setSkipped(value) { - this.accessor_.setString(5, value); - } - - /** - * Serializes into binary data. - * @return {!ArrayBuffer} - */ - serialize() { - return this.accessor_.serialize(); - } -} - -exports = ConformanceResponse; diff --git a/experimental/runtime/kernel/conformance/conformance_testee.js b/experimental/runtime/kernel/conformance/conformance_testee.js deleted file mode 100755 index 2945228..0000000 --- a/experimental/runtime/kernel/conformance/conformance_testee.js +++ /dev/null @@ -1,103 +0,0 @@ -goog.module('javascript.protobuf.conformance'); - -const ConformanceRequest = goog.require('proto.conformance.ConformanceRequest'); -const ConformanceResponse = goog.require('proto.conformance.ConformanceResponse'); -const TestAllTypesProto2 = goog.require('proto.conformance.TestAllTypesProto2'); -const TestAllTypesProto3 = goog.require('proto.conformance.TestAllTypesProto3'); -const WireFormat = goog.require('proto.conformance.WireFormat'); -const base64 = goog.require('goog.crypt.base64'); - -/** - * Creates a `proto.conformance.ConformanceResponse` response according to the - * `proto.conformance.ConformanceRequest` request. - * @param {!ConformanceRequest} request - * @return {!ConformanceResponse} response - */ -function doTest(request) { - const response = ConformanceResponse.createEmpty(); - - if(request.getPayloadCase() === ConformanceRequest.PayloadCase.JSON_PAYLOAD) { - response.setSkipped('Json is not supported as input format.'); - return response; - } - - if(request.getPayloadCase() === ConformanceRequest.PayloadCase.TEXT_PAYLOAD) { - response.setSkipped('Text format is not supported as input format.'); - return response; - } - - if(request.getPayloadCase() === ConformanceRequest.PayloadCase.PAYLOAD_NOT_SET) { - response.setRuntimeError('Request didn\'t have payload.'); - return response; - } - - if(request.getPayloadCase() !== ConformanceRequest.PayloadCase.PROTOBUF_PAYLOAD) { - throw new Error('Request didn\'t have accepted input format.'); - } - - if (request.getRequestedOutputFormat() === WireFormat.JSON) { - response.setSkipped('Json is not supported as output format.'); - return response; - } - - if (request.getRequestedOutputFormat() === WireFormat.TEXT_FORMAT) { - response.setSkipped('Text format is not supported as output format.'); - return response; - } - - if (request.getRequestedOutputFormat() === WireFormat.TEXT_FORMAT) { - response.setRuntimeError('Unspecified output format'); - return response; - } - - if (request.getRequestedOutputFormat() !== WireFormat.PROTOBUF) { - throw new Error('Request didn\'t have accepted output format.'); - } - - if (request.getMessageType() === 'conformance.FailureSet') { - response.setProtobufPayload(new ArrayBuffer(0)); - } else if ( - request.getMessageType() === - 'protobuf_test_messages.proto2.TestAllTypesProto2') { - try { - const testMessage = - TestAllTypesProto2.deserialize(request.getProtobufPayload()); - response.setProtobufPayload(testMessage.serialize()); - } catch (err) { - response.setParseError(err.toString()); - } - } else if ( - request.getMessageType() === - 'protobuf_test_messages.proto3.TestAllTypesProto3') { - try { - const testMessage = - TestAllTypesProto3.deserialize(request.getProtobufPayload()); - response.setProtobufPayload(testMessage.serialize()); - } catch (err) { - response.setParseError(err.toString()); - } - } else { - throw new Error( - `Payload message not supported: ${request.getMessageType()}.`); - } - - return response; -} - -/** - * Same as doTest, but both request and response are in base64. - * @param {string} base64Request - * @return {string} response - */ -function runConformanceTest(base64Request) { - const request = - ConformanceRequest.deserialize( - base64.decodeStringToUint8Array(base64Request).buffer); - const response = doTest(request); - return base64.encodeByteArray(new Uint8Array(response.serialize())); -} - -// Needed for node test -exports.doTest = doTest; -// Needed for browser test -goog.exportSymbol('runConformanceTest', runConformanceTest); diff --git a/experimental/runtime/kernel/conformance/conformance_testee_runner_node.js b/experimental/runtime/kernel/conformance/conformance_testee_runner_node.js deleted file mode 100755 index c12f363..0000000 --- a/experimental/runtime/kernel/conformance/conformance_testee_runner_node.js +++ /dev/null @@ -1,62 +0,0 @@ -const ConformanceRequest = goog.require('proto.conformance.ConformanceRequest'); -const {doTest} = goog.require('javascript.protobuf.conformance'); -const fs = require('fs'); - - -/** - * Reads a buffer of N bytes. - * @param {number} bytes Number of bytes to read. - * @return {!Buffer} Buffer which contains data. - */ -function readBuffer(bytes) { - // Linux cannot use process.stdin.fd (which isn't set up as sync) - const buf = new Buffer.alloc(bytes); - const fd = fs.openSync('/dev/stdin', 'r'); - fs.readSync(fd, buf, 0, bytes); - fs.closeSync(fd); - return buf; -} - -/** - * Writes all data in buffer. - * @param {!Buffer} buffer Buffer which contains data. - */ -function writeBuffer(buffer) { - // Under linux, process.stdout.fd is async. Needs to open stdout in a synced - // way for sync write. - const fd = fs.openSync('/dev/stdout', 'w'); - fs.writeSync(fd, buffer, 0, buffer.length); - fs.closeSync(fd); -} - -/** - * Returns true if the test ran successfully, false on legitimate EOF. - * @return {boolean} Whether to continue test. - */ -function runConformanceTest() { - const requestLengthBuf = readBuffer(4); - const requestLength = requestLengthBuf.readInt32LE(0); - if (!requestLength) { - return false; - } - - const serializedRequest = readBuffer(requestLength); - const array = new Uint8Array(serializedRequest); - const request = ConformanceRequest.deserialize(array.buffer); - const response = doTest(request); - - const serializedResponse = response.serialize(); - - const responseLengthBuf = new Buffer.alloc(4); - responseLengthBuf.writeInt32LE(serializedResponse.byteLength, 0); - writeBuffer(responseLengthBuf); - writeBuffer(new Buffer.from(serializedResponse)); - - return true; -} - -while (true) { - if (!runConformanceTest()) { - break; - } -} diff --git a/experimental/runtime/kernel/conformance/test_all_types_proto2.js b/experimental/runtime/kernel/conformance/test_all_types_proto2.js deleted file mode 100644 index 3be1bee..0000000 --- a/experimental/runtime/kernel/conformance/test_all_types_proto2.js +++ /dev/null @@ -1,309 +0,0 @@ -/** - * @fileoverview Handwritten code of TestAllTypesProto2. - */ -goog.module('proto.conformance.TestAllTypesProto2'); - -const InternalMessage = goog.require('protobuf.binary.InternalMessage'); -const Kernel = goog.require('protobuf.runtime.Kernel'); - -/** - * Handwritten code of conformance.TestAllTypesProto2. - * Check google/protobuf/test_messages_proto3.proto for more details. - * @implements {InternalMessage} - * @final - */ -class TestAllTypesProto2 { - /** - * @param {!Kernel=} accessor - * @private - */ - constructor(accessor = Kernel.createEmpty()) { - /** @private @const {!Kernel} */ - this.accessor_ = accessor; - } - - /** - * @override - * @package - * @return {!Kernel} - */ - internalGetKernel() { - return this.accessor_; - } - - /** - * Create a request instance with the given bytes data. - * If we directly use the accessor created by the binary decoding, the - * Kernel instance will only copy the same data over for encoding. By - * explicitly fetching data from the previous accessor and setting all fields - * into a new accessor, we will actually test encoding/decoding for the binary - * format. - * @param {!ArrayBuffer} bytes - * @return {!TestAllTypesProto2} - */ - static deserialize(bytes) { - const msg = new TestAllTypesProto2(); - const requestAccessor = Kernel.fromArrayBuffer(bytes); - - if (requestAccessor.hasFieldNumber(1)) { - const value = requestAccessor.getInt32WithDefault(1); - msg.accessor_.setInt32(1, value); - } - - if (requestAccessor.hasFieldNumber(2)) { - const value = requestAccessor.getInt64WithDefault(2); - msg.accessor_.setInt64(2, value); - } - - if (requestAccessor.hasFieldNumber(3)) { - const value = requestAccessor.getUint32WithDefault(3); - msg.accessor_.setUint32(3, value); - } - - if (requestAccessor.hasFieldNumber(4)) { - const value = requestAccessor.getUint64WithDefault(4); - msg.accessor_.setUint64(4, value); - } - - if (requestAccessor.hasFieldNumber(5)) { - const value = requestAccessor.getSint32WithDefault(5); - msg.accessor_.setSint32(5, value); - } - - if (requestAccessor.hasFieldNumber(6)) { - const value = requestAccessor.getSint64WithDefault(6); - msg.accessor_.setSint64(6, value); - } - - if (requestAccessor.hasFieldNumber(7)) { - const value = requestAccessor.getFixed32WithDefault(7); - msg.accessor_.setFixed32(7, value); - } - - if (requestAccessor.hasFieldNumber(8)) { - const value = requestAccessor.getFixed64WithDefault(8); - msg.accessor_.setFixed64(8, value); - } - - if (requestAccessor.hasFieldNumber(9)) { - const value = requestAccessor.getSfixed32WithDefault(9); - msg.accessor_.setSfixed32(9, value); - } - - if (requestAccessor.hasFieldNumber(10)) { - const value = requestAccessor.getSfixed64WithDefault(10); - msg.accessor_.setSfixed64(10, value); - } - - if (requestAccessor.hasFieldNumber(11)) { - const value = requestAccessor.getFloatWithDefault(11); - msg.accessor_.setFloat(11, value); - } - - if (requestAccessor.hasFieldNumber(12)) { - const value = requestAccessor.getDoubleWithDefault(12); - msg.accessor_.setDouble(12, value); - } - - if (requestAccessor.hasFieldNumber(13)) { - const value = requestAccessor.getBoolWithDefault(13); - msg.accessor_.setBool(13, value); - } - - if (requestAccessor.hasFieldNumber(14)) { - const value = requestAccessor.getStringWithDefault(14); - msg.accessor_.setString(14, value); - } - - if (requestAccessor.hasFieldNumber(15)) { - const value = requestAccessor.getBytesWithDefault(15); - msg.accessor_.setBytes(15, value); - } - - if (requestAccessor.hasFieldNumber(18)) { - const value = requestAccessor.getMessage( - 18, (accessor) => new TestAllTypesProto2(accessor)); - msg.accessor_.setMessage(18, value); - } - - if (requestAccessor.hasFieldNumber(21)) { - // Unknown enum is not checked here, because even if an enum is unknown, - // it should be kept during encoding. For the purpose of wire format test, - // we can simplify the implementation by treating it as an int32 field, - // which has the same semantic except for the unknown value checking. - const value = requestAccessor.getInt32WithDefault(21); - msg.accessor_.setInt32(21, value); - } - - if (requestAccessor.hasFieldNumber(31)) { - const value = requestAccessor.getRepeatedInt32Iterable(31); - msg.accessor_.setUnpackedInt32Iterable(31, value); - } - - if (requestAccessor.hasFieldNumber(32)) { - const value = requestAccessor.getRepeatedInt64Iterable(32); - msg.accessor_.setUnpackedInt64Iterable(32, value); - } - - if (requestAccessor.hasFieldNumber(33)) { - const value = requestAccessor.getRepeatedUint32Iterable(33); - msg.accessor_.setUnpackedUint32Iterable(33, value); - } - - if (requestAccessor.hasFieldNumber(34)) { - const value = requestAccessor.getRepeatedUint64Iterable(34); - msg.accessor_.setUnpackedUint64Iterable(34, value); - } - - if (requestAccessor.hasFieldNumber(35)) { - const value = requestAccessor.getRepeatedSint32Iterable(35); - msg.accessor_.setUnpackedSint32Iterable(35, value); - } - - if (requestAccessor.hasFieldNumber(36)) { - const value = requestAccessor.getRepeatedSint64Iterable(36); - msg.accessor_.setUnpackedSint64Iterable(36, value); - } - - if (requestAccessor.hasFieldNumber(37)) { - const value = requestAccessor.getRepeatedFixed32Iterable(37); - msg.accessor_.setUnpackedFixed32Iterable(37, value); - } - - if (requestAccessor.hasFieldNumber(38)) { - const value = requestAccessor.getRepeatedFixed64Iterable(38); - msg.accessor_.setUnpackedFixed64Iterable(38, value); - } - - if (requestAccessor.hasFieldNumber(39)) { - const value = requestAccessor.getRepeatedSfixed32Iterable(39); - msg.accessor_.setUnpackedSfixed32Iterable(39, value); - } - - if (requestAccessor.hasFieldNumber(40)) { - const value = requestAccessor.getRepeatedSfixed64Iterable(40); - msg.accessor_.setUnpackedSfixed64Iterable(40, value); - } - - if (requestAccessor.hasFieldNumber(41)) { - const value = requestAccessor.getRepeatedFloatIterable(41); - msg.accessor_.setUnpackedFloatIterable(41, value); - } - - if (requestAccessor.hasFieldNumber(42)) { - const value = requestAccessor.getRepeatedDoubleIterable(42); - msg.accessor_.setUnpackedDoubleIterable(42, value); - } - - if (requestAccessor.hasFieldNumber(43)) { - const value = requestAccessor.getRepeatedBoolIterable(43); - msg.accessor_.setUnpackedBoolIterable(43, value); - } - - if (requestAccessor.hasFieldNumber(44)) { - const value = requestAccessor.getRepeatedStringIterable(44); - msg.accessor_.setRepeatedStringIterable(44, value); - } - - if (requestAccessor.hasFieldNumber(45)) { - const value = requestAccessor.getRepeatedBytesIterable(45); - msg.accessor_.setRepeatedBytesIterable(45, value); - } - - if (requestAccessor.hasFieldNumber(48)) { - const value = requestAccessor.getRepeatedMessageIterable( - 48, (accessor) => new TestAllTypesProto2(accessor)); - msg.accessor_.setRepeatedMessageIterable(48, value); - } - - if (requestAccessor.hasFieldNumber(51)) { - // Unknown enum is not checked here, because even if an enum is unknown, - // it should be kept during encoding. For the purpose of wire format test, - // we can simplify the implementation by treating it as an int32 field, - // which has the same semantic except for the unknown value checking. - const value = requestAccessor.getRepeatedInt32Iterable(51); - msg.accessor_.setUnpackedInt32Iterable(51, value); - } - - if (requestAccessor.hasFieldNumber(75)) { - const value = requestAccessor.getRepeatedInt32Iterable(75); - msg.accessor_.setPackedInt32Iterable(75, value); - } - - if (requestAccessor.hasFieldNumber(76)) { - const value = requestAccessor.getRepeatedInt64Iterable(76); - msg.accessor_.setPackedInt64Iterable(76, value); - } - - if (requestAccessor.hasFieldNumber(77)) { - const value = requestAccessor.getRepeatedUint32Iterable(77); - msg.accessor_.setPackedUint32Iterable(77, value); - } - - if (requestAccessor.hasFieldNumber(78)) { - const value = requestAccessor.getRepeatedUint64Iterable(78); - msg.accessor_.setPackedUint64Iterable(78, value); - } - - if (requestAccessor.hasFieldNumber(79)) { - const value = requestAccessor.getRepeatedSint32Iterable(79); - msg.accessor_.setPackedSint32Iterable(79, value); - } - - if (requestAccessor.hasFieldNumber(80)) { - const value = requestAccessor.getRepeatedSint64Iterable(80); - msg.accessor_.setPackedSint64Iterable(80, value); - } - - if (requestAccessor.hasFieldNumber(81)) { - const value = requestAccessor.getRepeatedFixed32Iterable(81); - msg.accessor_.setPackedFixed32Iterable(81, value); - } - - if (requestAccessor.hasFieldNumber(82)) { - const value = requestAccessor.getRepeatedFixed64Iterable(82); - msg.accessor_.setPackedFixed64Iterable(82, value); - } - - if (requestAccessor.hasFieldNumber(83)) { - const value = requestAccessor.getRepeatedSfixed32Iterable(83); - msg.accessor_.setPackedSfixed32Iterable(83, value); - } - - if (requestAccessor.hasFieldNumber(84)) { - const value = requestAccessor.getRepeatedSfixed64Iterable(84); - msg.accessor_.setPackedSfixed64Iterable(84, value); - } - - if (requestAccessor.hasFieldNumber(85)) { - const value = requestAccessor.getRepeatedFloatIterable(85); - msg.accessor_.setPackedFloatIterable(85, value); - } - - if (requestAccessor.hasFieldNumber(86)) { - const value = requestAccessor.getRepeatedDoubleIterable(86); - msg.accessor_.setPackedDoubleIterable(86, value); - } - - if (requestAccessor.hasFieldNumber(87)) { - const value = requestAccessor.getRepeatedBoolIterable(87); - msg.accessor_.setPackedBoolIterable(87, value); - } - - if (requestAccessor.hasFieldNumber(88)) { - const value = requestAccessor.getRepeatedInt32Iterable(88); - msg.accessor_.setPackedInt32Iterable(88, value); - } - return msg; - } - - /** - * Serializes into binary data. - * @return {!ArrayBuffer} - */ - serialize() { - return this.accessor_.serialize(); - } -} - -exports = TestAllTypesProto2; diff --git a/experimental/runtime/kernel/conformance/test_all_types_proto3.js b/experimental/runtime/kernel/conformance/test_all_types_proto3.js deleted file mode 100644 index c68d370..0000000 --- a/experimental/runtime/kernel/conformance/test_all_types_proto3.js +++ /dev/null @@ -1,310 +0,0 @@ -/** - * @fileoverview Handwritten code of TestAllTypesProto3. - */ -goog.module('proto.conformance.TestAllTypesProto3'); - -const InternalMessage = goog.require('protobuf.binary.InternalMessage'); -const Kernel = goog.require('protobuf.runtime.Kernel'); - -/** - * Handwritten code of conformance.TestAllTypesProto3. - * Check google/protobuf/test_messages_proto3.proto for more details. - * @implements {InternalMessage} - * @final - */ -class TestAllTypesProto3 { - /** - * @param {!Kernel=} accessor - * @private - */ - constructor(accessor = Kernel.createEmpty()) { - /** @private @const {!Kernel} */ - this.accessor_ = accessor; - } - - /** - * @override - * @package - * @return {!Kernel} - */ - internalGetKernel() { - return this.accessor_; - } - - /** - * Create a request instance with the given bytes data. - * If we directly use the accessor created by the binary decoding, the - * Kernel instance will only copy the same data over for encoding. By - * explicitly fetching data from the previous accessor and setting all fields - * into a new accessor, we will actually test encoding/decoding for the binary - * format. - * @param {!ArrayBuffer} bytes - * @return {!TestAllTypesProto3} - */ - static deserialize(bytes) { - const msg = new TestAllTypesProto3(); - const requestAccessor = Kernel.fromArrayBuffer(bytes); - - if (requestAccessor.hasFieldNumber(1)) { - const value = requestAccessor.getInt32WithDefault(1); - msg.accessor_.setInt32(1, value); - } - - if (requestAccessor.hasFieldNumber(2)) { - const value = requestAccessor.getInt64WithDefault(2); - msg.accessor_.setInt64(2, value); - } - - if (requestAccessor.hasFieldNumber(3)) { - const value = requestAccessor.getUint32WithDefault(3); - msg.accessor_.setUint32(3, value); - } - - if (requestAccessor.hasFieldNumber(4)) { - const value = requestAccessor.getUint64WithDefault(4); - msg.accessor_.setUint64(4, value); - } - - if (requestAccessor.hasFieldNumber(5)) { - const value = requestAccessor.getSint32WithDefault(5); - msg.accessor_.setSint32(5, value); - } - - if (requestAccessor.hasFieldNumber(6)) { - const value = requestAccessor.getSint64WithDefault(6); - msg.accessor_.setSint64(6, value); - } - - if (requestAccessor.hasFieldNumber(7)) { - const value = requestAccessor.getFixed32WithDefault(7); - msg.accessor_.setFixed32(7, value); - } - - if (requestAccessor.hasFieldNumber(8)) { - const value = requestAccessor.getFixed64WithDefault(8); - msg.accessor_.setFixed64(8, value); - } - - if (requestAccessor.hasFieldNumber(9)) { - const value = requestAccessor.getSfixed32WithDefault(9); - msg.accessor_.setSfixed32(9, value); - } - - if (requestAccessor.hasFieldNumber(10)) { - const value = requestAccessor.getSfixed64WithDefault(10); - msg.accessor_.setSfixed64(10, value); - } - - if (requestAccessor.hasFieldNumber(11)) { - const value = requestAccessor.getFloatWithDefault(11); - msg.accessor_.setFloat(11, value); - } - - if (requestAccessor.hasFieldNumber(12)) { - const value = requestAccessor.getDoubleWithDefault(12); - msg.accessor_.setDouble(12, value); - } - - if (requestAccessor.hasFieldNumber(13)) { - const value = requestAccessor.getBoolWithDefault(13); - msg.accessor_.setBool(13, value); - } - - if (requestAccessor.hasFieldNumber(14)) { - const value = requestAccessor.getStringWithDefault(14); - msg.accessor_.setString(14, value); - } - - if (requestAccessor.hasFieldNumber(15)) { - const value = requestAccessor.getBytesWithDefault(15); - msg.accessor_.setBytes(15, value); - } - - if (requestAccessor.hasFieldNumber(18)) { - const value = requestAccessor.getMessage( - 18, (accessor) => new TestAllTypesProto3(accessor)); - msg.accessor_.setMessage(18, value); - } - - if (requestAccessor.hasFieldNumber(21)) { - // Unknown enum is not checked here, because even if an enum is unknown, - // it should be kept during encoding. For the purpose of wire format test, - // we can simplify the implementation by treating it as an int32 field, - // which has the same semantic except for the unknown value checking. - const value = requestAccessor.getInt32WithDefault(21); - msg.accessor_.setInt32(21, value); - } - - if (requestAccessor.hasFieldNumber(31)) { - const value = requestAccessor.getRepeatedInt32Iterable(31); - msg.accessor_.setPackedInt32Iterable(31, value); - } - - if (requestAccessor.hasFieldNumber(32)) { - const value = requestAccessor.getRepeatedInt64Iterable(32); - msg.accessor_.setPackedInt64Iterable(32, value); - } - - if (requestAccessor.hasFieldNumber(33)) { - const value = requestAccessor.getRepeatedUint32Iterable(33); - msg.accessor_.setPackedUint32Iterable(33, value); - } - - if (requestAccessor.hasFieldNumber(34)) { - const value = requestAccessor.getRepeatedUint64Iterable(34); - msg.accessor_.setPackedUint64Iterable(34, value); - } - - if (requestAccessor.hasFieldNumber(35)) { - const value = requestAccessor.getRepeatedSint32Iterable(35); - msg.accessor_.setPackedSint32Iterable(35, value); - } - - if (requestAccessor.hasFieldNumber(36)) { - const value = requestAccessor.getRepeatedSint64Iterable(36); - msg.accessor_.setPackedSint64Iterable(36, value); - } - - if (requestAccessor.hasFieldNumber(37)) { - const value = requestAccessor.getRepeatedFixed32Iterable(37); - msg.accessor_.setPackedFixed32Iterable(37, value); - } - - if (requestAccessor.hasFieldNumber(38)) { - const value = requestAccessor.getRepeatedFixed64Iterable(38); - msg.accessor_.setPackedFixed64Iterable(38, value); - } - - if (requestAccessor.hasFieldNumber(39)) { - const value = requestAccessor.getRepeatedSfixed32Iterable(39); - msg.accessor_.setPackedSfixed32Iterable(39, value); - } - - if (requestAccessor.hasFieldNumber(40)) { - const value = requestAccessor.getRepeatedSfixed64Iterable(40); - msg.accessor_.setPackedSfixed64Iterable(40, value); - } - - if (requestAccessor.hasFieldNumber(41)) { - const value = requestAccessor.getRepeatedFloatIterable(41); - msg.accessor_.setPackedFloatIterable(41, value); - } - - if (requestAccessor.hasFieldNumber(42)) { - const value = requestAccessor.getRepeatedDoubleIterable(42); - msg.accessor_.setPackedDoubleIterable(42, value); - } - - if (requestAccessor.hasFieldNumber(43)) { - const value = requestAccessor.getRepeatedBoolIterable(43); - msg.accessor_.setPackedBoolIterable(43, value); - } - - if (requestAccessor.hasFieldNumber(44)) { - const value = requestAccessor.getRepeatedStringIterable(44); - msg.accessor_.setRepeatedStringIterable(44, value); - } - - if (requestAccessor.hasFieldNumber(45)) { - const value = requestAccessor.getRepeatedBytesIterable(45); - msg.accessor_.setRepeatedBytesIterable(45, value); - } - - if (requestAccessor.hasFieldNumber(48)) { - const value = requestAccessor.getRepeatedMessageIterable( - 48, (accessor) => new TestAllTypesProto3(accessor)); - msg.accessor_.setRepeatedMessageIterable(48, value); - } - - if (requestAccessor.hasFieldNumber(51)) { - // Unknown enum is not checked here, because even if an enum is unknown, - // it should be kept during encoding. For the purpose of wire format test, - // we can simplify the implementation by treating it as an int32 field, - // which has the same semantic except for the unknown value checking. - const value = requestAccessor.getRepeatedInt32Iterable(51); - msg.accessor_.setPackedInt32Iterable(51, value); - } - - if (requestAccessor.hasFieldNumber(89)) { - const value = requestAccessor.getRepeatedInt32Iterable(89); - msg.accessor_.setUnpackedInt32Iterable(89, value); - } - - if (requestAccessor.hasFieldNumber(90)) { - const value = requestAccessor.getRepeatedInt64Iterable(90); - msg.accessor_.setUnpackedInt64Iterable(90, value); - } - - if (requestAccessor.hasFieldNumber(91)) { - const value = requestAccessor.getRepeatedUint32Iterable(91); - msg.accessor_.setUnpackedUint32Iterable(91, value); - } - - if (requestAccessor.hasFieldNumber(92)) { - const value = requestAccessor.getRepeatedUint64Iterable(92); - msg.accessor_.setUnpackedUint64Iterable(92, value); - } - - if (requestAccessor.hasFieldNumber(93)) { - const value = requestAccessor.getRepeatedSint32Iterable(93); - msg.accessor_.setUnpackedSint32Iterable(93, value); - } - - if (requestAccessor.hasFieldNumber(94)) { - const value = requestAccessor.getRepeatedSint64Iterable(94); - msg.accessor_.setUnpackedSint64Iterable(94, value); - } - - if (requestAccessor.hasFieldNumber(95)) { - const value = requestAccessor.getRepeatedFixed32Iterable(95); - msg.accessor_.setUnpackedFixed32Iterable(95, value); - } - - if (requestAccessor.hasFieldNumber(96)) { - const value = requestAccessor.getRepeatedFixed64Iterable(96); - msg.accessor_.setUnpackedFixed64Iterable(96, value); - } - - if (requestAccessor.hasFieldNumber(97)) { - const value = requestAccessor.getRepeatedSfixed32Iterable(97); - msg.accessor_.setUnpackedSfixed32Iterable(97, value); - } - - if (requestAccessor.hasFieldNumber(98)) { - const value = requestAccessor.getRepeatedSfixed64Iterable(98); - msg.accessor_.setUnpackedSfixed64Iterable(98, value); - } - - if (requestAccessor.hasFieldNumber(99)) { - const value = requestAccessor.getRepeatedFloatIterable(99); - msg.accessor_.setUnpackedFloatIterable(99, value); - } - - if (requestAccessor.hasFieldNumber(100)) { - const value = requestAccessor.getRepeatedDoubleIterable(100); - msg.accessor_.setUnpackedDoubleIterable(100, value); - } - - if (requestAccessor.hasFieldNumber(101)) { - const value = requestAccessor.getRepeatedBoolIterable(101); - msg.accessor_.setUnpackedBoolIterable(101, value); - } - - if (requestAccessor.hasFieldNumber(102)) { - const value = requestAccessor.getRepeatedInt32Iterable(102); - msg.accessor_.setUnpackedInt32Iterable(102, value); - } - - return msg; - } - - /** - * Serializes into binary data. - * @return {!ArrayBuffer} - */ - serialize() { - return this.accessor_.serialize(); - } -} - -exports = TestAllTypesProto3; diff --git a/experimental/runtime/kernel/conformance/wire_format.js b/experimental/runtime/kernel/conformance/wire_format.js deleted file mode 100644 index 636e827..0000000 --- a/experimental/runtime/kernel/conformance/wire_format.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * @fileoverview Handwritten code of WireFormat. - */ -goog.module('proto.conformance.WireFormat'); - -/** - * @enum {number} - */ -const WireFormat = { - UNSPECIFIED: 0, - PROTOBUF: 1, - JSON: 2, - TEXT_FORMAT: 4, -}; - -exports = WireFormat; diff --git a/experimental/runtime/kernel/kernel_repeated_test.js b/experimental/runtime/kernel/kernel_repeated_test.js index 6a798b6..059f5fc 100644 --- a/experimental/runtime/kernel/kernel_repeated_test.js +++ b/experimental/runtime/kernel/kernel_repeated_test.js @@ -1,7 +1,7 @@ /** * @fileoverview Tests for repeated methods in kernel.js. */ -goog.module('protobuf.runtime.KernelTest'); +goog.module('protobuf.runtime.KernelRepeatedTest'); goog.setTestOnly(); diff --git a/generator/js_generator.cc b/generator/js_generator.cc index a881c3d..0098f29 100644 --- a/generator/js_generator.cc +++ b/generator/js_generator.cc @@ -1087,14 +1087,17 @@ std::string JSBinaryMethodType(const FieldDescriptor* field, bool is_writer) { std::string JSBinaryReadWriteMethodName(const FieldDescriptor* field, bool is_writer) { std::string name = JSBinaryMethodType(field, is_writer); - if (field->is_packed()) { + if (is_writer && field->is_packed()) { name = "Packed" + name; + } else if (!is_writer && field->is_packable()) { + name = "Packable" + name + "Into"; } else if (is_writer && field->is_repeated()) { name = "Repeated" + name; } return name; } + std::string JSBinaryReaderMethodName(const GeneratorOptions& options, const FieldDescriptor* field) { return "jspb.BinaryReader.prototype.read" + @@ -1857,6 +1860,7 @@ void Generator::GenerateRequiresImpl(const GeneratorOptions& options, bool require_map) const { if (require_jspb) { required->insert("jspb.Message"); + required->insert("jspb.internal.public_for_gencode"); required->insert("jspb.BinaryReader"); required->insert("jspb.BinaryWriter"); } @@ -3129,13 +3133,11 @@ void Generator::GenerateClassDeserializeBinaryField( : ""); } else if (field->is_packable()) { printer->Print( - " var values = /** @type {$fieldtype$} */ " - "(reader.isDelimited() " - "? reader.read$reader$() : [reader.read$reader$()]);\n", - "fieldtype", - JSFieldTypeAnnotation(options, field, false, true, - /* singular_if_not_packed */ false, BYTES_U8), - "reader", JSBinaryReadWriteMethodName(field, /* is_writer=*/false)); + " reader.read$reader$(msg.get$name$());\n", "reader", + JSBinaryReadWriteMethodName(field, /* is_writer=*/false), "name", + JSGetterName(options, field, BYTES_DEFAULT, /* drop_list = */ false)); + printer->Print(" break;\n"); + return; } else { printer->Print( " var value = /** @type {$fieldtype$} */ " @@ -3147,14 +3149,7 @@ void Generator::GenerateClassDeserializeBinaryField( JSBinaryReadWriteMethodName(field, /* is_writer = */ false)); } - if (field->is_packable()) { - printer->Print( - " for (var i = 0; i < values.length; i++) {\n" - " msg.add$name$(values[i]);\n" - " }\n", - "name", - JSGetterName(options, field, BYTES_DEFAULT, /* drop_list = */ true)); - } else if (field->is_repeated()) { + if (field->is_repeated()) { printer->Print( " msg.add$name$(value);\n", "name", JSGetterName(options, field, BYTES_DEFAULT, /* drop_list = */ true)); @@ -3217,6 +3212,30 @@ void Generator::GenerateClassSerializeBinary(const GeneratorOptions& options, "\n"); } +// Generates the code to access a single field value for the binary serializer. +void GenerateClassSerializeBinaryFieldAccess(const GeneratorOptions& options, + io::Printer* printer, + const FieldDescriptor* field) { + if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { + std::string typed_annotation = + JSFieldTypeAnnotation(options, field, + /* is_setter_argument = */ false, + /* force_present = */ false, + /* singular_if_not_packed = */ false, + /* bytes_mode = */ BYTES_DEFAULT); + printer->Print( + " /** @type {$type$} */ " + "(message.internal_getField($index$))", + "index", JSFieldIndex(field), "type", typed_annotation); + } else { + printer->Print( + " message.get$name$($nolazy$)", "name", + JSGetterName(options, field, BYTES_U8), + // No lazy creation for maps containers -- fastpath the empty case. + "nolazy", field->is_map() ? "true" : ""); + } +} + void Generator::GenerateClassSerializeBinaryField( const GeneratorOptions& options, io::Printer* printer, const FieldDescriptor* field) const { @@ -3292,15 +3311,20 @@ void Generator::GenerateClassSerializeBinaryField( if (field->is_map()) { const FieldDescriptor* key_field = MapFieldKey(field); const FieldDescriptor* value_field = MapFieldValue(field); + printer->Print("jspb.internal.public_for_gencode.serializeMapToBinary(\n"); + GenerateClassSerializeBinaryFieldAccess(options, printer, field); printer->Print( - " f.serializeBinary($index$, writer, " - "$keyWriterFn$, $valueWriterFn$", + ",\n $index$,\n" + " writer,\n" + " $keyWriterFn$,\n" + " $valueWriterFn$", "index", absl::StrCat(field->number()), "keyWriterFn", JSBinaryWriterMethodName(options, key_field), "valueWriterFn", JSBinaryWriterMethodName(options, value_field)); if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) { - printer->Print(", $messageType$.serializeBinaryToWriter", "messageType", + printer->Print(",\n $messageType$.serializeBinaryToWriter", + "messageType", GetMessagePath(options, value_field->message_type())); } @@ -3429,7 +3453,7 @@ void Generator::GenerateExtension(const GeneratorOptions& options, : "undefined"); printer->Print(" $isPacked$);\n", "isPacked", - (field->is_packed() ? "true" : "false")); + (field->is_packable() ? "true" : "false")); printer->Print( "// This registers the extension field with the extended class, so that\n" diff --git a/generator/js_generator.h b/generator/js_generator.h index 98b8126..60a5221 100644 --- a/generator/js_generator.h +++ b/generator/js_generator.h @@ -151,9 +151,12 @@ class Generator : public CodeGenerator { std::string* error) const override; uint64_t GetSupportedFeatures() const override { - return FEATURE_PROTO3_OPTIONAL; + return FEATURE_PROTO3_OPTIONAL | FEATURE_SUPPORTS_EDITIONS; } + Edition GetMinimumEdition() const override { return Edition::EDITION_PROTO2; } + Edition GetMaximumEdition() const override { return Edition::EDITION_2023; } + private: void GenerateHeader(const GeneratorOptions& options, const FileDescriptor* file, io::Printer* printer) const; diff --git a/gulpfile.js b/gulpfile.js index 426e0f1..3703193 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,4 +1,4 @@ -const {series} = require('gulp'); +const { series } = require('gulp'); const execFile = require('child_process').execFile; const glob = require('glob'); @@ -6,10 +6,15 @@ function exec(command, cb) { execFile('sh', ['-c', command], cb); } -const plugin = '--plugin=protoc-gen-js=bazel-bin/generator/protoc-gen-js'; +const plugin = '--plugin=protoc-gen-js=bazel-bin/generator/protoc-gen-js'; const protoc = [(process.env.PROTOC || 'protoc'), plugin].join(' '); const protocInc = process.env.PROTOC_INC || '../src'; +// Obtained by running bazel build //conformance:conformance_test_runner in +// https://github.com/protocolbuffers/protobuf under +// bazel-bin/conformance/conformance_test_runner +const protoConfonformanceRunner = process.env.PROTO_CONFORMANCE_RUNNER || 'conformance_test_runner'; + // See https://github.com/google/closure-compiler/wiki/Flags-and-Options let compilationLevel = 'SIMPLE'; @@ -59,6 +64,15 @@ const group3Protos = [ 'protos/test10.proto' ]; +const conformanceProtos = [ + 'conformance/protos/conformance.proto', + 'conformance/protos/test_messages_proto2.proto', + 'conformance/protos/test_messages_proto3.proto', + 'conformance/protos/test_messages_edition2023.proto', + 'conformance/protos/test_messages_proto2_editions.proto', + 'conformance/protos/test_messages_proto3_editions.proto' +]; + function make_exec_logging_callback(cb) { return (err, stdout, stderr) => { console.log(stdout); @@ -68,7 +82,7 @@ function make_exec_logging_callback(cb) { } function enableAdvancedOptimizations(cb) { - compilationLevel = 'ADVANCED'; + compilationLevel = 'SIMPLE'; cb(); } @@ -79,21 +93,21 @@ function enableSimpleOptimizations(cb) { function genproto_well_known_types_closure(cb) { exec(protoc + ' --js_out=one_output_file_per_input_file,binary:. -I ' + protocInc + ' -I . ' + wellKnownTypes.join(' '), - make_exec_logging_callback(cb)); + make_exec_logging_callback(cb)); } function genproto_group1_closure(cb) { exec(protoc + ' --js_out=library=testproto_libs1,binary:. -I ' + protocInc + ' -I . ' + group1Protos.join(' '), - make_exec_logging_callback(cb)); + make_exec_logging_callback(cb)); } function genproto_group2_closure(cb) { exec( - protoc + - ' --experimental_allow_proto3_optional' + - ' --js_out=library=testproto_libs2,binary:. -I ' + protocInc + ' -I . -I commonjs ' + - group2Protos.join(' '), - make_exec_logging_callback(cb)); + protoc + + ' --experimental_allow_proto3_optional' + + ' --js_out=library=testproto_libs2,binary:. -I ' + protocInc + ' -I . -I commonjs ' + + group2Protos.join(' '), + make_exec_logging_callback(cb)); } function genproto_well_known_types_commonjs(cb) { @@ -101,32 +115,52 @@ function genproto_well_known_types_commonjs(cb) { make_exec_logging_callback(cb)); } +function genproto_conformance_commonjs(cb) { + exec(`${protoc} --js_out=import_style=commonjs,binary:conformance/protos -I ${protocInc} -I conformance/protos ${conformanceProtos.join(' ')}`, + make_exec_logging_callback(cb)); +} + +function pack_google_protobuf(cb) { + exec('npm pack', + make_exec_logging_callback(cb)); +} + +function install_conformance_test_deps(cb) { + exec('cd conformance && npm install ../google-protobuf-3.21.4.tgz', + make_exec_logging_callback(cb)); +} + +function run_conformance_tests(cb) { + exec(`${protoConfonformanceRunner} --enforce_recommended --maximum_edition 2023 --output_dir conformance/ conformance/runner.js`, + make_exec_logging_callback(cb)); +} + function genproto_group1_commonjs(cb) { - exec('mkdir -p commonjs_out && ' + protoc + ' --js_out=import_style=commonjs,binary:commonjs_out -I ' + protocInc + ' -I commonjs -I . ' + group1Protos.join(' '), - make_exec_logging_callback(cb)); + exec('mkdir -p commonjs_out && ' + protoc + ' --js_out=import_style=commonjs,binary:commonjs_out -I ' + protocInc + ' -I commonjs -I . ' + group1Protos.join(' '), + make_exec_logging_callback(cb)); } function genproto_group2_commonjs(cb) { exec( - 'mkdir -p commonjs_out && ' + protoc + - ' --experimental_allow_proto3_optional --js_out=import_style=commonjs,binary:commonjs_out -I ' + protocInc + ' -I commonjs -I . ' + - group2Protos.join(' '), - make_exec_logging_callback(cb)); + 'mkdir -p commonjs_out && ' + protoc + + ' --experimental_allow_proto3_optional --js_out=import_style=commonjs,binary:commonjs_out -I ' + protocInc + ' -I commonjs -I . ' + + group2Protos.join(' '), + make_exec_logging_callback(cb)); } function genproto_commonjs_wellknowntypes(cb) { - exec('mkdir -p commonjs_out/node_modules/google-protobuf && ' + protoc + ' --js_out=import_style=commonjs,binary:commonjs_out/node_modules/google-protobuf -I ' + protocInc + ' ' + wellKnownTypes.join(' '), - make_exec_logging_callback(cb)); + exec('mkdir -p commonjs_out/node_modules/google-protobuf && ' + protoc + ' --js_out=import_style=commonjs,binary:commonjs_out/node_modules/google-protobuf -I ' + protocInc + ' ' + wellKnownTypes.join(' '), + make_exec_logging_callback(cb)); } function genproto_wellknowntypes(cb) { - exec(protoc + ' --js_out=import_style=commonjs,binary:. -I ' + protocInc + ' ' + wellKnownTypes.join(' '), - make_exec_logging_callback(cb)); + exec(protoc + ' --js_out=import_style=commonjs,binary:. -I ' + protocInc + ' ' + wellKnownTypes.join(' '), + make_exec_logging_callback(cb)); } function genproto_group3_commonjs_strict(cb) { - exec('mkdir -p commonjs_out && ' + protoc + ' --js_out=import_style=commonjs_strict,binary:commonjs_out -I ' + protocInc + ' -I commonjs -I . ' + group3Protos.join(' '), - make_exec_logging_callback(cb)); + exec('mkdir -p commonjs_out && ' + protoc + ' --js_out=import_style=commonjs_strict,binary:commonjs_out -I ' + protocInc + ' -I commonjs -I . ' + group3Protos.join(' '), + make_exec_logging_callback(cb)); } @@ -138,16 +172,15 @@ function getClosureCompilerCommand(exportsFile, outputFile) { `--js=${closureLib}/third_party/closure/goog/**.js`, '--js=asserts.js', '--js=debug.js', + '--js=internal_bytes.js', + '--js=internal_options.js', + '--js=internal_public.js', '--js=map.js', '--js=message.js', - '--js=binary/arith.js', - '--js=binary/constants.js', - '--js=binary/decoder.js', - '--js=binary/encoder.js', - '--js=binary/reader.js', - '--js=binary/utf8.js', - '--js=binary/utils.js', - '--js=binary/writer.js', + '--js=bytestring.js', + '--js=unsafe_bytestring.js', + '--js=binary/**.js', + '--js=!binary/**_test.js', `--js=${exportsFile}`, '--generate_exports', `--compilation_level=${compilationLevel}`, @@ -159,115 +192,116 @@ function getClosureCompilerCommand(exportsFile, outputFile) { function gen_google_protobuf_js(cb) { exec( - getClosureCompilerCommand('commonjs/export.js', 'google-protobuf.js'), - make_exec_logging_callback(cb)); + getClosureCompilerCommand('commonjs/export.js', 'google-protobuf.js'), + make_exec_logging_callback(cb)); } function commonjs_testdeps(cb) { - exec( - 'mkdir -p commonjs_out/test_node_modules && ' + - getClosureCompilerCommand( - 'commonjs/export_testdeps.js', - 'commonjs_out/test_node_modules/testdeps_commonjs.js'), - make_exec_logging_callback(cb)); + exec( + 'mkdir -p commonjs_out/test_node_modules && ' + + getClosureCompilerCommand( + 'commonjs/export_testdeps.js', + 'commonjs_out/test_node_modules/testdeps_commonjs.js'), + make_exec_logging_callback(cb)); } function commonjs_out(cb) { - let cmd = - 'mkdir -p commonjs_out/binary && mkdir -p commonjs_out/test_node_modules && '; - function addTestFile(file) { - cmd += 'node commonjs/rewrite_tests_for_commonjs.js < ' + file + - ' > commonjs_out/' + file + '&& '; - } - - glob.sync('*_test.js').forEach(addTestFile); - glob.sync('binary/*_test.js').forEach(addTestFile); - - exec( - cmd + 'cp commonjs/jasmine.json commonjs_out/jasmine.json && ' + - 'cp google-protobuf.js commonjs_out/test_node_modules && ' + - 'cp commonjs/strict_test.js commonjs_out/strict_test.js &&' + - 'cp commonjs/import_test.js commonjs_out/import_test.js', - make_exec_logging_callback(cb)); + let cmd = + 'mkdir -p commonjs_out/binary && mkdir -p commonjs_out/test_node_modules && '; + function addTestFile(file) { + cmd += 'node commonjs/rewrite_tests_for_commonjs.js < ' + file + + ' > commonjs_out/' + file + '&& '; + } + + glob.sync('*_test.js').forEach(addTestFile); + glob.sync('binary/*_test.js').forEach(addTestFile); + + exec( + cmd + 'cp commonjs/jasmine.json commonjs_out/jasmine.json && ' + + 'cp google-protobuf.js commonjs_out/test_node_modules && ' + + 'cp commonjs/strict_test.js commonjs_out/strict_test.js &&' + + 'cp commonjs/import_test.js commonjs_out/import_test.js', + make_exec_logging_callback(cb)); } function closure_make_deps(cb) { exec( - './node_modules/.bin/closure-make-deps --closure-path=. --file=node_modules/google-closure-library/closure/goog/deps.js binary/arith.js binary/constants.js binary/decoder.js binary/encoder.js binary/reader.js binary/utf8.js binary/utils.js binary/writer.js asserts.js debug.js map.js message.js node_loader.js test_bootstrap.js > deps.js', - make_exec_logging_callback(cb)); + './node_modules/.bin/closure-make-deps --closure-path=. --file=node_modules/google-closure-library/closure/goog/deps.js bytestring.js internal_bytes.js internal_options.js internal_public.js binary/arith.js binary/bytesource.js binary/binary_constants.js binary/decoder.js binary/decoder_alias.js binary/encoder.js binary/encoder_alias.js binary/errors.js binary/internal_buffer.js binary/reader.js binary/reader_alias.js binary/test_utils.js binary/utf8.js binary/utils.js binary/writer.js binary/writer_alias.js asserts.js debug.js map.js message.js node_loader.js test_bootstrap.js unsafe_bytestring.js > deps.js', + make_exec_logging_callback(cb)); } function test_closure(cb) { exec( - 'JASMINE_CONFIG_PATH=jasmine.json ./node_modules/.bin/jasmine', - make_exec_logging_callback(cb)); + 'JASMINE_CONFIG_PATH=jasmine.json ./node_modules/.bin/jasmine --random=false', + make_exec_logging_callback(cb)); } function test_commonjs(cb) { - exec('cd commonjs_out && JASMINE_CONFIG_PATH=jasmine.json NODE_PATH=test_node_modules ../node_modules/.bin/jasmine', - make_exec_logging_callback(cb)); + exec('cd commonjs_out && JASMINE_CONFIG_PATH=jasmine.json NODE_PATH=test_node_modules ../node_modules/.bin/jasmine --random=false', + make_exec_logging_callback(cb)); } function remove_gen_files(cb) { - exec('rm -rf commonjs_out google-protobuf.js deps.js', + exec('rm -rf commonjs_out google-protobuf.js deps.js google-protobuf-*.tgz conformance/protos/*.js', make_exec_logging_callback(cb)); } exports.build_protoc_plugin = function (cb) { exec('bazel build generator:protoc-gen-js', - make_exec_logging_callback(cb)); + make_exec_logging_callback(cb)); } const dist = series(exports.build_protoc_plugin, - genproto_wellknowntypes, - gen_google_protobuf_js); + genproto_wellknowntypes, + gen_google_protobuf_js); exports.dist = series(enableAdvancedOptimizations, dist); exports.build_commonjs = series( - dist, - genproto_well_known_types_commonjs, - genproto_group1_commonjs, genproto_group2_commonjs, - genproto_commonjs_wellknowntypes, - commonjs_testdeps, genproto_group3_commonjs_strict, - commonjs_out); + dist, + genproto_well_known_types_commonjs, + genproto_group1_commonjs, genproto_group2_commonjs, + genproto_commonjs_wellknowntypes, + commonjs_testdeps, genproto_group3_commonjs_strict, + commonjs_out); exports.build_closure = series(exports.build_protoc_plugin, - genproto_well_known_types_closure, - genproto_group1_closure, - genproto_group2_closure, - closure_make_deps); + genproto_well_known_types_closure, + genproto_group1_closure, + genproto_group2_closure, + closure_make_deps); const test_closure_series = series( - exports.build_closure, - test_closure); + exports.build_closure, + test_closure); exports.test_closure = series(enableSimpleOptimizations, - test_closure_series); + test_closure_series); exports.test_closure_opt = series(enableAdvancedOptimizations, - test_closure_series); - + test_closure_series); const test_commonjs_series = series( - exports.build_commonjs, - test_commonjs); + exports.build_commonjs, + test_commonjs); exports.test_commonjs = series(enableSimpleOptimizations, - test_commonjs_series); + test_commonjs_series); exports.test_commonjs_opt = series(enableAdvancedOptimizations, - test_commonjs_series); + test_commonjs_series); const test_series = series(test_closure_series, - test_commonjs_series); + test_commonjs_series); exports.test = series(enableSimpleOptimizations, - test_series); + test_series); exports.test_opt = series(enableAdvancedOptimizations, - test_series); + test_series); + +exports.test_conformance = series(dist, genproto_conformance_commonjs, pack_google_protobuf, install_conformance_test_deps, run_conformance_tests); exports.clean = series(remove_gen_files); diff --git a/internal_bytes.js b/internal_bytes.js new file mode 100644 index 0000000..87b3f2b --- /dev/null +++ b/internal_bytes.js @@ -0,0 +1,238 @@ +/** + * @fileoverview Internal runtime functions related to bytes data. + */ +goog.module('jspb.internal_bytes'); + +const base64 = goog.require('goog.crypt.base64'); +const userAgent = goog.require('goog.userAgent'); +const {fail} = goog.require('goog.asserts'); + +/** + * Does this JavaScript environment support Uint8Array typed arrays? + * + * NOTE: this really should be `typeof Uint8Array === 'function'` but in + * go/cobalt browsers `typeof Uint8Array === 'object'` so we need a looser check + * here. + * We assume availability if featureset year is >=2018. Any number > 2012 would + * probably suffice but those years aren't defined, so we pick the ealiest + * defined year. + * + * @const {boolean} + */ +const SUPPORTS_UINT8ARRAY = + goog.FEATURESET_YEAR >= 2018 || (typeof Uint8Array !== 'undefined'); + +/** + * @define {boolean} Indicates that we should look for WEBSAFE encodings before + * using atob/btoa for base64 encoding. This incurs some walltime cost but + * is required for backcompat. + */ +const HANDLE_WEB_SAFE_ENCODINGS_WITH_ATOB_AND_BTOA = + goog.define('jspb.HANDLE_WEB_SAFE_ENCODINGS_WITH_ATOB_AND_BTOA', true); + +/** + * @define {boolean} If set, use atob/btoa when available. + * + * More specifically, if enabled and 'goog.FEATURESET_YEAR >= 2018', sets + * USE_ATOB_BTOA without feature detection. Using featureset years >= 2018 + * which is conservative but excluded IE and no one is picking numbers less that + * that anyway. If disabled, the slower JS implementation is always used; this + * is appropriate for non-Web environments where 'atob' and 'btoa' are not + * available. + */ +const CAN_USE_ATOB_AND_BTOA = goog.define('jspb.USE_ATOB_AND_BTOA', true); + +const /** boolean */ ASSUME_ATOB_AND_BTOA_AVAILABLE = + goog.FEATURESET_YEAR >= 2018; + +/** + * Whether this application has native support for `atob` and `btoa`. + * + * IE has a broken implementation; and we would be able to fast-track WEBKIT + * if it weren't for cobalt. + * + * @const {boolean} + */ +const USE_ATOB_BTOA = CAN_USE_ATOB_AND_BTOA && + (ASSUME_ATOB_AND_BTOA_AVAILABLE || + (!userAgent.IE && typeof btoa === 'function')); + +/** + * Maximum arg spread for String.fromCharCode. + * + * Chrome's maximum stack size is of the order of 100k so here we conservatively + * set this to 10k. + */ +const UINT8ARRAY_MAX_SIZE_FOR_SPREAD = 10240; + +/** + * Encodes a Uint8Array as base64. + * + * Note that we can always use btoa/atob if we can use Uint8Array because + * every browser that supports Uint8Array also supports them: see + * https://caniuse.com/?search=Uint8Array and https://caniuse.com/atob-btoa + * + * @param {!Uint8Array} u8 + * @return {string} + */ +function encodeByteArray(u8) { + if (!USE_ATOB_BTOA) { + return base64.encodeByteArray(u8); + } + + /** @type {string} */ + let binary = ''; + let offset = 0; + const limit = u8.length - UINT8ARRAY_MAX_SIZE_FOR_SPREAD; + while (offset < limit) { + binary += String.fromCharCode.apply( + null, u8.subarray(offset, offset += UINT8ARRAY_MAX_SIZE_FOR_SPREAD)); + } + binary += String.fromCharCode.apply(null, offset ? u8.subarray(offset) : u8); + return btoa(binary); +} + +/** + * Websafe padding characters for replacement. + * @const {!RegExp} + */ +const WEBSAFE_BASE64_CHARS = /** @pureOrBreakMyCode */ (/[-_.]/g); + +/** @const {!Object} */ +const websafeReplacer = + /** @pureOrBreakMyCode */ ({'-': '+', '_': '/', '.': '='}); + +/** + * Replaces websafe characters with default alphabet characters. + * @param {string} char + * @return {string} + */ +function replaceWebsafe(char) { + return websafeReplacer[char] || ''; +} + +/** + * Replaces websafe characters in a string with default alphabet characters. + * @param {string} str + * @return {string} + */ +function replaceWebsafeString(str) { + if (WEBSAFE_BASE64_CHARS.test(str)) { + return str.replace(WEBSAFE_BASE64_CHARS, replaceWebsafe); + } + return str; +} + +/** + * Decodes base64 into a Uint8Array. + * + * Note that we can always use btoa/atob if we can use Uint8Array because + * every browser that supports Uint8Array also supports them: see + * https://caniuse.com/?search=Uint8Array and https://caniuse.com/atob-btoa + * + * @param {string} b64 + * @return {!Uint8Array} + */ +function decodeByteArray(b64) { + // Without our flag, fall back to Closure's implementation. + if (!USE_ATOB_BTOA) { + return base64.decodeStringToUint8Array(b64); + } + + // If this encoding used the websafe alphabet, we must convert it for atob + // to work. This is rare so we condition any replace operation on a regex + // match. One also presumes this will happen exclusively for URL mappings + // so they should also be relatively short. + // + // Note that atob natively handles missing padding so we do not need to + // handle that here. + let encoded = b64; + if (HANDLE_WEB_SAFE_ENCODINGS_WITH_ATOB_AND_BTOA) { + encoded = replaceWebsafeString(encoded); + } + + // Convert b64 to binary string. + let /** string|undefined */ binary; + if (goog.DEBUG) { + try { + binary = atob(encoded); + } catch (e) { + throw new Error(`invalid encoding '${b64}': ${e}`); + } + } else /* if (!goog.DEBUG) */ { + binary = atob(encoded); + } + + // Convert back from binary string to Uint8Array. + const u8 = new Uint8Array(binary.length); + for (let i = 0; i < binary.length; i++) { + u8[i] = binary.charCodeAt(i); + } + return u8; +} + + +/** + * Coerce data of a 'bytes' field to a Uint8Array byte buffer. + * Note that Uint8Array is not supported on IE versions before 10 nor on Opera + * Mini. @see http://caniuse.com/Uint8Array + * @param {string|!Uint8Array|null} value + * @return {?Uint8Array} The field's coerced value. + */ +function dataAsU8(value) { + if (value == null || isU8(value)) { + return /** @type {?Uint8Array} */ (value); + } + if (typeof value === 'string') { + return decodeByteArray(value); + } + fail('Cannot coerce to Uint8Array: ' + goog.typeOf(value)); + return null; +} + +/** + * Returns whether the given value is a Uint8Array. + * @param {*} value + * @return {boolean} + */ +function isU8(value) { + return SUPPORTS_UINT8ARRAY && value != null && value instanceof Uint8Array; +} + +/** @return {boolean} */ +function uint8ArrayEquals(/** !Uint8Array */ a, /** !Uint8Array */ b) { + // Compare byte-by-byte. + // + // Note that we do not technically need to length-check since out-of-range + // subscripts will simply yield `undefined`; but that may result in some + // deoptimization. + const aLength = a.length; + if (aLength !== b.length) { + return false; + } + for (let i = 0; i < aLength; i++) { + if (a[i] !== b[i]) { + return false; + } + } + return true; +} + +/** + * A token to check that internal only bytestring functions are only called by + * internal functions. + * @const + */ +const I_AM_INTERNAL = {}; + +exports = { + I_AM_INTERNAL, + SUPPORTS_UINT8ARRAY, + encodeByteArray, + decodeByteArray, + dataAsU8, + isU8, + replaceWebsafeString, + uint8ArrayEquals, + USE_ATOB_BTOA, // exported for tests. +}; diff --git a/internal_options.js b/internal_options.js new file mode 100644 index 0000000..ecdac9e --- /dev/null +++ b/internal_options.js @@ -0,0 +1,46 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://protobuf.dev/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/** + * @fileoverview Internal options for. + */ +goog.module('jspb.internal_options'); + +/** + * @return {boolean} True if BigInt is permitted for use and supported by the + * platform. + * @nosideeffects + */ +function isBigIntAvailable() { + return goog.FEATURESET_YEAR >= 2021 || (typeof BigInt === 'function'); +} + +exports = { + isBigIntAvailable, +}; diff --git a/internal_public.js b/internal_public.js new file mode 100644 index 0000000..cf4a61d --- /dev/null +++ b/internal_public.js @@ -0,0 +1,112 @@ +/** + * @fileoverview Public APIs exposed purely for use by generated code. Use of + * these APIs outside of that context is not supported and actively discouraged. + * @public + * + * DO NOT USE THIS OUTSIDE OF THIS PACKAGE. + */ + +goog.module('jspb.internal.public_for_gencode'); +goog.module.declareLegacyNamespace(); + +const asserts = goog.require('goog.asserts'); +const { BinaryReader } = goog.require('jspb.binary.reader'); +const { BinaryWriter } = goog.requireType('jspb.binary.writer'); +const {Map: JspbMap} = goog.requireType('jspb.Map'); + +/** + * Write this Map field in wire format to a BinaryWriter, using the given + * field number. + * @param {?JspbMap} map + * @param {number} fieldNumber + * @param {!BinaryWriter} writer + * @param {function(this:BinaryWriter,number,K_OR_NULL)} keyWriterFn + * The method on BinaryWriter that writes type K to the stream. + * @param {function(this:BinaryWriter,number,V,?=)| + * function(this:BinaryWriter,number,V,?)} valueWriterFn + * The method on BinaryWriter that writes type V to the stream. May be + * writeMessage, in which case the second callback arg form is used. + * @param {function(V,!BinaryWriter)=} valueWriterCallback + * The BinaryWriter serialization callback for type V, if V is a message + * type. + * @template K,V + * Use go/closure-ttl to create a `K|null` type for the keyWriterFn argument + * closure type inference will occasionally infer K based on the keyWriterFn + * argument instead of the map argument which will cause type errors when they + * don't match + * @template K_OR_NULL := union(K, 'null') =: + */ +function serializeMapToBinary( + map, fieldNumber, writer, keyWriterFn, valueWriterFn, valueWriterCallback) { + if (!map) { + return; + } + map.forEach((value, key) => { + writer.writeMessage( + fieldNumber, /* we need a non-null value to pass here */ map, + (ignored, w) => { + keyWriterFn.call(w, 1, key); + valueWriterFn.call(w, 2, value, valueWriterCallback); + }); + }); +} + +/** + * Read one key/value message from the given BinaryReader. Compatible as the + * `reader` callback parameter to BinaryReader.readMessage, to be called + * when a key/value pair submessage is encountered. If the Key is undefined, + * we should default it to 0. + * @template K, V + * @param {!JspbMap} map + * @param {!BinaryReader} reader + * @param {function(this:BinaryReader):K} keyReaderFn + * The method on BinaryReader that reads type K from the stream. + * + * @param {K} defaultKey + * The default value for the type of map keys. Accepting map entries with + * unset keys is required for maps to be backwards compatible with the + * repeated message representation described here: goo.gl/zuoLAC + * + * @param {function(this:BinaryReader):V|function(V,!BinaryReader)} + * valueReaderFn + * The method on BinaryReader that reads type V from the stream, or a + * callback for readMessage. + * + * @param {V} defaultValue + * The default value for the type of map values. Accepting map entries with + * unset values is required for maps to be backwards compatible with the + * repeated message representation described here: goo.gl/zuoLAC + */ +function deserializeMapFromBinary( + map, reader, keyReaderFn, defaultKey, valueReaderFn, defaultValue) { + reader.readMessage(map, (message, reader) => { + let key = defaultKey; + let value = defaultValue; + + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + const field = reader.getFieldNumber(); + + if (field == 1) { + // Key. + key = keyReaderFn.call(reader); + } else if (field == 2) { + // Value. + if (map.valueCtor) { + reader.readMessage(value, valueReaderFn); + } else { + value = (/** @type {function(this:BinaryReader):?} */ (valueReaderFn)) + .call(reader); + } + } + } + + asserts.assert(key != undefined); + asserts.assert(value != undefined); + map.set(key, value); + }); +} + +exports = {deserializeMapFromBinary, serializeMapToBinary}; diff --git a/map.js b/map.js index 9bb6eb5..e917941 100644 --- a/map.js +++ b/map.js @@ -31,10 +31,10 @@ /** * @fileoverview - * @suppress {missingRequire} TODO(b/152540451): this shouldn't be needed */ goog.provide('jspb.Map'); + goog.require('jspb.asserts'); goog.requireType('jspb.BinaryReader'); @@ -425,43 +425,6 @@ jspb.Map.prototype.has = function(key) { return (keyValue in this.map_); }; - -/** - * Write this Map field in wire format to a BinaryWriter, using the given field - * number. - * @param {number} fieldNumber - * @param {!jspb.BinaryWriter} writer - * @param {function(this:jspb.BinaryWriter,number,K)} keyWriterFn - * The method on BinaryWriter that writes type K to the stream. - * @param {function(this:jspb.BinaryWriter,number,V,?=)| - * function(this:jspb.BinaryWriter,number,V,?)} valueWriterFn - * The method on BinaryWriter that writes type V to the stream. May be - * writeMessage, in which case the second callback arg form is used. - * @param {function(V,!jspb.BinaryWriter)=} opt_valueWriterCallback - * The BinaryWriter serialization callback for type V, if V is a message - * type. - * @export - */ -jspb.Map.prototype.serializeBinary = function( - fieldNumber, writer, keyWriterFn, valueWriterFn, opt_valueWriterCallback) { - var strKeys = this.stringKeys_(); - strKeys.sort(); - for (var i = 0; i < strKeys.length; i++) { - var entry = this.map_[strKeys[i]]; - writer.beginSubMessage(fieldNumber); - keyWriterFn.call(writer, 1, entry.key); - if (this.valueCtor_) { - valueWriterFn.call(writer, 2, this.wrapEntry_(entry), - opt_valueWriterCallback); - } else { - /** @type {function(this:jspb.BinaryWriter,number,?)} */ (valueWriterFn) - .call(writer, 2, entry.value); - } - writer.endSubMessage(); - } -}; - - /** * Read one key/value message from the given BinaryReader. Compatible as the * `reader` callback parameter to jspb.BinaryReader.readMessage, to be called diff --git a/message.js b/message.js index a13d856..f4db81a 100644 --- a/message.js +++ b/message.js @@ -43,7 +43,7 @@ goog.require('goog.array'); goog.require('goog.crypt.base64'); goog.require('jspb.asserts'); -goog.require('jspb.BinaryReader'); +goog.require('jspb.binary.reader'); goog.require('jspb.Map'); @@ -657,7 +657,14 @@ jspb.Message.readBinaryExtension = function( reader, value, binaryFieldInfo.binaryMessageDeserializeFn); } else { // All other types. - value = binaryFieldInfo.binaryReaderFn.call(reader); + if (fieldInfo.isRepeated && binaryFieldInfo.isPacked) { + value = getExtensionFn.call(msg, fieldInfo) ?? []; + binaryFieldInfo.binaryReaderFn.call(reader, value); + setExtensionFn.call(msg, fieldInfo, value); + return; + } else { + value = binaryFieldInfo.binaryReaderFn.call(reader); + } } if (fieldInfo.isRepeated && !binaryFieldInfo.isPacked) { diff --git a/node_loader.js b/node_loader.js index 3f25e92..82e5a68 100644 --- a/node_loader.js +++ b/node_loader.js @@ -32,7 +32,11 @@ * @fileoverview Loader that handles goog.require() for Node.JS. */ -var oldLoader = goog.global.CLOSURE_IMPORT_SCRIPT; +const fs = require('fs'); +const path = require('path'); + +// For goog.require() +const OLD_CLOSURE_IMPORT_SCRIPT = goog.global.CLOSURE_IMPORT_SCRIPT; goog.global.CLOSURE_IMPORT_SCRIPT = function(src, opt_sourceText) { if (opt_sourceText === undefined) { @@ -45,5 +49,15 @@ goog.global.CLOSURE_IMPORT_SCRIPT = function(src, opt_sourceText) { } } - return oldLoader(src, opt_sourceText); + return OLD_CLOSURE_IMPORT_SCRIPT(src, opt_sourceText); +}; + +const OLD_CLOSURE_LOAD_FILE_SYNC = goog.global.CLOSURE_LOAD_FILE_SYNC; + +goog.global.CLOSURE_LOAD_FILE_SYNC = function (src) { + try { + return fs.readFileSync(path.resolve('.', src), { encoding: 'utf-8' }); + } catch (e) { + return OLD_CLOSURE_LOAD_FILE_SYNC(src); + } }; diff --git a/package-lock.json b/package-lock.json index 4fe22bb..088cd4a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,18 +1,18 @@ { "name": "google-protobuf", - "version": "3.21.4", + "version": "3.21.5", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "google-protobuf", - "version": "3.21.4", + "version": "3.21.5", "license": "(BSD-3-Clause AND Apache-2.0)", "devDependencies": { "glob": "~7.1.4", - "google-closure-compiler": "~20190819.0.0", - "google-closure-deps": "^20210406.0.0", - "google-closure-library": "~20200315.0.0", + "google-closure-compiler": "20230802.0.0", + "google-closure-deps": "20230802.0.0", + "google-closure-library": "20230802.0.0", "gulp": "~5.0.0", "jasmine": "~3.5.0" } @@ -48,15 +48,19 @@ } }, "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { - "color-convert": "^1.9.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/anymatch": { @@ -253,17 +257,20 @@ } }, "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, "node_modules/chokidar": { @@ -337,19 +344,24 @@ } }, "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { - "color-name": "1.1.3" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" }, "node_modules/concat-map": { "version": "0.0.1", @@ -428,15 +440,6 @@ "node": ">=6" } }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/expand-tilde": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", @@ -731,14 +734,14 @@ } }, "node_modules/google-closure-compiler": { - "version": "20190819.0.0", - "resolved": "https://registry.npmjs.org/google-closure-compiler/-/google-closure-compiler-20190819.0.0.tgz", - "integrity": "sha512-5cwcui89TSFrKCa+oH5zq6F0esSHkGbWt1U2LgywakFhe5F27j/0F6NR7QyFYkBf3leDt5kPBvC2Dlc3ZwuFVA==", + "version": "20230802.0.0", + "resolved": "https://registry.npmjs.org/google-closure-compiler/-/google-closure-compiler-20230802.0.0.tgz", + "integrity": "sha512-o2fYoc8lqOBdhm95Ick0vWrtwH2Icd5yLZhbTcQ0T7NfGiBepYvx1BB63hR8ebgzEZemz9Fh+O6Kg/3Mjm28ww==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "chalk": "2.x", - "google-closure-compiler-java": "^20190819.0.0", - "google-closure-compiler-js": "^20190819.0.0", + "chalk": "4.x", + "google-closure-compiler-java": "^20230802.0.0", "minimist": "1.x", "vinyl": "2.x", "vinyl-sourcemaps-apply": "^0.2.0" @@ -747,73 +750,73 @@ "google-closure-compiler": "cli.js" }, "engines": { - "node": ">=8" + "node": ">=10" }, "optionalDependencies": { - "google-closure-compiler-linux": "^20190819.0.0", - "google-closure-compiler-osx": "^20190819.0.0", - "google-closure-compiler-windows": "^20190819.0.0" + "google-closure-compiler-linux": "^20230802.0.0", + "google-closure-compiler-osx": "^20230802.0.0", + "google-closure-compiler-windows": "^20230802.0.0" } }, "node_modules/google-closure-compiler-java": { - "version": "20190819.0.0", - "resolved": "https://registry.npmjs.org/google-closure-compiler-java/-/google-closure-compiler-java-20190819.0.0.tgz", - "integrity": "sha512-i8KzPJZBEF0aZWSn2vlkH0JCeQGIxBVfQaUwc2fCjPbm/v5YfpZzkj38LoMDbE95BlYsq2cPveHUNC4w85UgGw==", - "dev": true - }, - "node_modules/google-closure-compiler-js": { - "version": "20190819.0.0", - "resolved": "https://registry.npmjs.org/google-closure-compiler-js/-/google-closure-compiler-js-20190819.0.0.tgz", - "integrity": "sha512-c1MrCW2sBsJ5d5judH6YnBPpxbOzts6D7XYa0KN4I97S0LjXzX5cENBlMUqMGGeSdFyjGr5FP0BxGp49k5UKxQ==", - "dev": true + "version": "20230802.0.0", + "resolved": "https://registry.npmjs.org/google-closure-compiler-java/-/google-closure-compiler-java-20230802.0.0.tgz", + "integrity": "sha512-PWKLMLwj7pR/U0yYbiy649LLqAscu+F1gyY4Y/jK6CmSLb8cIJbL8BTJd00828TzTNfWnYwxbkcQw0y9C2YsGw==", + "dev": true, + "license": "Apache-2.0" }, "node_modules/google-closure-compiler-linux": { - "version": "20190819.0.0", - "resolved": "https://registry.npmjs.org/google-closure-compiler-linux/-/google-closure-compiler-linux-20190819.0.0.tgz", - "integrity": "sha512-+ia89Ot4dPyRioLlxvkfYiISwJO+2NV7SY0Zp/KfTt9x+eJaGQ9GRIQage50d1mGkUyPmFfxsdPUePpT1QlpaA==", + "version": "20230802.0.0", + "resolved": "https://registry.npmjs.org/google-closure-compiler-linux/-/google-closure-compiler-linux-20230802.0.0.tgz", + "integrity": "sha512-F13U4iSXiWeGtHOFS25LVem1s6zI+pJvXVPVR7zSib5ppoUJ0JXnABJQezUR3FnpxmnkALG4oIGW0syH9zPLZA==", "cpu": [ - "x64", - "x86" + "x32", + "x64" ], "dev": true, + "license": "Apache-2.0", "optional": true, "os": [ "linux" ] }, "node_modules/google-closure-compiler-osx": { - "version": "20190819.0.0", - "resolved": "https://registry.npmjs.org/google-closure-compiler-osx/-/google-closure-compiler-osx-20190819.0.0.tgz", - "integrity": "sha512-woANg+oA2zjFebtdYTA4lLtqbOVO9yE9yy8ibGjt76FNlw0bAyxTO4z2ab4CwUNNpOeRoxZyGt9CejlCmNpxJg==", + "version": "20230802.0.0", + "resolved": "https://registry.npmjs.org/google-closure-compiler-osx/-/google-closure-compiler-osx-20230802.0.0.tgz", + "integrity": "sha512-ANAi/ux92Tt+Na7vFDLeK2hRzotjC5j+nxoPtE0OcuNcbjji5dREKoJxkq7r0YwRTCzAFZszK5ip/NPdTOdCEg==", "cpu": [ + "x32", "x64", - "x86" + "arm64" ], "dev": true, + "license": "Apache-2.0", "optional": true, "os": [ "darwin" ] }, "node_modules/google-closure-compiler-windows": { - "version": "20190819.0.0", - "resolved": "https://registry.npmjs.org/google-closure-compiler-windows/-/google-closure-compiler-windows-20190819.0.0.tgz", - "integrity": "sha512-WglPY706c1oN03KiZF02FUWr/7M0eFoev4CQPncSihfjYXpD5E5PMKJ3ppawhzj60CQ9ceC/Omx7VN7Kp0uOQg==", + "version": "20230802.0.0", + "resolved": "https://registry.npmjs.org/google-closure-compiler-windows/-/google-closure-compiler-windows-20230802.0.0.tgz", + "integrity": "sha512-ZQPujoNiiUyTGl8zEGR/0yAygWnbMtX/NQ/S/EHVgq5nmYkvDEVuiVbgpPAmO9lzBTq0hvUTRRATZbTU2ISxgA==", "cpu": [ - "x64", - "x86" + "x32", + "x64" ], "dev": true, + "license": "Apache-2.0", "optional": true, "os": [ "win32" ] }, "node_modules/google-closure-deps": { - "version": "20210406.0.0", - "resolved": "https://registry.npmjs.org/google-closure-deps/-/google-closure-deps-20210406.0.0.tgz", - "integrity": "sha512-4mn6qZ8u4c/9fhebKccxyN882l5/0O4nuJ+ibuxDy0y7XMgolSLNF/Gmg1HEhEgX00CF/JBKrc/rw0WVjnlSfw==", + "version": "20230802.0.0", + "resolved": "https://registry.npmjs.org/google-closure-deps/-/google-closure-deps-20230802.0.0.tgz", + "integrity": "sha512-5xhXO8xgxdXYZMsc8ZRzmnCm4prm0TcD33tcNr8l3OjSBovFO9MpgtrZxH/ZVnZMny6oOBmdeNqcO3afCYY9Lw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "minimatch": "^3.0.4", "yargs": "^16.2.0" @@ -824,10 +827,11 @@ } }, "node_modules/google-closure-library": { - "version": "20200315.0.0", - "resolved": "https://registry.npmjs.org/google-closure-library/-/google-closure-library-20200315.0.0.tgz", - "integrity": "sha512-LdCecdztxDvA9K+8b6E9aE4Hw7ABdYokfA7d5qW1sd/iy8O1l0+eXLlddE2JtW62gf8UjcPskBua4fU4J5lmHA==", - "dev": true + "version": "20230802.0.0", + "resolved": "https://registry.npmjs.org/google-closure-library/-/google-closure-library-20230802.0.0.tgz", + "integrity": "sha512-h2lBEX2tjWwfR+dhFukGER15vKY+4cA3nRqwKSOsBdyizlOxTAHOWbEYiGnMoom3/SrVeQ5uG0eKsbxQ3wbsxA==", + "dev": true, + "license": "Apache-2.0" }, "node_modules/graceful-fs": { "version": "4.2.11", @@ -879,76 +883,6 @@ "node": ">=10.13.0" } }, - "node_modules/gulp-cli/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/gulp-cli/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/gulp-cli/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/gulp-cli/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/gulp-cli/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/gulp-cli/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/gulplog": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-2.2.0.tgz", @@ -962,12 +896,13 @@ } }, "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/hasown": { @@ -1699,15 +1634,16 @@ } }, "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/supports-preserve-symlinks-flag": { @@ -2015,39 +1951,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -2114,12 +2017,12 @@ "dev": true }, "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "color-convert": "^1.9.0" + "color-convert": "^2.0.1" } }, "anymatch": { @@ -2260,14 +2163,13 @@ } }, "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" } }, "chokidar": { @@ -2327,18 +2229,18 @@ } }, "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "color-name": "1.1.3" + "color-name": "~1.1.4" } }, "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, "concat-map": { @@ -2406,12 +2308,6 @@ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - }, "expand-tilde": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", @@ -2641,59 +2537,52 @@ } }, "google-closure-compiler": { - "version": "20190819.0.0", - "resolved": "https://registry.npmjs.org/google-closure-compiler/-/google-closure-compiler-20190819.0.0.tgz", - "integrity": "sha512-5cwcui89TSFrKCa+oH5zq6F0esSHkGbWt1U2LgywakFhe5F27j/0F6NR7QyFYkBf3leDt5kPBvC2Dlc3ZwuFVA==", + "version": "20230802.0.0", + "resolved": "https://registry.npmjs.org/google-closure-compiler/-/google-closure-compiler-20230802.0.0.tgz", + "integrity": "sha512-o2fYoc8lqOBdhm95Ick0vWrtwH2Icd5yLZhbTcQ0T7NfGiBepYvx1BB63hR8ebgzEZemz9Fh+O6Kg/3Mjm28ww==", "dev": true, "requires": { - "chalk": "2.x", - "google-closure-compiler-java": "^20190819.0.0", - "google-closure-compiler-js": "^20190819.0.0", - "google-closure-compiler-linux": "^20190819.0.0", - "google-closure-compiler-osx": "^20190819.0.0", - "google-closure-compiler-windows": "^20190819.0.0", + "chalk": "4.x", + "google-closure-compiler-java": "^20230802.0.0", + "google-closure-compiler-linux": "^20230802.0.0", + "google-closure-compiler-osx": "^20230802.0.0", + "google-closure-compiler-windows": "^20230802.0.0", "minimist": "1.x", "vinyl": "2.x", "vinyl-sourcemaps-apply": "^0.2.0" } }, "google-closure-compiler-java": { - "version": "20190819.0.0", - "resolved": "https://registry.npmjs.org/google-closure-compiler-java/-/google-closure-compiler-java-20190819.0.0.tgz", - "integrity": "sha512-i8KzPJZBEF0aZWSn2vlkH0JCeQGIxBVfQaUwc2fCjPbm/v5YfpZzkj38LoMDbE95BlYsq2cPveHUNC4w85UgGw==", - "dev": true - }, - "google-closure-compiler-js": { - "version": "20190819.0.0", - "resolved": "https://registry.npmjs.org/google-closure-compiler-js/-/google-closure-compiler-js-20190819.0.0.tgz", - "integrity": "sha512-c1MrCW2sBsJ5d5judH6YnBPpxbOzts6D7XYa0KN4I97S0LjXzX5cENBlMUqMGGeSdFyjGr5FP0BxGp49k5UKxQ==", + "version": "20230802.0.0", + "resolved": "https://registry.npmjs.org/google-closure-compiler-java/-/google-closure-compiler-java-20230802.0.0.tgz", + "integrity": "sha512-PWKLMLwj7pR/U0yYbiy649LLqAscu+F1gyY4Y/jK6CmSLb8cIJbL8BTJd00828TzTNfWnYwxbkcQw0y9C2YsGw==", "dev": true }, "google-closure-compiler-linux": { - "version": "20190819.0.0", - "resolved": "https://registry.npmjs.org/google-closure-compiler-linux/-/google-closure-compiler-linux-20190819.0.0.tgz", - "integrity": "sha512-+ia89Ot4dPyRioLlxvkfYiISwJO+2NV7SY0Zp/KfTt9x+eJaGQ9GRIQage50d1mGkUyPmFfxsdPUePpT1QlpaA==", + "version": "20230802.0.0", + "resolved": "https://registry.npmjs.org/google-closure-compiler-linux/-/google-closure-compiler-linux-20230802.0.0.tgz", + "integrity": "sha512-F13U4iSXiWeGtHOFS25LVem1s6zI+pJvXVPVR7zSib5ppoUJ0JXnABJQezUR3FnpxmnkALG4oIGW0syH9zPLZA==", "dev": true, "optional": true }, "google-closure-compiler-osx": { - "version": "20190819.0.0", - "resolved": "https://registry.npmjs.org/google-closure-compiler-osx/-/google-closure-compiler-osx-20190819.0.0.tgz", - "integrity": "sha512-woANg+oA2zjFebtdYTA4lLtqbOVO9yE9yy8ibGjt76FNlw0bAyxTO4z2ab4CwUNNpOeRoxZyGt9CejlCmNpxJg==", + "version": "20230802.0.0", + "resolved": "https://registry.npmjs.org/google-closure-compiler-osx/-/google-closure-compiler-osx-20230802.0.0.tgz", + "integrity": "sha512-ANAi/ux92Tt+Na7vFDLeK2hRzotjC5j+nxoPtE0OcuNcbjji5dREKoJxkq7r0YwRTCzAFZszK5ip/NPdTOdCEg==", "dev": true, "optional": true }, "google-closure-compiler-windows": { - "version": "20190819.0.0", - "resolved": "https://registry.npmjs.org/google-closure-compiler-windows/-/google-closure-compiler-windows-20190819.0.0.tgz", - "integrity": "sha512-WglPY706c1oN03KiZF02FUWr/7M0eFoev4CQPncSihfjYXpD5E5PMKJ3ppawhzj60CQ9ceC/Omx7VN7Kp0uOQg==", + "version": "20230802.0.0", + "resolved": "https://registry.npmjs.org/google-closure-compiler-windows/-/google-closure-compiler-windows-20230802.0.0.tgz", + "integrity": "sha512-ZQPujoNiiUyTGl8zEGR/0yAygWnbMtX/NQ/S/EHVgq5nmYkvDEVuiVbgpPAmO9lzBTq0hvUTRRATZbTU2ISxgA==", "dev": true, "optional": true }, "google-closure-deps": { - "version": "20210406.0.0", - "resolved": "https://registry.npmjs.org/google-closure-deps/-/google-closure-deps-20210406.0.0.tgz", - "integrity": "sha512-4mn6qZ8u4c/9fhebKccxyN882l5/0O4nuJ+ibuxDy0y7XMgolSLNF/Gmg1HEhEgX00CF/JBKrc/rw0WVjnlSfw==", + "version": "20230802.0.0", + "resolved": "https://registry.npmjs.org/google-closure-deps/-/google-closure-deps-20230802.0.0.tgz", + "integrity": "sha512-5xhXO8xgxdXYZMsc8ZRzmnCm4prm0TcD33tcNr8l3OjSBovFO9MpgtrZxH/ZVnZMny6oOBmdeNqcO3afCYY9Lw==", "dev": true, "requires": { "minimatch": "^3.0.4", @@ -2701,9 +2590,9 @@ } }, "google-closure-library": { - "version": "20200315.0.0", - "resolved": "https://registry.npmjs.org/google-closure-library/-/google-closure-library-20200315.0.0.tgz", - "integrity": "sha512-LdCecdztxDvA9K+8b6E9aE4Hw7ABdYokfA7d5qW1sd/iy8O1l0+eXLlddE2JtW62gf8UjcPskBua4fU4J5lmHA==", + "version": "20230802.0.0", + "resolved": "https://registry.npmjs.org/google-closure-library/-/google-closure-library-20230802.0.0.tgz", + "integrity": "sha512-h2lBEX2tjWwfR+dhFukGER15vKY+4cA3nRqwKSOsBdyizlOxTAHOWbEYiGnMoom3/SrVeQ5uG0eKsbxQ3wbsxA==", "dev": true }, "graceful-fs": { @@ -2742,57 +2631,6 @@ "string-width": "^4.2.3", "v8flags": "^4.0.0", "yargs": "^16.2.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } } }, "gulplog": { @@ -2805,9 +2643,9 @@ } }, "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, "hasown": { @@ -3363,12 +3201,12 @@ } }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" } }, "supports-preserve-symlinks-flag": { @@ -3614,32 +3452,6 @@ "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - } } }, "wrappy": { diff --git a/package.json b/package.json index 277fed4..c35f530 100644 --- a/package.json +++ b/package.json @@ -12,12 +12,11 @@ "package.json", "README.md" ], - "dependencies": {}, "devDependencies": { "glob": "~7.1.4", - "google-closure-compiler": "~20190819.0.0", - "google-closure-deps": "^20210406.0.0", - "google-closure-library": "~20200315.0.0", + "google-closure-compiler": "20230802.0.0", + "google-closure-deps": "20230802.0.0", + "google-closure-library": "20230802.0.0", "gulp": "~5.0.0", "jasmine": "~3.5.0" }, diff --git a/proto3_test.js b/proto3_test.js index c1b3a44..5c0af41 100644 --- a/proto3_test.js +++ b/proto3_test.js @@ -225,15 +225,15 @@ describe('proto3Test', () => { let msg = new proto.jspb.test.TestProto3(); msg.setSingularInt32(-42); - msg.setSingularInt64(-0x7fffffff00000000); + msg.setSingularInt64(String(-BigInt('0x7fffffff00000000'))); msg.setSingularUint32(0x80000000); - msg.setSingularUint64(0xf000000000000000); + msg.setSingularUint64(String(BigInt('0xf000000000000000'))); msg.setSingularSint32(-100); - msg.setSingularSint64(-0x8000000000000000); + msg.setSingularSint64(String(-BigInt('0x8000000000000000'))); msg.setSingularFixed32(1234); - msg.setSingularFixed64(0x1234567800000000); + msg.setSingularFixed64(String(BigInt('0x1234567800000000'))); msg.setSingularSfixed32(-1234); - msg.setSingularSfixed64(-0x1234567800000000); + msg.setSingularSfixed64(String(-BigInt('0x1234567800000000'))); msg.setSingularFloat(1.5); msg.setSingularDouble(-1.5); msg.setSingularBool(true); @@ -245,15 +245,15 @@ describe('proto3Test', () => { msg.setSingularForeignEnum(proto.jspb.test.Proto3Enum.PROTO3_BAR); msg.setRepeatedInt32List([-42]); - msg.setRepeatedInt64List([-0x7fffffff00000000]); + msg.setRepeatedInt64List([String(-BigInt('0x7fffffff00000000'))]); msg.setRepeatedUint32List([0x80000000]); - msg.setRepeatedUint64List([0xf000000000000000]); + msg.setRepeatedUint64List([String(BigInt('0xf000000000000000'))]); msg.setRepeatedSint32List([-100]); - msg.setRepeatedSint64List([-0x8000000000000000]); + msg.setRepeatedSint64List([String(-BigInt('0x8000000000000000'))]); msg.setRepeatedFixed32List([1234]); - msg.setRepeatedFixed64List([0x1234567800000000]); + msg.setRepeatedFixed64List([String(BigInt('0x1234567800000000'))]); msg.setRepeatedSfixed32List([-1234]); - msg.setRepeatedSfixed64List([-0x1234567800000000]); + msg.setRepeatedSfixed64List([String(-BigInt('0x1234567800000000'))]); msg.setRepeatedFloatList([1.5]); msg.setRepeatedDoubleList([-1.5]); msg.setRepeatedBoolList([true]); @@ -270,15 +270,15 @@ describe('proto3Test', () => { msg = proto.jspb.test.TestProto3.deserializeBinary(serialized); expect(msg.getSingularInt32()).toEqual(-42); - expect(msg.getSingularInt64()).toEqual(-0x7fffffff00000000); + expect(msg.getSingularInt64()).toEqual(String(-BigInt('0x7fffffff00000000'))); expect(msg.getSingularUint32()).toEqual(0x80000000); - expect(msg.getSingularUint64()).toEqual(0xf000000000000000); + expect(msg.getSingularUint64()).toEqual(String(BigInt('0xf000000000000000'))); expect(msg.getSingularSint32()).toEqual(-100); - expect(msg.getSingularSint64()).toEqual(-0x8000000000000000); + expect(msg.getSingularSint64()).toEqual(String(-BigInt('0x8000000000000000'))); expect(msg.getSingularFixed32()).toEqual(1234); - expect(msg.getSingularFixed64()).toEqual(0x1234567800000000); + expect(msg.getSingularFixed64()).toEqual(String(BigInt('0x1234567800000000'))); expect(msg.getSingularSfixed32()).toEqual(-1234); - expect(msg.getSingularSfixed64()).toEqual(-0x1234567800000000); + expect(msg.getSingularSfixed64()).toEqual(String(-BigInt('0x1234567800000000'))); expect(msg.getSingularFloat()).toEqual(1.5); expect(msg.getSingularDouble()).toEqual(-1.5); expect(msg.getSingularBool()).toBeTrue(); @@ -289,15 +289,15 @@ describe('proto3Test', () => { .toEqual(proto.jspb.test.Proto3Enum.PROTO3_BAR); expect(msg.getRepeatedInt32List()).toEqual([-42]); - expect(msg.getRepeatedInt64List()).toEqual([-0x7fffffff00000000]); + expect(msg.getRepeatedInt64List()).toEqual([String(-BigInt('0x7fffffff00000000'))]); expect(msg.getRepeatedUint32List()).toEqual([0x80000000]); - expect(msg.getRepeatedUint64List()).toEqual([0xf000000000000000]); + expect(msg.getRepeatedUint64List()).toEqual([String(BigInt('0xf000000000000000'))]); expect(msg.getRepeatedSint32List()).toEqual([-100]); - expect(msg.getRepeatedSint64List()).toEqual([-0x8000000000000000]); + expect(msg.getRepeatedSint64List()).toEqual([String(-BigInt('0x8000000000000000'))]); expect(msg.getRepeatedFixed32List()).toEqual([1234]); - expect(msg.getRepeatedFixed64List()).toEqual([0x1234567800000000]); + expect(msg.getRepeatedFixed64List()).toEqual([String(BigInt('0x1234567800000000'))]); expect(msg.getRepeatedSfixed32List()).toEqual([-1234]); - expect(msg.getRepeatedSfixed64List()).toEqual([-0x1234567800000000]); + expect(msg.getRepeatedSfixed64List()).toEqual([String(-BigInt('0x1234567800000000'))]); expect(msg.getRepeatedFloatList()).toEqual([1.5]); expect(msg.getRepeatedDoubleList()).toEqual([-1.5]); expect(msg.getRepeatedBoolList()).toEqual([true]); diff --git a/unsafe_bytestring.js b/unsafe_bytestring.js new file mode 100644 index 0000000..d939df2 --- /dev/null +++ b/unsafe_bytestring.js @@ -0,0 +1,71 @@ +/** + * @fileoverview Provides unsafe routines for constructing and manipulating + * ByteString objects. + * + * These can be used to construct a `ByteString` from a `Uint8Array` without a + * copy or to access a `Uint8Array` from a `ByteString` without a copy. + * + * These operations are unsafe because the contract on `ByteString` is that it + * is immutable and these functions can be used to violate that contract. + * + * If the `Uint8Array` objects returned from or passed to these functions are + * mutated the results will be unpredictable. + * + * - These mutations may or may not be reflected in later reads of the + * ByteString + * - equality operations may not be consistent + * - Other protos parsed from these ByteString objects may themselves contain + * ByteString objects that contain mutable data. + * + * Because it is very unpredictable when or how these mutations might affect + * behavior far away in an application, access to these APIs is restricted. If + * you find yourself wanting to use these APIs please reach out to + * web-protos-dev@ + * + */ + +goog.module('jspb.unsafe_bytestring'); + +const {ByteString} = goog.require('jspb.bytestring'); +const {I_AM_INTERNAL} = goog.require('jspb.internal_bytes'); +const {assertInstanceof} = goog.require('goog.asserts'); + +/** + * Constructs a ByteString from the Uint8Array without a copy. + * + * @return {!ByteString} + */ +function unsafeByteStringFromUint8Array(/** !Uint8Array*/ array) { + assertInstanceof(array, Uint8Array); + return array.length == 0 ? ByteString.empty() : + new ByteString(array, I_AM_INTERNAL); +} + +/** + * Returns the Uint8Array from the ByteString without a defensive copy. + * + * Mutating the returned Uint8Array (if any) can lead to unpredictable behavior. + * + * @return {!Uint8Array} + */ +function unsafeUint8ArrayFromByteString(/** !ByteString*/ bytestring) { + assertInstanceof(bytestring, ByteString); + return bytestring.internalBytesUnsafe(I_AM_INTERNAL) || new Uint8Array(0); +} + +/** + * Returns the Uint8Array or base64 string from the bytestring with no copies. + * + * Mutating the returned Uint8Array (if any) can lead to unpredictable behavior + * @return {!Uint8Array|string} + */ +function unsafeUnwrapByteString(/** !ByteString*/ bytestring) { + assertInstanceof(bytestring, ByteString); + return bytestring.internalUnwrap(I_AM_INTERNAL); +} + +exports = { + unsafeByteStringFromUint8Array, + unsafeUint8ArrayFromByteString, + unsafeUnwrapByteString, +}; diff --git a/yarn.lock b/yarn.lock index 4f70eed..814ae3a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -19,21 +19,7 @@ ansi-regex@^5.0.1: resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0: - version "4.3.0" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -ansi-styles@^4.1.0: +ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== @@ -140,7 +126,7 @@ buffer@^6.0.3: base64-js "^1.3.1" ieee754 "^1.2.1" -chalk@^4.1.2: +chalk@^4.1.2, chalk@4.x: version "4.1.2" resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -148,15 +134,6 @@ chalk@^4.1.2: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@2.x: - version "2.4.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - chokidar@^3.5.3: version "3.6.0" resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz" @@ -205,13 +182,6 @@ cloneable-readable@^1.0.0: process-nextick-args "^2.0.0" readable-stream "^2.3.5" -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - color-convert@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" @@ -224,11 +194,6 @@ color-name@~1.1.4: resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - concat-map@0.0.1: version "0.0.1" resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" @@ -282,11 +247,6 @@ escalade@^3.1.1: resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== - expand-tilde@^2.0.0, expand-tilde@^2.0.2: version "2.0.2" resolved "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz" @@ -466,49 +426,43 @@ glogg@^2.2.0: dependencies: sparkles "^2.1.0" -google-closure-compiler-java@^20190819.0.0: - version "20190819.0.0" - resolved "https://registry.npmjs.org/google-closure-compiler-java/-/google-closure-compiler-java-20190819.0.0.tgz" - integrity sha512-i8KzPJZBEF0aZWSn2vlkH0JCeQGIxBVfQaUwc2fCjPbm/v5YfpZzkj38LoMDbE95BlYsq2cPveHUNC4w85UgGw== - -google-closure-compiler-js@^20190819.0.0: - version "20190819.0.0" - resolved "https://registry.npmjs.org/google-closure-compiler-js/-/google-closure-compiler-js-20190819.0.0.tgz" - integrity sha512-c1MrCW2sBsJ5d5judH6YnBPpxbOzts6D7XYa0KN4I97S0LjXzX5cENBlMUqMGGeSdFyjGr5FP0BxGp49k5UKxQ== - -google-closure-compiler-linux@^20190819.0.0: - version "20190819.0.0" - resolved "https://registry.npmjs.org/google-closure-compiler-linux/-/google-closure-compiler-linux-20190819.0.0.tgz" - integrity sha512-+ia89Ot4dPyRioLlxvkfYiISwJO+2NV7SY0Zp/KfTt9x+eJaGQ9GRIQage50d1mGkUyPmFfxsdPUePpT1QlpaA== - -google-closure-compiler@~20190819.0.0: - version "20190819.0.0" - resolved "https://registry.npmjs.org/google-closure-compiler/-/google-closure-compiler-20190819.0.0.tgz" - integrity sha512-5cwcui89TSFrKCa+oH5zq6F0esSHkGbWt1U2LgywakFhe5F27j/0F6NR7QyFYkBf3leDt5kPBvC2Dlc3ZwuFVA== - dependencies: - chalk "2.x" - google-closure-compiler-java "^20190819.0.0" - google-closure-compiler-js "^20190819.0.0" +google-closure-compiler-java@^20230802.0.0: + version "20230802.0.0" + resolved "https://registry.npmjs.org/google-closure-compiler-java/-/google-closure-compiler-java-20230802.0.0.tgz" + integrity sha512-PWKLMLwj7pR/U0yYbiy649LLqAscu+F1gyY4Y/jK6CmSLb8cIJbL8BTJd00828TzTNfWnYwxbkcQw0y9C2YsGw== + +google-closure-compiler-linux@^20230802.0.0: + version "20230802.0.0" + resolved "https://registry.npmjs.org/google-closure-compiler-linux/-/google-closure-compiler-linux-20230802.0.0.tgz" + integrity sha512-F13U4iSXiWeGtHOFS25LVem1s6zI+pJvXVPVR7zSib5ppoUJ0JXnABJQezUR3FnpxmnkALG4oIGW0syH9zPLZA== + +google-closure-compiler@20230802.0.0: + version "20230802.0.0" + resolved "https://registry.npmjs.org/google-closure-compiler/-/google-closure-compiler-20230802.0.0.tgz" + integrity sha512-o2fYoc8lqOBdhm95Ick0vWrtwH2Icd5yLZhbTcQ0T7NfGiBepYvx1BB63hR8ebgzEZemz9Fh+O6Kg/3Mjm28ww== + dependencies: + chalk "4.x" + google-closure-compiler-java "^20230802.0.0" minimist "1.x" vinyl "2.x" vinyl-sourcemaps-apply "^0.2.0" optionalDependencies: - google-closure-compiler-linux "^20190819.0.0" - google-closure-compiler-osx "^20190819.0.0" - google-closure-compiler-windows "^20190819.0.0" + google-closure-compiler-linux "^20230802.0.0" + google-closure-compiler-osx "^20230802.0.0" + google-closure-compiler-windows "^20230802.0.0" -google-closure-deps@^20210406.0.0: - version "20210406.0.0" - resolved "https://registry.npmjs.org/google-closure-deps/-/google-closure-deps-20210406.0.0.tgz" - integrity sha512-4mn6qZ8u4c/9fhebKccxyN882l5/0O4nuJ+ibuxDy0y7XMgolSLNF/Gmg1HEhEgX00CF/JBKrc/rw0WVjnlSfw== +google-closure-deps@20230802.0.0: + version "20230802.0.0" + resolved "https://registry.npmjs.org/google-closure-deps/-/google-closure-deps-20230802.0.0.tgz" + integrity sha512-5xhXO8xgxdXYZMsc8ZRzmnCm4prm0TcD33tcNr8l3OjSBovFO9MpgtrZxH/ZVnZMny6oOBmdeNqcO3afCYY9Lw== dependencies: minimatch "^3.0.4" yargs "^16.2.0" -google-closure-library@~20200315.0.0: - version "20200315.0.0" - resolved "https://registry.npmjs.org/google-closure-library/-/google-closure-library-20200315.0.0.tgz" - integrity sha512-LdCecdztxDvA9K+8b6E9aE4Hw7ABdYokfA7d5qW1sd/iy8O1l0+eXLlddE2JtW62gf8UjcPskBua4fU4J5lmHA== +google-closure-library@20230802.0.0: + version "20230802.0.0" + resolved "https://registry.npmjs.org/google-closure-library/-/google-closure-library-20230802.0.0.tgz" + integrity sha512-h2lBEX2tjWwfR+dhFukGER15vKY+4cA3nRqwKSOsBdyizlOxTAHOWbEYiGnMoom3/SrVeQ5uG0eKsbxQ3wbsxA== graceful-fs@^4.2.10, graceful-fs@^4.2.11, graceful-fs@^4.2.8: version "4.2.11" @@ -550,11 +504,6 @@ gulplog@^2.2.0: dependencies: glogg "^2.2.0" -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== - has-flag@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" @@ -1023,13 +972,6 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - supports-color@^7.1.0: version "7.2.0" resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" From 3050f037fa29809db07a043fe465a21a418bd885 Mon Sep 17 00:00:00 2001 From: Stephanie DiBenedetto Date: Mon, 11 Aug 2025 10:26:36 -0700 Subject: [PATCH 13/22] Do not ignore descriptor extensions Previously, we blanket ignored extensions against the descriptor well known type for historical reasons. We marked this for cleanup in #85; this change follows through on it. --- generator/js_generator.cc | 12 ++---------- jasmine.json | 1 + 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/generator/js_generator.cc b/generator/js_generator.cc index 0098f29..d6a9e79 100644 --- a/generator/js_generator.cc +++ b/generator/js_generator.cc @@ -430,20 +430,12 @@ std::string GetEnumFileName(const GeneratorOptions& options, // Returns the message/response ID, if set. std::string GetMessageId(const Descriptor* desc) { return std::string(); } -bool IgnoreExtensionField(const FieldDescriptor* field) { - // Exclude descriptor extensions from output "to avoid clutter" (from original - // codegen). - if (!field->is_extension()) return false; - const FileDescriptor* file = field->containing_type()->file(); - return file->name() == "net/proto2/proto/descriptor.proto" || - file->name() == "google/protobuf/descriptor.proto"; -} - // Used inside Google only -- do not remove. bool IsResponse(const Descriptor* desc) { return false; } bool IgnoreField(const FieldDescriptor* field) { - return IgnoreExtensionField(field); + // no-op in open source + return false; } // Do we ignore this message type? diff --git a/jasmine.json b/jasmine.json index aeea72f..229fd3a 100644 --- a/jasmine.json +++ b/jasmine.json @@ -11,6 +11,7 @@ "google/protobuf/any.js", "google/protobuf/struct.js", "google/protobuf/timestamp.js", + "google/protobuf/descriptor.js", "testproto_libs1.js", "testproto_libs2.js" ] From e6d763860001ba1a76a63adcff5efb12b1c96024 Mon Sep 17 00:00:00 2001 From: Stephanie DiBenedetto Date: Wed, 13 Aug 2025 13:36:51 -0700 Subject: [PATCH 14/22] Limit global resolution to globalThis Historically we've supported old platforms with a variety of fallback options for determining a global object. However, our use of Function('return this') is essentially an eval, which causes issues for strict CSP. On consulation with other teams, we think we can just rely on globalThis at this point in time. --- generator/js_generator.cc | 21 +-------------------- internal_options.js | 3 +-- 2 files changed, 2 insertions(+), 22 deletions(-) diff --git a/generator/js_generator.cc b/generator/js_generator.cc index d6a9e79..a1619fa 100644 --- a/generator/js_generator.cc +++ b/generator/js_generator.cc @@ -3641,26 +3641,7 @@ void Generator::GenerateFile(const GeneratorOptions& options, if (options.import_style == GeneratorOptions::kImportCommonJsStrict) { printer->Print("var proto = {};\n\n"); } else { - // To get the global object we call a function with .call(null), this will - // set "this" inside the function to the global object. This does not work - // if we are running in strict mode ("use strict"), so we fallback to the - // following things (in order from first to last): - // - globalThis: cross-platform standard, might not be defined in older - // versions of browsers - // - window: defined in browsers - // - global: defined in most server side environments like NodeJS - // - self: defined inside Web Workers (WorkerGlobalScope) - // - Function('return this')(): this will work on most platforms, but it - // may be blocked by things like CSP. - // Function('') is almost the same as eval('') - printer->Print( - "var global =\n" - " (typeof globalThis !== 'undefined' && globalThis) ||\n" - " (typeof window !== 'undefined' && window) ||\n" - " (typeof global !== 'undefined' && global) ||\n" - " (typeof self !== 'undefined' && self) ||\n" - " (function () { return this; }).call(null) ||\n" - " Function('return this')();\n\n"); + printer->Print("var global = globalThis;\n\n"); } for (int i = 0; i < file->dependency_count(); i++) { diff --git a/internal_options.js b/internal_options.js index ecdac9e..aff1018 100644 --- a/internal_options.js +++ b/internal_options.js @@ -28,14 +28,13 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** - * @fileoverview Internal options for. + * @fileoverview Internal options. */ goog.module('jspb.internal_options'); /** * @return {boolean} True if BigInt is permitted for use and supported by the * platform. - * @nosideeffects */ function isBigIntAvailable() { return goog.FEATURESET_YEAR >= 2021 || (typeof BigInt === 'function'); From 100c10bd4d5b8e25b46a3c102a766d2055cddc7a Mon Sep 17 00:00:00 2001 From: Stephanie DiBenedetto Date: Wed, 13 Aug 2025 14:01:31 -0700 Subject: [PATCH 15/22] Update windows build from windows-2019 -> 2022 image windows-2019 is a deprecated github runner. Updating to 2022 which is considered `latest`. --- .bazelrc | 12 +++++++++++- .github/workflows/build.yml | 6 +++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/.bazelrc b/.bazelrc index 01314ff..74109e9 100644 --- a/.bazelrc +++ b/.bazelrc @@ -1,4 +1,5 @@ -build --cxxopt=-std=c++17 --host_cxxopt=-std=c++17 +build:linux --cxxopt=-std=c++17 --host_cxxopt=-std=c++17 +build:macos --cxxopt=-std=c++17 --host_cxxopt=-std=c++17 build:dbg --compilation_mode=dbg @@ -26,5 +27,14 @@ build:ubsan --copt=-fno-sanitize=function --copt=-fno-sanitize=vptr # Important: this flag ensures that we remain compliant with the C++ layering # check. build --features=layering_check +common --enable_platform_specific_config + +build:windows --cxxopt=/std:c++17 +build:windows --host_cxxopt=/std:c++17 common --repo_env=BAZEL_NO_APPLE_CPP_TOOLCHAIN=1 + + +# Allow building with MSVC, which is being deprecated. +# See: https://github.com/protocolbuffers/protobuf/issues/20085 +build --define=protobuf_allow_msvc=true diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index eca575f..6fb046d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -68,10 +68,10 @@ jobs: # - ppc64 include: # to ensure backwards compatibility as long as possible, use earliest versions of OSs available on Github Actions - - os: windows-2019 + - os: windows-2022 cpu: x64_windows bazel_target: dist_zip - - os: windows-2019 + - os: windows-2022 cpu: x64_x86_windows bazel_target: dist_zip # disabling Mac OS releases for now since they are working through existing build process @@ -88,7 +88,7 @@ jobs: with: name: js - - uses: bazel-contrib/setup-bazel@0.8.5 + - uses: bazel-contrib/setup-bazel@0.15.0 with: token: ${{ secrets.GITHUB_TOKEN }} From 78f5b151ebe8b271422f83527dd15b686435145e Mon Sep 17 00:00:00 2001 From: Stephanie DiBenedetto Date: Thu, 14 Aug 2025 16:25:07 -0700 Subject: [PATCH 16/22] Prepare 4.0.0 release Notable inclusions: * edition 2023 support * improved binary serialization/deserialization * global result now only depends on globalThis There are no material changes to our JS API. However, serialization/deserialization and strict dependence on globalThis may be significant in terms of supported clients and behavior. We generally expect the new binary handling code to be more reliable and conformant. --- .github/workflows/build.yml | 2 +- package-lock.json | 4 ++-- package.json | 2 +- protobuf_javascript_release.bzl | 2 +- yarn.lock | 15 +++++++++++++++ 5 files changed, 20 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6fb046d..d5bd243 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,7 +6,7 @@ permissions: read-all # update in build.yml and codeql.yml at same time env: - PROTOC_VERSION: "31.0" + PROTOC_VERSION: "32.0" jobs: build: diff --git a/package-lock.json b/package-lock.json index 088cd4a..6239081 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "google-protobuf", - "version": "3.21.5", + "version": "4.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "google-protobuf", - "version": "3.21.5", + "version": "4.0.0", "license": "(BSD-3-Clause AND Apache-2.0)", "devDependencies": { "glob": "~7.1.4", diff --git a/package.json b/package.json index c35f530..68344e1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "google-protobuf", - "version": "3.21.4", + "version": "4.0.0", "description": "Protocol Buffers for JavaScript", "main": "google-protobuf.js", "files": [ diff --git a/protobuf_javascript_release.bzl b/protobuf_javascript_release.bzl index 3f9090a..0dbb505 100644 --- a/protobuf_javascript_release.bzl +++ b/protobuf_javascript_release.bzl @@ -3,7 +3,7 @@ load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain") load("@rules_pkg//pkg:providers.bzl", "PackageVariablesInfo") -_PROTOBUF_JAVASCRIPT_VERSION = "3.21.4" +_PROTOBUF_JAVASCRIPT_VERSION = "4.0.0" def _package_naming_impl(ctx): values = {} diff --git a/yarn.lock b/yarn.lock index 814ae3a..27858e0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -341,6 +341,11 @@ fs.realpath@^1.0.0: resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== +fsevents@~2.3.2: + version "2.3.3" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + function-bind@^1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" @@ -436,6 +441,16 @@ google-closure-compiler-linux@^20230802.0.0: resolved "https://registry.npmjs.org/google-closure-compiler-linux/-/google-closure-compiler-linux-20230802.0.0.tgz" integrity sha512-F13U4iSXiWeGtHOFS25LVem1s6zI+pJvXVPVR7zSib5ppoUJ0JXnABJQezUR3FnpxmnkALG4oIGW0syH9zPLZA== +google-closure-compiler-osx@^20230802.0.0: + version "20230802.0.0" + resolved "https://registry.npmjs.org/google-closure-compiler-osx/-/google-closure-compiler-osx-20230802.0.0.tgz" + integrity sha512-ANAi/ux92Tt+Na7vFDLeK2hRzotjC5j+nxoPtE0OcuNcbjji5dREKoJxkq7r0YwRTCzAFZszK5ip/NPdTOdCEg== + +google-closure-compiler-windows@^20230802.0.0: + version "20230802.0.0" + resolved "https://registry.npmjs.org/google-closure-compiler-windows/-/google-closure-compiler-windows-20230802.0.0.tgz" + integrity sha512-ZQPujoNiiUyTGl8zEGR/0yAygWnbMtX/NQ/S/EHVgq5nmYkvDEVuiVbgpPAmO9lzBTq0hvUTRRATZbTU2ISxgA== + google-closure-compiler@20230802.0.0: version "20230802.0.0" resolved "https://registry.npmjs.org/google-closure-compiler/-/google-closure-compiler-20230802.0.0.tgz" From 0db1d6b00ecafc036c05cd22f118d1d336d17428 Mon Sep 17 00:00:00 2001 From: Stephanie DiBenedetto Date: Thu, 14 Aug 2025 10:08:19 -0700 Subject: [PATCH 17/22] enable builds on macos x86_64 and aarch64 runners --- .github/workflows/build.yml | 12 +++++++----- BUILD.bazel | 12 ++++++++++++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d5bd243..9b06e72 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -74,11 +74,13 @@ jobs: - os: windows-2022 cpu: x64_x86_windows bazel_target: dist_zip -# disabling Mac OS releases for now since they are working through existing build process -# - os: macos-11 -# cpu: darwin_arm64 -# - os: macos-11 -# cpu: darwin_x86_64 + - os: macos-14 + cpu: darwin_arm64 + bazel_target: dist_zip + - os: macos-13 + cpu: darwin_x86_64 + bazel_target: dist_zip + steps: - uses: actions/checkout@v4 diff --git a/BUILD.bazel b/BUILD.bazel index 0a4b73b..62355ce 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -21,12 +21,24 @@ config_setting( values = {"cpu": "k8"}, ) +config_setting( + name = "darwin_arm64", + values = {"cpu": "darwin_arm64"}, +) + +config_setting( + name = "darwin_x86_64", + values = {"cpu": "darwin_x86_64"}, +) + package_naming( name = "protobuf_javascript_pkg_naming", platform = select({ ":k8": "linux-x86_64", # currently the only supported build type in Github Actions ":x64_x86_windows": "win32", ":x64_windows": "win64", + ":darwin_arm64": "osx-aarch_64", + ":darwin_x86_64": "osx-x86_64", "//conditions:default": "" # continues with current behavior when no --cpu is specified allowing existing internal builds to function }) ) From 861c8020a5c0cba9b7cdf915dffde96a4421a1f4 Mon Sep 17 00:00:00 2001 From: Stephanie DiBenedetto Date: Fri, 15 Aug 2025 14:09:45 -0700 Subject: [PATCH 18/22] Bump module versions for 4.0.0 release --- MODULE.bazel | 6 ++--- MODULE.bazel.lock | 56 ++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 51 insertions(+), 11 deletions(-) diff --git a/MODULE.bazel b/MODULE.bazel index a603777..d120d61 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -1,5 +1,5 @@ -module(name = "protobuf_javascript", version = "3.21.4") +module(name = "protobuf_javascript", version = "4.0.0") -bazel_dep(name = "protobuf", version = "31.1", repo_name = "com_google_protobuf") +bazel_dep(name = "protobuf", version = "32.0", repo_name = "com_google_protobuf") bazel_dep(name = "rules_pkg", version = "1.0.1") -bazel_dep(name = "abseil-cpp", version = "20250127.0") +bazel_dep(name = "abseil-cpp", version = "20250512.1") diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index 7299fdd..86b517a 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -10,8 +10,9 @@ "https://bcr.bazel.build/modules/abseil-cpp/20230802.1/MODULE.bazel": "fa92e2eb41a04df73cdabeec37107316f7e5272650f81d6cc096418fe647b915", "https://bcr.bazel.build/modules/abseil-cpp/20240116.1/MODULE.bazel": "37bcdb4440fbb61df6a1c296ae01b327f19e9bb521f9b8e26ec854b6f97309ed", "https://bcr.bazel.build/modules/abseil-cpp/20240116.2/MODULE.bazel": "73939767a4686cd9a520d16af5ab440071ed75cec1a876bf2fcfaf1f71987a16", - "https://bcr.bazel.build/modules/abseil-cpp/20250127.0/MODULE.bazel": "d1086e248cda6576862b4b3fe9ad76a214e08c189af5b42557a6e1888812c5d5", - "https://bcr.bazel.build/modules/abseil-cpp/20250127.0/source.json": "1b996859f840d8efc7c720efc61dcf2a84b1261cb3974cbbe9b6666ebf567775", + "https://bcr.bazel.build/modules/abseil-cpp/20250127.1/MODULE.bazel": "c4a89e7ceb9bf1e25cf84a9f830ff6b817b72874088bf5141b314726e46a57c1", + "https://bcr.bazel.build/modules/abseil-cpp/20250512.1/MODULE.bazel": "d209fdb6f36ffaf61c509fcc81b19e81b411a999a934a032e10cd009a0226215", + "https://bcr.bazel.build/modules/abseil-cpp/20250512.1/source.json": "d725d73707d01bb46ab3ca59ba408b8e9bd336642ca77a2269d4bfb8bbfd413d", "https://bcr.bazel.build/modules/apple_support/1.11.1/MODULE.bazel": "1843d7cd8a58369a444fc6000e7304425fba600ff641592161d9f15b179fb896", "https://bcr.bazel.build/modules/apple_support/1.15.1/MODULE.bazel": "a0556fefca0b1bb2de8567b8827518f94db6a6e7e7d632b4c48dc5f865bc7c85", "https://bcr.bazel.build/modules/apple_support/1.15.1/source.json": "517f2b77430084c541bc9be2db63fdcbb7102938c5f64c17ee60ffda2e5cf07b", @@ -47,7 +48,8 @@ "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6", "https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f", "https://bcr.bazel.build/modules/googletest/1.15.2/MODULE.bazel": "6de1edc1d26cafb0ea1a6ab3f4d4192d91a312fd2d360b63adaa213cd00b2108", - "https://bcr.bazel.build/modules/googletest/1.15.2/source.json": "dbdda654dcb3a0d7a8bc5d0ac5fc7e150b58c2a986025ae5bc634bb2cb61f470", + "https://bcr.bazel.build/modules/googletest/1.17.0/MODULE.bazel": "dbec758171594a705933a29fcf69293d2468c49ec1f2ebca65c36f504d72df46", + "https://bcr.bazel.build/modules/googletest/1.17.0/source.json": "38e4454b25fc30f15439c0378e57909ab1fd0a443158aa35aec685da727cd713", "https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075", "https://bcr.bazel.build/modules/jsoncpp/1.9.6/MODULE.bazel": "2f8d20d3b7d54143213c4dfc3d98225c42de7d666011528dc8fe91591e2e17b0", "https://bcr.bazel.build/modules/jsoncpp/1.9.6/source.json": "a04756d367a2126c3541682864ecec52f92cdee80a35735a3cb249ce015ca000", @@ -69,9 +71,10 @@ "https://bcr.bazel.build/modules/protobuf/29.0-rc2/MODULE.bazel": "6241d35983510143049943fc0d57937937122baf1b287862f9dc8590fc4c37df", "https://bcr.bazel.build/modules/protobuf/29.0-rc3/MODULE.bazel": "33c2dfa286578573afc55a7acaea3cada4122b9631007c594bf0729f41c8de92", "https://bcr.bazel.build/modules/protobuf/29.0/MODULE.bazel": "319dc8bf4c679ff87e71b1ccfb5a6e90a6dbc4693501d471f48662ac46d04e4e", + "https://bcr.bazel.build/modules/protobuf/29.1/MODULE.bazel": "557c3457560ff49e122ed76c0bc3397a64af9574691cb8201b4e46d4ab2ecb95", "https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0", - "https://bcr.bazel.build/modules/protobuf/31.1/MODULE.bazel": "379a389bb330b7b8c1cdf331cc90bf3e13de5614799b3b52cdb7c6f389f6b38e", - "https://bcr.bazel.build/modules/protobuf/31.1/source.json": "25af5d0219da0c0fc4d1191a24ce438e6ca7f49d2e1a94f354efeba6ef10426f", + "https://bcr.bazel.build/modules/protobuf/32.0/MODULE.bazel": "0741cf24f8e1185286578069060e905ed67d68eef5990bfa3dea3fc1afba14c7", + "https://bcr.bazel.build/modules/protobuf/32.0/source.json": "1e278267d3642ab361dc460cc1f2d8e607e8292b9b3f799a47181a3acf4f3294", "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e", "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/MODULE.bazel": "e6f4c20442eaa7c90d7190d8dc539d0ab422f95c65a57cc59562170c58ae3d34", "https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/source.json": "6900fdc8a9e95866b8c0d4ad4aba4d4236317b5c1cd04c502df3f0d33afed680", @@ -136,7 +139,8 @@ "https://bcr.bazel.build/modules/rules_proto/6.0.0-rc1/MODULE.bazel": "1e5b502e2e1a9e825eef74476a5a1ee524a92297085015a052510b09a1a09483", "https://bcr.bazel.build/modules/rules_proto/6.0.2/MODULE.bazel": "ce916b775a62b90b61888052a416ccdda405212b6aaeb39522f7dc53431a5e73", "https://bcr.bazel.build/modules/rules_proto/7.0.2/MODULE.bazel": "bf81793bd6d2ad89a37a40693e56c61b0ee30f7a7fdbaf3eabbf5f39de47dea2", - "https://bcr.bazel.build/modules/rules_proto/7.0.2/source.json": "1e5e7260ae32ef4f2b52fd1d0de8d03b606a44c91b694d2f1afb1d3b28a48ce1", + "https://bcr.bazel.build/modules/rules_proto/7.1.0/MODULE.bazel": "002d62d9108f75bb807cd56245d45648f38275cb3a99dcd45dfb864c5d74cb96", + "https://bcr.bazel.build/modules/rules_proto/7.1.0/source.json": "39f89066c12c24097854e8f57ab8558929f9c8d474d34b2c00ac04630ad8940e", "https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f", "https://bcr.bazel.build/modules/rules_python/0.23.1/MODULE.bazel": "49ffccf0511cb8414de28321f5fcf2a31312b47c40cc21577144b7447f2bf300", "https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382", @@ -145,8 +149,8 @@ "https://bcr.bazel.build/modules/rules_python/0.33.2/MODULE.bazel": "3e036c4ad8d804a4dad897d333d8dce200d943df4827cb849840055be8d2e937", "https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c", "https://bcr.bazel.build/modules/rules_python/0.40.0/MODULE.bazel": "9d1a3cd88ed7d8e39583d9ffe56ae8a244f67783ae89b60caafc9f5cf318ada7", - "https://bcr.bazel.build/modules/rules_python/1.0.0/MODULE.bazel": "898a3d999c22caa585eb062b600f88654bf92efb204fa346fb55f6f8edffca43", - "https://bcr.bazel.build/modules/rules_python/1.0.0/source.json": "b0162a65c6312e45e7912e39abd1a7f8856c2c7e41ecc9b6dc688a6f6400a917", + "https://bcr.bazel.build/modules/rules_python/1.4.1/MODULE.bazel": "8991ad45bdc25018301d6b7e1d3626afc3c8af8aaf4bc04f23d0b99c938b73a6", + "https://bcr.bazel.build/modules/rules_python/1.4.1/source.json": "8ec8c90c70ccacc4de8ca1b97f599e756fb59173e898ee08b733006650057c07", "https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c", "https://bcr.bazel.build/modules/rules_shell/0.3.0/MODULE.bazel": "de4402cd12f4cc8fda2354fce179fdb068c0b9ca1ec2d2b17b3e21b24c1a937b", "https://bcr.bazel.build/modules/rules_shell/0.3.0/source.json": "c55ed591aa5009401ddf80ded9762ac32c358d2517ee7820be981e2de9756cf3", @@ -264,6 +268,42 @@ ] ] } + }, + "@@rules_python+//python/uv:uv.bzl%uv": { + "general": { + "bzlTransitiveDigest": "Xpqjnjzy6zZ90Es9Wa888ZLHhn7IsNGbph/e6qoxzw8=", + "usagesDigest": "4JapxcpS0mL3524k0TZJffAtVyuRjDHZvN9kBRxxF1U=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "uv": { + "repoRuleId": "@@rules_python+//python/uv/private:uv_toolchains_repo.bzl%uv_toolchains_repo", + "attributes": { + "toolchain_type": "'@@rules_python+//python/uv:uv_toolchain_type'", + "toolchain_names": [ + "none" + ], + "toolchain_implementations": { + "none": "'@@rules_python+//python:none'" + }, + "toolchain_compatible_with": { + "none": [ + "@platforms//:incompatible" + ] + }, + "toolchain_target_settings": {} + } + } + }, + "recordedRepoMappingEntries": [ + [ + "rules_python+", + "platforms", + "platforms" + ] + ] + } } } } From 8e45d423e4dbfee123a5d7bcaa7c9f85d7172632 Mon Sep 17 00:00:00 2001 From: Stephanie DiBenedetto Date: Tue, 19 Aug 2025 13:34:29 -0700 Subject: [PATCH 19/22] Create SECURITY.md --- SECURITY.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..78e405c --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,5 @@ +# Security Policy + +To report security concerns or vulnerabilities within protobuf-javascript, please use Google's official reporting channel: + +https://www.google.com/appserve/security-bugs/m2/new From 8f74abe8452082cf31de7c9db1b9e1c08aded372 Mon Sep 17 00:00:00 2001 From: Stephanie DiBenedetto Date: Tue, 19 Aug 2025 13:45:34 -0700 Subject: [PATCH 20/22] Remove (unused) release step of build.yml --- .github/workflows/build.yml | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9b06e72..045bfca 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,4 +1,4 @@ -name: Build, Test and Release +name: Build and Test on: push @@ -108,25 +108,3 @@ jobs: with: name: release-${{ matrix.os }}-${{ matrix.cpu }} path: out - - release: - needs: package - if: startsWith(github.ref, 'refs/tags/') - - runs-on: ubuntu-latest - permissions: - contents: write - - steps: - - uses: actions/download-artifact@v4 - with: - name: release-${{ matrix.os }}-${{ matrix.cpu }} - - - name: Release - uses: svenstaro/upload-release-action@v2 - with: - repo_token: ${{ secrets.GITHUB_TOKEN }} - file: protobuf-javascript-* - file_glob: true - tag: ${{ github.ref }} - overwrite: true From 16d403004e88387e9d4e26a48a00fb6a419b58d6 Mon Sep 17 00:00:00 2001 From: Stephanie DiBenedetto Date: Tue, 19 Aug 2025 19:12:25 -0700 Subject: [PATCH 21/22] Rename scorecard.yml -> scorecards.yml Current seeing the error "The Action workflow file .github/workflows/scorecards.yml no longer exists." Renaming the workflow file to try to fix. --- .github/workflows/{scorecard.yml => scorecards.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{scorecard.yml => scorecards.yml} (100%) diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecards.yml similarity index 100% rename from .github/workflows/scorecard.yml rename to .github/workflows/scorecards.yml From cbeded24c7ebf62ed4d83ead2638c41b3078033b Mon Sep 17 00:00:00 2001 From: Stephanie DiBenedetto Date: Tue, 19 Aug 2025 20:18:20 -0700 Subject: [PATCH 22/22] Fixup scorecards.yml - try to fix 'invalid name' error for upload file artifact by just removing the setting; it's optional and will default to 'artifact' - bump various action versions --- .github/workflows/scorecards.yml | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index d4588b0..aa88846 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -37,15 +37,10 @@ jobs: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1 + uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2 with: results_file: results.sarif results_format: sarif - # (Optional) "write" PAT token. Uncomment the `repo_token` line below if: - # - you want to enable the Branch-Protection check on a *public* repository, or - # - you are installing Scorecard on a *private* repository - # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action?tab=readme-ov-file#authentication-with-fine-grained-pat-optional. - # repo_token: ${{ secrets.SCORECARD_TOKEN }} # Public repositories: # - Publish results to OpenSSF REST API for easy access by consumers @@ -59,15 +54,14 @@ jobs: # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@97a0fba1372883ab732affbe8f94b823f91727db # v3.pre.node20 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: - name: SARIF file path: results.sarif retention-days: 5 # Upload the results to GitHub's code scanning dashboard (optional). # Commenting out will disable upload of results to your repo's Code Scanning dashboard - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@v3 + uses: github/codeql-action/upload-sarif@96f518a34f7a870018057716cc4d7a5c014bd61c # v3.29.10 with: sarif_file: results.sarif