1/**
2 * @fileoverview Kernel is a class to provide type-checked accessing
3 * (read/write bool/int32/string/...) on binary data.
4 *
5 * When creating the Kernel with the binary data, there is no deep
6 * decoding done (which requires full type information). The deep decoding is
7 * deferred until the first time accessing (when accessors can provide
8 * full type information).
9 *
10 * Because accessors can be statically analyzed and stripped, unlike eager
11 * binary decoding (which requires the full type information of all defined
12 * fields), Kernel will only need the full type information of used
13 * fields.
14 */
15goog.module('protobuf.runtime.Kernel');
16
17const BinaryStorage = goog.require('protobuf.runtime.BinaryStorage');
18const BufferDecoder = goog.require('protobuf.binary.BufferDecoder');
19const ByteString = goog.require('protobuf.ByteString');
20const Int64 = goog.require('protobuf.Int64');
21const InternalMessage = goog.require('protobuf.binary.InternalMessage');
22const Storage = goog.require('protobuf.runtime.Storage');
23const WireType = goog.require('protobuf.binary.WireType');
24const Writer = goog.require('protobuf.binary.Writer');
25const reader = goog.require('protobuf.binary.reader');
26const {CHECK_TYPE, checkCriticalElementIndex, checkCriticalState, checkCriticalType, checkCriticalTypeBool, checkCriticalTypeBoolArray, checkCriticalTypeByteString, checkCriticalTypeByteStringArray, checkCriticalTypeDouble, checkCriticalTypeDoubleArray, checkCriticalTypeFloat, checkCriticalTypeFloatIterable, checkCriticalTypeMessageArray, checkCriticalTypeSignedInt32, checkCriticalTypeSignedInt32Array, checkCriticalTypeSignedInt64, checkCriticalTypeSignedInt64Array, checkCriticalTypeString, checkCriticalTypeStringArray, checkCriticalTypeUnsignedInt32, checkCriticalTypeUnsignedInt32Array, checkDefAndNotNull, checkElementIndex, checkFieldNumber, checkFunctionExists, checkState, checkTypeDouble, checkTypeFloat, checkTypeSignedInt32, checkTypeSignedInt64, checkTypeUnsignedInt32} = goog.require('protobuf.internal.checks');
27const {Field, IndexEntry} = goog.require('protobuf.binary.field');
28const {buildIndex} = goog.require('protobuf.binary.indexer');
29const {createTag, get32BitVarintLength, getTagLength} = goog.require('protobuf.binary.tag');
30
31
32/**
33 * Validates the index entry has the correct wire type.
34 * @param {!IndexEntry} indexEntry
35 * @param {!WireType} expected
36 */
37function validateWireType(indexEntry, expected) {
38  const wireType = Field.getWireType(indexEntry);
39  checkCriticalState(
40      wireType === expected,
41      `Expected wire type: ${expected} but found: ${wireType}`);
42}
43
44/**
45 * Checks if the object implements InternalMessage interface.
46 * @param {?} obj
47 * @return {!InternalMessage}
48 */
49function checkIsInternalMessage(obj) {
50  const message = /** @type {!InternalMessage} */ (obj);
51  checkFunctionExists(message.internalGetKernel);
52  return message;
53}
54
55/**
56 * Checks if the instanceCreator returns an instance that implements the
57 * InternalMessage interface.
58 * @param {function(!Kernel):T} instanceCreator
59 * @template T
60 */
61function checkInstanceCreator(instanceCreator) {
62  if (CHECK_TYPE) {
63    const emptyMessage = instanceCreator(Kernel.createEmpty());
64    checkFunctionExists(emptyMessage.internalGetKernel);
65  }
66}
67
68/**
69 * Reads the last entry of the index array using the given read function.
70 * This is used to implement parsing singular primitive fields.
71 * @param {!Array<!IndexEntry>} indexArray
72 * @param {!BufferDecoder} bufferDecoder
73 * @param {function(!BufferDecoder, number):T} readFunc
74 * @param {!WireType} wireType
75 * @return {T}
76 * @template T
77 */
78function readOptional(indexArray, bufferDecoder, readFunc, wireType) {
79  const index = indexArray.length - 1;
80  checkElementIndex(index, indexArray.length);
81  const indexEntry = indexArray[index];
82  validateWireType(indexEntry, wireType);
83  return readFunc(bufferDecoder, Field.getStartIndex(indexEntry));
84}
85
86/**
87 * Converts all entries of the index array to the template type using given read
88 * methods and return an Iterable containing those converted values.
89 * Primitive repeated fields may be encoded either packed or unpacked. Thus, two
90 * read methods are needed for those two cases.
91 * This is used to implement parsing repeated primitive fields.
92 * @param {!Array<!IndexEntry>} indexArray
93 * @param {!BufferDecoder} bufferDecoder
94 * @param {function(!BufferDecoder, number):T} singularReadFunc
95 * @param {function(!BufferDecoder, number):!Array<T>} packedReadFunc
96 * @param {!WireType} expectedWireType
97 * @return {!Array<T>}
98 * @template T
99 */
100function readRepeatedPrimitive(
101    indexArray, bufferDecoder, singularReadFunc, packedReadFunc,
102    expectedWireType) {
103  // Fast path when there is a single packed entry.
104  if (indexArray.length === 1 &&
105      Field.getWireType(indexArray[0]) === WireType.DELIMITED) {
106    return packedReadFunc(bufferDecoder, Field.getStartIndex(indexArray[0]));
107  }
108
109  let /** !Array<T> */ result = [];
110  for (const indexEntry of indexArray) {
111    const wireType = Field.getWireType(indexEntry);
112    const startIndex = Field.getStartIndex(indexEntry);
113    if (wireType === WireType.DELIMITED) {
114      result = result.concat(packedReadFunc(bufferDecoder, startIndex));
115    } else {
116      validateWireType(indexEntry, expectedWireType);
117      result.push(singularReadFunc(bufferDecoder, startIndex));
118    }
119  }
120  return result;
121}
122
123/**
124 * Converts all entries of the index array to the template type using the given
125 * read function and return an Array containing those converted values. This is
126 * used to implement parsing repeated non-primitive fields.
127 * @param {!Array<!IndexEntry>} indexArray
128 * @param {!BufferDecoder} bufferDecoder
129 * @param {function(!BufferDecoder, number):T} singularReadFunc
130 * @return {!Array<T>}
131 * @template T
132 */
133function readRepeatedNonPrimitive(indexArray, bufferDecoder, singularReadFunc) {
134  const result = new Array(indexArray.length);
135  for (let i = 0; i < indexArray.length; i++) {
136    validateWireType(indexArray[i], WireType.DELIMITED);
137    result[i] =
138        singularReadFunc(bufferDecoder, Field.getStartIndex(indexArray[i]));
139  }
140  return result;
141}
142
143/**
144 * Converts all entries of the index array to the template type using the given
145 * read function and return an Array containing those converted values. This is
146 * used to implement parsing repeated non-primitive fields.
147 * @param {!Array<!IndexEntry>} indexArray
148 * @param {!BufferDecoder} bufferDecoder
149 * @param {number} fieldNumber
150 * @param {function(!Kernel):T} instanceCreator
151 * @param {number=} pivot
152 * @return {!Array<T>}
153 * @template T
154 */
155function readRepeatedGroup(
156    indexArray, bufferDecoder, fieldNumber, instanceCreator, pivot) {
157  const result = new Array(indexArray.length);
158  for (let i = 0; i < indexArray.length; i++) {
159    result[i] = doReadGroup(
160        bufferDecoder, indexArray[i], fieldNumber, instanceCreator, pivot);
161  }
162  return result;
163}
164
165/**
166 * Creates a new bytes array to contain all data of a submessage.
167 * When there are multiple entries, merge them together.
168 * @param {!Array<!IndexEntry>} indexArray
169 * @param {!BufferDecoder} bufferDecoder
170 * @return {!BufferDecoder}
171 */
172function mergeMessageArrays(indexArray, bufferDecoder) {
173  const dataArrays = indexArray.map(
174      indexEntry =>
175          reader.readDelimited(bufferDecoder, Field.getStartIndex(indexEntry)));
176  return BufferDecoder.merge(dataArrays);
177}
178
179/**
180 * @param {!Array<!IndexEntry>} indexArray
181 * @param {!BufferDecoder} bufferDecoder
182 * @param {number=} pivot
183 * @return {!Kernel}
184 */
185function readAccessor(indexArray, bufferDecoder, pivot = undefined) {
186  checkState(indexArray.length > 0);
187  let accessorBuffer;
188  // Faster access for one member.
189  if (indexArray.length === 1) {
190    const indexEntry = indexArray[0];
191    validateWireType(indexEntry, WireType.DELIMITED);
192    accessorBuffer =
193        reader.readDelimited(bufferDecoder, Field.getStartIndex(indexEntry));
194  } else {
195    indexArray.forEach(indexEntry => {
196      validateWireType(indexEntry, WireType.DELIMITED);
197    });
198    accessorBuffer = mergeMessageArrays(indexArray, bufferDecoder);
199  }
200  return Kernel.fromBufferDecoder_(accessorBuffer, pivot);
201}
202
203/**
204 * Merges all index entries of the index array using the given read function.
205 * This is used to implement parsing singular message fields.
206 * @param {!Array<!IndexEntry>} indexArray
207 * @param {!BufferDecoder} bufferDecoder
208 * @param {function(!Kernel):T} instanceCreator
209 * @param {number=} pivot
210 * @return {T}
211 * @template T
212 */
213function readMessage(indexArray, bufferDecoder, instanceCreator, pivot) {
214  checkInstanceCreator(instanceCreator);
215  const accessor = readAccessor(indexArray, bufferDecoder, pivot);
216  return instanceCreator(accessor);
217}
218
219/**
220 * Merges all index entries of the index array using the given read function.
221 * This is used to implement parsing singular group fields.
222 * @param {!Array<!IndexEntry>} indexArray
223 * @param {!BufferDecoder} bufferDecoder
224 * @param {number} fieldNumber
225 * @param {function(!Kernel):T} instanceCreator
226 * @param {number=} pivot
227 * @return {T}
228 * @template T
229 */
230function readGroup(
231    indexArray, bufferDecoder, fieldNumber, instanceCreator, pivot) {
232  checkInstanceCreator(instanceCreator);
233  checkState(indexArray.length > 0);
234  return doReadGroup(
235      bufferDecoder, indexArray[indexArray.length - 1], fieldNumber,
236      instanceCreator, pivot);
237}
238
239/**
240 * Merges all index entries of the index array using the given read function.
241 * This is used to implement parsing singular message fields.
242 * @param {!BufferDecoder} bufferDecoder
243 * @param {!IndexEntry} indexEntry
244 * @param {number} fieldNumber
245 * @param {function(!Kernel):T} instanceCreator
246 * @param {number=} pivot
247 * @return {T}
248 * @template T
249 */
250function doReadGroup(
251    bufferDecoder, indexEntry, fieldNumber, instanceCreator, pivot) {
252  validateWireType(indexEntry, WireType.START_GROUP);
253  const fieldStartIndex = Field.getStartIndex(indexEntry);
254  const tag = createTag(WireType.START_GROUP, fieldNumber);
255  const groupTagLength = get32BitVarintLength(tag);
256  const groupLength = getTagLength(
257      bufferDecoder, fieldStartIndex, WireType.START_GROUP, fieldNumber);
258  const accessorBuffer = bufferDecoder.subBufferDecoder(
259      fieldStartIndex, groupLength - groupTagLength);
260  const kernel = Kernel.fromBufferDecoder_(accessorBuffer, pivot);
261  return instanceCreator(kernel);
262}
263
264/**
265 * @param {!Writer} writer
266 * @param {number} fieldNumber
267 * @param {?InternalMessage} value
268 */
269function writeMessage(writer, fieldNumber, value) {
270  writer.writeDelimited(
271      fieldNumber, checkDefAndNotNull(value).internalGetKernel().serialize());
272}
273
274/**
275 * @param {!Writer} writer
276 * @param {number} fieldNumber
277 * @param {?InternalMessage} value
278 */
279function writeGroup(writer, fieldNumber, value) {
280  const kernel = checkDefAndNotNull(value).internalGetKernel();
281  writer.writeStartGroup(fieldNumber);
282  kernel.serializeToWriter(writer);
283  writer.writeEndGroup(fieldNumber);
284}
285
286/**
287 * Writes the array of Messages into the writer for the given field number.
288 * @param {!Writer} writer
289 * @param {number} fieldNumber
290 * @param {!Iterable<!InternalMessage>} values
291 */
292function writeRepeatedMessage(writer, fieldNumber, values) {
293  for (const value of values) {
294    writeMessage(writer, fieldNumber, value);
295  }
296}
297
298/**
299 * Writes the array of Messages into the writer for the given field number.
300 * @param {!Writer} writer
301 * @param {number} fieldNumber
302 * @param {!Array<!InternalMessage>} values
303 */
304function writeRepeatedGroup(writer, fieldNumber, values) {
305  for (const value of values) {
306    writeGroup(writer, fieldNumber, value);
307  }
308}
309
310/**
311 * Array.from has a weird type definition in google3/javascript/externs/es6.js
312 * and wants the mapping function accept strings.
313 * @const {function((string|number)): number}
314 */
315const fround = /** @type {function((string|number)): number} */ (Math.fround);
316
317/**
318 * Wraps an array and exposes it as an Iterable. This class is used to provide
319 * immutable access of the array to the caller.
320 * @implements {Iterable<T>}
321 * @template T
322 */
323class ArrayIterable {
324  /**
325   * @param {!Array<T>} array
326   */
327  constructor(array) {
328    /** @private @const {!Array<T>} */
329    this.array_ = array;
330  }
331
332  /** @return {!Iterator<T>} */
333  [Symbol.iterator]() {
334    return this.array_[Symbol.iterator]();
335  }
336}
337
338/**
339 * Accesses protobuf fields on binary format data. Binary data is decoded lazily
340 * at the first access.
341 * @final
342 */
343class Kernel {
344  /**
345   * Create a Kernel for the given binary bytes.
346   * The bytes array is kept by the Kernel. DON'T MODIFY IT.
347   * @param {!ArrayBuffer} arrayBuffer Binary bytes.
348   * @param {number=} pivot Fields with a field number no greater than the pivot
349   *     value will be stored in an array for fast access. Other fields will be
350   *     stored in a map. A higher pivot value can improve runtime performance
351   *     at the expense of requiring more memory. It's recommended to set the
352   *     value to the max field number of the message unless the field numbers
353   *     are too sparse. If the value is not set, a default value specified in
354   *     storage.js will be used.
355   * @return {!Kernel}
356   */
357  static fromArrayBuffer(arrayBuffer, pivot = undefined) {
358    const bufferDecoder = BufferDecoder.fromArrayBuffer(arrayBuffer);
359    return Kernel.fromBufferDecoder_(bufferDecoder, pivot);
360  }
361
362  /**
363   * Creates an empty Kernel.
364   * @param {number=} pivot Fields with a field number no greater than the pivot
365   *     value will be stored in an array for fast access. Other fields will be
366   *     stored in a map. A higher pivot value can improve runtime performance
367   *     at the expense of requiring more memory. It's recommended to set the
368   *     value to the max field number of the message unless the field numbers
369   *     are too sparse. If the value is not set, a default value specified in
370   *     storage.js will be used.
371   * @return {!Kernel}
372   */
373  static createEmpty(pivot = undefined) {
374    return new Kernel(/* bufferDecoder= */ null, new BinaryStorage(pivot));
375  }
376
377  /**
378   * Create a Kernel for the given binary bytes.
379   * The bytes array is kept by the Kernel. DON'T MODIFY IT.
380   * @param {!BufferDecoder} bufferDecoder Binary bytes.
381   * @param {number|undefined} pivot
382   * @return {!Kernel}
383   * @private
384   */
385  static fromBufferDecoder_(bufferDecoder, pivot) {
386    return new Kernel(bufferDecoder, buildIndex(bufferDecoder, pivot));
387  }
388
389  /**
390   * @param {?BufferDecoder} bufferDecoder Binary bytes. Accessor treats the
391   *     bytes as immutable and will never attempt to write to it.
392   * @param {!Storage<!Field>} fields A map of field number to Field. The
393   *     IndexEntry in each Field needs to be populated with the location of the
394   *     field in the binary data.
395   * @private
396   */
397  constructor(bufferDecoder, fields) {
398    /** @private @const {?BufferDecoder} */
399    this.bufferDecoder_ = bufferDecoder;
400    /** @private @const {!Storage<!Field>} */
401    this.fields_ = fields;
402  }
403
404  /**
405   * Creates a shallow copy of the accessor.
406   * @return {!Kernel}
407   */
408  shallowCopy() {
409    return new Kernel(this.bufferDecoder_, this.fields_.shallowCopy());
410  }
411
412  /**
413   * See definition of the pivot parameter on the fromArrayBuffer() method.
414   * @return {number}
415   */
416  getPivot() {
417    return this.fields_.getPivot();
418  }
419
420  /**
421   * Clears the field for the given field number.
422   * @param {number} fieldNumber
423   */
424  clearField(fieldNumber) {
425    this.fields_.delete(fieldNumber);
426  }
427
428  /**
429   * Returns data for a field specified by the given field number. Also cache
430   * the data if it doesn't already exist in the cache. When no data is
431   * available, return the given default value.
432   * @param {number} fieldNumber
433   * @param {?T} defaultValue
434   * @param {function(!Array<!IndexEntry>, !BufferDecoder):T} readFunc
435   * @param {function(!Writer, number, T)=} encoder
436   * @return {T}
437   * @template T
438   * @private
439   */
440  getFieldWithDefault_(
441      fieldNumber, defaultValue, readFunc, encoder = undefined) {
442    checkFieldNumber(fieldNumber);
443
444    const field = this.fields_.get(fieldNumber);
445    if (field === undefined) {
446      return defaultValue;
447    }
448
449    if (field.hasDecodedValue()) {
450      checkState(!encoder || !!field.getEncoder());
451      return field.getDecodedValue();
452    }
453
454    const parsed = readFunc(
455        checkDefAndNotNull(field.getIndexArray()),
456        checkDefAndNotNull(this.bufferDecoder_));
457    field.setCache(parsed, encoder);
458    return parsed;
459  }
460
461  /**
462   * Sets data for a singular field specified by the given field number.
463   * @param {number} fieldNumber
464   * @param {T} value
465   * @param {function(!Writer, number, T)} encoder
466   * @return {T}
467   * @template T
468   * @private
469   */
470  setField_(fieldNumber, value, encoder) {
471    checkFieldNumber(fieldNumber);
472    this.fields_.set(fieldNumber, Field.fromDecodedValue(value, encoder));
473  }
474
475  /**
476   * Serializes internal contents to binary format bytes array to the
477   * given writer.
478   * @param {!Writer} writer
479   * @package
480   */
481  serializeToWriter(writer) {
482    // If we use for...of here, jscompiler returns an array of both types for
483    // fieldNumber and field without specifying which type is for
484    // field, which prevents us to use fieldNumber. Thus, we use
485    // forEach here.
486    this.fields_.forEach((field, fieldNumber) => {
487      // If encoder doesn't exist, there is no need to encode the value
488      // because the data in the index is still valid.
489      if (field.getEncoder() !== undefined) {
490        const encoder = checkDefAndNotNull(field.getEncoder());
491        encoder(writer, fieldNumber, field.getDecodedValue());
492        return;
493      }
494
495      const indexArr = field.getIndexArray();
496      if (indexArr) {
497        for (const indexEntry of indexArr) {
498          writer.writeTag(fieldNumber, Field.getWireType(indexEntry));
499          writer.writeBufferDecoder(
500              checkDefAndNotNull(this.bufferDecoder_),
501              Field.getStartIndex(indexEntry), Field.getWireType(indexEntry),
502              fieldNumber);
503        }
504      }
505    });
506  }
507
508  /**
509   * Serializes internal contents to binary format bytes array.
510   * @return {!ArrayBuffer}
511   */
512  serialize() {
513    const writer = new Writer();
514    this.serializeToWriter(writer);
515    return writer.getAndResetResultBuffer();
516  }
517
518  /**
519   * Returns whether data exists at the given field number.
520   * @param {number} fieldNumber
521   * @return {boolean}
522   */
523  hasFieldNumber(fieldNumber) {
524    checkFieldNumber(fieldNumber);
525    const field = this.fields_.get(fieldNumber);
526
527    if (field === undefined) {
528      return false;
529    }
530
531    if (field.getIndexArray() !== null) {
532      return true;
533    }
534
535    if (Array.isArray(field.getDecodedValue())) {
536      // For repeated fields, existence is decided by number of elements.
537      return (/** !Array<?> */ (field.getDecodedValue())).length > 0;
538    }
539    return true;
540  }
541
542  /***************************************************************************
543   *                        OPTIONAL GETTER METHODS
544   ***************************************************************************/
545
546  /**
547   * Returns data as boolean for the given field number.
548   * If no default is given, use false as the default.
549   * @param {number} fieldNumber
550   * @param {boolean=} defaultValue
551   * @return {boolean}
552   */
553  getBoolWithDefault(fieldNumber, defaultValue = false) {
554    return this.getFieldWithDefault_(
555        fieldNumber, defaultValue,
556        (indexArray, bytes) =>
557            readOptional(indexArray, bytes, reader.readBool, WireType.VARINT));
558  }
559
560  /**
561   * Returns data as a ByteString for the given field number.
562   * If no default is given, use false as the default.
563   * @param {number} fieldNumber
564   * @param {!ByteString=} defaultValue
565   * @return {!ByteString}
566   */
567  getBytesWithDefault(fieldNumber, defaultValue = ByteString.EMPTY) {
568    return this.getFieldWithDefault_(
569        fieldNumber, defaultValue,
570        (indexArray, bytes) => readOptional(
571            indexArray, bytes, reader.readBytes, WireType.DELIMITED));
572  }
573
574  /**
575   * Returns a double for the given field number.
576   * If no default is given uses zero as the default.
577   * @param {number} fieldNumber
578   * @param {number=} defaultValue
579   * @return {number}
580   */
581  getDoubleWithDefault(fieldNumber, defaultValue = 0) {
582    checkTypeDouble(defaultValue);
583    return this.getFieldWithDefault_(
584        fieldNumber, defaultValue,
585        (indexArray, bytes) => readOptional(
586            indexArray, bytes, reader.readDouble, WireType.FIXED64));
587  }
588
589  /**
590   * Returns a fixed32 for the given field number.
591   * If no default is given zero as the default.
592   * @param {number} fieldNumber
593   * @param {number=} defaultValue
594   * @return {number}
595   */
596  getFixed32WithDefault(fieldNumber, defaultValue = 0) {
597    checkTypeUnsignedInt32(defaultValue);
598    return this.getFieldWithDefault_(
599        fieldNumber, defaultValue,
600        (indexArray, bytes) => readOptional(
601            indexArray, bytes, reader.readFixed32, WireType.FIXED32));
602  }
603
604  /**
605   * Returns a fixed64 for the given field number.
606   * Note: Since g.m.Long does not support unsigned int64 values we are going
607   * the Java route here for now and simply output the number as a signed int64.
608   * Users can get to individual bits by themselves.
609   * @param {number} fieldNumber
610   * @param {!Int64=} defaultValue
611   * @return {!Int64}
612   */
613  getFixed64WithDefault(fieldNumber, defaultValue = Int64.getZero()) {
614    return this.getSfixed64WithDefault(fieldNumber, defaultValue);
615  }
616
617  /**
618   * Returns a float for the given field number.
619   * If no default is given zero as the default.
620   * @param {number} fieldNumber
621   * @param {number=} defaultValue
622   * @return {number}
623   */
624  getFloatWithDefault(fieldNumber, defaultValue = 0) {
625    checkTypeFloat(defaultValue);
626    return this.getFieldWithDefault_(
627        fieldNumber, defaultValue,
628        (indexArray, bytes) => readOptional(
629            indexArray, bytes, reader.readFloat, WireType.FIXED32));
630  }
631
632  /**
633   * Returns a int32 for the given field number.
634   * If no default is given zero as the default.
635   * @param {number} fieldNumber
636   * @param {number=} defaultValue
637   * @return {number}
638   */
639  getInt32WithDefault(fieldNumber, defaultValue = 0) {
640    checkTypeSignedInt32(defaultValue);
641    return this.getFieldWithDefault_(
642        fieldNumber, defaultValue,
643        (indexArray, bytes) =>
644            readOptional(indexArray, bytes, reader.readInt32, WireType.VARINT));
645  }
646
647  /**
648   * Returns a int64 for the given field number.
649   * If no default is given zero as the default.
650   * @param {number} fieldNumber
651   * @param {!Int64=} defaultValue
652   * @return {!Int64}
653   */
654  getInt64WithDefault(fieldNumber, defaultValue = Int64.getZero()) {
655    checkTypeSignedInt64(defaultValue);
656    return this.getFieldWithDefault_(
657        fieldNumber, defaultValue,
658        (indexArray, bytes) =>
659            readOptional(indexArray, bytes, reader.readInt64, WireType.VARINT));
660  }
661
662  /**
663   * Returns a sfixed32 for the given field number.
664   * If no default is given zero as the default.
665   * @param {number} fieldNumber
666   * @param {number=} defaultValue
667   * @return {number}
668   */
669  getSfixed32WithDefault(fieldNumber, defaultValue = 0) {
670    checkTypeSignedInt32(defaultValue);
671    return this.getFieldWithDefault_(
672        fieldNumber, defaultValue,
673        (indexArray, bytes) => readOptional(
674            indexArray, bytes, reader.readSfixed32, WireType.FIXED32));
675  }
676
677  /**
678   * Returns a sfixed64 for the given field number.
679   * If no default is given zero as the default.
680   * @param {number} fieldNumber
681   * @param {!Int64=} defaultValue
682   * @return {!Int64}
683   */
684  getSfixed64WithDefault(fieldNumber, defaultValue = Int64.getZero()) {
685    checkTypeSignedInt64(defaultValue);
686    return this.getFieldWithDefault_(
687        fieldNumber, defaultValue,
688        (indexArray, bytes) => readOptional(
689            indexArray, bytes, reader.readSfixed64, WireType.FIXED64));
690  }
691
692  /**
693   * Returns a sint32 for the given field number.
694   * If no default is given zero as the default.
695   * @param {number} fieldNumber
696   * @param {number=} defaultValue
697   * @return {number}
698   */
699  getSint32WithDefault(fieldNumber, defaultValue = 0) {
700    checkTypeSignedInt32(defaultValue);
701    return this.getFieldWithDefault_(
702        fieldNumber, defaultValue,
703        (indexArray, bytes) => readOptional(
704            indexArray, bytes, reader.readSint32, WireType.VARINT));
705  }
706
707  /**
708   * Returns a sint64 for the given field number.
709   * If no default is given zero as the default.
710   * @param {number} fieldNumber
711   * @param {!Int64=} defaultValue
712   * @return {!Int64}
713   */
714  getSint64WithDefault(fieldNumber, defaultValue = Int64.getZero()) {
715    checkTypeSignedInt64(defaultValue);
716    return this.getFieldWithDefault_(
717        fieldNumber, defaultValue,
718        (indexArray, bytes) => readOptional(
719            indexArray, bytes, reader.readSint64, WireType.VARINT));
720  }
721
722  /**
723   * Returns a string for the given field number.
724   * If no default is given uses empty string as the default.
725   * @param {number} fieldNumber
726   * @param {string=} defaultValue
727   * @return {string}
728   */
729  getStringWithDefault(fieldNumber, defaultValue = '') {
730    return this.getFieldWithDefault_(
731        fieldNumber, defaultValue,
732        (indexArray, bytes) => readOptional(
733            indexArray, bytes, reader.readString, WireType.DELIMITED));
734  }
735
736  /**
737   * Returns a uint32 for the given field number.
738   * If no default is given zero as the default.
739   * @param {number} fieldNumber
740   * @param {number=} defaultValue
741   * @return {number}
742   */
743  getUint32WithDefault(fieldNumber, defaultValue = 0) {
744    checkTypeUnsignedInt32(defaultValue);
745    return this.getFieldWithDefault_(
746        fieldNumber, defaultValue,
747        (indexArray, bytes) => readOptional(
748            indexArray, bytes, reader.readUint32, WireType.VARINT));
749  }
750
751  /**
752   * Returns a uint64 for the given field number.
753   * Note: Since g.m.Long does not support unsigned int64 values we are going
754   * the Java route here for now and simply output the number as a signed int64.
755   * Users can get to individual bits by themselves.
756   * @param {number} fieldNumber
757   * @param {!Int64=} defaultValue
758   * @return {!Int64}
759   */
760  getUint64WithDefault(fieldNumber, defaultValue = Int64.getZero()) {
761    return this.getInt64WithDefault(fieldNumber, defaultValue);
762  }
763
764  /**
765   * Returns data as a mutable proto Message for the given field number.
766   * If no value has been set, return null.
767   * If hasFieldNumber(fieldNumber) == false before calling, it remains false.
768   *
769   * This method should not be used along with getMessage, since calling
770   * getMessageOrNull after getMessage will not register the encoder.
771   *
772   * @param {number} fieldNumber
773   * @param {function(!Kernel):T} instanceCreator
774   * @param {number=} pivot
775   * @return {?T}
776   * @template T
777   */
778  getMessageOrNull(fieldNumber, instanceCreator, pivot = undefined) {
779    return this.getFieldWithDefault_(
780        fieldNumber, null,
781        (indexArray, bytes) =>
782            readMessage(indexArray, bytes, instanceCreator, pivot),
783        writeMessage);
784  }
785
786  /**
787   * Returns data as a mutable proto Message for the given field number.
788   * If no value has been set, return null.
789   * If hasFieldNumber(fieldNumber) == false before calling, it remains false.
790   *
791   * This method should not be used along with getMessage, since calling
792   * getMessageOrNull after getMessage will not register the encoder.
793   *
794   * @param {number} fieldNumber
795   * @param {function(!Kernel):T} instanceCreator
796   * @param {number=} pivot
797   * @return {?T}
798   * @template T
799   */
800  getGroupOrNull(fieldNumber, instanceCreator, pivot = undefined) {
801    return this.getFieldWithDefault_(
802        fieldNumber, null,
803        (indexArray, bytes) =>
804            readGroup(indexArray, bytes, fieldNumber, instanceCreator, pivot),
805        writeGroup);
806  }
807
808  /**
809   * Returns data as a mutable proto Message for the given field number.
810   * If no value has been set previously, creates and attaches an instance.
811   * Postcondition: hasFieldNumber(fieldNumber) == true.
812   *
813   * This method should not be used along with getMessage, since calling
814   * getMessageAttach after getMessage will not register the encoder.
815   *
816   * @param {number} fieldNumber
817   * @param {function(!Kernel):T} instanceCreator
818   * @param {number=} pivot
819   * @return {T}
820   * @template T
821   */
822  getMessageAttach(fieldNumber, instanceCreator, pivot = undefined) {
823    checkInstanceCreator(instanceCreator);
824    let instance = this.getMessageOrNull(fieldNumber, instanceCreator, pivot);
825    if (!instance) {
826      instance = instanceCreator(Kernel.createEmpty());
827      this.setField_(fieldNumber, instance, writeMessage);
828    }
829    return instance;
830  }
831
832  /**
833   * Returns data as a mutable proto Message for the given field number.
834   * If no value has been set previously, creates and attaches an instance.
835   * Postcondition: hasFieldNumber(fieldNumber) == true.
836   *
837   * This method should not be used along with getMessage, since calling
838   * getMessageAttach after getMessage will not register the encoder.
839   *
840   * @param {number} fieldNumber
841   * @param {function(!Kernel):T} instanceCreator
842   * @param {number=} pivot
843   * @return {T}
844   * @template T
845   */
846  getGroupAttach(fieldNumber, instanceCreator, pivot = undefined) {
847    checkInstanceCreator(instanceCreator);
848    let instance = this.getGroupOrNull(fieldNumber, instanceCreator, pivot);
849    if (!instance) {
850      instance = instanceCreator(Kernel.createEmpty());
851      this.setField_(fieldNumber, instance, writeGroup);
852    }
853    return instance;
854  }
855
856  /**
857   * Returns data as a proto Message for the given field number.
858   * If no value has been set, return a default instance.
859   * This default instance is guaranteed to be the same instance, unless this
860   * field is cleared.
861   * Does not register the encoder, so changes made to the returned
862   * sub-message will not be included when serializing the parent message.
863   * Use getMessageAttach() if the resulting sub-message should be mutable.
864   *
865   * This method should not be used along with getMessageOrNull or
866   * getMessageAttach, since these methods register the encoder.
867   *
868   * @param {number} fieldNumber
869   * @param {function(!Kernel):T} instanceCreator
870   * @param {number=} pivot
871   * @return {T}
872   * @template T
873   */
874  getMessage(fieldNumber, instanceCreator, pivot = undefined) {
875    checkInstanceCreator(instanceCreator);
876    const message = this.getFieldWithDefault_(
877        fieldNumber, null,
878        (indexArray, bytes) =>
879            readMessage(indexArray, bytes, instanceCreator, pivot));
880    // Returns an empty message as the default value if the field doesn't exist.
881    // We don't pass the default value to getFieldWithDefault_ to reduce object
882    // allocation.
883    return message === null ? instanceCreator(Kernel.createEmpty()) : message;
884  }
885
886  /**
887   * Returns data as a proto Message for the given field number.
888   * If no value has been set, return a default instance.
889   * This default instance is guaranteed to be the same instance, unless this
890   * field is cleared.
891   * Does not register the encoder, so changes made to the returned
892   * sub-message will not be included when serializing the parent message.
893   * Use getMessageAttach() if the resulting sub-message should be mutable.
894   *
895   * This method should not be used along with getMessageOrNull or
896   * getMessageAttach, since these methods register the encoder.
897   *
898   * @param {number} fieldNumber
899   * @param {function(!Kernel):T} instanceCreator
900   * @param {number=} pivot
901   * @return {T}
902   * @template T
903   */
904  getGroup(fieldNumber, instanceCreator, pivot = undefined) {
905    checkInstanceCreator(instanceCreator);
906    const message = this.getFieldWithDefault_(
907        fieldNumber, null,
908        (indexArray, bytes) =>
909            readGroup(indexArray, bytes, fieldNumber, instanceCreator, pivot));
910    // Returns an empty message as the default value if the field doesn't exist.
911    // We don't pass the default value to getFieldWithDefault_ to reduce object
912    // allocation.
913    return message === null ? instanceCreator(Kernel.createEmpty()) : message;
914  }
915
916  /**
917   * Returns the accessor for the given singular message, or returns null if
918   * it hasn't been set.
919   * @param {number} fieldNumber
920   * @param {number=} pivot
921   * @return {?Kernel}
922   */
923  getMessageAccessorOrNull(fieldNumber, pivot = undefined) {
924    checkFieldNumber(fieldNumber);
925    const field = this.fields_.get(fieldNumber);
926    if (field === undefined) {
927      return null;
928    }
929
930    if (field.hasDecodedValue()) {
931      return checkIsInternalMessage(field.getDecodedValue())
932          .internalGetKernel();
933    } else {
934      return readAccessor(
935          checkDefAndNotNull(field.getIndexArray()),
936          checkDefAndNotNull(this.bufferDecoder_), pivot);
937    }
938  }
939
940  /***************************************************************************
941   *                        REPEATED GETTER METHODS
942   ***************************************************************************/
943
944  /* Bool */
945
946  /**
947   * Returns an Array instance containing boolean values for the given field
948   * number.
949   * @param {number} fieldNumber
950   * @return {!Array<boolean>}
951   * @private
952   */
953  getRepeatedBoolArray_(fieldNumber) {
954    return this.getFieldWithDefault_(
955        fieldNumber, /* defaultValue= */[],
956        (indexArray, bytes) => readRepeatedPrimitive(
957            indexArray, bytes, reader.readBool, reader.readPackedBool,
958            WireType.VARINT));
959  }
960
961  /**
962   * Returns the element at index for the given field number.
963   * @param {number} fieldNumber
964   * @param {number} index
965   * @return {boolean}
966   */
967  getRepeatedBoolElement(fieldNumber, index) {
968    const array = this.getRepeatedBoolArray_(fieldNumber);
969    checkCriticalElementIndex(index, array.length);
970    return array[index];
971  }
972
973  /**
974   * Returns an Iterable instance containing boolean values for the given field
975   * number.
976   * @param {number} fieldNumber
977   * @return {!Iterable<boolean>}
978   */
979  getRepeatedBoolIterable(fieldNumber) {
980    // Don't split this statement unless needed. JS compiler thinks
981    // getRepeatedBoolArray_ might have side effects and doesn't inline the
982    // call in the compiled code. See cl/293894484 for details.
983    return new ArrayIterable(this.getRepeatedBoolArray_(fieldNumber));
984  }
985
986  /**
987   * Returns the size of the repeated field.
988   * @param {number} fieldNumber
989   * @return {number}
990   */
991  getRepeatedBoolSize(fieldNumber) {
992    return this.getRepeatedBoolArray_(fieldNumber).length;
993  }
994
995  /* Double */
996
997  /**
998   * Returns an Array instance containing double values for the given field
999   * number.
1000   * @param {number} fieldNumber
1001   * @return {!Array<number>}
1002   * @private
1003   */
1004  getRepeatedDoubleArray_(fieldNumber) {
1005    return this.getFieldWithDefault_(
1006        fieldNumber, /* defaultValue= */[],
1007        (indexArray, bytes) => readRepeatedPrimitive(
1008            indexArray, bytes, reader.readDouble, reader.readPackedDouble,
1009            WireType.FIXED64));
1010  }
1011
1012  /**
1013   * Returns the element at index for the given field number.
1014   * @param {number} fieldNumber
1015   * @param {number} index
1016   * @return {number}
1017   */
1018  getRepeatedDoubleElement(fieldNumber, index) {
1019    const array = this.getRepeatedDoubleArray_(fieldNumber);
1020    checkCriticalElementIndex(index, array.length);
1021    return array[index];
1022  }
1023
1024  /**
1025   * Returns an Iterable instance containing double values for the given field
1026   * number.
1027   * @param {number} fieldNumber
1028   * @return {!Iterable<number>}
1029   */
1030  getRepeatedDoubleIterable(fieldNumber) {
1031    // Don't split this statement unless needed. JS compiler thinks
1032    // getRepeatedDoubleArray_ might have side effects and doesn't inline the
1033    // call in the compiled code. See cl/293894484 for details.
1034    return new ArrayIterable(this.getRepeatedDoubleArray_(fieldNumber));
1035  }
1036
1037  /**
1038   * Returns the size of the repeated field.
1039   * @param {number} fieldNumber
1040   * @return {number}
1041   */
1042  getRepeatedDoubleSize(fieldNumber) {
1043    return this.getRepeatedDoubleArray_(fieldNumber).length;
1044  }
1045
1046  /* Fixed32 */
1047
1048  /**
1049   * Returns an Array instance containing fixed32 values for the given field
1050   * number.
1051   * @param {number} fieldNumber
1052   * @return {!Array<number>}
1053   * @private
1054   */
1055  getRepeatedFixed32Array_(fieldNumber) {
1056    return this.getFieldWithDefault_(
1057        fieldNumber, /* defaultValue= */[],
1058        (indexArray, bytes) => readRepeatedPrimitive(
1059            indexArray, bytes, reader.readFixed32, reader.readPackedFixed32,
1060            WireType.FIXED32));
1061  }
1062
1063  /**
1064   * Returns the element at index for the given field number.
1065   * @param {number} fieldNumber
1066   * @param {number} index
1067   * @return {number}
1068   */
1069  getRepeatedFixed32Element(fieldNumber, index) {
1070    const array = this.getRepeatedFixed32Array_(fieldNumber);
1071    checkCriticalElementIndex(index, array.length);
1072    return array[index];
1073  }
1074
1075  /**
1076   * Returns an Iterable instance containing fixed32 values for the given field
1077   * number.
1078   * @param {number} fieldNumber
1079   * @return {!Iterable<number>}
1080   */
1081  getRepeatedFixed32Iterable(fieldNumber) {
1082    // Don't split this statement unless needed. JS compiler thinks
1083    // getRepeatedFixed32Array_ might have side effects and doesn't inline the
1084    // call in the compiled code. See cl/293894484 for details.
1085    return new ArrayIterable(this.getRepeatedFixed32Array_(fieldNumber));
1086  }
1087
1088  /**
1089   * Returns the size of the repeated field.
1090   * @param {number} fieldNumber
1091   * @return {number}
1092   */
1093  getRepeatedFixed32Size(fieldNumber) {
1094    return this.getRepeatedFixed32Array_(fieldNumber).length;
1095  }
1096
1097  /* Fixed64 */
1098
1099  /**
1100   * Returns the element at index for the given field number.
1101   * @param {number} fieldNumber
1102   * @param {number} index
1103   * @return {!Int64}
1104   */
1105  getRepeatedFixed64Element(fieldNumber, index) {
1106    return this.getRepeatedSfixed64Element(fieldNumber, index);
1107  }
1108
1109  /**
1110   * Returns an Iterable instance containing fixed64 values for the given field
1111   * number.
1112   * @param {number} fieldNumber
1113   * @return {!Iterable<!Int64>}
1114   */
1115  getRepeatedFixed64Iterable(fieldNumber) {
1116    return this.getRepeatedSfixed64Iterable(fieldNumber);
1117  }
1118
1119  /**
1120   * Returns the size of the repeated field.
1121   * @param {number} fieldNumber
1122   * @return {number}
1123   */
1124  getRepeatedFixed64Size(fieldNumber) {
1125    return this.getRepeatedSfixed64Size(fieldNumber);
1126  }
1127
1128  /* Float */
1129
1130  /**
1131   * Returns an Array instance containing float values for the given field
1132   * number.
1133   * @param {number} fieldNumber
1134   * @return {!Array<number>}
1135   * @private
1136   */
1137  getRepeatedFloatArray_(fieldNumber) {
1138    return this.getFieldWithDefault_(
1139        fieldNumber, /* defaultValue= */[],
1140        (indexArray, bytes) => readRepeatedPrimitive(
1141            indexArray, bytes, reader.readFloat, reader.readPackedFloat,
1142            WireType.FIXED32));
1143  }
1144
1145  /**
1146   * Returns the element at index for the given field number.
1147   * @param {number} fieldNumber
1148   * @param {number} index
1149   * @return {number}
1150   */
1151  getRepeatedFloatElement(fieldNumber, index) {
1152    const array = this.getRepeatedFloatArray_(fieldNumber);
1153    checkCriticalElementIndex(index, array.length);
1154    return array[index];
1155  }
1156
1157  /**
1158   * Returns an Iterable instance containing float values for the given field
1159   * number.
1160   * @param {number} fieldNumber
1161   * @return {!Iterable<number>}
1162   */
1163  getRepeatedFloatIterable(fieldNumber) {
1164    // Don't split this statement unless needed. JS compiler thinks
1165    // getRepeatedFloatArray_ might have side effects and doesn't inline the
1166    // call in the compiled code. See cl/293894484 for details.
1167    return new ArrayIterable(this.getRepeatedFloatArray_(fieldNumber));
1168  }
1169
1170  /**
1171   * Returns the size of the repeated field.
1172   * @param {number} fieldNumber
1173   * @return {number}
1174   */
1175  getRepeatedFloatSize(fieldNumber) {
1176    return this.getRepeatedFloatArray_(fieldNumber).length;
1177  }
1178
1179  /* Int32 */
1180
1181  /**
1182   * Returns an Array instance containing int32 values for the given field
1183   * number.
1184   * @param {number} fieldNumber
1185   * @return {!Array<number>}
1186   * @private
1187   */
1188  getRepeatedInt32Array_(fieldNumber) {
1189    return this.getFieldWithDefault_(
1190        fieldNumber, /* defaultValue= */[],
1191        (indexArray, bytes) => readRepeatedPrimitive(
1192            indexArray, bytes, reader.readInt32, reader.readPackedInt32,
1193            WireType.VARINT));
1194  }
1195
1196  /**
1197   * Returns the element at index for the given field number.
1198   * @param {number} fieldNumber
1199   * @param {number} index
1200   * @return {number}
1201   */
1202  getRepeatedInt32Element(fieldNumber, index) {
1203    const array = this.getRepeatedInt32Array_(fieldNumber);
1204    checkCriticalElementIndex(index, array.length);
1205    return array[index];
1206  }
1207
1208  /**
1209   * Returns an Iterable instance containing int32 values for the given field
1210   * number.
1211   * @param {number} fieldNumber
1212   * @return {!Iterable<number>}
1213   */
1214  getRepeatedInt32Iterable(fieldNumber) {
1215    // Don't split this statement unless needed. JS compiler thinks
1216    // getRepeatedInt32Array_ might have side effects and doesn't inline the
1217    // call in the compiled code. See cl/293894484 for details.
1218    return new ArrayIterable(this.getRepeatedInt32Array_(fieldNumber));
1219  }
1220
1221  /**
1222   * Returns the size of the repeated field.
1223   * @param {number} fieldNumber
1224   * @return {number}
1225   */
1226  getRepeatedInt32Size(fieldNumber) {
1227    return this.getRepeatedInt32Array_(fieldNumber).length;
1228  }
1229
1230  /* Int64 */
1231
1232  /**
1233   * Returns an Array instance containing int64 values for the given field
1234   * number.
1235   * @param {number} fieldNumber
1236   * @return {!Array<!Int64>}
1237   * @private
1238   */
1239  getRepeatedInt64Array_(fieldNumber) {
1240    return this.getFieldWithDefault_(
1241        fieldNumber, /* defaultValue= */[],
1242        (indexArray, bytes) => readRepeatedPrimitive(
1243            indexArray, bytes, reader.readInt64, reader.readPackedInt64,
1244            WireType.VARINT));
1245  }
1246
1247  /**
1248   * Returns the element at index for the given field number.
1249   * @param {number} fieldNumber
1250   * @param {number} index
1251   * @return {!Int64}
1252   */
1253  getRepeatedInt64Element(fieldNumber, index) {
1254    const array = this.getRepeatedInt64Array_(fieldNumber);
1255    checkCriticalElementIndex(index, array.length);
1256    return array[index];
1257  }
1258
1259  /**
1260   * Returns an Iterable instance containing int64 values for the given field
1261   * number.
1262   * @param {number} fieldNumber
1263   * @return {!Iterable<!Int64>}
1264   */
1265  getRepeatedInt64Iterable(fieldNumber) {
1266    // Don't split this statement unless needed. JS compiler thinks
1267    // getRepeatedInt64Array_ might have side effects and doesn't inline the
1268    // call in the compiled code. See cl/293894484 for details.
1269    return new ArrayIterable(this.getRepeatedInt64Array_(fieldNumber));
1270  }
1271
1272  /**
1273   * Returns the size of the repeated field.
1274   * @param {number} fieldNumber
1275   * @return {number}
1276   */
1277  getRepeatedInt64Size(fieldNumber) {
1278    return this.getRepeatedInt64Array_(fieldNumber).length;
1279  }
1280
1281  /* Sfixed32 */
1282
1283  /**
1284   * Returns an Array instance containing sfixed32 values for the given field
1285   * number.
1286   * @param {number} fieldNumber
1287   * @return {!Array<number>}
1288   * @private
1289   */
1290  getRepeatedSfixed32Array_(fieldNumber) {
1291    return this.getFieldWithDefault_(
1292        fieldNumber, /* defaultValue= */[],
1293        (indexArray, bytes) => readRepeatedPrimitive(
1294            indexArray, bytes, reader.readSfixed32, reader.readPackedSfixed32,
1295            WireType.FIXED32));
1296  }
1297
1298  /**
1299   * Returns the element at index for the given field number.
1300   * @param {number} fieldNumber
1301   * @param {number} index
1302   * @return {number}
1303   */
1304  getRepeatedSfixed32Element(fieldNumber, index) {
1305    const array = this.getRepeatedSfixed32Array_(fieldNumber);
1306    checkCriticalElementIndex(index, array.length);
1307    return array[index];
1308  }
1309
1310  /**
1311   * Returns an Iterable instance containing sfixed32 values for the given field
1312   * number.
1313   * @param {number} fieldNumber
1314   * @return {!Iterable<number>}
1315   */
1316  getRepeatedSfixed32Iterable(fieldNumber) {
1317    // Don't split this statement unless needed. JS compiler thinks
1318    // getRepeatedSfixed32Array_ might have side effects and doesn't inline the
1319    // call in the compiled code. See cl/293894484 for details.
1320    return new ArrayIterable(this.getRepeatedSfixed32Array_(fieldNumber));
1321  }
1322
1323  /**
1324   * Returns the size of the repeated field.
1325   * @param {number} fieldNumber
1326   * @return {number}
1327   */
1328  getRepeatedSfixed32Size(fieldNumber) {
1329    return this.getRepeatedSfixed32Array_(fieldNumber).length;
1330  }
1331
1332  /* Sfixed64 */
1333
1334  /**
1335   * Returns an Array instance containing sfixed64 values for the given field
1336   * number.
1337   * @param {number} fieldNumber
1338   * @return {!Array<!Int64>}
1339   * @private
1340   */
1341  getRepeatedSfixed64Array_(fieldNumber) {
1342    return this.getFieldWithDefault_(
1343        fieldNumber, /* defaultValue= */[],
1344        (indexArray, bytes) => readRepeatedPrimitive(
1345            indexArray, bytes, reader.readSfixed64, reader.readPackedSfixed64,
1346            WireType.FIXED64));
1347  }
1348
1349  /**
1350   * Returns the element at index for the given field number.
1351   * @param {number} fieldNumber
1352   * @param {number} index
1353   * @return {!Int64}
1354   */
1355  getRepeatedSfixed64Element(fieldNumber, index) {
1356    const array = this.getRepeatedSfixed64Array_(fieldNumber);
1357    checkCriticalElementIndex(index, array.length);
1358    return array[index];
1359  }
1360
1361  /**
1362   * Returns an Iterable instance containing sfixed64 values for the given field
1363   * number.
1364   * @param {number} fieldNumber
1365   * @return {!Iterable<!Int64>}
1366   */
1367  getRepeatedSfixed64Iterable(fieldNumber) {
1368    // Don't split this statement unless needed. JS compiler thinks
1369    // getRepeatedSfixed64Array_ might have side effects and doesn't inline the
1370    // call in the compiled code. See cl/293894484 for details.
1371    return new ArrayIterable(this.getRepeatedSfixed64Array_(fieldNumber));
1372  }
1373
1374  /**
1375   * Returns the size of the repeated field.
1376   * @param {number} fieldNumber
1377   * @return {number}
1378   */
1379  getRepeatedSfixed64Size(fieldNumber) {
1380    return this.getRepeatedSfixed64Array_(fieldNumber).length;
1381  }
1382
1383  /* Sint32 */
1384
1385  /**
1386   * Returns an Array instance containing sint32 values for the given field
1387   * number.
1388   * @param {number} fieldNumber
1389   * @return {!Array<number>}
1390   * @private
1391   */
1392  getRepeatedSint32Array_(fieldNumber) {
1393    return this.getFieldWithDefault_(
1394        fieldNumber, /* defaultValue= */[],
1395        (indexArray, bytes) => readRepeatedPrimitive(
1396            indexArray, bytes, reader.readSint32, reader.readPackedSint32,
1397            WireType.VARINT));
1398  }
1399
1400  /**
1401   * Returns the element at index for the given field number.
1402   * @param {number} fieldNumber
1403   * @param {number} index
1404   * @return {number}
1405   */
1406  getRepeatedSint32Element(fieldNumber, index) {
1407    const array = this.getRepeatedSint32Array_(fieldNumber);
1408    checkCriticalElementIndex(index, array.length);
1409    return array[index];
1410  }
1411
1412  /**
1413   * Returns an Iterable instance containing sint32 values for the given field
1414   * number.
1415   * @param {number} fieldNumber
1416   * @return {!Iterable<number>}
1417   */
1418  getRepeatedSint32Iterable(fieldNumber) {
1419    // Don't split this statement unless needed. JS compiler thinks
1420    // getRepeatedSint32Array_ might have side effects and doesn't inline the
1421    // call in the compiled code. See cl/293894484 for details.
1422    return new ArrayIterable(this.getRepeatedSint32Array_(fieldNumber));
1423  }
1424
1425  /**
1426   * Returns the size of the repeated field.
1427   * @param {number} fieldNumber
1428   * @return {number}
1429   */
1430  getRepeatedSint32Size(fieldNumber) {
1431    return this.getRepeatedSint32Array_(fieldNumber).length;
1432  }
1433
1434  /* Sint64 */
1435
1436  /**
1437   * Returns an Array instance containing sint64 values for the given field
1438   * number.
1439   * @param {number} fieldNumber
1440   * @return {!Array<!Int64>}
1441   * @private
1442   */
1443  getRepeatedSint64Array_(fieldNumber) {
1444    return this.getFieldWithDefault_(
1445        fieldNumber, /* defaultValue= */[],
1446        (indexArray, bytes) => readRepeatedPrimitive(
1447            indexArray, bytes, reader.readSint64, reader.readPackedSint64,
1448            WireType.VARINT));
1449  }
1450
1451  /**
1452   * Returns the element at index for the given field number.
1453   * @param {number} fieldNumber
1454   * @param {number} index
1455   * @return {!Int64}
1456   */
1457  getRepeatedSint64Element(fieldNumber, index) {
1458    const array = this.getRepeatedSint64Array_(fieldNumber);
1459    checkCriticalElementIndex(index, array.length);
1460    return array[index];
1461  }
1462
1463  /**
1464   * Returns an Iterable instance containing sint64 values for the given field
1465   * number.
1466   * @param {number} fieldNumber
1467   * @return {!Iterable<!Int64>}
1468   */
1469  getRepeatedSint64Iterable(fieldNumber) {
1470    // Don't split this statement unless needed. JS compiler thinks
1471    // getRepeatedSint64Array_ might have side effects and doesn't inline the
1472    // call in the compiled code. See cl/293894484 for details.
1473    return new ArrayIterable(this.getRepeatedSint64Array_(fieldNumber));
1474  }
1475
1476  /**
1477   * Returns the size of the repeated field.
1478   * @param {number} fieldNumber
1479   * @return {number}
1480   */
1481  getRepeatedSint64Size(fieldNumber) {
1482    return this.getRepeatedSint64Array_(fieldNumber).length;
1483  }
1484
1485  /* Uint32 */
1486
1487  /**
1488   * Returns an Array instance containing uint32 values for the given field
1489   * number.
1490   * @param {number} fieldNumber
1491   * @return {!Array<number>}
1492   * @private
1493   */
1494  getRepeatedUint32Array_(fieldNumber) {
1495    return this.getFieldWithDefault_(
1496        fieldNumber, /* defaultValue= */[],
1497        (indexArray, bytes) => readRepeatedPrimitive(
1498            indexArray, bytes, reader.readUint32, reader.readPackedUint32,
1499            WireType.VARINT));
1500  }
1501
1502  /**
1503   * Returns the element at index for the given field number.
1504   * @param {number} fieldNumber
1505   * @param {number} index
1506   * @return {number}
1507   */
1508  getRepeatedUint32Element(fieldNumber, index) {
1509    const array = this.getRepeatedUint32Array_(fieldNumber);
1510    checkCriticalElementIndex(index, array.length);
1511    return array[index];
1512  }
1513
1514  /**
1515   * Returns an Iterable instance containing uint32 values for the given field
1516   * number.
1517   * @param {number} fieldNumber
1518   * @return {!Iterable<number>}
1519   */
1520  getRepeatedUint32Iterable(fieldNumber) {
1521    // Don't split this statement unless needed. JS compiler thinks
1522    // getRepeatedUint32Array_ might have side effects and doesn't inline the
1523    // call in the compiled code. See cl/293894484 for details.
1524    return new ArrayIterable(this.getRepeatedUint32Array_(fieldNumber));
1525  }
1526
1527  /**
1528   * Returns the size of the repeated field.
1529   * @param {number} fieldNumber
1530   * @return {number}
1531   */
1532  getRepeatedUint32Size(fieldNumber) {
1533    return this.getRepeatedUint32Array_(fieldNumber).length;
1534  }
1535
1536  /* Uint64 */
1537
1538  /**
1539   * Returns the element at index for the given field number.
1540   * @param {number} fieldNumber
1541   * @param {number} index
1542   * @return {!Int64}
1543   */
1544  getRepeatedUint64Element(fieldNumber, index) {
1545    return this.getRepeatedInt64Element(fieldNumber, index);
1546  }
1547
1548  /**
1549   * Returns an Iterable instance containing uint64 values for the given field
1550   * number.
1551   * @param {number} fieldNumber
1552   * @return {!Iterable<!Int64>}
1553   */
1554  getRepeatedUint64Iterable(fieldNumber) {
1555    return this.getRepeatedInt64Iterable(fieldNumber);
1556  }
1557
1558  /**
1559   * Returns the size of the repeated field.
1560   * @param {number} fieldNumber
1561   * @return {number}
1562   */
1563  getRepeatedUint64Size(fieldNumber) {
1564    return this.getRepeatedInt64Size(fieldNumber);
1565  }
1566
1567  /* Bytes */
1568
1569  /**
1570   * Returns an array instance containing bytes values for the given field
1571   * number.
1572   * @param {number} fieldNumber
1573   * @return {!Array<!ByteString>}
1574   * @private
1575   */
1576  getRepeatedBytesArray_(fieldNumber) {
1577    return this.getFieldWithDefault_(
1578        fieldNumber, /* defaultValue= */[],
1579        (indexArray, bytes) =>
1580            readRepeatedNonPrimitive(indexArray, bytes, reader.readBytes));
1581  }
1582
1583  /**
1584   * Returns the element at index for the given field number as a bytes.
1585   * @param {number} fieldNumber
1586   * @param {number} index
1587   * @return {!ByteString}
1588   */
1589  getRepeatedBytesElement(fieldNumber, index) {
1590    const array = this.getRepeatedBytesArray_(fieldNumber);
1591    checkCriticalElementIndex(index, array.length);
1592    return array[index];
1593  }
1594
1595  /**
1596   * Returns an Iterable instance containing bytes values for the given field
1597   * number.
1598   * @param {number} fieldNumber
1599   * @return {!Iterable<!ByteString>}
1600   */
1601  getRepeatedBytesIterable(fieldNumber) {
1602    // Don't split this statement unless needed. JS compiler thinks
1603    // getRepeatedBytesArray_ might have side effects and doesn't inline the
1604    // call in the compiled code. See cl/293894484 for details.
1605    return new ArrayIterable(this.getRepeatedBytesArray_(fieldNumber));
1606  }
1607
1608  /**
1609   * Returns the size of the repeated field.
1610   * @param {number} fieldNumber
1611   * @return {number}
1612   */
1613  getRepeatedBytesSize(fieldNumber) {
1614    return this.getRepeatedBytesArray_(fieldNumber).length;
1615  }
1616
1617  /* String */
1618
1619  /**
1620   * Returns an array instance containing string values for the given field
1621   * number.
1622   * @param {number} fieldNumber
1623   * @return {!Array<string>}
1624   * @private
1625   */
1626  getRepeatedStringArray_(fieldNumber) {
1627    return this.getFieldWithDefault_(
1628        fieldNumber, /* defaultValue= */[],
1629        (indexArray, bufferDecoder) => readRepeatedNonPrimitive(
1630            indexArray, bufferDecoder, reader.readString));
1631  }
1632
1633  /**
1634   * Returns the element at index for the given field number as a string.
1635   * @param {number} fieldNumber
1636   * @param {number} index
1637   * @return {string}
1638   */
1639  getRepeatedStringElement(fieldNumber, index) {
1640    const array = this.getRepeatedStringArray_(fieldNumber);
1641    checkCriticalElementIndex(index, array.length);
1642    return array[index];
1643  }
1644
1645  /**
1646   * Returns an Iterable instance containing string values for the given field
1647   * number.
1648   * @param {number} fieldNumber
1649   * @return {!Iterable<string>}
1650   */
1651  getRepeatedStringIterable(fieldNumber) {
1652    // Don't split this statement unless needed. JS compiler thinks
1653    // getRepeatedStringArray_ might have side effects and doesn't inline the
1654    // call in the compiled code. See cl/293894484 for details.
1655    return new ArrayIterable(this.getRepeatedStringArray_(fieldNumber));
1656  }
1657
1658  /**
1659   * Returns the size of the repeated field.
1660   * @param {number} fieldNumber
1661   * @return {number}
1662   */
1663  getRepeatedStringSize(fieldNumber) {
1664    return this.getRepeatedStringArray_(fieldNumber).length;
1665  }
1666
1667  /* Message */
1668
1669  /**
1670   * Returns an Array instance containing boolean values for the given field
1671   * number.
1672   * @param {number} fieldNumber
1673   * @param {function(!Kernel):T} instanceCreator
1674   * @param {number|undefined} pivot
1675   * @return {!Array<T>}
1676   * @template T
1677   * @private
1678   */
1679  getRepeatedMessageArray_(fieldNumber, instanceCreator, pivot) {
1680    // This method can be shortened using getFieldWithDefault and
1681    // getRepeatedNonPrimitive methods. But that will require creating and
1682    // passing a reader closure every time getRepeatedMessageArray_ is called,
1683    // which is expensive.
1684    checkInstanceCreator(instanceCreator);
1685    checkFieldNumber(fieldNumber);
1686
1687    const field = this.fields_.get(fieldNumber);
1688    if (field === undefined) {
1689      return [];
1690    }
1691
1692    if (field.hasDecodedValue()) {
1693      return field.getDecodedValue();
1694    }
1695
1696    const indexArray = checkDefAndNotNull(field.getIndexArray());
1697    const result = new Array(indexArray.length);
1698    for (let i = 0; i < indexArray.length; i++) {
1699      validateWireType(indexArray[i], WireType.DELIMITED);
1700      const subMessageBuffer = reader.readDelimited(
1701          checkDefAndNotNull(this.bufferDecoder_),
1702          Field.getStartIndex(indexArray[i]));
1703      result[i] =
1704          instanceCreator(Kernel.fromBufferDecoder_(subMessageBuffer, pivot));
1705    }
1706    field.setCache(result, writeRepeatedMessage);
1707
1708    return result;
1709  }
1710
1711  /**
1712   * Returns the element at index for the given field number as a message.
1713   * @param {number} fieldNumber
1714   * @param {function(!Kernel):T} instanceCreator
1715   * @param {number} index
1716   * @param {number=} pivot
1717   * @return {T}
1718   * @template T
1719   */
1720  getRepeatedMessageElement(
1721      fieldNumber, instanceCreator, index, pivot = undefined) {
1722    const array =
1723        this.getRepeatedMessageArray_(fieldNumber, instanceCreator, pivot);
1724    checkCriticalElementIndex(index, array.length);
1725    return array[index];
1726  }
1727
1728  /**
1729   * Returns an Iterable instance containing message values for the given field
1730   * number.
1731   * @param {number} fieldNumber
1732   * @param {function(!Kernel):T} instanceCreator
1733   * @param {number=} pivot
1734   * @return {!Iterable<T>}
1735   * @template T
1736   */
1737  getRepeatedMessageIterable(fieldNumber, instanceCreator, pivot = undefined) {
1738    // Don't split this statement unless needed. JS compiler thinks
1739    // getRepeatedMessageArray_ might have side effects and doesn't inline the
1740    // call in the compiled code. See cl/293894484 for details.
1741    return new ArrayIterable(
1742        this.getRepeatedMessageArray_(fieldNumber, instanceCreator, pivot));
1743  }
1744
1745  /**
1746   * Returns an Iterable instance containing message accessors for the given
1747   * field number.
1748   * @param {number} fieldNumber
1749   * @param {number=} pivot
1750   * @return {!Iterable<!Kernel>}
1751   */
1752  getRepeatedMessageAccessorIterable(fieldNumber, pivot = undefined) {
1753    checkFieldNumber(fieldNumber);
1754
1755    const field = this.fields_.get(fieldNumber);
1756    if (!field) {
1757      return [];
1758    }
1759
1760    if (field.hasDecodedValue()) {
1761      return new ArrayIterable(field.getDecodedValue().map(
1762          value => checkIsInternalMessage(value).internalGetKernel()));
1763    }
1764
1765    const readMessageFunc = (bufferDecoder, start) => Kernel.fromBufferDecoder_(
1766        reader.readDelimited(bufferDecoder, start), pivot);
1767    const array = readRepeatedNonPrimitive(
1768        checkDefAndNotNull(field.getIndexArray()),
1769        checkDefAndNotNull(this.bufferDecoder_), readMessageFunc);
1770    return new ArrayIterable(array);
1771  }
1772
1773  /**
1774   * Returns the size of the repeated field.
1775   * @param {number} fieldNumber
1776   * @param {function(!Kernel):T} instanceCreator
1777   * @return {number}
1778   * @param {number=} pivot
1779   * @template T
1780   */
1781  getRepeatedMessageSize(fieldNumber, instanceCreator, pivot = undefined) {
1782    return this.getRepeatedMessageArray_(fieldNumber, instanceCreator, pivot)
1783        .length;
1784  }
1785
1786  /**
1787   * Returns an Array instance containing boolean values for the given field
1788   * number.
1789   * @param {number} fieldNumber
1790   * @param {function(!Kernel):T} instanceCreator
1791   * @param {number|undefined} pivot
1792   * @return {!Array<T>}
1793   * @template T
1794   * @private
1795   */
1796  getRepeatedGroupArray_(fieldNumber, instanceCreator, pivot) {
1797    return this.getFieldWithDefault_(
1798        fieldNumber, [],
1799        (indexArray, bufferDecoder) => readRepeatedGroup(
1800            indexArray, bufferDecoder, fieldNumber, instanceCreator, pivot),
1801        writeRepeatedGroup);
1802  }
1803
1804  /**
1805   * Returns the element at index for the given field number as a group.
1806   * @param {number} fieldNumber
1807   * @param {function(!Kernel):T} instanceCreator
1808   * @param {number} index
1809   * @param {number=} pivot
1810   * @return {T}
1811   * @template T
1812   */
1813  getRepeatedGroupElement(
1814      fieldNumber, instanceCreator, index, pivot = undefined) {
1815    const array =
1816        this.getRepeatedGroupArray_(fieldNumber, instanceCreator, pivot);
1817    checkCriticalElementIndex(index, array.length);
1818    return array[index];
1819  }
1820
1821  /**
1822   * Returns an Iterable instance containing group values for the given field
1823   * number.
1824   * @param {number} fieldNumber
1825   * @param {function(!Kernel):T} instanceCreator
1826   * @param {number=} pivot
1827   * @return {!Iterable<T>}
1828   * @template T
1829   */
1830  getRepeatedGroupIterable(fieldNumber, instanceCreator, pivot = undefined) {
1831    // Don't split this statement unless needed. JS compiler thinks
1832    // getRepeatedMessageArray_ might have side effects and doesn't inline the
1833    // call in the compiled code. See cl/293894484 for details.
1834    return new ArrayIterable(
1835        this.getRepeatedGroupArray_(fieldNumber, instanceCreator, pivot));
1836  }
1837
1838  /**
1839   * Returns the size of the repeated field.
1840   * @param {number} fieldNumber
1841   * @param {function(!Kernel):T} instanceCreator
1842   * @return {number}
1843   * @param {number=} pivot
1844   * @template T
1845   */
1846  getRepeatedGroupSize(fieldNumber, instanceCreator, pivot = undefined) {
1847    return this.getRepeatedGroupArray_(fieldNumber, instanceCreator, pivot)
1848        .length;
1849  }
1850
1851  /***************************************************************************
1852   *                        OPTIONAL SETTER METHODS
1853   ***************************************************************************/
1854
1855  /**
1856   * Sets a boolean value to the field with the given field number.
1857   * @param {number} fieldNumber
1858   * @param {boolean} value
1859   */
1860  setBool(fieldNumber, value) {
1861    checkCriticalTypeBool(value);
1862    this.setField_(fieldNumber, value, (writer, fieldNumber, value) => {
1863      writer.writeBool(fieldNumber, value);
1864    });
1865  }
1866
1867  /**
1868   * Sets a boolean value to the field with the given field number.
1869   * @param {number} fieldNumber
1870   * @param {!ByteString} value
1871   */
1872  setBytes(fieldNumber, value) {
1873    checkCriticalTypeByteString(value);
1874    this.setField_(fieldNumber, value, (writer, fieldNumber, value) => {
1875      writer.writeBytes(fieldNumber, value);
1876    });
1877  }
1878
1879  /**
1880   * Sets a double value to the field with the given field number.
1881   * @param {number} fieldNumber
1882   * @param {number} value
1883   */
1884  setDouble(fieldNumber, value) {
1885    checkCriticalTypeDouble(value);
1886    this.setField_(fieldNumber, value, (writer, fieldNumber, value) => {
1887      writer.writeDouble(fieldNumber, value);
1888    });
1889  }
1890
1891  /**
1892   * Sets a fixed32 value to the field with the given field number.
1893   * @param {number} fieldNumber
1894   * @param {number} value
1895   */
1896  setFixed32(fieldNumber, value) {
1897    checkCriticalTypeUnsignedInt32(value);
1898    this.setField_(fieldNumber, value, (writer, fieldNumber, value) => {
1899      writer.writeFixed32(fieldNumber, value);
1900    });
1901  }
1902
1903  /**
1904   * Sets a uint64 value to the field with the given field number.\
1905   * Note: Since g.m.Long does not support unsigned int64 values we are going
1906   * the Java route here for now and simply output the number as a signed int64.
1907   * Users can get to individual bits by themselves.
1908   * @param {number} fieldNumber
1909   * @param {!Int64} value
1910   */
1911  setFixed64(fieldNumber, value) {
1912    this.setSfixed64(fieldNumber, value);
1913  }
1914
1915  /**
1916   * Sets a float value to the field with the given field number.
1917   * @param {number} fieldNumber
1918   * @param {number} value
1919   */
1920  setFloat(fieldNumber, value) {
1921    checkCriticalTypeFloat(value);
1922    // Eagerly round to 32-bit precision so that reading back after set will
1923    // yield the same value a reader will receive after serialization.
1924    const floatValue = Math.fround(value);
1925    this.setField_(fieldNumber, floatValue, (writer, fieldNumber, value) => {
1926      writer.writeFloat(fieldNumber, value);
1927    });
1928  }
1929
1930  /**
1931   * Sets a int32 value to the field with the given field number.
1932   * @param {number} fieldNumber
1933   * @param {number} value
1934   */
1935  setInt32(fieldNumber, value) {
1936    checkCriticalTypeSignedInt32(value);
1937    this.setField_(fieldNumber, value, (writer, fieldNumber, value) => {
1938      writer.writeInt32(fieldNumber, value);
1939    });
1940  }
1941
1942  /**
1943   * Sets a int64 value to the field with the given field number.
1944   * @param {number} fieldNumber
1945   * @param {!Int64} value
1946   */
1947  setInt64(fieldNumber, value) {
1948    checkCriticalTypeSignedInt64(value);
1949    this.setField_(fieldNumber, value, (writer, fieldNumber, value) => {
1950      writer.writeInt64(fieldNumber, value);
1951    });
1952  }
1953
1954  /**
1955   * Sets a sfixed32 value to the field with the given field number.
1956   * @param {number} fieldNumber
1957   * @param {number} value
1958   */
1959  setSfixed32(fieldNumber, value) {
1960    checkCriticalTypeSignedInt32(value);
1961    this.setField_(fieldNumber, value, (writer, fieldNumber, value) => {
1962      writer.writeSfixed32(fieldNumber, value);
1963    });
1964  }
1965
1966  /**
1967   * Sets a sfixed64 value to the field with the given field number.
1968   * @param {number} fieldNumber
1969   * @param {!Int64} value
1970   */
1971  setSfixed64(fieldNumber, value) {
1972    checkCriticalTypeSignedInt64(value);
1973    this.setField_(fieldNumber, value, (writer, fieldNumber, value) => {
1974      writer.writeSfixed64(fieldNumber, value);
1975    });
1976  }
1977
1978  /**
1979   * Sets a sint32 value to the field with the given field number.
1980   * @param {number} fieldNumber
1981   * @param {number} value
1982   */
1983  setSint32(fieldNumber, value) {
1984    checkCriticalTypeSignedInt32(value);
1985    this.setField_(fieldNumber, value, (writer, fieldNumber, value) => {
1986      writer.writeSint32(fieldNumber, value);
1987    });
1988  }
1989
1990  /**
1991   * Sets a sint64 value to the field with the given field number.
1992   * @param {number} fieldNumber
1993   * @param {!Int64} value
1994   */
1995  setSint64(fieldNumber, value) {
1996    checkCriticalTypeSignedInt64(value);
1997    this.setField_(fieldNumber, value, (writer, fieldNumber, value) => {
1998      writer.writeSint64(fieldNumber, value);
1999    });
2000  }
2001
2002  /**
2003   * Sets a boolean value to the field with the given field number.
2004   * @param {number} fieldNumber
2005   * @param {string} value
2006   */
2007  setString(fieldNumber, value) {
2008    checkCriticalTypeString(value);
2009    this.setField_(fieldNumber, value, (writer, fieldNumber, value) => {
2010      writer.writeString(fieldNumber, value);
2011    });
2012  }
2013
2014  /**
2015   * Sets a uint32 value to the field with the given field number.
2016   * @param {number} fieldNumber
2017   * @param {number} value
2018   */
2019  setUint32(fieldNumber, value) {
2020    checkCriticalTypeUnsignedInt32(value);
2021    this.setField_(fieldNumber, value, (writer, fieldNumber, value) => {
2022      writer.writeUint32(fieldNumber, value);
2023    });
2024  }
2025
2026  /**
2027   * Sets a uint64 value to the field with the given field number.\
2028   * Note: Since g.m.Long does not support unsigned int64 values we are going
2029   * the Java route here for now and simply output the number as a signed int64.
2030   * Users can get to individual bits by themselves.
2031   * @param {number} fieldNumber
2032   * @param {!Int64} value
2033   */
2034  setUint64(fieldNumber, value) {
2035    this.setInt64(fieldNumber, value);
2036  }
2037
2038  /**
2039   * Sets a proto Group to the field with the given field number.
2040   * Instead of working with the Kernel inside of the message directly, we
2041   * need the message instance to keep its reference equality for subsequent
2042   * gettings.
2043   * @param {number} fieldNumber
2044   * @param {!InternalMessage} value
2045   */
2046  setGroup(fieldNumber, value) {
2047    checkCriticalType(
2048        value !== null, 'Given value is not a message instance: null');
2049    this.setField_(fieldNumber, value, writeGroup);
2050  }
2051
2052  /**
2053   * Sets a proto Message to the field with the given field number.
2054   * Instead of working with the Kernel inside of the message directly, we
2055   * need the message instance to keep its reference equality for subsequent
2056   * gettings.
2057   * @param {number} fieldNumber
2058   * @param {!InternalMessage} value
2059   */
2060  setMessage(fieldNumber, value) {
2061    checkCriticalType(
2062        value !== null, 'Given value is not a message instance: null');
2063    this.setField_(fieldNumber, value, writeMessage);
2064  }
2065
2066  /***************************************************************************
2067   *                        REPEATED SETTER METHODS
2068   ***************************************************************************/
2069
2070  /* Bool */
2071
2072  /**
2073   * Adds all boolean values into the field for the given field number.
2074   * How these values are encoded depends on the given write function.
2075   * @param {number} fieldNumber
2076   * @param {!Iterable<boolean>} values
2077   * @param {function(!Writer, number, !Array<boolean>): undefined} encoder
2078   * @private
2079   */
2080  addRepeatedBoolIterable_(fieldNumber, values, encoder) {
2081    const array = [...this.getRepeatedBoolArray_(fieldNumber), ...values];
2082    checkCriticalTypeBoolArray(array);
2083    // Needs to set it back because the default empty array was not cached.
2084    this.setField_(fieldNumber, array, encoder);
2085  }
2086
2087  /**
2088   * Adds a single boolean value into the field for the given field number.
2089   * All values will be encoded as packed values.
2090   * @param {number} fieldNumber
2091   * @param {boolean} value
2092   */
2093  addPackedBoolElement(fieldNumber, value) {
2094    this.addRepeatedBoolIterable_(
2095        fieldNumber, [value], (writer, fieldNumber, values) => {
2096          writer.writePackedBool(fieldNumber, values);
2097        });
2098  }
2099
2100  /**
2101   * Adds all boolean values into the field for the given field number.
2102   * All these values will be encoded as packed values.
2103   * @param {number} fieldNumber
2104   * @param {!Iterable<boolean>} values
2105   */
2106  addPackedBoolIterable(fieldNumber, values) {
2107    this.addRepeatedBoolIterable_(
2108        fieldNumber, values, (writer, fieldNumber, values) => {
2109          writer.writePackedBool(fieldNumber, values);
2110        });
2111  }
2112
2113  /**
2114   * Adds a single boolean value into the field for the given field number.
2115   * All values will be encoded as unpacked values.
2116   * @param {number} fieldNumber
2117   * @param {boolean} value
2118   */
2119  addUnpackedBoolElement(fieldNumber, value) {
2120    this.addRepeatedBoolIterable_(
2121        fieldNumber, [value], (writer, fieldNumber, values) => {
2122          writer.writeRepeatedBool(fieldNumber, values);
2123        });
2124  }
2125
2126  /**
2127   * Adds all boolean values into the field for the given field number.
2128   * All these values will be encoded as unpacked values.
2129   * @param {number} fieldNumber
2130   * @param {!Iterable<boolean>} values
2131   */
2132  addUnpackedBoolIterable(fieldNumber, values) {
2133    this.addRepeatedBoolIterable_(
2134        fieldNumber, values, (writer, fieldNumber, values) => {
2135          writer.writeRepeatedBool(fieldNumber, values);
2136        });
2137  }
2138
2139  /**
2140   * Sets a single boolean value into the field for the given field number at
2141   * the given index. How these values are encoded depends on the given write
2142   * function.
2143   * @param {number} fieldNumber
2144   * @param {number} index
2145   * @param {boolean} value
2146   * @param {function(!Writer, number, !Array<boolean>): undefined} encoder
2147   * @throws {!Error} if index is out of range when check mode is critical
2148   * @private
2149   */
2150  setRepeatedBoolElement_(fieldNumber, index, value, encoder) {
2151    checkCriticalTypeBool(value);
2152    const array = this.getRepeatedBoolArray_(fieldNumber);
2153    checkCriticalElementIndex(index, array.length);
2154    array[index] = value;
2155    // Needs to set it back to set encoder.
2156    this.setField_(fieldNumber, array, encoder);
2157  }
2158
2159  /**
2160   * Sets a single boolean value into the field for the given field number at
2161   * the given index. All values will be encoded as packed values.
2162   * @param {number} fieldNumber
2163   * @param {number} index
2164   * @param {boolean} value
2165   * @throws {!Error} if index is out of range when check mode is critical
2166   */
2167  setPackedBoolElement(fieldNumber, index, value) {
2168    this.setRepeatedBoolElement_(
2169        fieldNumber, index, value, (writer, fieldNumber, values) => {
2170          writer.writePackedBool(fieldNumber, values);
2171        });
2172  }
2173
2174  /**
2175   * Sets all boolean values into the field for the given field number.
2176   * All these values will be encoded as packed values.
2177   * @param {number} fieldNumber
2178   * @param {!Iterable<boolean>} values
2179   */
2180  setPackedBoolIterable(fieldNumber, values) {
2181    const /** !Array<boolean> */ array = Array.from(values);
2182    checkCriticalTypeBoolArray(array);
2183    this.setField_(fieldNumber, array, (writer, fieldNumber, values) => {
2184      writer.writePackedBool(fieldNumber, values);
2185    });
2186  }
2187
2188  /**
2189   * Sets a single boolean value into the field for the given field number at
2190   * the given index. All values will be encoded as unpacked values.
2191   * @param {number} fieldNumber
2192   * @param {number} index
2193   * @param {boolean} value
2194   * @throws {!Error} if index is out of range when check mode is critical
2195   */
2196  setUnpackedBoolElement(fieldNumber, index, value) {
2197    this.setRepeatedBoolElement_(
2198        fieldNumber, index, value, (writer, fieldNumber, values) => {
2199          writer.writeRepeatedBool(fieldNumber, values);
2200        });
2201  }
2202
2203  /**
2204   * Sets all boolean values into the field for the given field number.
2205   * All these values will be encoded as unpacked values.
2206   * @param {number} fieldNumber
2207   * @param {!Iterable<boolean>} values
2208   */
2209  setUnpackedBoolIterable(fieldNumber, values) {
2210    const /** !Array<boolean> */ array = Array.from(values);
2211    checkCriticalTypeBoolArray(array);
2212    this.setField_(fieldNumber, array, (writer, fieldNumber, values) => {
2213      writer.writeRepeatedBool(fieldNumber, values);
2214    });
2215  }
2216
2217  /* Double */
2218
2219  /**
2220   * Adds all double values into the field for the given field number.
2221   * How these values are encoded depends on the given write function.
2222   * @param {number} fieldNumber
2223   * @param {!Iterable<number>} values
2224   * @param {function(!Writer, number, !Array<number>): undefined} encoder
2225   * @private
2226   */
2227  addRepeatedDoubleIterable_(fieldNumber, values, encoder) {
2228    const array = [...this.getRepeatedDoubleArray_(fieldNumber), ...values];
2229    checkCriticalTypeDoubleArray(array);
2230    // Needs to set it back because the default empty array was not cached.
2231    this.setField_(fieldNumber, array, encoder);
2232  }
2233
2234  /**
2235   * Adds a single double value into the field for the given field number.
2236   * All values will be encoded as packed values.
2237   * @param {number} fieldNumber
2238   * @param {number} value
2239   */
2240  addPackedDoubleElement(fieldNumber, value) {
2241    this.addRepeatedDoubleIterable_(
2242        fieldNumber, [value], (writer, fieldNumber, values) => {
2243          writer.writePackedDouble(fieldNumber, values);
2244        });
2245  }
2246
2247  /**
2248   * Adds all double values into the field for the given field number.
2249   * All these values will be encoded as packed values.
2250   * @param {number} fieldNumber
2251   * @param {!Iterable<number>} values
2252   */
2253  addPackedDoubleIterable(fieldNumber, values) {
2254    this.addRepeatedDoubleIterable_(
2255        fieldNumber, values, (writer, fieldNumber, values) => {
2256          writer.writePackedDouble(fieldNumber, values);
2257        });
2258  }
2259
2260  /**
2261   * Adds a single double value into the field for the given field number.
2262   * All values will be encoded as unpacked values.
2263   * @param {number} fieldNumber
2264   * @param {number} value
2265   */
2266  addUnpackedDoubleElement(fieldNumber, value) {
2267    this.addRepeatedDoubleIterable_(
2268        fieldNumber, [value], (writer, fieldNumber, values) => {
2269          writer.writeRepeatedDouble(fieldNumber, values);
2270        });
2271  }
2272
2273  /**
2274   * Adds all double values into the field for the given field number.
2275   * All these values will be encoded as unpacked values.
2276   * @param {number} fieldNumber
2277   * @param {!Iterable<number>} values
2278   */
2279  addUnpackedDoubleIterable(fieldNumber, values) {
2280    this.addRepeatedDoubleIterable_(
2281        fieldNumber, values, (writer, fieldNumber, values) => {
2282          writer.writeRepeatedDouble(fieldNumber, values);
2283        });
2284  }
2285
2286  /**
2287   * Sets a single double value into the field for the given field number at the
2288   * given index.
2289   * How these values are encoded depends on the given write function.
2290   * @param {number} fieldNumber
2291   * @param {number} index
2292   * @param {number} value
2293   * @param {function(!Writer, number, !Array<number>): undefined} encoder
2294   * @throws {!Error} if index is out of range when check mode is critical
2295   * @private
2296   */
2297  setRepeatedDoubleElement_(fieldNumber, index, value, encoder) {
2298    checkCriticalTypeDouble(value);
2299    const array = this.getRepeatedDoubleArray_(fieldNumber);
2300    checkCriticalElementIndex(index, array.length);
2301    array[index] = value;
2302    // Needs to set it back to set encoder.
2303    this.setField_(fieldNumber, array, encoder);
2304  }
2305
2306  /**
2307   * Sets a single double value into the field for the given field number at the
2308   * given index.
2309   * All values will be encoded as packed values.
2310   * @param {number} fieldNumber
2311   * @param {number} index
2312   * @param {number} value
2313   * @throws {!Error} if index is out of range when check mode is critical
2314   */
2315  setPackedDoubleElement(fieldNumber, index, value) {
2316    this.setRepeatedDoubleElement_(
2317        fieldNumber, index, value, (writer, fieldNumber, values) => {
2318          writer.writePackedDouble(fieldNumber, values);
2319        });
2320  }
2321
2322  /**
2323   * Sets all double values into the field for the given field number.
2324   * All these values will be encoded as packed values.
2325   * @param {number} fieldNumber
2326   * @param {!Iterable<number>} values
2327   */
2328  setPackedDoubleIterable(fieldNumber, values) {
2329    const array = Array.from(values);
2330    checkCriticalTypeDoubleArray(array);
2331    this.setField_(fieldNumber, array, (writer, fieldNumber, values) => {
2332      writer.writePackedDouble(fieldNumber, values);
2333    });
2334  }
2335
2336  /**
2337   * Sets a single double value into the field for the given field number at the
2338   * given index.
2339   * All values will be encoded as unpacked values.
2340   * @param {number} fieldNumber
2341   * @param {number} index
2342   * @param {number} value
2343   * @throws {!Error} if index is out of range when check mode is critical
2344   */
2345  setUnpackedDoubleElement(fieldNumber, index, value) {
2346    this.setRepeatedDoubleElement_(
2347        fieldNumber, index, value, (writer, fieldNumber, values) => {
2348          writer.writeRepeatedDouble(fieldNumber, values);
2349        });
2350  }
2351
2352  /**
2353   * Sets all double values into the field for the given field number.
2354   * All these values will be encoded as unpacked values.
2355   * @param {number} fieldNumber
2356   * @param {!Iterable<number>} values
2357   */
2358  setUnpackedDoubleIterable(fieldNumber, values) {
2359    const array = Array.from(values);
2360    checkCriticalTypeDoubleArray(array);
2361    this.setField_(fieldNumber, array, (writer, fieldNumber, values) => {
2362      writer.writeRepeatedDouble(fieldNumber, values);
2363    });
2364  }
2365
2366  /* Fixed32 */
2367
2368  /**
2369   * Adds all fixed32 values into the field for the given field number.
2370   * How these values are encoded depends on the given write function.
2371   * @param {number} fieldNumber
2372   * @param {!Iterable<number>} values
2373   * @param {function(!Writer, number, !Array<number>): undefined} encoder
2374   * @private
2375   */
2376  addRepeatedFixed32Iterable_(fieldNumber, values, encoder) {
2377    const array = [...this.getRepeatedFixed32Array_(fieldNumber), ...values];
2378    checkCriticalTypeUnsignedInt32Array(array);
2379    // Needs to set it back because the default empty array was not cached.
2380    this.setField_(fieldNumber, array, encoder);
2381  }
2382
2383  /**
2384   * Adds a single fixed32 value into the field for the given field number.
2385   * All values will be encoded as packed values.
2386   * @param {number} fieldNumber
2387   * @param {number} value
2388   */
2389  addPackedFixed32Element(fieldNumber, value) {
2390    this.addRepeatedFixed32Iterable_(
2391        fieldNumber, [value], (writer, fieldNumber, values) => {
2392          writer.writePackedFixed32(fieldNumber, values);
2393        });
2394  }
2395
2396  /**
2397   * Adds all fixed32 values into the field for the given field number.
2398   * All these values will be encoded as packed values.
2399   * @param {number} fieldNumber
2400   * @param {!Iterable<number>} values
2401   */
2402  addPackedFixed32Iterable(fieldNumber, values) {
2403    this.addRepeatedFixed32Iterable_(
2404        fieldNumber, values, (writer, fieldNumber, values) => {
2405          writer.writePackedFixed32(fieldNumber, values);
2406        });
2407  }
2408
2409  /**
2410   * Adds a single fixed32 value into the field for the given field number.
2411   * All values will be encoded as unpacked values.
2412   * @param {number} fieldNumber
2413   * @param {number} value
2414   */
2415  addUnpackedFixed32Element(fieldNumber, value) {
2416    this.addRepeatedFixed32Iterable_(
2417        fieldNumber, [value], (writer, fieldNumber, values) => {
2418          writer.writeRepeatedFixed32(fieldNumber, values);
2419        });
2420  }
2421
2422  /**
2423   * Adds all fixed32 values into the field for the given field number.
2424   * All these values will be encoded as unpacked values.
2425   * @param {number} fieldNumber
2426   * @param {!Iterable<number>} values
2427   */
2428  addUnpackedFixed32Iterable(fieldNumber, values) {
2429    this.addRepeatedFixed32Iterable_(
2430        fieldNumber, values, (writer, fieldNumber, values) => {
2431          writer.writeRepeatedFixed32(fieldNumber, values);
2432        });
2433  }
2434
2435  /**
2436   * Sets a single fixed32 value into the field for the given field number at
2437   * the given index. How these values are encoded depends on the given write
2438   * function.
2439   * @param {number} fieldNumber
2440   * @param {number} index
2441   * @param {number} value
2442   * @param {function(!Writer, number, !Array<number>): undefined} encoder
2443   * @throws {!Error} if index is out of range when check mode is critical
2444   * @private
2445   */
2446  setRepeatedFixed32Element_(fieldNumber, index, value, encoder) {
2447    checkCriticalTypeUnsignedInt32(value);
2448    const array = this.getRepeatedFixed32Array_(fieldNumber);
2449    checkCriticalElementIndex(index, array.length);
2450    array[index] = value;
2451    // Needs to set it back to set encoder.
2452    this.setField_(fieldNumber, array, encoder);
2453  }
2454
2455  /**
2456   * Sets a single fixed32 value into the field for the given field number at
2457   * the given index. All values will be encoded as packed values.
2458   * @param {number} fieldNumber
2459   * @param {number} index
2460   * @param {number} value
2461   * @throws {!Error} if index is out of range when check mode is critical
2462   */
2463  setPackedFixed32Element(fieldNumber, index, value) {
2464    this.setRepeatedFixed32Element_(
2465        fieldNumber, index, value, (writer, fieldNumber, values) => {
2466          writer.writePackedFixed32(fieldNumber, values);
2467        });
2468  }
2469
2470  /**
2471   * Sets all fixed32 values into the field for the given field number.
2472   * All these values will be encoded as packed values.
2473   * @param {number} fieldNumber
2474   * @param {!Iterable<number>} values
2475   */
2476  setPackedFixed32Iterable(fieldNumber, values) {
2477    const array = Array.from(values);
2478    checkCriticalTypeUnsignedInt32Array(array);
2479    this.setField_(fieldNumber, array, (writer, fieldNumber, values) => {
2480      writer.writePackedFixed32(fieldNumber, values);
2481    });
2482  }
2483
2484  /**
2485   * Sets a single fixed32 value into the field for the given field number at
2486   * the given index. All values will be encoded as unpacked values.
2487   * @param {number} fieldNumber
2488   * @param {number} index
2489   * @param {number} value
2490   * @throws {!Error} if index is out of range when check mode is critical
2491   */
2492  setUnpackedFixed32Element(fieldNumber, index, value) {
2493    this.setRepeatedFixed32Element_(
2494        fieldNumber, index, value, (writer, fieldNumber, values) => {
2495          writer.writeRepeatedFixed32(fieldNumber, values);
2496        });
2497  }
2498
2499  /**
2500   * Sets all fixed32 values into the field for the given field number.
2501   * All these values will be encoded as unpacked values.
2502   * @param {number} fieldNumber
2503   * @param {!Iterable<number>} values
2504   */
2505  setUnpackedFixed32Iterable(fieldNumber, values) {
2506    const array = Array.from(values);
2507    checkCriticalTypeUnsignedInt32Array(array);
2508    this.setField_(fieldNumber, array, (writer, fieldNumber, values) => {
2509      writer.writeRepeatedFixed32(fieldNumber, values);
2510    });
2511  }
2512
2513  /* Fixed64 */
2514
2515  /**
2516   * Adds a single fixed64 value into the field for the given field number.
2517   * All values will be encoded as packed values.
2518   * @param {number} fieldNumber
2519   * @param {!Int64} value
2520   */
2521  addPackedFixed64Element(fieldNumber, value) {
2522    this.addPackedSfixed64Element(fieldNumber, value);
2523  }
2524
2525  /**
2526   * Adds all fixed64 values into the field for the given field number.
2527   * All these values will be encoded as packed values.
2528   * @param {number} fieldNumber
2529   * @param {!Iterable<!Int64>} values
2530   */
2531  addPackedFixed64Iterable(fieldNumber, values) {
2532    this.addPackedSfixed64Iterable(fieldNumber, values);
2533  }
2534
2535  /**
2536   * Adds a single fixed64 value into the field for the given field number.
2537   * All values will be encoded as unpacked values.
2538   * @param {number} fieldNumber
2539   * @param {!Int64} value
2540   */
2541  addUnpackedFixed64Element(fieldNumber, value) {
2542    this.addUnpackedSfixed64Element(fieldNumber, value);
2543  }
2544
2545  /**
2546   * Adds all fixed64 values into the field for the given field number.
2547   * All these values will be encoded as unpacked values.
2548   * @param {number} fieldNumber
2549   * @param {!Iterable<!Int64>} values
2550   */
2551  addUnpackedFixed64Iterable(fieldNumber, values) {
2552    this.addUnpackedSfixed64Iterable(fieldNumber, values);
2553  }
2554
2555  /**
2556   * Sets a single fixed64 value into the field for the given field number at
2557   * the given index. All values will be encoded as packed values.
2558   * @param {number} fieldNumber
2559   * @param {number} index
2560   * @param {!Int64} value
2561   * @throws {!Error} if index is out of range when check mode is critical
2562   */
2563  setPackedFixed64Element(fieldNumber, index, value) {
2564    this.setPackedSfixed64Element(fieldNumber, index, value);
2565  }
2566
2567  /**
2568   * Sets all fixed64 values into the field for the given field number.
2569   * All these values will be encoded as packed values.
2570   * @param {number} fieldNumber
2571   * @param {!Iterable<!Int64>} values
2572   */
2573  setPackedFixed64Iterable(fieldNumber, values) {
2574    this.setPackedSfixed64Iterable(fieldNumber, values);
2575  }
2576
2577  /**
2578   * Sets a single fixed64 value into the field for the given field number at
2579   * the given index. All values will be encoded as unpacked values.
2580   * @param {number} fieldNumber
2581   * @param {number} index
2582   * @param {!Int64} value
2583   * @throws {!Error} if index is out of range when check mode is critical
2584   */
2585  setUnpackedFixed64Element(fieldNumber, index, value) {
2586    this.setUnpackedSfixed64Element(fieldNumber, index, value);
2587  }
2588
2589  /**
2590   * Sets all fixed64 values into the field for the given field number.
2591   * All these values will be encoded as unpacked values.
2592   * @param {number} fieldNumber
2593   * @param {!Iterable<!Int64>} values
2594   */
2595  setUnpackedFixed64Iterable(fieldNumber, values) {
2596    this.setUnpackedSfixed64Iterable(fieldNumber, values);
2597  }
2598
2599  /* Float */
2600
2601  /**
2602   * Adds all float values into the field for the given field number.
2603   * How these values are encoded depends on the given write function.
2604   * @param {number} fieldNumber
2605   * @param {!Iterable<number>} values
2606   * @param {function(!Writer, number, !Array<number>): undefined} encoder
2607   * @private
2608   */
2609  addRepeatedFloatIterable_(fieldNumber, values, encoder) {
2610    checkCriticalTypeFloatIterable(values);
2611    // Eagerly round to 32-bit precision so that reading back after set will
2612    // yield the same value a reader will receive after serialization.
2613    const floatValues = Array.from(values, fround);
2614    const array = [...this.getRepeatedFloatArray_(fieldNumber), ...floatValues];
2615    checkCriticalTypeFloatIterable(array);
2616    // Needs to set it back because the default empty array was not cached.
2617    this.setField_(fieldNumber, array, encoder);
2618  }
2619
2620  /**
2621   * Adds a single float value into the field for the given field number.
2622   * All values will be encoded as packed values.
2623   * @param {number} fieldNumber
2624   * @param {number} value
2625   */
2626  addPackedFloatElement(fieldNumber, value) {
2627    this.addRepeatedFloatIterable_(
2628        fieldNumber, [value], (writer, fieldNumber, values) => {
2629          writer.writePackedFloat(fieldNumber, values);
2630        });
2631  }
2632
2633  /**
2634   * Adds all float values into the field for the given field number.
2635   * All these values will be encoded as packed values.
2636   * @param {number} fieldNumber
2637   * @param {!Iterable<number>} values
2638   */
2639  addPackedFloatIterable(fieldNumber, values) {
2640    this.addRepeatedFloatIterable_(
2641        fieldNumber, values, (writer, fieldNumber, values) => {
2642          writer.writePackedFloat(fieldNumber, values);
2643        });
2644  }
2645
2646  /**
2647   * Adds a single float value into the field for the given field number.
2648   * All values will be encoded as unpacked values.
2649   * @param {number} fieldNumber
2650   * @param {number} value
2651   */
2652  addUnpackedFloatElement(fieldNumber, value) {
2653    this.addRepeatedFloatIterable_(
2654        fieldNumber, [value], (writer, fieldNumber, values) => {
2655          writer.writeRepeatedFloat(fieldNumber, values);
2656        });
2657  }
2658
2659  /**
2660   * Adds all float values into the field for the given field number.
2661   * All these values will be encoded as unpacked values.
2662   * @param {number} fieldNumber
2663   * @param {!Iterable<number>} values
2664   */
2665  addUnpackedFloatIterable(fieldNumber, values) {
2666    this.addRepeatedFloatIterable_(
2667        fieldNumber, values, (writer, fieldNumber, values) => {
2668          writer.writeRepeatedFloat(fieldNumber, values);
2669        });
2670  }
2671
2672  /**
2673   * Sets a single float value into the field for the given field number at the
2674   * given index.
2675   * How these values are encoded depends on the given write function.
2676   * @param {number} fieldNumber
2677   * @param {number} index
2678   * @param {number} value
2679   * @param {function(!Writer, number, !Array<number>): undefined} encoder
2680   * @throws {!Error} if index is out of range when check mode is critical
2681   * @private
2682   */
2683  setRepeatedFloatElement_(fieldNumber, index, value, encoder) {
2684    checkCriticalTypeFloat(value);
2685    // Eagerly round to 32-bit precision so that reading back after set will
2686    // yield the same value a reader will receive after serialization.
2687    const floatValue = Math.fround(value);
2688    const array = this.getRepeatedFloatArray_(fieldNumber);
2689    checkCriticalElementIndex(index, array.length);
2690    array[index] = floatValue;
2691    // Needs to set it back to set encoder.
2692    this.setField_(fieldNumber, array, encoder);
2693  }
2694
2695  /**
2696   * Sets a single float value into the field for the given field number at the
2697   * given index.
2698   * All values will be encoded as packed values.
2699   * @param {number} fieldNumber
2700   * @param {number} index
2701   * @param {number} value
2702   * @throws {!Error} if index is out of range when check mode is critical
2703   */
2704  setPackedFloatElement(fieldNumber, index, value) {
2705    this.setRepeatedFloatElement_(
2706        fieldNumber, index, value, (writer, fieldNumber, values) => {
2707          writer.writePackedFloat(fieldNumber, values);
2708        });
2709  }
2710
2711  /**
2712   * Sets all float values into the field for the given field number.
2713   * All these values will be encoded as packed values.
2714   * @param {number} fieldNumber
2715   * @param {!Iterable<number>} values
2716   */
2717  setPackedFloatIterable(fieldNumber, values) {
2718    checkCriticalTypeFloatIterable(values);
2719    // Eagerly round to 32-bit precision so that reading back after set will
2720    // yield the same value a reader will receive after serialization.
2721    const array = Array.from(values, fround);
2722    this.setField_(fieldNumber, array, (writer, fieldNumber, values) => {
2723      writer.writePackedFloat(fieldNumber, values);
2724    });
2725  }
2726
2727  /**
2728   * Sets a single float value into the field for the given field number at the
2729   * given index.
2730   * All values will be encoded as unpacked values.
2731   * @param {number} fieldNumber
2732   * @param {number} index
2733   * @param {number} value
2734   * @throws {!Error} if index is out of range when check mode is critical
2735   */
2736  setUnpackedFloatElement(fieldNumber, index, value) {
2737    this.setRepeatedFloatElement_(
2738        fieldNumber, index, value, (writer, fieldNumber, values) => {
2739          writer.writeRepeatedFloat(fieldNumber, values);
2740        });
2741  }
2742
2743  /**
2744   * Sets all float values into the field for the given field number.
2745   * All these values will be encoded as unpacked values.
2746   * @param {number} fieldNumber
2747   * @param {!Iterable<number>} values
2748   */
2749  setUnpackedFloatIterable(fieldNumber, values) {
2750    checkCriticalTypeFloatIterable(values);
2751    // Eagerly round to 32-bit precision so that reading back after set will
2752    // yield the same value a reader will receive after serialization.
2753    const array = Array.from(values, fround);
2754    this.setField_(fieldNumber, array, (writer, fieldNumber, values) => {
2755      writer.writeRepeatedFloat(fieldNumber, values);
2756    });
2757  }
2758
2759  /* Int32 */
2760
2761  /**
2762   * Adds all int32 values into the field for the given field number.
2763   * How these values are encoded depends on the given write function.
2764   * @param {number} fieldNumber
2765   * @param {!Iterable<number>} values
2766   * @param {function(!Writer, number, !Array<number>): undefined} encoder
2767   * @private
2768   */
2769  addRepeatedInt32Iterable_(fieldNumber, values, encoder) {
2770    const array = [...this.getRepeatedInt32Array_(fieldNumber), ...values];
2771    checkCriticalTypeSignedInt32Array(array);
2772    // Needs to set it back because the default empty array was not cached.
2773    this.setField_(fieldNumber, array, encoder);
2774  }
2775
2776  /**
2777   * Adds a single int32 value into the field for the given field number.
2778   * All values will be encoded as packed values.
2779   * @param {number} fieldNumber
2780   * @param {number} value
2781   */
2782  addPackedInt32Element(fieldNumber, value) {
2783    this.addRepeatedInt32Iterable_(
2784        fieldNumber, [value], (writer, fieldNumber, values) => {
2785          writer.writePackedInt32(fieldNumber, values);
2786        });
2787  }
2788
2789  /**
2790   * Adds all int32 values into the field for the given field number.
2791   * All these values will be encoded as packed values.
2792   * @param {number} fieldNumber
2793   * @param {!Iterable<number>} values
2794   */
2795  addPackedInt32Iterable(fieldNumber, values) {
2796    this.addRepeatedInt32Iterable_(
2797        fieldNumber, values, (writer, fieldNumber, values) => {
2798          writer.writePackedInt32(fieldNumber, values);
2799        });
2800  }
2801
2802  /**
2803   * Adds a single int32 value into the field for the given field number.
2804   * All values will be encoded as unpacked values.
2805   * @param {number} fieldNumber
2806   * @param {number} value
2807   */
2808  addUnpackedInt32Element(fieldNumber, value) {
2809    this.addRepeatedInt32Iterable_(
2810        fieldNumber, [value], (writer, fieldNumber, values) => {
2811          writer.writeRepeatedInt32(fieldNumber, values);
2812        });
2813  }
2814
2815  /**
2816   * Adds all int32 values into the field for the given field number.
2817   * All these values will be encoded as unpacked values.
2818   * @param {number} fieldNumber
2819   * @param {!Iterable<number>} values
2820   */
2821  addUnpackedInt32Iterable(fieldNumber, values) {
2822    this.addRepeatedInt32Iterable_(
2823        fieldNumber, values, (writer, fieldNumber, values) => {
2824          writer.writeRepeatedInt32(fieldNumber, values);
2825        });
2826  }
2827
2828  /**
2829   * Sets a single int32 value into the field for the given field number at
2830   * the given index. How these values are encoded depends on the given write
2831   * function.
2832   * @param {number} fieldNumber
2833   * @param {number} index
2834   * @param {number} value
2835   * @param {function(!Writer, number, !Array<number>): undefined} encoder
2836   * @throws {!Error} if index is out of range when check mode is critical
2837   * @private
2838   */
2839  setRepeatedInt32Element_(fieldNumber, index, value, encoder) {
2840    checkCriticalTypeSignedInt32(value);
2841    const array = this.getRepeatedInt32Array_(fieldNumber);
2842    checkCriticalElementIndex(index, array.length);
2843    array[index] = value;
2844    // Needs to set it back to set encoder.
2845    this.setField_(fieldNumber, array, encoder);
2846  }
2847
2848  /**
2849   * Sets a single int32 value into the field for the given field number at
2850   * the given index. All values will be encoded as packed values.
2851   * @param {number} fieldNumber
2852   * @param {number} index
2853   * @param {number} value
2854   * @throws {!Error} if index is out of range when check mode is critical
2855   */
2856  setPackedInt32Element(fieldNumber, index, value) {
2857    this.setRepeatedInt32Element_(
2858        fieldNumber, index, value, (writer, fieldNumber, values) => {
2859          writer.writePackedInt32(fieldNumber, values);
2860        });
2861  }
2862
2863  /**
2864   * Sets all int32 values into the field for the given field number.
2865   * All these values will be encoded as packed values.
2866   * @param {number} fieldNumber
2867   * @param {!Iterable<number>} values
2868   */
2869  setPackedInt32Iterable(fieldNumber, values) {
2870    const array = Array.from(values);
2871    checkCriticalTypeSignedInt32Array(array);
2872    this.setField_(fieldNumber, array, (writer, fieldNumber, values) => {
2873      writer.writePackedInt32(fieldNumber, values);
2874    });
2875  }
2876
2877  /**
2878   * Sets a single int32 value into the field for the given field number at
2879   * the given index. All values will be encoded as unpacked values.
2880   * @param {number} fieldNumber
2881   * @param {number} index
2882   * @param {number} value
2883   * @throws {!Error} if index is out of range when check mode is critical
2884   */
2885  setUnpackedInt32Element(fieldNumber, index, value) {
2886    this.setRepeatedInt32Element_(
2887        fieldNumber, index, value, (writer, fieldNumber, values) => {
2888          writer.writeRepeatedInt32(fieldNumber, values);
2889        });
2890  }
2891
2892  /**
2893   * Sets all int32 values into the field for the given field number.
2894   * All these values will be encoded as unpacked values.
2895   * @param {number} fieldNumber
2896   * @param {!Iterable<number>} values
2897   */
2898  setUnpackedInt32Iterable(fieldNumber, values) {
2899    const array = Array.from(values);
2900    checkCriticalTypeSignedInt32Array(array);
2901    this.setField_(fieldNumber, array, (writer, fieldNumber, values) => {
2902      writer.writeRepeatedInt32(fieldNumber, values);
2903    });
2904  }
2905
2906  /* Int64 */
2907
2908  /**
2909   * Adds all int64 values into the field for the given field number.
2910   * How these values are encoded depends on the given write function.
2911   * @param {number} fieldNumber
2912   * @param {!Iterable<!Int64>} values
2913   * @param {function(!Writer, number, !Array<!Int64>): undefined} encoder
2914   * @private
2915   */
2916  addRepeatedInt64Iterable_(fieldNumber, values, encoder) {
2917    const array = [...this.getRepeatedInt64Array_(fieldNumber), ...values];
2918    checkCriticalTypeSignedInt64Array(array);
2919    // Needs to set it back because the default empty array was not cached.
2920    this.setField_(fieldNumber, array, encoder);
2921  }
2922
2923  /**
2924   * Adds a single int64 value into the field for the given field number.
2925   * All values will be encoded as packed values.
2926   * @param {number} fieldNumber
2927   * @param {!Int64} value
2928   */
2929  addPackedInt64Element(fieldNumber, value) {
2930    this.addRepeatedInt64Iterable_(
2931        fieldNumber, [value], (writer, fieldNumber, values) => {
2932          writer.writePackedInt64(fieldNumber, values);
2933        });
2934  }
2935
2936  /**
2937   * Adds all int64 values into the field for the given field number.
2938   * All these values will be encoded as packed values.
2939   * @param {number} fieldNumber
2940   * @param {!Iterable<!Int64>} values
2941   */
2942  addPackedInt64Iterable(fieldNumber, values) {
2943    this.addRepeatedInt64Iterable_(
2944        fieldNumber, values, (writer, fieldNumber, values) => {
2945          writer.writePackedInt64(fieldNumber, values);
2946        });
2947  }
2948
2949  /**
2950   * Adds a single int64 value into the field for the given field number.
2951   * All values will be encoded as unpacked values.
2952   * @param {number} fieldNumber
2953   * @param {!Int64} value
2954   */
2955  addUnpackedInt64Element(fieldNumber, value) {
2956    this.addRepeatedInt64Iterable_(
2957        fieldNumber, [value], (writer, fieldNumber, values) => {
2958          writer.writeRepeatedInt64(fieldNumber, values);
2959        });
2960  }
2961
2962  /**
2963   * Adds all int64 values into the field for the given field number.
2964   * All these values will be encoded as unpacked values.
2965   * @param {number} fieldNumber
2966   * @param {!Iterable<!Int64>} values
2967   */
2968  addUnpackedInt64Iterable(fieldNumber, values) {
2969    this.addRepeatedInt64Iterable_(
2970        fieldNumber, values, (writer, fieldNumber, values) => {
2971          writer.writeRepeatedInt64(fieldNumber, values);
2972        });
2973  }
2974
2975  /**
2976   * Sets a single int64 value into the field for the given field number at
2977   * the given index. How these values are encoded depends on the given write
2978   * function.
2979   * @param {number} fieldNumber
2980   * @param {number} index
2981   * @param {!Int64} value
2982   * @param {function(!Writer, number, !Array<!Int64>): undefined} encoder
2983   * @throws {!Error} if index is out of range when check mode is critical
2984   * @private
2985   */
2986  setRepeatedInt64Element_(fieldNumber, index, value, encoder) {
2987    checkCriticalTypeSignedInt64(value);
2988    const array = this.getRepeatedInt64Array_(fieldNumber);
2989    checkCriticalElementIndex(index, array.length);
2990    array[index] = value;
2991    // Needs to set it back to set encoder.
2992    this.setField_(fieldNumber, array, encoder);
2993  }
2994
2995  /**
2996   * Sets a single int64 value into the field for the given field number at
2997   * the given index. All values will be encoded as packed values.
2998   * @param {number} fieldNumber
2999   * @param {number} index
3000   * @param {!Int64} value
3001   * @throws {!Error} if index is out of range when check mode is critical
3002   */
3003  setPackedInt64Element(fieldNumber, index, value) {
3004    this.setRepeatedInt64Element_(
3005        fieldNumber, index, value, (writer, fieldNumber, values) => {
3006          writer.writePackedInt64(fieldNumber, values);
3007        });
3008  }
3009
3010  /**
3011   * Sets all int64 values into the field for the given field number.
3012   * All these values will be encoded as packed values.
3013   * @param {number} fieldNumber
3014   * @param {!Iterable<!Int64>} values
3015   */
3016  setPackedInt64Iterable(fieldNumber, values) {
3017    const array = Array.from(values);
3018    checkCriticalTypeSignedInt64Array(array);
3019    this.setField_(fieldNumber, array, (writer, fieldNumber, values) => {
3020      writer.writePackedInt64(fieldNumber, values);
3021    });
3022  }
3023
3024  /**
3025   * Sets a single int64 value into the field for the given field number at
3026   * the given index. All values will be encoded as unpacked values.
3027   * @param {number} fieldNumber
3028   * @param {number} index
3029   * @param {!Int64} value
3030   * @throws {!Error} if index is out of range when check mode is critical
3031   */
3032  setUnpackedInt64Element(fieldNumber, index, value) {
3033    this.setRepeatedInt64Element_(
3034        fieldNumber, index, value, (writer, fieldNumber, values) => {
3035          writer.writeRepeatedInt64(fieldNumber, values);
3036        });
3037  }
3038
3039  /**
3040   * Sets all int64 values into the field for the given field number.
3041   * All these values will be encoded as unpacked values.
3042   * @param {number} fieldNumber
3043   * @param {!Iterable<!Int64>} values
3044   */
3045  setUnpackedInt64Iterable(fieldNumber, values) {
3046    const array = Array.from(values);
3047    checkCriticalTypeSignedInt64Array(array);
3048    this.setField_(fieldNumber, array, (writer, fieldNumber, values) => {
3049      writer.writeRepeatedInt64(fieldNumber, values);
3050    });
3051  }
3052
3053  /* Sfixed32 */
3054
3055  /**
3056   * Adds all sfixed32 values into the field for the given field number.
3057   * How these values are encoded depends on the given write function.
3058   * @param {number} fieldNumber
3059   * @param {!Iterable<number>} values
3060   * @param {function(!Writer, number, !Array<number>): undefined} encoder
3061   * @private
3062   */
3063  addRepeatedSfixed32Iterable_(fieldNumber, values, encoder) {
3064    const array = [...this.getRepeatedSfixed32Array_(fieldNumber), ...values];
3065    checkCriticalTypeSignedInt32Array(array);
3066    // Needs to set it back because the default empty array was not cached.
3067    this.setField_(fieldNumber, array, encoder);
3068  }
3069
3070  /**
3071   * Adds a single sfixed32 value into the field for the given field number.
3072   * All values will be encoded as packed values.
3073   * @param {number} fieldNumber
3074   * @param {number} value
3075   */
3076  addPackedSfixed32Element(fieldNumber, value) {
3077    this.addRepeatedSfixed32Iterable_(
3078        fieldNumber, [value], (writer, fieldNumber, values) => {
3079          writer.writePackedSfixed32(fieldNumber, values);
3080        });
3081  }
3082
3083  /**
3084   * Adds all sfixed32 values into the field for the given field number.
3085   * All these values will be encoded as packed values.
3086   * @param {number} fieldNumber
3087   * @param {!Iterable<number>} values
3088   */
3089  addPackedSfixed32Iterable(fieldNumber, values) {
3090    this.addRepeatedSfixed32Iterable_(
3091        fieldNumber, values, (writer, fieldNumber, values) => {
3092          writer.writePackedSfixed32(fieldNumber, values);
3093        });
3094  }
3095
3096  /**
3097   * Adds a single sfixed32 value into the field for the given field number.
3098   * All values will be encoded as unpacked values.
3099   * @param {number} fieldNumber
3100   * @param {number} value
3101   */
3102  addUnpackedSfixed32Element(fieldNumber, value) {
3103    this.addRepeatedSfixed32Iterable_(
3104        fieldNumber, [value], (writer, fieldNumber, values) => {
3105          writer.writeRepeatedSfixed32(fieldNumber, values);
3106        });
3107  }
3108
3109  /**
3110   * Adds all sfixed32 values into the field for the given field number.
3111   * All these values will be encoded as unpacked values.
3112   * @param {number} fieldNumber
3113   * @param {!Iterable<number>} values
3114   */
3115  addUnpackedSfixed32Iterable(fieldNumber, values) {
3116    this.addRepeatedSfixed32Iterable_(
3117        fieldNumber, values, (writer, fieldNumber, values) => {
3118          writer.writeRepeatedSfixed32(fieldNumber, values);
3119        });
3120  }
3121
3122  /**
3123   * Sets a single sfixed32 value into the field for the given field number at
3124   * the given index. How these values are encoded depends on the given write
3125   * function.
3126   * @param {number} fieldNumber
3127   * @param {number} index
3128   * @param {number} value
3129   * @param {function(!Writer, number, !Array<number>): undefined} encoder
3130   * @throws {!Error} if index is out of range when check mode is critical
3131   * @private
3132   */
3133  setRepeatedSfixed32Element_(fieldNumber, index, value, encoder) {
3134    checkCriticalTypeSignedInt32(value);
3135    const array = this.getRepeatedSfixed32Array_(fieldNumber);
3136    checkCriticalElementIndex(index, array.length);
3137    array[index] = value;
3138    // Needs to set it back to set encoder.
3139    this.setField_(fieldNumber, array, encoder);
3140  }
3141
3142  /**
3143   * Sets a single sfixed32 value into the field for the given field number at
3144   * the given index. All values will be encoded as packed values.
3145   * @param {number} fieldNumber
3146   * @param {number} index
3147   * @param {number} value
3148   * @throws {!Error} if index is out of range when check mode is critical
3149   */
3150  setPackedSfixed32Element(fieldNumber, index, value) {
3151    this.setRepeatedSfixed32Element_(
3152        fieldNumber, index, value, (writer, fieldNumber, values) => {
3153          writer.writePackedSfixed32(fieldNumber, values);
3154        });
3155  }
3156
3157  /**
3158   * Sets all sfixed32 values into the field for the given field number.
3159   * All these values will be encoded as packed values.
3160   * @param {number} fieldNumber
3161   * @param {!Iterable<number>} values
3162   */
3163  setPackedSfixed32Iterable(fieldNumber, values) {
3164    const array = Array.from(values);
3165    checkCriticalTypeSignedInt32Array(array);
3166    this.setField_(fieldNumber, array, (writer, fieldNumber, values) => {
3167      writer.writePackedSfixed32(fieldNumber, values);
3168    });
3169  }
3170
3171  /**
3172   * Sets a single sfixed32 value into the field for the given field number at
3173   * the given index. All values will be encoded as unpacked values.
3174   * @param {number} fieldNumber
3175   * @param {number} index
3176   * @param {number} value
3177   * @throws {!Error} if index is out of range when check mode is critical
3178   */
3179  setUnpackedSfixed32Element(fieldNumber, index, value) {
3180    this.setRepeatedSfixed32Element_(
3181        fieldNumber, index, value, (writer, fieldNumber, values) => {
3182          writer.writeRepeatedSfixed32(fieldNumber, values);
3183        });
3184  }
3185
3186  /**
3187   * Sets all sfixed32 values into the field for the given field number.
3188   * All these values will be encoded as unpacked values.
3189   * @param {number} fieldNumber
3190   * @param {!Iterable<number>} values
3191   */
3192  setUnpackedSfixed32Iterable(fieldNumber, values) {
3193    const array = Array.from(values);
3194    checkCriticalTypeSignedInt32Array(array);
3195    this.setField_(fieldNumber, array, (writer, fieldNumber, values) => {
3196      writer.writeRepeatedSfixed32(fieldNumber, values);
3197    });
3198  }
3199
3200  /* Sfixed64 */
3201
3202  /**
3203   * Adds all sfixed64 values into the field for the given field number.
3204   * How these values are encoded depends on the given write function.
3205   * @param {number} fieldNumber
3206   * @param {!Iterable<!Int64>} values
3207   * @param {function(!Writer, number, !Array<!Int64>): undefined} encoder
3208   * @private
3209   */
3210  addRepeatedSfixed64Iterable_(fieldNumber, values, encoder) {
3211    const array = [...this.getRepeatedSfixed64Array_(fieldNumber), ...values];
3212    checkCriticalTypeSignedInt64Array(array);
3213    // Needs to set it back because the default empty array was not cached.
3214    this.setField_(fieldNumber, array, encoder);
3215  }
3216
3217  /**
3218   * Adds a single sfixed64 value into the field for the given field number.
3219   * All values will be encoded as packed values.
3220   * @param {number} fieldNumber
3221   * @param {!Int64} value
3222   */
3223  addPackedSfixed64Element(fieldNumber, value) {
3224    this.addRepeatedSfixed64Iterable_(
3225        fieldNumber, [value], (writer, fieldNumber, values) => {
3226          writer.writePackedSfixed64(fieldNumber, values);
3227        });
3228  }
3229
3230  /**
3231   * Adds all sfixed64 values into the field for the given field number.
3232   * All these values will be encoded as packed values.
3233   * @param {number} fieldNumber
3234   * @param {!Iterable<!Int64>} values
3235   */
3236  addPackedSfixed64Iterable(fieldNumber, values) {
3237    this.addRepeatedSfixed64Iterable_(
3238        fieldNumber, values, (writer, fieldNumber, values) => {
3239          writer.writePackedSfixed64(fieldNumber, values);
3240        });
3241  }
3242
3243  /**
3244   * Adds a single sfixed64 value into the field for the given field number.
3245   * All values will be encoded as unpacked values.
3246   * @param {number} fieldNumber
3247   * @param {!Int64} value
3248   */
3249  addUnpackedSfixed64Element(fieldNumber, value) {
3250    this.addRepeatedSfixed64Iterable_(
3251        fieldNumber, [value], (writer, fieldNumber, values) => {
3252          writer.writeRepeatedSfixed64(fieldNumber, values);
3253        });
3254  }
3255
3256  /**
3257   * Adds all sfixed64 values into the field for the given field number.
3258   * All these values will be encoded as unpacked values.
3259   * @param {number} fieldNumber
3260   * @param {!Iterable<!Int64>} values
3261   */
3262  addUnpackedSfixed64Iterable(fieldNumber, values) {
3263    this.addRepeatedSfixed64Iterable_(
3264        fieldNumber, values, (writer, fieldNumber, values) => {
3265          writer.writeRepeatedSfixed64(fieldNumber, values);
3266        });
3267  }
3268
3269  /**
3270   * Sets a single sfixed64 value into the field for the given field number at
3271   * the given index. How these values are encoded depends on the given write
3272   * function.
3273   * @param {number} fieldNumber
3274   * @param {number} index
3275   * @param {!Int64} value
3276   * @param {function(!Writer, number, !Array<!Int64>): undefined} encoder
3277   * @throws {!Error} if index is out of range when check mode is critical
3278   * @private
3279   */
3280  setRepeatedSfixed64Element_(fieldNumber, index, value, encoder) {
3281    checkCriticalTypeSignedInt64(value);
3282    const array = this.getRepeatedSfixed64Array_(fieldNumber);
3283    checkCriticalElementIndex(index, array.length);
3284    array[index] = value;
3285    // Needs to set it back to set encoder.
3286    this.setField_(fieldNumber, array, encoder);
3287  }
3288
3289  /**
3290   * Sets a single sfixed64 value into the field for the given field number at
3291   * the given index. All values will be encoded as packed values.
3292   * @param {number} fieldNumber
3293   * @param {number} index
3294   * @param {!Int64} value
3295   * @throws {!Error} if index is out of range when check mode is critical
3296   */
3297  setPackedSfixed64Element(fieldNumber, index, value) {
3298    this.setRepeatedSfixed64Element_(
3299        fieldNumber, index, value, (writer, fieldNumber, values) => {
3300          writer.writePackedSfixed64(fieldNumber, values);
3301        });
3302  }
3303
3304  /**
3305   * Sets all sfixed64 values into the field for the given field number.
3306   * All these values will be encoded as packed values.
3307   * @param {number} fieldNumber
3308   * @param {!Iterable<!Int64>} values
3309   */
3310  setPackedSfixed64Iterable(fieldNumber, values) {
3311    const array = Array.from(values);
3312    checkCriticalTypeSignedInt64Array(array);
3313    this.setField_(fieldNumber, array, (writer, fieldNumber, values) => {
3314      writer.writePackedSfixed64(fieldNumber, values);
3315    });
3316  }
3317
3318  /**
3319   * Sets a single sfixed64 value into the field for the given field number at
3320   * the given index. All values will be encoded as unpacked values.
3321   * @param {number} fieldNumber
3322   * @param {number} index
3323   * @param {!Int64} value
3324   * @throws {!Error} if index is out of range when check mode is critical
3325   */
3326  setUnpackedSfixed64Element(fieldNumber, index, value) {
3327    this.setRepeatedSfixed64Element_(
3328        fieldNumber, index, value, (writer, fieldNumber, values) => {
3329          writer.writeRepeatedSfixed64(fieldNumber, values);
3330        });
3331  }
3332
3333  /**
3334   * Sets all sfixed64 values into the field for the given field number.
3335   * All these values will be encoded as unpacked values.
3336   * @param {number} fieldNumber
3337   * @param {!Iterable<!Int64>} values
3338   */
3339  setUnpackedSfixed64Iterable(fieldNumber, values) {
3340    const array = Array.from(values);
3341    checkCriticalTypeSignedInt64Array(array);
3342    this.setField_(fieldNumber, array, (writer, fieldNumber, values) => {
3343      writer.writeRepeatedSfixed64(fieldNumber, values);
3344    });
3345  }
3346
3347  /* Sint32 */
3348
3349  /**
3350   * Adds all sint32 values into the field for the given field number.
3351   * How these values are encoded depends on the given write function.
3352   * @param {number} fieldNumber
3353   * @param {!Iterable<number>} values
3354   * @param {function(!Writer, number, !Array<number>): undefined} encoder
3355   * @private
3356   */
3357  addRepeatedSint32Iterable_(fieldNumber, values, encoder) {
3358    const array = [...this.getRepeatedSint32Array_(fieldNumber), ...values];
3359    checkCriticalTypeSignedInt32Array(array);
3360    // Needs to set it back because the default empty array was not cached.
3361    this.setField_(fieldNumber, array, encoder);
3362  }
3363
3364  /**
3365   * Adds a single sint32 value into the field for the given field number.
3366   * All values will be encoded as packed values.
3367   * @param {number} fieldNumber
3368   * @param {number} value
3369   */
3370  addPackedSint32Element(fieldNumber, value) {
3371    this.addRepeatedSint32Iterable_(
3372        fieldNumber, [value], (writer, fieldNumber, values) => {
3373          writer.writePackedSint32(fieldNumber, values);
3374        });
3375  }
3376
3377  /**
3378   * Adds all sint32 values into the field for the given field number.
3379   * All these values will be encoded as packed values.
3380   * @param {number} fieldNumber
3381   * @param {!Iterable<number>} values
3382   */
3383  addPackedSint32Iterable(fieldNumber, values) {
3384    this.addRepeatedSint32Iterable_(
3385        fieldNumber, values, (writer, fieldNumber, values) => {
3386          writer.writePackedSint32(fieldNumber, values);
3387        });
3388  }
3389
3390  /**
3391   * Adds a single sint32 value into the field for the given field number.
3392   * All values will be encoded as unpacked values.
3393   * @param {number} fieldNumber
3394   * @param {number} value
3395   */
3396  addUnpackedSint32Element(fieldNumber, value) {
3397    this.addRepeatedSint32Iterable_(
3398        fieldNumber, [value], (writer, fieldNumber, values) => {
3399          writer.writeRepeatedSint32(fieldNumber, values);
3400        });
3401  }
3402
3403  /**
3404   * Adds all sint32 values into the field for the given field number.
3405   * All these values will be encoded as unpacked values.
3406   * @param {number} fieldNumber
3407   * @param {!Iterable<number>} values
3408   */
3409  addUnpackedSint32Iterable(fieldNumber, values) {
3410    this.addRepeatedSint32Iterable_(
3411        fieldNumber, values, (writer, fieldNumber, values) => {
3412          writer.writeRepeatedSint32(fieldNumber, values);
3413        });
3414  }
3415
3416  /**
3417   * Sets a single sint32 value into the field for the given field number at
3418   * the given index. How these values are encoded depends on the given write
3419   * function.
3420   * @param {number} fieldNumber
3421   * @param {number} index
3422   * @param {number} value
3423   * @param {function(!Writer, number, !Array<number>): undefined} encoder
3424   * @throws {!Error} if index is out of range when check mode is critical
3425   * @private
3426   */
3427  setRepeatedSint32Element_(fieldNumber, index, value, encoder) {
3428    checkCriticalTypeSignedInt32(value);
3429    const array = this.getRepeatedSint32Array_(fieldNumber);
3430    checkCriticalElementIndex(index, array.length);
3431    array[index] = value;
3432    // Needs to set it back to set encoder.
3433    this.setField_(fieldNumber, array, encoder);
3434  }
3435
3436  /**
3437   * Sets a single sint32 value into the field for the given field number at
3438   * the given index. All values will be encoded as packed values.
3439   * @param {number} fieldNumber
3440   * @param {number} index
3441   * @param {number} value
3442   * @throws {!Error} if index is out of range when check mode is critical
3443   */
3444  setPackedSint32Element(fieldNumber, index, value) {
3445    this.setRepeatedSint32Element_(
3446        fieldNumber, index, value, (writer, fieldNumber, values) => {
3447          writer.writePackedSint32(fieldNumber, values);
3448        });
3449  }
3450
3451  /**
3452   * Sets all sint32 values into the field for the given field number.
3453   * All these values will be encoded as packed values.
3454   * @param {number} fieldNumber
3455   * @param {!Iterable<number>} values
3456   */
3457  setPackedSint32Iterable(fieldNumber, values) {
3458    const array = Array.from(values);
3459    checkCriticalTypeSignedInt32Array(array);
3460    this.setField_(fieldNumber, array, (writer, fieldNumber, values) => {
3461      writer.writePackedSint32(fieldNumber, values);
3462    });
3463  }
3464
3465  /**
3466   * Sets a single sint32 value into the field for the given field number at
3467   * the given index. All values will be encoded as unpacked values.
3468   * @param {number} fieldNumber
3469   * @param {number} index
3470   * @param {number} value
3471   * @throws {!Error} if index is out of range when check mode is critical
3472   */
3473  setUnpackedSint32Element(fieldNumber, index, value) {
3474    this.setRepeatedSint32Element_(
3475        fieldNumber, index, value, (writer, fieldNumber, values) => {
3476          writer.writeRepeatedSint32(fieldNumber, values);
3477        });
3478  }
3479
3480  /**
3481   * Sets all sint32 values into the field for the given field number.
3482   * All these values will be encoded as unpacked values.
3483   * @param {number} fieldNumber
3484   * @param {!Iterable<number>} values
3485   */
3486  setUnpackedSint32Iterable(fieldNumber, values) {
3487    const array = Array.from(values);
3488    checkCriticalTypeSignedInt32Array(array);
3489    this.setField_(fieldNumber, array, (writer, fieldNumber, values) => {
3490      writer.writeRepeatedSint32(fieldNumber, values);
3491    });
3492  }
3493
3494  /* Sint64 */
3495
3496  /**
3497   * Adds all sint64 values into the field for the given field number.
3498   * How these values are encoded depends on the given write function.
3499   * @param {number} fieldNumber
3500   * @param {!Iterable<!Int64>} values
3501   * @param {function(!Writer, number, !Array<!Int64>): undefined} encoder
3502   * @private
3503   */
3504  addRepeatedSint64Iterable_(fieldNumber, values, encoder) {
3505    const array = [...this.getRepeatedSint64Array_(fieldNumber), ...values];
3506    checkCriticalTypeSignedInt64Array(array);
3507    // Needs to set it back because the default empty array was not cached.
3508    this.setField_(fieldNumber, array, encoder);
3509  }
3510
3511  /**
3512   * Adds a single sint64 value into the field for the given field number.
3513   * All values will be encoded as packed values.
3514   * @param {number} fieldNumber
3515   * @param {!Int64} value
3516   */
3517  addPackedSint64Element(fieldNumber, value) {
3518    this.addRepeatedSint64Iterable_(
3519        fieldNumber, [value], (writer, fieldNumber, values) => {
3520          writer.writePackedSint64(fieldNumber, values);
3521        });
3522  }
3523
3524  /**
3525   * Adds all sint64 values into the field for the given field number.
3526   * All these values will be encoded as packed values.
3527   * @param {number} fieldNumber
3528   * @param {!Iterable<!Int64>} values
3529   */
3530  addPackedSint64Iterable(fieldNumber, values) {
3531    this.addRepeatedSint64Iterable_(
3532        fieldNumber, values, (writer, fieldNumber, values) => {
3533          writer.writePackedSint64(fieldNumber, values);
3534        });
3535  }
3536
3537  /**
3538   * Adds a single sint64 value into the field for the given field number.
3539   * All values will be encoded as unpacked values.
3540   * @param {number} fieldNumber
3541   * @param {!Int64} value
3542   */
3543  addUnpackedSint64Element(fieldNumber, value) {
3544    this.addRepeatedSint64Iterable_(
3545        fieldNumber, [value], (writer, fieldNumber, values) => {
3546          writer.writeRepeatedSint64(fieldNumber, values);
3547        });
3548  }
3549
3550  /**
3551   * Adds all sint64 values into the field for the given field number.
3552   * All these values will be encoded as unpacked values.
3553   * @param {number} fieldNumber
3554   * @param {!Iterable<!Int64>} values
3555   */
3556  addUnpackedSint64Iterable(fieldNumber, values) {
3557    this.addRepeatedSint64Iterable_(
3558        fieldNumber, values, (writer, fieldNumber, values) => {
3559          writer.writeRepeatedSint64(fieldNumber, values);
3560        });
3561  }
3562
3563  /**
3564   * Sets a single sint64 value into the field for the given field number at
3565   * the given index. How these values are encoded depends on the given write
3566   * function.
3567   * @param {number} fieldNumber
3568   * @param {number} index
3569   * @param {!Int64} value
3570   * @param {function(!Writer, number, !Array<!Int64>): undefined} encoder
3571   * @throws {!Error} if index is out of range when check mode is critical
3572   * @private
3573   */
3574  setRepeatedSint64Element_(fieldNumber, index, value, encoder) {
3575    checkCriticalTypeSignedInt64(value);
3576    const array = this.getRepeatedSint64Array_(fieldNumber);
3577    checkCriticalElementIndex(index, array.length);
3578    array[index] = value;
3579    // Needs to set it back to set encoder.
3580    this.setField_(fieldNumber, array, encoder);
3581  }
3582
3583  /**
3584   * Sets a single sint64 value into the field for the given field number at
3585   * the given index. All values will be encoded as packed values.
3586   * @param {number} fieldNumber
3587   * @param {number} index
3588   * @param {!Int64} value
3589   * @throws {!Error} if index is out of range when check mode is critical
3590   */
3591  setPackedSint64Element(fieldNumber, index, value) {
3592    this.setRepeatedSint64Element_(
3593        fieldNumber, index, value, (writer, fieldNumber, values) => {
3594          writer.writePackedSint64(fieldNumber, values);
3595        });
3596  }
3597
3598  /**
3599   * Sets all sint64 values into the field for the given field number.
3600   * All these values will be encoded as packed values.
3601   * @param {number} fieldNumber
3602   * @param {!Iterable<!Int64>} values
3603   */
3604  setPackedSint64Iterable(fieldNumber, values) {
3605    const array = Array.from(values);
3606    checkCriticalTypeSignedInt64Array(array);
3607    this.setField_(fieldNumber, array, (writer, fieldNumber, values) => {
3608      writer.writePackedSint64(fieldNumber, values);
3609    });
3610  }
3611
3612  /**
3613   * Sets a single sint64 value into the field for the given field number at
3614   * the given index. All values will be encoded as unpacked values.
3615   * @param {number} fieldNumber
3616   * @param {number} index
3617   * @param {!Int64} value
3618   * @throws {!Error} if index is out of range when check mode is critical
3619   */
3620  setUnpackedSint64Element(fieldNumber, index, value) {
3621    this.setRepeatedSint64Element_(
3622        fieldNumber, index, value, (writer, fieldNumber, values) => {
3623          writer.writeRepeatedSint64(fieldNumber, values);
3624        });
3625  }
3626
3627  /**
3628   * Sets all sint64 values into the field for the given field number.
3629   * All these values will be encoded as unpacked values.
3630   * @param {number} fieldNumber
3631   * @param {!Iterable<!Int64>} values
3632   */
3633  setUnpackedSint64Iterable(fieldNumber, values) {
3634    const array = Array.from(values);
3635    checkCriticalTypeSignedInt64Array(array);
3636    this.setField_(fieldNumber, array, (writer, fieldNumber, values) => {
3637      writer.writeRepeatedSint64(fieldNumber, values);
3638    });
3639  }
3640
3641  /* Uint32 */
3642
3643  /**
3644   * Adds all uint32 values into the field for the given field number.
3645   * How these values are encoded depends on the given write function.
3646   * @param {number} fieldNumber
3647   * @param {!Iterable<number>} values
3648   * @param {function(!Writer, number, !Array<number>): undefined} encoder
3649   * @private
3650   */
3651  addRepeatedUint32Iterable_(fieldNumber, values, encoder) {
3652    const array = [...this.getRepeatedUint32Array_(fieldNumber), ...values];
3653    checkCriticalTypeUnsignedInt32Array(array);
3654    // Needs to set it back because the default empty array was not cached.
3655    this.setField_(fieldNumber, array, encoder);
3656  }
3657
3658  /**
3659   * Adds a single uint32 value into the field for the given field number.
3660   * All values will be encoded as packed values.
3661   * @param {number} fieldNumber
3662   * @param {number} value
3663   */
3664  addPackedUint32Element(fieldNumber, value) {
3665    this.addRepeatedUint32Iterable_(
3666        fieldNumber, [value], (writer, fieldNumber, values) => {
3667          writer.writePackedUint32(fieldNumber, values);
3668        });
3669  }
3670
3671  /**
3672   * Adds all uint32 values into the field for the given field number.
3673   * All these values will be encoded as packed values.
3674   * @param {number} fieldNumber
3675   * @param {!Iterable<number>} values
3676   */
3677  addPackedUint32Iterable(fieldNumber, values) {
3678    this.addRepeatedUint32Iterable_(
3679        fieldNumber, values, (writer, fieldNumber, values) => {
3680          writer.writePackedUint32(fieldNumber, values);
3681        });
3682  }
3683
3684  /**
3685   * Adds a single uint32 value into the field for the given field number.
3686   * All values will be encoded as unpacked values.
3687   * @param {number} fieldNumber
3688   * @param {number} value
3689   */
3690  addUnpackedUint32Element(fieldNumber, value) {
3691    this.addRepeatedUint32Iterable_(
3692        fieldNumber, [value], (writer, fieldNumber, values) => {
3693          writer.writeRepeatedUint32(fieldNumber, values);
3694        });
3695  }
3696
3697  /**
3698   * Adds all uint32 values into the field for the given field number.
3699   * All these values will be encoded as unpacked values.
3700   * @param {number} fieldNumber
3701   * @param {!Iterable<number>} values
3702   */
3703  addUnpackedUint32Iterable(fieldNumber, values) {
3704    this.addRepeatedUint32Iterable_(
3705        fieldNumber, values, (writer, fieldNumber, values) => {
3706          writer.writeRepeatedUint32(fieldNumber, values);
3707        });
3708  }
3709
3710  /**
3711   * Sets a single uint32 value into the field for the given field number at
3712   * the given index. How these values are encoded depends on the given write
3713   * function.
3714   * @param {number} fieldNumber
3715   * @param {number} index
3716   * @param {number} value
3717   * @param {function(!Writer, number, !Array<number>): undefined} encoder
3718   * @throws {!Error} if index is out of range when check mode is critical
3719   * @private
3720   */
3721  setRepeatedUint32Element_(fieldNumber, index, value, encoder) {
3722    checkCriticalTypeUnsignedInt32(value);
3723    const array = this.getRepeatedUint32Array_(fieldNumber);
3724    checkCriticalElementIndex(index, array.length);
3725    array[index] = value;
3726    // Needs to set it back to set encoder.
3727    this.setField_(fieldNumber, array, encoder);
3728  }
3729
3730  /**
3731   * Sets a single uint32 value into the field for the given field number at
3732   * the given index. All values will be encoded as packed values.
3733   * @param {number} fieldNumber
3734   * @param {number} index
3735   * @param {number} value
3736   * @throws {!Error} if index is out of range when check mode is critical
3737   */
3738  setPackedUint32Element(fieldNumber, index, value) {
3739    this.setRepeatedUint32Element_(
3740        fieldNumber, index, value, (writer, fieldNumber, values) => {
3741          writer.writePackedUint32(fieldNumber, values);
3742        });
3743  }
3744
3745  /**
3746   * Sets all uint32 values into the field for the given field number.
3747   * All these values will be encoded as packed values.
3748   * @param {number} fieldNumber
3749   * @param {!Iterable<number>} values
3750   */
3751  setPackedUint32Iterable(fieldNumber, values) {
3752    const array = Array.from(values);
3753    checkCriticalTypeUnsignedInt32Array(array);
3754    this.setField_(fieldNumber, array, (writer, fieldNumber, values) => {
3755      writer.writePackedUint32(fieldNumber, values);
3756    });
3757  }
3758
3759  /**
3760   * Sets a single uint32 value into the field for the given field number at
3761   * the given index. All values will be encoded as unpacked values.
3762   * @param {number} fieldNumber
3763   * @param {number} index
3764   * @param {number} value
3765   * @throws {!Error} if index is out of range when check mode is critical
3766   */
3767  setUnpackedUint32Element(fieldNumber, index, value) {
3768    this.setRepeatedUint32Element_(
3769        fieldNumber, index, value, (writer, fieldNumber, values) => {
3770          writer.writeRepeatedUint32(fieldNumber, values);
3771        });
3772  }
3773
3774  /**
3775   * Sets all uint32 values into the field for the given field number.
3776   * All these values will be encoded as unpacked values.
3777   * @param {number} fieldNumber
3778   * @param {!Iterable<number>} values
3779   */
3780  setUnpackedUint32Iterable(fieldNumber, values) {
3781    const array = Array.from(values);
3782    checkCriticalTypeUnsignedInt32Array(array);
3783    this.setField_(fieldNumber, array, (writer, fieldNumber, values) => {
3784      writer.writeRepeatedUint32(fieldNumber, values);
3785    });
3786  }
3787
3788  /* Uint64 */
3789
3790  /**
3791   * Adds a single uint64 value into the field for the given field number.
3792   * All values will be encoded as packed values.
3793   * @param {number} fieldNumber
3794   * @param {!Int64} value
3795   */
3796  addPackedUint64Element(fieldNumber, value) {
3797    this.addPackedInt64Element(fieldNumber, value);
3798  }
3799
3800  /**
3801   * Adds all uint64 values into the field for the given field number.
3802   * All these values will be encoded as packed values.
3803   * @param {number} fieldNumber
3804   * @param {!Iterable<!Int64>} values
3805   */
3806  addPackedUint64Iterable(fieldNumber, values) {
3807    this.addPackedInt64Iterable(fieldNumber, values);
3808  }
3809
3810  /**
3811   * Adds a single uint64 value into the field for the given field number.
3812   * All values will be encoded as unpacked values.
3813   * @param {number} fieldNumber
3814   * @param {!Int64} value
3815   */
3816  addUnpackedUint64Element(fieldNumber, value) {
3817    this.addUnpackedInt64Element(fieldNumber, value);
3818  }
3819
3820  /**
3821   * Adds all uint64 values into the field for the given field number.
3822   * All these values will be encoded as unpacked values.
3823   * @param {number} fieldNumber
3824   * @param {!Iterable<!Int64>} values
3825   */
3826  addUnpackedUint64Iterable(fieldNumber, values) {
3827    this.addUnpackedInt64Iterable(fieldNumber, values);
3828  }
3829
3830  /**
3831   * Sets a single uint64 value into the field for the given field number at
3832   * the given index. All values will be encoded as packed values.
3833   * @param {number} fieldNumber
3834   * @param {number} index
3835   * @param {!Int64} value
3836   * @throws {!Error} if index is out of range when check mode is critical
3837   */
3838  setPackedUint64Element(fieldNumber, index, value) {
3839    this.setPackedInt64Element(fieldNumber, index, value);
3840  }
3841
3842  /**
3843   * Sets all uint64 values into the field for the given field number.
3844   * All these values will be encoded as packed values.
3845   * @param {number} fieldNumber
3846   * @param {!Iterable<!Int64>} values
3847   */
3848  setPackedUint64Iterable(fieldNumber, values) {
3849    this.setPackedInt64Iterable(fieldNumber, values);
3850  }
3851
3852  /**
3853   * Sets a single uint64 value into the field for the given field number at
3854   * the given index. All values will be encoded as unpacked values.
3855   * @param {number} fieldNumber
3856   * @param {number} index
3857   * @param {!Int64} value
3858   * @throws {!Error} if index is out of range when check mode is critical
3859   */
3860  setUnpackedUint64Element(fieldNumber, index, value) {
3861    this.setUnpackedInt64Element(fieldNumber, index, value);
3862  }
3863
3864  /**
3865   * Sets all uint64 values into the field for the given field number.
3866   * All these values will be encoded as unpacked values.
3867   * @param {number} fieldNumber
3868   * @param {!Iterable<!Int64>} values
3869   */
3870  setUnpackedUint64Iterable(fieldNumber, values) {
3871    this.setUnpackedInt64Iterable(fieldNumber, values);
3872  }
3873
3874  /* Bytes */
3875
3876  /**
3877   * Sets all bytes values into the field for the given field number.
3878   * @param {number} fieldNumber
3879   * @param {!Iterable<!ByteString>} values
3880   */
3881  setRepeatedBytesIterable(fieldNumber, values) {
3882    const /** !Array<!ByteString> */ array = Array.from(values);
3883    checkCriticalTypeByteStringArray(array);
3884    this.setField_(fieldNumber, array, (writer, fieldNumber, values) => {
3885      writer.writeRepeatedBytes(fieldNumber, values);
3886    });
3887  }
3888
3889  /**
3890   * Adds all bytes values into the field for the given field number.
3891   * @param {number} fieldNumber
3892   * @param {!Iterable<!ByteString>} values
3893   */
3894  addRepeatedBytesIterable(fieldNumber, values) {
3895    const array = [...this.getRepeatedBytesArray_(fieldNumber), ...values];
3896    checkCriticalTypeByteStringArray(array);
3897    // Needs to set it back because the default empty array was not cached.
3898    this.setField_(fieldNumber, array, (writer, fieldNumber, values) => {
3899      writer.writeRepeatedBytes(fieldNumber, values);
3900    });
3901  }
3902
3903  /**
3904   * Sets a single bytes value into the field for the given field number at
3905   * the given index.
3906   * @param {number} fieldNumber
3907   * @param {number} index
3908   * @param {!ByteString} value
3909   * @throws {!Error} if index is out of range when check mode is critical
3910   */
3911  setRepeatedBytesElement(fieldNumber, index, value) {
3912    checkCriticalTypeByteString(value);
3913    const array = this.getRepeatedBytesArray_(fieldNumber);
3914    checkCriticalElementIndex(index, array.length);
3915    array[index] = value;
3916    // Needs to set it back to set encoder.
3917    this.setField_(fieldNumber, array, (writer, fieldNumber, values) => {
3918      writer.writeRepeatedBytes(fieldNumber, values);
3919    });
3920  }
3921
3922  /**
3923   * Adds a single bytes value into the field for the given field number.
3924   * @param {number} fieldNumber
3925   * @param {!ByteString} value
3926   */
3927  addRepeatedBytesElement(fieldNumber, value) {
3928    this.addRepeatedBytesIterable(fieldNumber, [value]);
3929  }
3930
3931  /* String */
3932
3933  /**
3934   * Sets all string values into the field for the given field number.
3935   * @param {number} fieldNumber
3936   * @param {!Iterable<string>} values
3937   */
3938  setRepeatedStringIterable(fieldNumber, values) {
3939    const /** !Array<string> */ array = Array.from(values);
3940    checkCriticalTypeStringArray(array);
3941    this.setField_(fieldNumber, array, (writer, fieldNumber, values) => {
3942      writer.writeRepeatedString(fieldNumber, values);
3943    });
3944  }
3945
3946  /**
3947   * Adds all string values into the field for the given field number.
3948   * @param {number} fieldNumber
3949   * @param {!Iterable<string>} values
3950   */
3951  addRepeatedStringIterable(fieldNumber, values) {
3952    const array = [...this.getRepeatedStringArray_(fieldNumber), ...values];
3953    checkCriticalTypeStringArray(array);
3954    // Needs to set it back because the default empty array was not cached.
3955    this.setField_(fieldNumber, array, (writer, fieldNumber, values) => {
3956      writer.writeRepeatedString(fieldNumber, values);
3957    });
3958  }
3959
3960  /**
3961   * Sets a single string value into the field for the given field number at
3962   * the given index.
3963   * @param {number} fieldNumber
3964   * @param {number} index
3965   * @param {string} value
3966   * @throws {!Error} if index is out of range when check mode is critical
3967   */
3968  setRepeatedStringElement(fieldNumber, index, value) {
3969    checkCriticalTypeString(value);
3970    const array = this.getRepeatedStringArray_(fieldNumber);
3971    checkCriticalElementIndex(index, array.length);
3972    array[index] = value;
3973    // Needs to set it back to set encoder.
3974    this.setField_(fieldNumber, array, (writer, fieldNumber, values) => {
3975      writer.writeRepeatedString(fieldNumber, values);
3976    });
3977  }
3978
3979  /**
3980   * Adds a single string value into the field for the given field number.
3981   * @param {number} fieldNumber
3982   * @param {string} value
3983   */
3984  addRepeatedStringElement(fieldNumber, value) {
3985    this.addRepeatedStringIterable(fieldNumber, [value]);
3986  }
3987
3988  /* Message */
3989
3990  /**
3991   * Sets all message values into the field for the given field number.
3992   * @param {number} fieldNumber
3993   * @param {!Iterable<!InternalMessage>} values
3994   */
3995  setRepeatedMessageIterable(fieldNumber, values) {
3996    const /** !Array<!InternalMessage> */ array = Array.from(values);
3997    checkCriticalTypeMessageArray(array);
3998    this.setField_(fieldNumber, array, (writer, fieldNumber, values) => {
3999      writeRepeatedMessage(writer, fieldNumber, values);
4000    });
4001  }
4002
4003  /**
4004   * Adds all message values into the field for the given field number.
4005   * @param {number} fieldNumber
4006   * @param {!Iterable<!InternalMessage>} values
4007   * @param {function(!Kernel):!InternalMessage} instanceCreator
4008   * @param {number=} pivot
4009   */
4010  addRepeatedMessageIterable(
4011      fieldNumber, values, instanceCreator, pivot = undefined) {
4012    const array = [
4013      ...this.getRepeatedMessageArray_(fieldNumber, instanceCreator, pivot),
4014      ...values,
4015    ];
4016    checkCriticalTypeMessageArray(array);
4017    // Needs to set it back with the new array.
4018    this.setField_(
4019        fieldNumber, array,
4020        (writer, fieldNumber, values) =>
4021            writeRepeatedMessage(writer, fieldNumber, values));
4022  }
4023
4024  /**
4025   * Sets a single message value into the field for the given field number at
4026   * the given index.
4027   * @param {number} fieldNumber
4028   * @param {!InternalMessage} value
4029   * @param {function(!Kernel):!InternalMessage} instanceCreator
4030   * @param {number} index
4031   * @param {number=} pivot
4032   * @throws {!Error} if index is out of range when check mode is critical
4033   */
4034  setRepeatedMessageElement(
4035      fieldNumber, value, instanceCreator, index, pivot = undefined) {
4036    checkInstanceCreator(instanceCreator);
4037    checkCriticalType(
4038        value !== null, 'Given value is not a message instance: null');
4039    const array =
4040        this.getRepeatedMessageArray_(fieldNumber, instanceCreator, pivot);
4041    checkCriticalElementIndex(index, array.length);
4042    array[index] = value;
4043  }
4044
4045  /**
4046   * Adds a single message value into the field for the given field number.
4047   * @param {number} fieldNumber
4048   * @param {!InternalMessage} value
4049   * @param {function(!Kernel):!InternalMessage} instanceCreator
4050   * @param {number=} pivot
4051   */
4052  addRepeatedMessageElement(
4053      fieldNumber, value, instanceCreator, pivot = undefined) {
4054    this.addRepeatedMessageIterable(
4055        fieldNumber, [value], instanceCreator, pivot);
4056  }
4057
4058  // Groups
4059  /**
4060   * Sets all message values into the field for the given field number.
4061   * @param {number} fieldNumber
4062   * @param {!Iterable<!InternalMessage>} values
4063   */
4064  setRepeatedGroupIterable(fieldNumber, values) {
4065    const /** !Array<!InternalMessage> */ array = Array.from(values);
4066    checkCriticalTypeMessageArray(array);
4067    this.setField_(fieldNumber, array, writeRepeatedGroup);
4068  }
4069
4070  /**
4071   * Adds all message values into the field for the given field number.
4072   * @param {number} fieldNumber
4073   * @param {!Iterable<!InternalMessage>} values
4074   * @param {function(!Kernel):!InternalMessage} instanceCreator
4075   * @param {number=} pivot
4076   */
4077  addRepeatedGroupIterable(
4078      fieldNumber, values, instanceCreator, pivot = undefined) {
4079    const array = [
4080      ...this.getRepeatedGroupArray_(fieldNumber, instanceCreator, pivot),
4081      ...values,
4082    ];
4083    checkCriticalTypeMessageArray(array);
4084    // Needs to set it back with the new array.
4085    this.setField_(fieldNumber, array, writeRepeatedGroup);
4086  }
4087
4088  /**
4089   * Sets a single message value into the field for the given field number at
4090   * the given index.
4091   * @param {number} fieldNumber
4092   * @param {!InternalMessage} value
4093   * @param {function(!Kernel):!InternalMessage} instanceCreator
4094   * @param {number} index
4095   * @param {number=} pivot
4096   * @throws {!Error} if index is out of range when check mode is critical
4097   */
4098  setRepeatedGroupElement(
4099      fieldNumber, value, instanceCreator, index, pivot = undefined) {
4100    checkInstanceCreator(instanceCreator);
4101    checkCriticalType(
4102        value !== null, 'Given value is not a message instance: null');
4103    const array =
4104        this.getRepeatedGroupArray_(fieldNumber, instanceCreator, pivot);
4105    checkCriticalElementIndex(index, array.length);
4106    array[index] = value;
4107  }
4108
4109  /**
4110   * Adds a single message value into the field for the given field number.
4111   * @param {number} fieldNumber
4112   * @param {!InternalMessage} value
4113   * @param {function(!Kernel):!InternalMessage} instanceCreator
4114   * @param {number=} pivot
4115   */
4116  addRepeatedGroupElement(
4117      fieldNumber, value, instanceCreator, pivot = undefined) {
4118    this.addRepeatedGroupIterable(fieldNumber, [value], instanceCreator, pivot);
4119  }
4120}
4121
4122exports = Kernel;
4123