| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927 | 
							- /**
 
-  * @fileoverview Tests for writer.js.
 
-  */
 
- goog.module('protobuf.binary.WriterTest');
 
- goog.setTestOnly();
 
- // Note to the reader:
 
- // Since the writer behavior changes with the checking level some of the tests
 
- // in this file have to know which checking level is enable to make correct
 
- // assertions.
 
- const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
 
- const ByteString = goog.require('protobuf.ByteString');
 
- const WireType = goog.require('protobuf.binary.WireType');
 
- const Writer = goog.require('protobuf.binary.Writer');
 
- const {CHECK_BOUNDS, CHECK_TYPE, MAX_FIELD_NUMBER} = goog.require('protobuf.internal.checks');
 
- const {arrayBufferSlice} = goog.require('protobuf.binary.typedArrays');
 
- const {getDoublePairs} = goog.require('protobuf.binary.doubleTestPairs');
 
- const {getFixed32Pairs} = goog.require('protobuf.binary.fixed32TestPairs');
 
- const {getFloatPairs} = goog.require('protobuf.binary.floatTestPairs');
 
- const {getInt32Pairs} = goog.require('protobuf.binary.int32TestPairs');
 
- const {getInt64Pairs} = goog.require('protobuf.binary.int64TestPairs');
 
- const {getPackedBoolPairs} = goog.require('protobuf.binary.packedBoolTestPairs');
 
- const {getPackedDoublePairs} = goog.require('protobuf.binary.packedDoubleTestPairs');
 
- const {getPackedFixed32Pairs} = goog.require('protobuf.binary.packedFixed32TestPairs');
 
- const {getPackedFloatPairs} = goog.require('protobuf.binary.packedFloatTestPairs');
 
- const {getPackedInt32Pairs} = goog.require('protobuf.binary.packedInt32TestPairs');
 
- const {getPackedInt64Pairs} = goog.require('protobuf.binary.packedInt64TestPairs');
 
- const {getPackedSfixed32Pairs} = goog.require('protobuf.binary.packedSfixed32TestPairs');
 
- const {getPackedSfixed64Pairs} = goog.require('protobuf.binary.packedSfixed64TestPairs');
 
- const {getPackedSint32Pairs} = goog.require('protobuf.binary.packedSint32TestPairs');
 
- const {getPackedSint64Pairs} = goog.require('protobuf.binary.packedSint64TestPairs');
 
- const {getPackedUint32Pairs} = goog.require('protobuf.binary.packedUint32TestPairs');
 
- const {getSfixed32Pairs} = goog.require('protobuf.binary.sfixed32TestPairs');
 
- const {getSfixed64Pairs} = goog.require('protobuf.binary.sfixed64TestPairs');
 
- const {getSint32Pairs} = goog.require('protobuf.binary.sint32TestPairs');
 
- const {getSint64Pairs} = goog.require('protobuf.binary.sint64TestPairs');
 
- const {getUint32Pairs} = goog.require('protobuf.binary.uint32TestPairs');
 
- /**
 
-  * @param {...number} bytes
 
-  * @return {!ArrayBuffer}
 
-  */
 
- function createArrayBuffer(...bytes) {
 
-   return new Uint8Array(bytes).buffer;
 
- }
 
- /******************************************************************************
 
-  *                        OPTIONAL FUNCTIONS
 
-  ******************************************************************************/
 
- describe('Writer does', () => {
 
-   it('return an empty ArrayBuffer when nothing is encoded', () => {
 
-     const writer = new Writer();
 
-     expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
 
-   });
 
-   it('encode tag', () => {
 
-     const writer = new Writer();
 
-     writer.writeTag(1, WireType.VARINT);
 
-     expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer(0x08));
 
-     writer.writeTag(0x0FFFFFFF, WireType.VARINT);
 
-     expect(writer.getAndResetResultBuffer())
 
-         .toEqual(createArrayBuffer(0xF8, 0xFF, 0xFF, 0xFF, 0x7));
 
-     writer.writeTag(0x10000000, WireType.VARINT);
 
-     expect(writer.getAndResetResultBuffer())
 
-         .toEqual(createArrayBuffer(0x80, 0x80, 0x80, 0x80, 0x08));
 
-     writer.writeTag(0x1FFFFFFF, WireType.VARINT);
 
-     expect(writer.getAndResetResultBuffer())
 
-         .toEqual(createArrayBuffer(0xF8, 0xFF, 0xFF, 0xFF, 0x0F));
 
-   });
 
-   it('reset after calling getAndResetResultBuffer', () => {
 
-     const writer = new Writer();
 
-     writer.writeTag(1, WireType.VARINT);
 
-     writer.getAndResetResultBuffer();
 
-     expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
 
-   });
 
-   it('fail when field number is too large for writeTag', () => {
 
-     const writer = new Writer();
 
-     if (CHECK_TYPE) {
 
-       expect(() => writer.writeTag(MAX_FIELD_NUMBER + 1, WireType.VARINT))
 
-           .toThrowError('Field number is out of range: 536870912');
 
-     } else {
 
-       // Note in unchecked mode we produce invalid output for invalid inputs.
 
-       // This test just documents our behavior in those cases.
 
-       // These values might change at any point and are not considered
 
-       // what the implementation should be doing here.
 
-       writer.writeTag(MAX_FIELD_NUMBER + 1, WireType.VARINT);
 
-       expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer(0));
 
-     }
 
-   });
 
-   it('fail when field number is negative for writeTag', () => {
 
-     const writer = new Writer();
 
-     if (CHECK_TYPE) {
 
-       expect(() => writer.writeTag(-1, WireType.VARINT))
 
-           .toThrowError('Field number is out of range: -1');
 
-     } else {
 
-       // Note in unchecked mode we produce invalid output for invalid inputs.
 
-       // This test just documents our behavior in those cases.
 
-       // These values might change at any point and are not considered
 
-       // what the implementation should be doing here.
 
-       writer.writeTag(-1, WireType.VARINT);
 
-       expect(writer.getAndResetResultBuffer())
 
-           .toEqual(createArrayBuffer(0xF8, 0xFF, 0xFF, 0xFF, 0xF));
 
-     }
 
-   });
 
-   it('fail when wire type is invalid for writeTag', () => {
 
-     const writer = new Writer();
 
-     if (CHECK_TYPE) {
 
-       expect(() => writer.writeTag(1, /** @type {!WireType} */ (0x08)))
 
-           .toThrowError('Invalid wire type: 8');
 
-     } else {
 
-       // Note in unchecked mode we produce invalid output for invalid inputs.
 
-       // This test just documents our behavior in those cases.
 
-       // These values might change at any point and are not considered
 
-       // what the implementation should be doing here.
 
-       writer.writeTag(1, /** @type {!WireType} */ (0x08));
 
-       expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer(0x08));
 
-     }
 
-   });
 
-   it('encode singular boolean value', () => {
 
-     const writer = new Writer();
 
-     writer.writeBool(1, true);
 
-     expect(writer.getAndResetResultBuffer())
 
-         .toEqual(createArrayBuffer(0x08, 0x01));
 
-   });
 
-   it('encode length delimited', () => {
 
-     const writer = new Writer();
 
-     writer.writeDelimited(1, createArrayBuffer(0x01, 0x02));
 
-     expect(writer.getAndResetResultBuffer())
 
-         .toEqual(createArrayBuffer(0x0A, 0x02, 0x01, 0x02));
 
-   });
 
- });
 
- describe('Writer.writeBufferDecoder does', () => {
 
-   it('encode BufferDecoder containing a varint value', () => {
 
-     const writer = new Writer();
 
-     const expected = createArrayBuffer(
 
-         0x08, /* varint start= */ 0xFF, /* varint end= */ 0x01, 0x08, 0x01);
 
-     writer.writeBufferDecoder(
 
-         BufferDecoder.fromArrayBuffer(expected), 1, WireType.VARINT);
 
-     const result = writer.getAndResetResultBuffer();
 
-     expect(result).toEqual(arrayBufferSlice(expected, 1, 3));
 
-   });
 
-   it('encode BufferDecoder containing a fixed64 value', () => {
 
-     const writer = new Writer();
 
-     const expected = createArrayBuffer(
 
-         0x09, /* fixed64 start= */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
 
-         /* fixed64 end= */ 0x08, 0x08, 0x01);
 
-     writer.writeBufferDecoder(
 
-         BufferDecoder.fromArrayBuffer(expected), 1, WireType.FIXED64);
 
-     const result = writer.getAndResetResultBuffer();
 
-     expect(result).toEqual(arrayBufferSlice(expected, 1, 9));
 
-   });
 
-   it('encode BufferDecoder containing a length delimited value', () => {
 
-     const writer = new Writer();
 
-     const expected = createArrayBuffer(
 
-         0xA, /* length= */ 0x03, /* data start= */ 0x01, 0x02,
 
-         /* data end= */ 0x03, 0x08, 0x01);
 
-     writer.writeBufferDecoder(
 
-         BufferDecoder.fromArrayBuffer(expected), 1, WireType.DELIMITED);
 
-     const result = writer.getAndResetResultBuffer();
 
-     expect(result).toEqual(arrayBufferSlice(expected, 1, 5));
 
-   });
 
-   it('encode BufferDecoder containing a group', () => {
 
-     const writer = new Writer();
 
-     const expected = createArrayBuffer(
 
-         0xB, /* group start= */ 0x08, 0x01, /* nested group start= */ 0x0B,
 
-         /* nested group end= */ 0x0C, /* group end= */ 0x0C, 0x08, 0x01);
 
-     writer.writeBufferDecoder(
 
-         BufferDecoder.fromArrayBuffer(expected), 1, WireType.START_GROUP);
 
-     const result = writer.getAndResetResultBuffer();
 
-     expect(result).toEqual(arrayBufferSlice(expected, 1, 6));
 
-   });
 
-   it('encode BufferDecoder containing a fixed32 value', () => {
 
-     const writer = new Writer();
 
-     const expected = createArrayBuffer(
 
-         0x09, /* fixed64 start= */ 0x01, 0x02, 0x03, /* fixed64 end= */ 0x04,
 
-         0x08, 0x01);
 
-     writer.writeBufferDecoder(
 
-         BufferDecoder.fromArrayBuffer(expected), 1, WireType.FIXED32);
 
-     const result = writer.getAndResetResultBuffer();
 
-     expect(result).toEqual(arrayBufferSlice(expected, 1, 5));
 
-   });
 
-   it('fail when encoding out of bound data', () => {
 
-     const writer = new Writer();
 
-     const buffer = createArrayBuffer(0x4, 0x0, 0x1, 0x2, 0x3);
 
-     const subBuffer = arrayBufferSlice(buffer, 0, 2);
 
-     expect(
 
-         () => writer.writeBufferDecoder(
 
-             BufferDecoder.fromArrayBuffer(subBuffer), 0, WireType.DELIMITED))
 
-         .toThrow();
 
-   });
 
- });
 
- describe('Writer.writeBytes does', () => {
 
-   let writer;
 
-   beforeEach(() => {
 
-     writer = new Writer();
 
-   });
 
-   it('encodes empty ByteString', () => {
 
-     writer.writeBytes(1, ByteString.EMPTY);
 
-     const buffer = writer.getAndResetResultBuffer();
 
-     expect(buffer.byteLength).toBe(2);
 
-   });
 
-   it('encodes empty array', () => {
 
-     writer.writeBytes(1, ByteString.fromArrayBuffer(new ArrayBuffer(0)));
 
-     expect(writer.getAndResetResultBuffer())
 
-         .toEqual(createArrayBuffer(
 
-             1 << 3 | 0x02,  // tag (fieldnumber << 3 | (length delimited))
 
-             0,              // length of the bytes
 
-             ));
 
-   });
 
-   it('encodes ByteString', () => {
 
-     const array = createArrayBuffer(1, 2, 3);
 
-     writer.writeBytes(1, ByteString.fromArrayBuffer(array));
 
-     expect(writer.getAndResetResultBuffer())
 
-         .toEqual(createArrayBuffer(
 
-             1 << 3 | 0x02,  // tag (fieldnumber << 3 | (length delimited))
 
-             3,              // length of the bytes
 
-             1,
 
-             2,
 
-             3,
 
-             ));
 
-   });
 
- });
 
- describe('Writer.writeDouble does', () => {
 
-   let writer;
 
-   beforeEach(() => {
 
-     writer = new Writer();
 
-   });
 
-   for (const pair of getDoublePairs()) {
 
-     it(`encode ${pair.name}`, () => {
 
-         writer.writeDouble(1, pair.doubleValue);
 
-         const buffer = new Uint8Array(writer.getAndResetResultBuffer());
 
-         expect(buffer.length).toBe(9);
 
-         // ensure we have a correct tag
 
-         expect(buffer[0]).toEqual(0x09);
 
-         // Encoded values are stored right after the tag
 
-         expect(buffer.subarray(1, 9))
 
-             .toEqual(pair.bufferDecoder.asUint8Array());
 
-     });
 
-   }
 
-   /**
 
-    * NaN may have different value in different browsers. Thus, we need to make
 
-    * the test lenient.
 
-    */
 
-   it('encode NaN', () => {
 
-     writer.writeDouble(1, NaN);
 
-     const buffer = new Uint8Array(writer.getAndResetResultBuffer());
 
-     expect(buffer.length).toBe(9);
 
-     // ensure we have a correct tag
 
-     expect(buffer[0]).toEqual(0x09);
 
-     // Encoded values are stored right after the tag
 
-     const float64 = new DataView(buffer.buffer);
 
-     expect(float64.getFloat64(1, true)).toBeNaN();
 
-   });
 
- });
 
- describe('Writer.writeFixed32 does', () => {
 
-   let writer;
 
-   beforeEach(() => {
 
-     writer = new Writer();
 
-   });
 
-   for (const pair of getFixed32Pairs()) {
 
-     it(`encode ${pair.name}`, () => {
 
-       writer.writeFixed32(1, pair.intValue);
 
-       const buffer = new Uint8Array(writer.getAndResetResultBuffer());
 
-       expect(buffer.length).toBe(5);
 
-       // ensure we have a correct tag
 
-       expect(buffer[0]).toEqual(0x0D);
 
-       // Encoded values are stored right after the tag
 
-       expect(buffer.subarray(1, 5)).toEqual(pair.bufferDecoder.asUint8Array());
 
-     });
 
-   }
 
- });
 
- describe('Writer.writeFloat does', () => {
 
-   let writer;
 
-   beforeEach(() => {
 
-     writer = new Writer();
 
-   });
 
-   for (const pair of getFloatPairs()) {
 
-     it(`encode ${pair.name}`, () => {
 
-       writer.writeFloat(1, pair.floatValue);
 
-       const buffer = new Uint8Array(writer.getAndResetResultBuffer());
 
-       expect(buffer.length).toBe(5);
 
-       // ensure we have a correct tag
 
-       expect(buffer[0]).toEqual(0x0D);
 
-       // Encoded values are stored right after the tag
 
-       expect(buffer.subarray(1, 5)).toEqual(pair.bufferDecoder.asUint8Array());
 
-     });
 
-   }
 
-   /**
 
-    * NaN may have different value in different browsers. Thus, we need to make
 
-    * the test lenient.
 
-    */
 
-   it('encode NaN', () => {
 
-     writer.writeFloat(1, NaN);
 
-     const buffer = new Uint8Array(writer.getAndResetResultBuffer());
 
-     expect(buffer.length).toBe(5);
 
-     // ensure we have a correct tag
 
-     expect(buffer[0]).toEqual(0x0D);
 
-     // Encoded values are stored right after the tag
 
-     const float32 = new DataView(buffer.buffer);
 
-     expect(float32.getFloat32(1, true)).toBeNaN();
 
-   });
 
- });
 
- describe('Writer.writeInt32 does', () => {
 
-   let writer;
 
-   beforeEach(() => {
 
-     writer = new Writer();
 
-   });
 
-   for (const pair of getInt32Pairs()) {
 
-     if (!pair.skip_writer) {
 
-       it(`encode ${pair.name}`, () => {
 
-         writer.writeInt32(1, pair.intValue);
 
-         const buffer = new Uint8Array(writer.getAndResetResultBuffer());
 
-         // ensure we have a correct tag
 
-         expect(buffer[0]).toEqual(0x08);
 
-         // Encoded values are stored right after the tag
 
-         expect(buffer.subarray(1, buffer.length))
 
-             .toEqual(pair.bufferDecoder.asUint8Array());
 
-       });
 
-     }
 
-   }
 
- });
 
- describe('Writer.writeSfixed32 does', () => {
 
-   let writer;
 
-   beforeEach(() => {
 
-     writer = new Writer();
 
-   });
 
-   it('encode empty array', () => {
 
-     writer.writePackedSfixed32(1, []);
 
-     expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
 
-   });
 
-   for (const pair of getSfixed32Pairs()) {
 
-     it(`encode ${pair.name}`, () => {
 
-       writer.writeSfixed32(1, pair.intValue);
 
-       const buffer = new Uint8Array(writer.getAndResetResultBuffer());
 
-       expect(buffer.length).toBe(5);
 
-       // ensure we have a correct tag
 
-       expect(buffer[0]).toEqual(0x0D);
 
-       // Encoded values are stored right after the tag
 
-       expect(buffer.subarray(1, 5)).toEqual(pair.bufferDecoder.asUint8Array());
 
-     });
 
-   }
 
- });
 
- describe('Writer.writeSfixed64 does', () => {
 
-   let writer;
 
-   beforeEach(() => {
 
-     writer = new Writer();
 
-   });
 
-   for (const pair of getSfixed64Pairs()) {
 
-     it(`encode ${pair.name}`, () => {
 
-       writer.writeSfixed64(1, pair.longValue);
 
-       const buffer = new Uint8Array(writer.getAndResetResultBuffer());
 
-       expect(buffer.length).toBe(9);
 
-       // ensure we have a correct tag
 
-       expect(buffer[0]).toEqual(0x09);
 
-       // Encoded values are stored right after the tag
 
-       expect(buffer.subarray(1, 9)).toEqual(pair.bufferDecoder.asUint8Array());
 
-     });
 
-   }
 
- });
 
- describe('Writer.writeSint32 does', () => {
 
-   let writer;
 
-   beforeEach(() => {
 
-     writer = new Writer();
 
-   });
 
-   for (const pair of getSint32Pairs()) {
 
-     if (!pair.skip_writer) {
 
-       it(`encode ${pair.name}`, () => {
 
-         writer.writeSint32(1, pair.intValue);
 
-         const buffer = new Uint8Array(writer.getAndResetResultBuffer());
 
-         // ensure we have a correct tag
 
-         expect(buffer[0]).toEqual(0x08);
 
-         // Encoded values are stored right after the tag
 
-         expect(buffer.subarray(1, buffer.length))
 
-             .toEqual(pair.bufferDecoder.asUint8Array());
 
-       });
 
-     }
 
-   }
 
- });
 
- describe('Writer.writeSint64 does', () => {
 
-   let writer;
 
-   beforeEach(() => {
 
-     writer = new Writer();
 
-   });
 
-   for (const pair of getSint64Pairs()) {
 
-     if (!pair.skip_writer) {
 
-       it(`encode ${pair.name}`, () => {
 
-         writer.writeSint64(1, pair.longValue);
 
-         const buffer = new Uint8Array(writer.getAndResetResultBuffer());
 
-         // ensure we have a correct tag
 
-         expect(buffer[0]).toEqual(0x08);
 
-         // Encoded values are stored right after the tag
 
-         expect(buffer.subarray(1, buffer.length))
 
-             .toEqual(pair.bufferDecoder.asUint8Array());
 
-       });
 
-     }
 
-   }
 
- });
 
- describe('Writer.writeInt64 does', () => {
 
-   let writer;
 
-   beforeEach(() => {
 
-     writer = new Writer();
 
-   });
 
-   for (const pair of getInt64Pairs()) {
 
-     if (!pair.skip_writer) {
 
-       it(`encode ${pair.name}`, () => {
 
-         writer.writeInt64(1, pair.longValue);
 
-         const buffer = new Uint8Array(writer.getAndResetResultBuffer());
 
-         // ensure we have a correct tag
 
-         expect(buffer[0]).toEqual(0x08);
 
-         // Encoded values are stored right after the tag
 
-         expect(buffer.subarray(1, buffer.length))
 
-             .toEqual(pair.bufferDecoder.asUint8Array());
 
-       });
 
-     }
 
-   }
 
- });
 
- describe('Writer.writeUint32 does', () => {
 
-   let writer;
 
-   beforeEach(() => {
 
-     writer = new Writer();
 
-   });
 
-   for (const pair of getUint32Pairs()) {
 
-     if (!pair.skip_writer) {
 
-       it(`encode ${pair.name}`, () => {
 
-         writer.writeUint32(1, pair.intValue);
 
-         const buffer = new Uint8Array(writer.getAndResetResultBuffer());
 
-         // ensure we have a correct tag
 
-         expect(buffer[0]).toEqual(0x08);
 
-         // Encoded values are stored right after the tag
 
-         expect(buffer.subarray(1, buffer.length))
 
-             .toEqual(pair.bufferDecoder.asUint8Array());
 
-       });
 
-     }
 
-   }
 
- });
 
- describe('Writer.writeString does', () => {
 
-   let writer;
 
-   beforeEach(() => {
 
-     writer = new Writer();
 
-   });
 
-   it('encode empty string', () => {
 
-     writer.writeString(1, '');
 
-     expect(writer.getAndResetResultBuffer())
 
-         .toEqual(createArrayBuffer(
 
-             1 << 3 | 0x02,  // tag (fieldnumber << 3 | (length delimited))
 
-             0,              // length of the string
 
-             ));
 
-   });
 
-   it('encode simple string', () => {
 
-     writer.writeString(1, 'hello');
 
-     expect(writer.getAndResetResultBuffer())
 
-         .toEqual(createArrayBuffer(
 
-             1 << 3 | 0x02,  // tag (fieldnumber << 3 | (length delimited))
 
-             5,              // length of the string
 
-             'h'.charCodeAt(0),
 
-             'e'.charCodeAt(0),
 
-             'l'.charCodeAt(0),
 
-             'l'.charCodeAt(0),
 
-             'o'.charCodeAt(0),
 
-             ));
 
-   });
 
-   it('throw for invalid fieldnumber', () => {
 
-     if (CHECK_BOUNDS) {
 
-       expect(() => writer.writeString(-1, 'a'))
 
-           .toThrowError('Field number is out of range: -1');
 
-     } else {
 
-       writer.writeString(-1, 'a');
 
-       expect(new Uint8Array(writer.getAndResetResultBuffer()))
 
-           .toEqual(new Uint8Array(createArrayBuffer(
 
-               -6,  // invalid tag
 
-               0xff,
 
-               0xff,
 
-               0xff,
 
-               0x0f,
 
-               1,  // string length
 
-               'a'.charCodeAt(0),
 
-               )));
 
-     }
 
-   });
 
-   it('throw for null string value', () => {
 
-     expect(
 
-         () => writer.writeString(
 
-             1, /** @type {string} */ (/** @type {*} */ (null))))
 
-         .toThrow();
 
-   });
 
- });
 
- /******************************************************************************
 
-  *                        REPEATED FUNCTIONS
 
-  ******************************************************************************/
 
- describe('Writer.writePackedBool does', () => {
 
-   let writer;
 
-   beforeEach(() => {
 
-     writer = new Writer();
 
-   });
 
-   it('encode empty array', () => {
 
-     writer.writePackedBool(1, []);
 
-     expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
 
-   });
 
-   for (const pair of getPackedBoolPairs()) {
 
-     if (!pair.skip_writer) {
 
-       it(`encode ${pair.name}`, () => {
 
-         writer.writePackedBool(1, pair.boolValues);
 
-         const buffer = new Uint8Array(writer.getAndResetResultBuffer());
 
-         // ensure we have a correct tag
 
-         expect(buffer[0]).toEqual(0x0A);
 
-         // Encoded values are stored right after the tag
 
-         expect(buffer.subarray(1, buffer.length))
 
-             .toEqual(pair.bufferDecoder.asUint8Array());
 
-       });
 
-     }
 
-   }
 
- });
 
- describe('Writer.writeRepeatedBool does', () => {
 
-   let writer;
 
-   beforeEach(() => {
 
-     writer = new Writer();
 
-   });
 
-   it('encode empty array', () => {
 
-     writer.writeRepeatedBool(1, []);
 
-     expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
 
-   });
 
-   it('encode repeated unpacked boolean values', () => {
 
-     const writer = new Writer();
 
-     writer.writeRepeatedBool(1, [true, false]);
 
-     expect(writer.getAndResetResultBuffer())
 
-         .toEqual(createArrayBuffer(
 
-             1 << 3 | 0x00,  // tag (fieldnumber << 3 | (varint))
 
-             0x01,           // value[0]
 
-             1 << 3 | 0x00,  // tag (fieldnumber << 3 | (varint))
 
-             0x00,           // value[1]
 
-             ));
 
-   });
 
- });
 
- describe('Writer.writePackedDouble does', () => {
 
-   let writer;
 
-   beforeEach(() => {
 
-     writer = new Writer();
 
-   });
 
-   it('encode empty array', () => {
 
-     writer.writePackedDouble(1, []);
 
-     expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
 
-   });
 
-   for (const pair of getPackedDoublePairs()) {
 
-     if (!pair.skip_writer) {
 
-       it(`encode ${pair.name}`, () => {
 
-         writer.writePackedDouble(1, pair.doubleValues);
 
-         const buffer = new Uint8Array(writer.getAndResetResultBuffer());
 
-         // ensure we have a correct tag
 
-         expect(buffer[0]).toEqual(0x0A);
 
-         // Encoded values are stored right after the tag
 
-         expect(buffer.subarray(1, buffer.length))
 
-             .toEqual(pair.bufferDecoder.asUint8Array());
 
-       });
 
-     }
 
-   }
 
- });
 
- describe('Writer.writePackedFixed32 does', () => {
 
-   let writer;
 
-   beforeEach(() => {
 
-     writer = new Writer();
 
-   });
 
-   it('encode empty array', () => {
 
-     writer.writePackedFixed32(1, []);
 
-     expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
 
-   });
 
-   for (const pair of getPackedFixed32Pairs()) {
 
-     if (!pair.skip_writer) {
 
-       it(`encode ${pair.name}`, () => {
 
-         writer.writePackedFixed32(1, pair.fixed32Values);
 
-         const buffer = new Uint8Array(writer.getAndResetResultBuffer());
 
-         // ensure we have a correct tag
 
-         expect(buffer[0]).toEqual(0x0A);
 
-         // Encoded values are stored right after the tag
 
-         expect(buffer.subarray(1, buffer.length))
 
-             .toEqual(pair.bufferDecoder.asUint8Array());
 
-       });
 
-     }
 
-   }
 
- });
 
- describe('Writer.writePackedFloat does', () => {
 
-   let writer;
 
-   beforeEach(() => {
 
-     writer = new Writer();
 
-   });
 
-   it('encode empty array', () => {
 
-     writer.writePackedFloat(1, []);
 
-     expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
 
-   });
 
-   for (const pair of getPackedFloatPairs()) {
 
-     if (!pair.skip_writer) {
 
-       it(`encode ${pair.name}`, () => {
 
-         writer.writePackedFloat(1, pair.floatValues);
 
-         const buffer = new Uint8Array(writer.getAndResetResultBuffer());
 
-         // ensure we have a correct tag
 
-         expect(buffer[0]).toEqual(0x0A);
 
-         // Encoded values are stored right after the tag
 
-         expect(buffer.subarray(1, buffer.length))
 
-             .toEqual(pair.bufferDecoder.asUint8Array());
 
-       });
 
-     }
 
-   }
 
- });
 
- describe('Writer.writePackedInt32 does', () => {
 
-   let writer;
 
-   beforeEach(() => {
 
-     writer = new Writer();
 
-   });
 
-   it('encode empty array', () => {
 
-     writer.writePackedInt32(1, []);
 
-     expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
 
-   });
 
-   for (const pair of getPackedInt32Pairs()) {
 
-     if (!pair.skip_writer) {
 
-       it(`encode ${pair.name}`, () => {
 
-         writer.writePackedInt32(1, pair.int32Values);
 
-         const buffer = new Uint8Array(writer.getAndResetResultBuffer());
 
-         // ensure we have a correct tag
 
-         expect(buffer[0]).toEqual(0x0A);
 
-         // Encoded values are stored right after the tag
 
-         expect(buffer.subarray(1, buffer.length))
 
-             .toEqual(pair.bufferDecoder.asUint8Array());
 
-       });
 
-     }
 
-   }
 
- });
 
- describe('Writer.writePackedInt64 does', () => {
 
-   let writer;
 
-   beforeEach(() => {
 
-     writer = new Writer();
 
-   });
 
-   it('encode empty array', () => {
 
-     writer.writePackedInt64(1, []);
 
-     expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
 
-   });
 
-   for (const pair of getPackedInt64Pairs()) {
 
-     if (!pair.skip_writer) {
 
-       it(`encode ${pair.name}`, () => {
 
-         writer.writePackedInt64(1, pair.int64Values);
 
-         const buffer = new Uint8Array(writer.getAndResetResultBuffer());
 
-         // ensure we have a correct tag
 
-         expect(buffer[0]).toEqual(0x0A);
 
-         // Encoded values are stored right after the tag
 
-         expect(buffer.subarray(1, buffer.length))
 
-             .toEqual(pair.bufferDecoder.asUint8Array());
 
-       });
 
-     }
 
-   }
 
- });
 
- describe('Writer.writePackedSfixed32 does', () => {
 
-   let writer;
 
-   beforeEach(() => {
 
-     writer = new Writer();
 
-   });
 
-   it('encode empty array', () => {
 
-     writer.writePackedSfixed32(1, []);
 
-     expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
 
-   });
 
-   for (const pair of getPackedSfixed32Pairs()) {
 
-     if (!pair.skip_writer) {
 
-       it(`encode ${pair.name}`, () => {
 
-         writer.writePackedSfixed32(1, pair.sfixed32Values);
 
-         const buffer = new Uint8Array(writer.getAndResetResultBuffer());
 
-         // ensure we have a correct tag
 
-         expect(buffer[0]).toEqual(0x0A);
 
-         // Encoded values are stored right after the tag
 
-         expect(buffer.subarray(1, buffer.length))
 
-             .toEqual(pair.bufferDecoder.asUint8Array());
 
-       });
 
-     }
 
-   }
 
- });
 
- describe('Writer.writePackedSfixed64 does', () => {
 
-   let writer;
 
-   beforeEach(() => {
 
-     writer = new Writer();
 
-   });
 
-   it('encode empty array', () => {
 
-     writer.writePackedSfixed64(1, []);
 
-     expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
 
-   });
 
-   for (const pair of getPackedSfixed64Pairs()) {
 
-     if (!pair.skip_writer) {
 
-       it(`encode ${pair.name}`, () => {
 
-         writer.writePackedSfixed64(1, pair.sfixed64Values);
 
-         const buffer = new Uint8Array(writer.getAndResetResultBuffer());
 
-         // ensure we have a correct tag
 
-         expect(buffer[0]).toEqual(0x0A);
 
-         // Encoded values are stored right after the tag
 
-         expect(buffer.subarray(1, buffer.length))
 
-             .toEqual(pair.bufferDecoder.asUint8Array());
 
-       });
 
-     }
 
-   }
 
- });
 
- describe('Writer.writePackedSint32 does', () => {
 
-   let writer;
 
-   beforeEach(() => {
 
-     writer = new Writer();
 
-   });
 
-   it('encode empty array', () => {
 
-     writer.writePackedSint32(1, []);
 
-     expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
 
-   });
 
-   for (const pair of getPackedSint32Pairs()) {
 
-     if (!pair.skip_writer) {
 
-       it(`encode ${pair.name}`, () => {
 
-         writer.writePackedSint32(1, pair.sint32Values);
 
-         const buffer = new Uint8Array(writer.getAndResetResultBuffer());
 
-         // ensure we have a correct tag
 
-         expect(buffer[0]).toEqual(0x0A);
 
-         // Encoded values are stored right after the tag
 
-         expect(buffer.subarray(1, buffer.length))
 
-             .toEqual(pair.bufferDecoder.asUint8Array());
 
-       });
 
-     }
 
-   }
 
- });
 
- describe('Writer.writePackedSint64 does', () => {
 
-   let writer;
 
-   beforeEach(() => {
 
-     writer = new Writer();
 
-   });
 
-   it('encode empty array', () => {
 
-     writer.writePackedSint64(1, []);
 
-     expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
 
-   });
 
-   for (const pair of getPackedSint64Pairs()) {
 
-     if (!pair.skip_writer) {
 
-       it(`encode ${pair.name}`, () => {
 
-         writer.writePackedSint64(1, pair.sint64Values);
 
-         const buffer = new Uint8Array(writer.getAndResetResultBuffer());
 
-         // ensure we have a correct tag
 
-         expect(buffer[0]).toEqual(0x0A);
 
-         // Encoded values are stored right after the tag
 
-         expect(buffer.subarray(1, buffer.length))
 
-             .toEqual(pair.bufferDecoder.asUint8Array());
 
-       });
 
-     }
 
-   }
 
- });
 
- describe('Writer.writePackedUint32 does', () => {
 
-   let writer;
 
-   beforeEach(() => {
 
-     writer = new Writer();
 
-   });
 
-   it('encode empty array', () => {
 
-     writer.writePackedUint32(1, []);
 
-     expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
 
-   });
 
-   for (const pair of getPackedUint32Pairs()) {
 
-     if (!pair.skip_writer) {
 
-       it(`encode ${pair.name}`, () => {
 
-         writer.writePackedUint32(1, pair.uint32Values);
 
-         const buffer = new Uint8Array(writer.getAndResetResultBuffer());
 
-         // ensure we have a correct tag
 
-         expect(buffer[0]).toEqual(0x0A);
 
-         // Encoded values are stored right after the tag
 
-         expect(buffer.subarray(1, buffer.length))
 
-             .toEqual(pair.bufferDecoder.asUint8Array());
 
-       });
 
-     }
 
-   }
 
- });
 
- describe('Writer.writeRepeatedBytes does', () => {
 
-   let writer;
 
-   beforeEach(() => {
 
-     writer = new Writer();
 
-   });
 
-   it('encode empty array', () => {
 
-     writer.writeRepeatedBytes(1, []);
 
-     expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
 
-   });
 
-   it('encode single value', () => {
 
-     const value = createArrayBuffer(0x61);
 
-     writer.writeRepeatedBytes(1, [ByteString.fromArrayBuffer(value)]);
 
-     expect(writer.getAndResetResultBuffer())
 
-         .toEqual(createArrayBuffer(
 
-             0x0A,
 
-             0x01,
 
-             0x61,  // a
 
-             ));
 
-   });
 
-   it('encode multiple values', () => {
 
-     const value1 = createArrayBuffer(0x61);
 
-     const value2 = createArrayBuffer(0x62);
 
-     writer.writeRepeatedBytes(1, [
 
-       ByteString.fromArrayBuffer(value1),
 
-       ByteString.fromArrayBuffer(value2),
 
-     ]);
 
-     expect(writer.getAndResetResultBuffer())
 
-         .toEqual(createArrayBuffer(
 
-             0x0A,
 
-             0x01,
 
-             0x61,  // a
 
-             0x0A,
 
-             0x01,
 
-             0x62,  // b
 
-             ));
 
-   });
 
- });
 
- describe('Writer.writeRepeatedString does', () => {
 
-   let writer;
 
-   beforeEach(() => {
 
-     writer = new Writer();
 
-   });
 
-   it('encode empty array', () => {
 
-     writer.writeRepeatedString(1, []);
 
-     expect(writer.getAndResetResultBuffer()).toEqual(createArrayBuffer());
 
-   });
 
-   it('encode single value', () => {
 
-     writer.writeRepeatedString(1, ['a']);
 
-     expect(writer.getAndResetResultBuffer())
 
-         .toEqual(createArrayBuffer(
 
-             0x0A,
 
-             0x01,
 
-             0x61,  // a
 
-             ));
 
-   });
 
-   it('encode multiple values', () => {
 
-     writer.writeRepeatedString(1, ['a', 'b']);
 
-     expect(writer.getAndResetResultBuffer())
 
-         .toEqual(createArrayBuffer(
 
-             0x0A,
 
-             0x01,
 
-             0x61,  // a
 
-             0x0A,
 
-             0x01,
 
-             0x62,  // b
 
-             ));
 
-   });
 
- });
 
 
  |