• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc.  All rights reserved.
3// https://developers.google.com/protocol-buffers/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9//     * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11//     * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15//     * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31/**
32 * @fileoverview This file contains utilities for encoding Javascript objects
33 * into binary, wire-format protocol buffers (in the form of Uint8Arrays) that
34 * a server can consume directly.
35 *
36 * jspb's BinaryWriter class defines methods for efficiently encoding
37 * Javascript objects into binary, wire-format protocol buffers and supports
38 * all the fundamental field types used in protocol buffers.
39 *
40 * Major caveat 1 - Users of this library _must_ keep their Javascript proto
41 * parsing code in sync with the original .proto file - presumably you'll be
42 * using the typed jspb code generator, but if you bypass that you'll need
43 * to keep things in sync by hand.
44 *
45 * Major caveat 2 - Javascript is unable to accurately represent integers
46 * larger than 2^53 due to its use of a double-precision floating point format
47 * for all numbers. BinaryWriter does not make any special effort to preserve
48 * precision for values above this limit - if you need to pass 64-bit integers
49 * (hash codes, for example) between the client and server without precision
50 * loss, do _not_ use this library.
51 *
52 * Major caveat 3 - This class uses typed arrays and must not be used on older
53 * browsers that do not support them.
54 *
55 * @author aappleby@google.com (Austin Appleby)
56 */
57
58goog.provide('jspb.BinaryWriter');
59
60goog.require('goog.asserts');
61goog.require('goog.crypt.base64');
62goog.require('jspb.BinaryConstants');
63goog.require('jspb.BinaryEncoder');
64goog.require('jspb.arith.Int64');
65goog.require('jspb.arith.UInt64');
66goog.require('jspb.utils');
67
68
69
70/**
71 * BinaryWriter implements encoders for all the wire types specified in
72 * https://developers.google.com/protocol-buffers/docs/encoding.
73 *
74 * @constructor
75 * @struct
76 */
77jspb.BinaryWriter = function() {
78  /**
79   * Blocks of serialized data that will be concatenated once all messages have
80   * been written.
81   * @private {!Array<!Uint8Array|!Array<number>>}
82   */
83  this.blocks_ = [];
84
85  /**
86   * Total number of bytes in the blocks_ array. Does _not_ include bytes in
87   * the encoder below.
88   * @private {number}
89   */
90  this.totalLength_ = 0;
91
92  /**
93   * Binary encoder holding pieces of a message that we're still serializing.
94   * When we get to a stopping point (either the start of a new submessage, or
95   * when we need to append a raw Uint8Array), the encoder's buffer will be
96   * added to the block array above and the encoder will be reset.
97   * @private {!jspb.BinaryEncoder}
98   */
99  this.encoder_ = new jspb.BinaryEncoder();
100
101  /**
102   * A stack of bookmarks containing the parent blocks for each message started
103   * via beginSubMessage(), needed as bookkeeping for endSubMessage().
104   * TODO(aappleby): Deprecated, users should be calling writeMessage().
105   * @private {!Array.<!Array.<number>>}
106   */
107  this.bookmarks_ = [];
108};
109
110
111/**
112 * Append a typed array of bytes onto the buffer.
113 *
114 * @param {!Uint8Array} arr The byte array to append.
115 * @private
116 */
117jspb.BinaryWriter.prototype.appendUint8Array_ = function(arr) {
118  var temp = this.encoder_.end();
119  this.blocks_.push(temp);
120  this.blocks_.push(arr);
121  this.totalLength_ += temp.length + arr.length;
122};
123
124
125/**
126 * Begins a new message by writing the field header and returning a bookmark
127 * which we will use to patch in the message length to in endDelimited_ below.
128 * @param {number} field
129 * @return {!Array.<number>}
130 * @private
131 */
132jspb.BinaryWriter.prototype.beginDelimited_ = function(field) {
133  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED);
134  var bookmark = this.encoder_.end();
135  this.blocks_.push(bookmark);
136  this.totalLength_ += bookmark.length;
137  bookmark.push(this.totalLength_);
138  return bookmark;
139};
140
141
142/**
143 * Ends a message by encoding the _change_ in length of the buffer to the
144 * parent block and adds the number of bytes needed to encode that length to
145 * the total byte length.
146 * @param {!Array.<number>} bookmark
147 * @private
148 */
149jspb.BinaryWriter.prototype.endDelimited_ = function(bookmark) {
150  var oldLength = bookmark.pop();
151  var messageLength = this.totalLength_ + this.encoder_.length() - oldLength;
152  goog.asserts.assert(messageLength >= 0);
153
154  while (messageLength > 127) {
155    bookmark.push((messageLength & 0x7f) | 0x80);
156    messageLength = messageLength >>> 7;
157    this.totalLength_++;
158  }
159
160  bookmark.push(messageLength);
161  this.totalLength_++;
162};
163
164
165/**
166 * Writes a pre-serialized message to the buffer.
167 * @param {!Uint8Array} bytes The array of bytes to write.
168 * @param {number} start The start of the range to write.
169 * @param {number} end The end of the range to write.
170 */
171jspb.BinaryWriter.prototype.writeSerializedMessage = function(
172    bytes, start, end) {
173  this.appendUint8Array_(bytes.subarray(start, end));
174};
175
176
177/**
178 * Writes a pre-serialized message to the buffer if the message and endpoints
179 * are non-null.
180 * @param {?Uint8Array} bytes The array of bytes to write.
181 * @param {?number} start The start of the range to write.
182 * @param {?number} end The end of the range to write.
183 */
184jspb.BinaryWriter.prototype.maybeWriteSerializedMessage = function(
185    bytes, start, end) {
186  if (bytes != null && start != null && end != null) {
187    this.writeSerializedMessage(bytes, start, end);
188  }
189};
190
191
192/**
193 * Resets the writer, throwing away any accumulated buffers.
194 */
195jspb.BinaryWriter.prototype.reset = function() {
196  this.blocks_ = [];
197  this.encoder_.end();
198  this.totalLength_ = 0;
199  this.bookmarks_ = [];
200};
201
202
203/**
204 * Converts the encoded data into a Uint8Array.
205 * @return {!Uint8Array}
206 */
207jspb.BinaryWriter.prototype.getResultBuffer = function() {
208  goog.asserts.assert(this.bookmarks_.length == 0);
209
210  var flat = new Uint8Array(this.totalLength_ + this.encoder_.length());
211
212  var blocks = this.blocks_;
213  var blockCount = blocks.length;
214  var offset = 0;
215
216  for (var i = 0; i < blockCount; i++) {
217    var block = blocks[i];
218    flat.set(block, offset);
219    offset += block.length;
220  }
221
222  var tail = this.encoder_.end();
223  flat.set(tail, offset);
224  offset += tail.length;
225
226  // Post condition: `flattened` must have had every byte written.
227  goog.asserts.assert(offset == flat.length);
228
229  // Replace our block list with the flattened block, which lets GC reclaim
230  // the temp blocks sooner.
231  this.blocks_ = [flat];
232
233  return flat;
234};
235
236
237/**
238 * Converts the encoded data into a bas64-encoded string.
239 * @return {string}
240 */
241jspb.BinaryWriter.prototype.getResultBase64String = function() {
242  return goog.crypt.base64.encodeByteArray(this.getResultBuffer());
243};
244
245
246/**
247 * Begins a new sub-message. The client must call endSubMessage() when they're
248 * done.
249 * TODO(aappleby): Deprecated. Move callers to writeMessage().
250 * @param {number} field The field number of the sub-message.
251 */
252jspb.BinaryWriter.prototype.beginSubMessage = function(field) {
253  this.bookmarks_.push(this.beginDelimited_(field));
254};
255
256
257/**
258 * Finishes a sub-message and packs it into the parent messages' buffer.
259 * TODO(aappleby): Deprecated. Move callers to writeMessage().
260 */
261jspb.BinaryWriter.prototype.endSubMessage = function() {
262  goog.asserts.assert(this.bookmarks_.length >= 0);
263  this.endDelimited_(this.bookmarks_.pop());
264};
265
266
267/**
268 * Encodes a (field number, wire type) tuple into a wire-format field header
269 * and stores it in the buffer as a varint.
270 * @param {number} field The field number.
271 * @param {number} wireType The wire-type of the field, as specified in the
272 *     protocol buffer documentation.
273 * @private
274 */
275jspb.BinaryWriter.prototype.writeFieldHeader_ =
276    function(field, wireType) {
277  goog.asserts.assert(field >= 1 && field == Math.floor(field));
278  var x = field * 8 + wireType;
279  this.encoder_.writeUnsignedVarint32(x);
280};
281
282
283/**
284 * Writes a field of any valid scalar type to the binary stream.
285 * @param {jspb.BinaryConstants.FieldType} fieldType
286 * @param {number} field
287 * @param {jspb.AnyFieldType} value
288 */
289jspb.BinaryWriter.prototype.writeAny = function(fieldType, field, value) {
290  var fieldTypes = jspb.BinaryConstants.FieldType;
291  switch (fieldType) {
292    case fieldTypes.DOUBLE:
293      this.writeDouble(field, /** @type {number} */(value));
294      return;
295    case fieldTypes.FLOAT:
296      this.writeFloat(field, /** @type {number} */(value));
297      return;
298    case fieldTypes.INT64:
299      this.writeInt64(field, /** @type {number} */(value));
300      return;
301    case fieldTypes.UINT64:
302      this.writeUint64(field, /** @type {number} */(value));
303      return;
304    case fieldTypes.INT32:
305      this.writeInt32(field, /** @type {number} */(value));
306      return;
307    case fieldTypes.FIXED64:
308      this.writeFixed64(field, /** @type {number} */(value));
309      return;
310    case fieldTypes.FIXED32:
311      this.writeFixed32(field, /** @type {number} */(value));
312      return;
313    case fieldTypes.BOOL:
314      this.writeBool(field, /** @type {boolean} */(value));
315      return;
316    case fieldTypes.STRING:
317      this.writeString(field, /** @type {string} */(value));
318      return;
319    case fieldTypes.GROUP:
320      goog.asserts.fail('Group field type not supported in writeAny()');
321      return;
322    case fieldTypes.MESSAGE:
323      goog.asserts.fail('Message field type not supported in writeAny()');
324      return;
325    case fieldTypes.BYTES:
326      this.writeBytes(field, /** @type {?Uint8Array} */(value));
327      return;
328    case fieldTypes.UINT32:
329      this.writeUint32(field, /** @type {number} */(value));
330      return;
331    case fieldTypes.ENUM:
332      this.writeEnum(field, /** @type {number} */(value));
333      return;
334    case fieldTypes.SFIXED32:
335      this.writeSfixed32(field, /** @type {number} */(value));
336      return;
337    case fieldTypes.SFIXED64:
338      this.writeSfixed64(field, /** @type {number} */(value));
339      return;
340    case fieldTypes.SINT32:
341      this.writeSint32(field, /** @type {number} */(value));
342      return;
343    case fieldTypes.SINT64:
344      this.writeSint64(field, /** @type {number} */(value));
345      return;
346    case fieldTypes.FHASH64:
347      this.writeFixedHash64(field, /** @type {string} */(value));
348      return;
349    case fieldTypes.VHASH64:
350      this.writeVarintHash64(field, /** @type {string} */(value));
351      return;
352    default:
353      goog.asserts.fail('Invalid field type in writeAny()');
354      return;
355  }
356};
357
358
359/**
360 * Writes a varint field to the buffer without range checking.
361 * @param {number} field The field number.
362 * @param {number?} value The value to write.
363 * @private
364 */
365jspb.BinaryWriter.prototype.writeUnsignedVarint32_ = function(field, value) {
366  if (value == null) return;
367  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT);
368  this.encoder_.writeUnsignedVarint32(value);
369};
370
371
372/**
373 * Writes a varint field to the buffer without range checking.
374 * @param {number} field The field number.
375 * @param {number?} value The value to write.
376 * @private
377 */
378jspb.BinaryWriter.prototype.writeSignedVarint32_ = function(field, value) {
379  if (value == null) return;
380  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT);
381  this.encoder_.writeSignedVarint32(value);
382};
383
384
385/**
386 * Writes a varint field to the buffer without range checking.
387 * @param {number} field The field number.
388 * @param {number?} value The value to write.
389 * @private
390 */
391jspb.BinaryWriter.prototype.writeUnsignedVarint64_ = function(field, value) {
392  if (value == null) return;
393  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT);
394  this.encoder_.writeUnsignedVarint64(value);
395};
396
397
398/**
399 * Writes a varint field to the buffer without range checking.
400 * @param {number} field The field number.
401 * @param {number?} value The value to write.
402 * @private
403 */
404jspb.BinaryWriter.prototype.writeSignedVarint64_ = function(field, value) {
405  if (value == null) return;
406  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT);
407  this.encoder_.writeSignedVarint64(value);
408};
409
410
411/**
412 * Writes a zigzag varint field to the buffer without range checking.
413 * @param {number} field The field number.
414 * @param {number?} value The value to write.
415 * @private
416 */
417jspb.BinaryWriter.prototype.writeZigzagVarint32_ = function(field, value) {
418  if (value == null) return;
419  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT);
420  this.encoder_.writeZigzagVarint32(value);
421};
422
423
424/**
425 * Writes a zigzag varint field to the buffer without range checking.
426 * @param {number} field The field number.
427 * @param {number?} value The value to write.
428 * @private
429 */
430jspb.BinaryWriter.prototype.writeZigzagVarint64_ = function(field, value) {
431  if (value == null) return;
432  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT);
433  this.encoder_.writeZigzagVarint64(value);
434};
435
436
437/**
438 * Writes an int32 field to the buffer. Numbers outside the range [-2^31,2^31)
439 * will be truncated.
440 * @param {number} field The field number.
441 * @param {number?} value The value to write.
442 */
443jspb.BinaryWriter.prototype.writeInt32 = function(field, value) {
444  if (value == null) return;
445  goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) &&
446                      (value < jspb.BinaryConstants.TWO_TO_31));
447  this.writeSignedVarint32_(field, value);
448};
449
450
451/**
452 * Writes an int32 field represented as a string to the buffer. Numbers outside
453 * the range [-2^31,2^31) will be truncated.
454 * @param {number} field The field number.
455 * @param {string?} value The value to write.
456 */
457jspb.BinaryWriter.prototype.writeInt32String = function(field, value) {
458  if (value == null) return;
459  var intValue = /** {number} */ parseInt(value, 10);
460  goog.asserts.assert((intValue >= -jspb.BinaryConstants.TWO_TO_31) &&
461                      (intValue < jspb.BinaryConstants.TWO_TO_31));
462  this.writeSignedVarint32_(field, intValue);
463};
464
465
466/**
467 * Writes an int64 field to the buffer. Numbers outside the range [-2^63,2^63)
468 * will be truncated.
469 * @param {number} field The field number.
470 * @param {number?} value The value to write.
471 */
472jspb.BinaryWriter.prototype.writeInt64 = function(field, value) {
473  if (value == null) return;
474  goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_63) &&
475                      (value < jspb.BinaryConstants.TWO_TO_63));
476  this.writeSignedVarint64_(field, value);
477};
478
479
480/**
481 * Writes a int64 field (with value as a string) to the buffer.
482 * @param {number} field The field number.
483 * @param {string?} value The value to write.
484 */
485jspb.BinaryWriter.prototype.writeInt64String = function(field, value) {
486  if (value == null) return;
487  var num = jspb.arith.Int64.fromString(value);
488  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT);
489  this.encoder_.writeSplitVarint64(num.lo, num.hi);
490};
491
492
493/**
494 * Writes a uint32 field to the buffer. Numbers outside the range [0,2^32)
495 * will be truncated.
496 * @param {number} field The field number.
497 * @param {number?} value The value to write.
498 */
499jspb.BinaryWriter.prototype.writeUint32 = function(field, value) {
500  if (value == null) return;
501  goog.asserts.assert((value >= 0) &&
502                      (value < jspb.BinaryConstants.TWO_TO_32));
503  this.writeUnsignedVarint32_(field, value);
504};
505
506
507/**
508 * Writes a uint32 field represented as a string to the buffer. Numbers outside
509 * the range [0,2^32) will be truncated.
510 * @param {number} field The field number.
511 * @param {string?} value The value to write.
512 */
513jspb.BinaryWriter.prototype.writeUint32String = function(field, value) {
514  if (value == null) return;
515  var intValue = /** {number} */ parseInt(value, 10);
516  goog.asserts.assert((intValue >= 0) &&
517                      (intValue < jspb.BinaryConstants.TWO_TO_32));
518  this.writeUnsignedVarint32_(field, intValue);
519};
520
521
522/**
523 * Writes a uint64 field to the buffer. Numbers outside the range [0,2^64)
524 * will be truncated.
525 * @param {number} field The field number.
526 * @param {number?} value The value to write.
527 */
528jspb.BinaryWriter.prototype.writeUint64 = function(field, value) {
529  if (value == null) return;
530  goog.asserts.assert((value >= 0) &&
531                      (value < jspb.BinaryConstants.TWO_TO_64));
532  this.writeUnsignedVarint64_(field, value);
533};
534
535
536/**
537 * Writes a uint64 field (with value as a string) to the buffer.
538 * @param {number} field The field number.
539 * @param {string?} value The value to write.
540 */
541jspb.BinaryWriter.prototype.writeUint64String = function(field, value) {
542  if (value == null) return;
543  var num = jspb.arith.UInt64.fromString(value);
544  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT);
545  this.encoder_.writeSplitVarint64(num.lo, num.hi);
546};
547
548
549/**
550 * Writes a sint32 field to the buffer. Numbers outside the range [-2^31,2^31)
551 * will be truncated.
552 * @param {number} field The field number.
553 * @param {number?} value The value to write.
554 */
555jspb.BinaryWriter.prototype.writeSint32 = function(field, value) {
556  if (value == null) return;
557  goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) &&
558                      (value < jspb.BinaryConstants.TWO_TO_31));
559  this.writeZigzagVarint32_(field, value);
560};
561
562
563/**
564 * Writes a sint64 field to the buffer. Numbers outside the range [-2^63,2^63)
565 * will be truncated.
566 * @param {number} field The field number.
567 * @param {number?} value The value to write.
568 */
569jspb.BinaryWriter.prototype.writeSint64 = function(field, value) {
570  if (value == null) return;
571  goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_63) &&
572                      (value < jspb.BinaryConstants.TWO_TO_63));
573  this.writeZigzagVarint64_(field, value);
574};
575
576
577/**
578 * Writes a fixed32 field to the buffer. Numbers outside the range [0,2^32)
579 * will be truncated.
580 * @param {number} field The field number.
581 * @param {number?} value The value to write.
582 */
583jspb.BinaryWriter.prototype.writeFixed32 = function(field, value) {
584  if (value == null) return;
585  goog.asserts.assert((value >= 0) &&
586                      (value < jspb.BinaryConstants.TWO_TO_32));
587  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED32);
588  this.encoder_.writeUint32(value);
589};
590
591
592/**
593 * Writes a fixed64 field to the buffer. Numbers outside the range [0,2^64)
594 * will be truncated.
595 * @param {number} field The field number.
596 * @param {number?} value The value to write.
597 */
598jspb.BinaryWriter.prototype.writeFixed64 = function(field, value) {
599  if (value == null) return;
600  goog.asserts.assert((value >= 0) &&
601                      (value < jspb.BinaryConstants.TWO_TO_64));
602  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64);
603  this.encoder_.writeUint64(value);
604};
605
606
607/**
608 * Writes a sfixed32 field to the buffer. Numbers outside the range
609 * [-2^31,2^31) will be truncated.
610 * @param {number} field The field number.
611 * @param {number?} value The value to write.
612 */
613jspb.BinaryWriter.prototype.writeSfixed32 = function(field, value) {
614  if (value == null) return;
615  goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) &&
616                      (value < jspb.BinaryConstants.TWO_TO_31));
617  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED32);
618  this.encoder_.writeInt32(value);
619};
620
621
622/**
623 * Writes a sfixed64 field to the buffer. Numbers outside the range
624 * [-2^63,2^63) will be truncated.
625 * @param {number} field The field number.
626 * @param {number?} value The value to write.
627 */
628jspb.BinaryWriter.prototype.writeSfixed64 = function(field, value) {
629  if (value == null) return;
630  goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_63) &&
631                      (value < jspb.BinaryConstants.TWO_TO_63));
632  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64);
633  this.encoder_.writeInt64(value);
634};
635
636
637/**
638 * Writes a single-precision floating point field to the buffer. Numbers
639 * requiring more than 32 bits of precision will be truncated.
640 * @param {number} field The field number.
641 * @param {number?} value The value to write.
642 */
643jspb.BinaryWriter.prototype.writeFloat = function(field, value) {
644  if (value == null) return;
645  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED32);
646  this.encoder_.writeFloat(value);
647};
648
649
650/**
651 * Writes a double-precision floating point field to the buffer. As this is the
652 * native format used by JavaScript, no precision will be lost.
653 * @param {number} field The field number.
654 * @param {number?} value The value to write.
655 */
656jspb.BinaryWriter.prototype.writeDouble = function(field, value) {
657  if (value == null) return;
658  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64);
659  this.encoder_.writeDouble(value);
660};
661
662
663/**
664 * Writes a boolean field to the buffer.
665 * @param {number} field The field number.
666 * @param {boolean?} value The value to write.
667 */
668jspb.BinaryWriter.prototype.writeBool = function(field, value) {
669  if (value == null) return;
670  goog.asserts.assert(goog.isBoolean(value));
671  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT);
672  this.encoder_.writeBool(value);
673};
674
675
676/**
677 * Writes an enum field to the buffer.
678 * @param {number} field The field number.
679 * @param {number?} value The value to write.
680 */
681jspb.BinaryWriter.prototype.writeEnum = function(field, value) {
682  if (value == null) return;
683  goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) &&
684                      (value < jspb.BinaryConstants.TWO_TO_31));
685  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT);
686  this.encoder_.writeSignedVarint32(value);
687};
688
689
690/**
691 * Writes a string field to the buffer.
692 * @param {number} field The field number.
693 * @param {string?} value The string to write.
694 */
695jspb.BinaryWriter.prototype.writeString = function(field, value) {
696  if (value == null) return;
697  var bookmark = this.beginDelimited_(field);
698  this.encoder_.writeString(value);
699  this.endDelimited_(bookmark);
700};
701
702
703/**
704 * Writes an arbitrary byte field to the buffer. Note - to match the behavior
705 * of the C++ implementation, empty byte arrays _are_ serialized.
706 * @param {number} field The field number.
707 * @param {?jspb.ByteSource} value The array of bytes to write.
708 */
709jspb.BinaryWriter.prototype.writeBytes = function(field, value) {
710  if (value == null) return;
711  var bytes = jspb.utils.byteSourceToUint8Array(value);
712  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED);
713  this.encoder_.writeUnsignedVarint32(bytes.length);
714  this.appendUint8Array_(bytes);
715};
716
717
718/**
719 * Writes a message to the buffer.
720 * @template MessageType
721 * @param {number} field The field number.
722 * @param {?MessageType} value The message to write.
723 * @param {!jspb.WriterFunction} writerCallback Will be invoked with the value
724 *     to write and the writer to write it with.
725 */
726jspb.BinaryWriter.prototype.writeMessage = function(
727    field, value, writerCallback) {
728  if (value == null) return;
729  var bookmark = this.beginDelimited_(field);
730  writerCallback(value, this);
731  this.endDelimited_(bookmark);
732};
733
734
735/**
736 * Writes a group message to the buffer.
737 *
738 * @template MessageType
739 * @param {number} field The field number.
740 * @param {?MessageType} value The message to write, wrapped with START_GROUP /
741 *     END_GROUP tags. Will be a no-op if 'value' is null.
742 * @param {!jspb.WriterFunction} writerCallback Will be invoked with the value
743 *     to write and the writer to write it with.
744 */
745jspb.BinaryWriter.prototype.writeGroup = function(
746    field, value, writerCallback) {
747  if (value == null) return;
748  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.START_GROUP);
749  writerCallback(value, this);
750  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.END_GROUP);
751};
752
753
754/**
755 * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to
756 * the buffer.
757 * @param {number} field The field number.
758 * @param {string?} value The hash string.
759 */
760jspb.BinaryWriter.prototype.writeFixedHash64 = function(field, value) {
761  if (value == null) return;
762  goog.asserts.assert(value.length == 8);
763  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64);
764  this.encoder_.writeFixedHash64(value);
765};
766
767
768/**
769 * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to
770 * the buffer.
771 * @param {number} field The field number.
772 * @param {string?} value The hash string.
773 */
774jspb.BinaryWriter.prototype.writeVarintHash64 = function(field, value) {
775  if (value == null) return;
776  goog.asserts.assert(value.length == 8);
777  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT);
778  this.encoder_.writeVarintHash64(value);
779};
780
781
782/**
783 * Writes an array of numbers to the buffer as a repeated varint field.
784 * @param {number} field The field number.
785 * @param {?Array.<number>} value The array of ints to write.
786 * @private
787 */
788jspb.BinaryWriter.prototype.writeRepeatedUnsignedVarint32_ =
789    function(field, value) {
790  if (value == null) return;
791  for (var i = 0; i < value.length; i++) {
792    this.writeUnsignedVarint32_(field, value[i]);
793  }
794};
795
796
797/**
798 * Writes an array of numbers to the buffer as a repeated varint field.
799 * @param {number} field The field number.
800 * @param {?Array.<number>} value The array of ints to write.
801 * @private
802 */
803jspb.BinaryWriter.prototype.writeRepeatedSignedVarint32_ =
804    function(field, value) {
805  if (value == null) return;
806  for (var i = 0; i < value.length; i++) {
807    this.writeSignedVarint32_(field, value[i]);
808  }
809};
810
811
812/**
813 * Writes an array of numbers to the buffer as a repeated varint field.
814 * @param {number} field The field number.
815 * @param {?Array.<number>} value The array of ints to write.
816 * @private
817 */
818jspb.BinaryWriter.prototype.writeRepeatedUnsignedVarint64_ =
819    function(field, value) {
820  if (value == null) return;
821  for (var i = 0; i < value.length; i++) {
822    this.writeUnsignedVarint64_(field, value[i]);
823  }
824};
825
826
827/**
828 * Writes an array of numbers to the buffer as a repeated varint field.
829 * @param {number} field The field number.
830 * @param {?Array.<number>} value The array of ints to write.
831 * @private
832 */
833jspb.BinaryWriter.prototype.writeRepeatedSignedVarint64_ =
834    function(field, value) {
835  if (value == null) return;
836  for (var i = 0; i < value.length; i++) {
837    this.writeSignedVarint64_(field, value[i]);
838  }
839};
840
841
842/**
843 * Writes an array of numbers to the buffer as a repeated zigzag field.
844 * @param {number} field The field number.
845 * @param {?Array.<number>} value The array of ints to write.
846 * @private
847 */
848jspb.BinaryWriter.prototype.writeRepeatedZigzag32_ = function(field, value) {
849  if (value == null) return;
850  for (var i = 0; i < value.length; i++) {
851    this.writeZigzagVarint32_(field, value[i]);
852  }
853};
854
855
856/**
857 * Writes an array of numbers to the buffer as a repeated zigzag field.
858 * @param {number} field The field number.
859 * @param {?Array.<number>} value The array of ints to write.
860 * @private
861 */
862jspb.BinaryWriter.prototype.writeRepeatedZigzag_ = function(field, value) {
863  if (value == null) return;
864  for (var i = 0; i < value.length; i++) {
865    this.writeZigzagVarint64_(field, value[i]);
866  }
867};
868
869
870/**
871 * Writes an array of numbers to the buffer as a repeated 32-bit int field.
872 * @param {number} field The field number.
873 * @param {?Array.<number>} value The array of ints to write.
874 */
875jspb.BinaryWriter.prototype.writeRepeatedInt32 =
876    jspb.BinaryWriter.prototype.writeRepeatedSignedVarint32_;
877
878
879/**
880 * Writes an array of numbers formatted as strings to the buffer as a repeated
881 * 32-bit int field.
882 * @param {number} field The field number.
883 * @param {?Array.<string>} value The array of ints to write.
884 */
885jspb.BinaryWriter.prototype.writeRepeatedInt32String =
886    function(field, value) {
887  if (value == null) return;
888  for (var i = 0; i < value.length; i++) {
889    this.writeInt32String(field, value[i]);
890  }
891};
892
893
894/**
895 * Writes an array of numbers to the buffer as a repeated 64-bit int field.
896 * @param {number} field The field number.
897 * @param {?Array.<number>} value The array of ints to write.
898 */
899jspb.BinaryWriter.prototype.writeRepeatedInt64 =
900    jspb.BinaryWriter.prototype.writeRepeatedSignedVarint64_;
901
902
903/**
904 * Writes an array of numbers formatted as strings to the buffer as a repeated
905 * 64-bit int field.
906 * @param {number} field The field number.
907 * @param {?Array.<string>} value The array of ints to write.
908 */
909jspb.BinaryWriter.prototype.writeRepeatedInt64String =
910    function(field, value) {
911  if (value == null) return;
912  for (var i = 0; i < value.length; i++) {
913    this.writeInt64String(field, value[i]);
914  }
915};
916
917
918/**
919 * Writes an array numbers to the buffer as a repeated unsigned 32-bit int
920 *     field.
921 * @param {number} field The field number.
922 * @param {?Array.<number>} value The array of ints to write.
923 */
924jspb.BinaryWriter.prototype.writeRepeatedUint32 =
925    jspb.BinaryWriter.prototype.writeRepeatedUnsignedVarint32_;
926
927
928/**
929 * Writes an array of numbers formatted as strings to the buffer as a repeated
930 * unsigned 32-bit int field.
931 * @param {number} field The field number.
932 * @param {?Array.<string>} value The array of ints to write.
933 */
934jspb.BinaryWriter.prototype.writeRepeatedUint32String =
935    function(field, value) {
936  if (value == null) return;
937  for (var i = 0; i < value.length; i++) {
938    this.writeUint32String(field, value[i]);
939  }
940};
941
942
943/**
944 * Writes an array numbers to the buffer as a repeated unsigned 64-bit int
945 *     field.
946 * @param {number} field The field number.
947 * @param {?Array.<number>} value The array of ints to write.
948 */
949jspb.BinaryWriter.prototype.writeRepeatedUint64 =
950    jspb.BinaryWriter.prototype.writeRepeatedUnsignedVarint64_;
951
952
953/**
954 * Writes an array of numbers formatted as strings to the buffer as a repeated
955 * unsigned 64-bit int field.
956 * @param {number} field The field number.
957 * @param {?Array.<string>} value The array of ints to write.
958 */
959jspb.BinaryWriter.prototype.writeRepeatedUint64String =
960    function(field, value) {
961  if (value == null) return;
962  for (var i = 0; i < value.length; i++) {
963    this.writeUint64String(field, value[i]);
964  }
965};
966
967
968/**
969 * Writes an array numbers to the buffer as a repeated signed 32-bit int field.
970 * @param {number} field The field number.
971 * @param {?Array.<number>} value The array of ints to write.
972 */
973jspb.BinaryWriter.prototype.writeRepeatedSint32 =
974    jspb.BinaryWriter.prototype.writeRepeatedZigzag32_;
975
976
977/**
978 * Writes an array numbers to the buffer as a repeated signed 64-bit int field.
979 * @param {number} field The field number.
980 * @param {?Array.<number>} value The array of ints to write.
981 */
982jspb.BinaryWriter.prototype.writeRepeatedSint64 =
983    jspb.BinaryWriter.prototype.writeRepeatedZigzag_;
984
985
986/**
987 * Writes an array of numbers to the buffer as a repeated fixed32 field. This
988 * works for both signed and unsigned fixed32s.
989 * @param {number} field The field number.
990 * @param {?Array.<number>} value The array of ints to write.
991 */
992jspb.BinaryWriter.prototype.writeRepeatedFixed32 = function(field, value) {
993  if (value == null) return;
994  for (var i = 0; i < value.length; i++) {
995    this.writeFixed32(field, value[i]);
996  }
997};
998
999
1000/**
1001 * Writes an array of numbers to the buffer as a repeated fixed64 field. This
1002 * works for both signed and unsigned fixed64s.
1003 * @param {number} field The field number.
1004 * @param {?Array.<number>} value The array of ints to write.
1005 */
1006jspb.BinaryWriter.prototype.writeRepeatedFixed64 = function(field, value) {
1007  if (value == null) return;
1008  for (var i = 0; i < value.length; i++) {
1009    this.writeFixed64(field, value[i]);
1010  }
1011};
1012
1013
1014/**
1015 * Writes an array of numbers to the buffer as a repeated sfixed32 field.
1016 * @param {number} field The field number.
1017 * @param {?Array.<number>} value The array of ints to write.
1018 */
1019jspb.BinaryWriter.prototype.writeRepeatedSfixed32 = function(field, value) {
1020  if (value == null) return;
1021  for (var i = 0; i < value.length; i++) {
1022    this.writeSfixed32(field, value[i]);
1023  }
1024};
1025
1026
1027/**
1028 * Writes an array of numbers to the buffer as a repeated sfixed64 field.
1029 * @param {number} field The field number.
1030 * @param {?Array.<number>} value The array of ints to write.
1031 */
1032jspb.BinaryWriter.prototype.writeRepeatedSfixed64 = function(field, value) {
1033  if (value == null) return;
1034  for (var i = 0; i < value.length; i++) {
1035    this.writeSfixed64(field, value[i]);
1036  }
1037};
1038
1039
1040/**
1041 * Writes an array of numbers to the buffer as a repeated float field.
1042 * @param {number} field The field number.
1043 * @param {?Array.<number>} value The array of ints to write.
1044 */
1045jspb.BinaryWriter.prototype.writeRepeatedFloat = function(field, value) {
1046  if (value == null) return;
1047  for (var i = 0; i < value.length; i++) {
1048    this.writeFloat(field, value[i]);
1049  }
1050};
1051
1052
1053/**
1054 * Writes an array of numbers to the buffer as a repeated double field.
1055 * @param {number} field The field number.
1056 * @param {?Array.<number>} value The array of ints to write.
1057 */
1058jspb.BinaryWriter.prototype.writeRepeatedDouble = function(field, value) {
1059  if (value == null) return;
1060  for (var i = 0; i < value.length; i++) {
1061    this.writeDouble(field, value[i]);
1062  }
1063};
1064
1065
1066/**
1067 * Writes an array of booleans to the buffer as a repeated bool field.
1068 * @param {number} field The field number.
1069 * @param {?Array.<boolean>} value The array of ints to write.
1070 */
1071jspb.BinaryWriter.prototype.writeRepeatedBool = function(field, value) {
1072  if (value == null) return;
1073  for (var i = 0; i < value.length; i++) {
1074    this.writeBool(field, value[i]);
1075  }
1076};
1077
1078
1079/**
1080 * Writes an array of enums to the buffer as a repeated enum field.
1081 * @param {number} field The field number.
1082 * @param {?Array.<number>} value The array of ints to write.
1083 */
1084jspb.BinaryWriter.prototype.writeRepeatedEnum = function(field, value) {
1085  if (value == null) return;
1086  for (var i = 0; i < value.length; i++) {
1087    this.writeEnum(field, value[i]);
1088  }
1089};
1090
1091
1092/**
1093 * Writes an array of strings to the buffer as a repeated string field.
1094 * @param {number} field The field number.
1095 * @param {?Array.<string>} value The array of strings to write.
1096 */
1097jspb.BinaryWriter.prototype.writeRepeatedString = function(field, value) {
1098  if (value == null) return;
1099  for (var i = 0; i < value.length; i++) {
1100    this.writeString(field, value[i]);
1101  }
1102};
1103
1104
1105/**
1106 * Writes an array of arbitrary byte fields to the buffer.
1107 * @param {number} field The field number.
1108 * @param {?Array.<!jspb.ByteSource>} value The arrays of arrays of bytes to
1109 *     write.
1110 */
1111jspb.BinaryWriter.prototype.writeRepeatedBytes = function(field, value) {
1112  if (value == null) return;
1113  for (var i = 0; i < value.length; i++) {
1114    this.writeBytes(field, value[i]);
1115  }
1116};
1117
1118
1119/**
1120 * Writes an array of messages to the buffer.
1121 * @template MessageType
1122 * @param {number} field The field number.
1123 * @param {?Array.<MessageType>} value The array of messages to
1124 *    write.
1125 * @param {!jspb.WriterFunction} writerCallback Will be invoked with the value
1126 *     to write and the writer to write it with.
1127 */
1128jspb.BinaryWriter.prototype.writeRepeatedMessage = function(
1129    field, value, writerCallback) {
1130  if (value == null) return;
1131  for (var i = 0; i < value.length; i++) {
1132    var bookmark = this.beginDelimited_(field);
1133    writerCallback(value[i], this);
1134    this.endDelimited_(bookmark);
1135  }
1136};
1137
1138
1139/**
1140 * Writes an array of group messages to the buffer.
1141 * @template MessageType
1142 * @param {number} field The field number.
1143 * @param {?Array.<MessageType>} value The array of messages to
1144 *    write.
1145 * @param {!jspb.WriterFunction} writerCallback Will be invoked with the value
1146 *     to write and the writer to write it with.
1147 */
1148jspb.BinaryWriter.prototype.writeRepeatedGroup = function(
1149    field, value, writerCallback) {
1150  if (value == null) return;
1151  for (var i = 0; i < value.length; i++) {
1152    this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.START_GROUP);
1153    writerCallback(value[i], this);
1154    this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.END_GROUP);
1155  }
1156};
1157
1158
1159/**
1160 * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to
1161 * the buffer.
1162 * @param {number} field The field number.
1163 * @param {?Array.<string>} value The array of hashes to write.
1164 */
1165jspb.BinaryWriter.prototype.writeRepeatedFixedHash64 =
1166    function(field, value) {
1167  if (value == null) return;
1168  for (var i = 0; i < value.length; i++) {
1169    this.writeFixedHash64(field, value[i]);
1170  }
1171};
1172
1173
1174/**
1175 * Writes a repeated 64-bit hash string field (8 characters @ 8 bits of data
1176 * each) to the buffer.
1177 * @param {number} field The field number.
1178 * @param {?Array.<string>} value The array of hashes to write.
1179 */
1180jspb.BinaryWriter.prototype.writeRepeatedVarintHash64 =
1181    function(field, value) {
1182  if (value == null) return;
1183  for (var i = 0; i < value.length; i++) {
1184    this.writeVarintHash64(field, value[i]);
1185  }
1186};
1187
1188
1189/**
1190 * Writes an array of numbers to the buffer as a packed varint field.
1191 * @param {number} field The field number.
1192 * @param {?Array.<number>} value The array of ints to write.
1193 * @private
1194 */
1195jspb.BinaryWriter.prototype.writePackedUnsignedVarint32_ = function(
1196    field, value) {
1197  if (value == null || !value.length) return;
1198  var bookmark = this.beginDelimited_(field);
1199  for (var i = 0; i < value.length; i++) {
1200    this.encoder_.writeUnsignedVarint32(value[i]);
1201  }
1202  this.endDelimited_(bookmark);
1203};
1204
1205
1206/**
1207 * Writes an array of numbers to the buffer as a packed varint field.
1208 * @param {number} field The field number.
1209 * @param {?Array.<number>} value The array of ints to write.
1210 * @private
1211 */
1212jspb.BinaryWriter.prototype.writePackedSignedVarint32_ = function(
1213    field, value) {
1214  if (value == null || !value.length) return;
1215  var bookmark = this.beginDelimited_(field);
1216  for (var i = 0; i < value.length; i++) {
1217    this.encoder_.writeSignedVarint32(value[i]);
1218  }
1219  this.endDelimited_(bookmark);
1220};
1221
1222
1223/**
1224 * Writes an array of numbers to the buffer as a packed varint field.
1225 * @param {number} field The field number.
1226 * @param {?Array.<number>} value The array of ints to write.
1227 * @private
1228 */
1229jspb.BinaryWriter.prototype.writePackedUnsignedVarint64_ = function(
1230    field, value) {
1231  if (value == null || !value.length) return;
1232  var bookmark = this.beginDelimited_(field);
1233  for (var i = 0; i < value.length; i++) {
1234    this.encoder_.writeUnsignedVarint64(value[i]);
1235  }
1236  this.endDelimited_(bookmark);
1237};
1238
1239
1240/**
1241 * Writes an array of numbers to the buffer as a packed varint field.
1242 * @param {number} field The field number.
1243 * @param {?Array.<number>} value The array of ints to write.
1244 * @private
1245 */
1246jspb.BinaryWriter.prototype.writePackedSignedVarint64_ = function(
1247    field, value) {
1248  if (value == null || !value.length) return;
1249  var bookmark = this.beginDelimited_(field);
1250  for (var i = 0; i < value.length; i++) {
1251    this.encoder_.writeSignedVarint64(value[i]);
1252  }
1253  this.endDelimited_(bookmark);
1254};
1255
1256
1257/**
1258 * Writes an array of numbers to the buffer as a packed zigzag field.
1259 * @param {number} field The field number.
1260 * @param {?Array.<number>} value The array of ints to write.
1261 * @private
1262 */
1263jspb.BinaryWriter.prototype.writePackedZigzag32_ = function(field, value) {
1264  if (value == null || !value.length) return;
1265  var bookmark = this.beginDelimited_(field);
1266  for (var i = 0; i < value.length; i++) {
1267    this.encoder_.writeZigzagVarint32(value[i]);
1268  }
1269  this.endDelimited_(bookmark);
1270};
1271
1272
1273/**
1274 * Writes an array of numbers to the buffer as a packed zigzag field.
1275 * @param {number} field The field number.
1276 * @param {?Array.<number>} value The array of ints to write.
1277 * @private
1278 */
1279jspb.BinaryWriter.prototype.writePackedZigzag64_ = function(field, value) {
1280  if (value == null || !value.length) return;
1281  var bookmark = this.beginDelimited_(field);
1282  for (var i = 0; i < value.length; i++) {
1283    this.encoder_.writeZigzagVarint64(value[i]);
1284  }
1285  this.endDelimited_(bookmark);
1286};
1287
1288
1289/**
1290 * Writes an array of numbers to the buffer as a packed 32-bit int field.
1291 * @param {number} field The field number.
1292 * @param {?Array.<number>} value The array of ints to write.
1293 */
1294jspb.BinaryWriter.prototype.writePackedInt32 =
1295    jspb.BinaryWriter.prototype.writePackedSignedVarint32_;
1296
1297
1298/**
1299 * Writes an array of numbers represented as strings to the buffer as a packed
1300 * 32-bit int field.
1301 * @param {number} field
1302 * @param {?Array.<string>} value
1303 */
1304jspb.BinaryWriter.prototype.writePackedInt32String = function(field, value) {
1305  if (value == null || !value.length) return;
1306  var bookmark = this.beginDelimited_(field);
1307  for (var i = 0; i < value.length; i++) {
1308    this.encoder_.writeSignedVarint32(parseInt(value[i], 10));
1309  }
1310  this.endDelimited_(bookmark);
1311};
1312
1313
1314/**
1315 * Writes an array of numbers to the buffer as a packed 64-bit int field.
1316 * @param {number} field The field number.
1317 * @param {?Array.<number>} value The array of ints to write.
1318 */
1319jspb.BinaryWriter.prototype.writePackedInt64 =
1320    jspb.BinaryWriter.prototype.writePackedSignedVarint64_;
1321
1322
1323/**
1324 * Writes an array of numbers represented as strings to the buffer as a packed
1325 * 64-bit int field.
1326 * @param {number} field
1327 * @param {?Array.<string>} value
1328 */
1329jspb.BinaryWriter.prototype.writePackedInt64String =
1330    function(field, value) {
1331  if (value == null || !value.length) return;
1332  var bookmark = this.beginDelimited_(field);
1333  for (var i = 0; i < value.length; i++) {
1334    var num = jspb.arith.Int64.fromString(value[i]);
1335    this.encoder_.writeSplitVarint64(num.lo, num.hi);
1336  }
1337  this.endDelimited_(bookmark);
1338};
1339
1340
1341/**
1342 * Writes an array numbers to the buffer as a packed unsigned 32-bit int field.
1343 * @param {number} field The field number.
1344 * @param {?Array.<number>} value The array of ints to write.
1345 */
1346jspb.BinaryWriter.prototype.writePackedUint32 =
1347    jspb.BinaryWriter.prototype.writePackedUnsignedVarint32_;
1348
1349
1350/**
1351 * Writes an array of numbers represented as strings to the buffer as a packed
1352 * unsigned 32-bit int field.
1353 * @param {number} field
1354 * @param {?Array.<string>} value
1355 */
1356jspb.BinaryWriter.prototype.writePackedUint32String =
1357    function(field, value) {
1358  if (value == null || !value.length) return;
1359  var bookmark = this.beginDelimited_(field);
1360  for (var i = 0; i < value.length; i++) {
1361    this.encoder_.writeUnsignedVarint32(parseInt(value[i], 10));
1362  }
1363  this.endDelimited_(bookmark);
1364};
1365
1366
1367/**
1368 * Writes an array numbers to the buffer as a packed unsigned 64-bit int field.
1369 * @param {number} field The field number.
1370 * @param {?Array.<number>} value The array of ints to write.
1371 */
1372jspb.BinaryWriter.prototype.writePackedUint64 =
1373    jspb.BinaryWriter.prototype.writePackedUnsignedVarint64_;
1374
1375
1376/**
1377 * Writes an array of numbers represented as strings to the buffer as a packed
1378 * unsigned 64-bit int field.
1379 * @param {number} field
1380 * @param {?Array.<string>} value
1381 */
1382jspb.BinaryWriter.prototype.writePackedUint64String =
1383    function(field, value) {
1384  if (value == null || !value.length) return;
1385  var bookmark = this.beginDelimited_(field);
1386  for (var i = 0; i < value.length; i++) {
1387    var num = jspb.arith.UInt64.fromString(value[i]);
1388    this.encoder_.writeSplitVarint64(num.lo, num.hi);
1389  }
1390  this.endDelimited_(bookmark);
1391};
1392
1393
1394/**
1395 * Writes an array numbers to the buffer as a packed signed 32-bit int field.
1396 * @param {number} field The field number.
1397 * @param {?Array.<number>} value The array of ints to write.
1398 */
1399jspb.BinaryWriter.prototype.writePackedSint32 =
1400    jspb.BinaryWriter.prototype.writePackedZigzag32_;
1401
1402
1403/**
1404 * Writes an array numbers to the buffer as a packed signed 64-bit int field.
1405 * @param {number} field The field number.
1406 * @param {?Array.<number>} value The array of ints to write.
1407 */
1408jspb.BinaryWriter.prototype.writePackedSint64 =
1409    jspb.BinaryWriter.prototype.writePackedZigzag64_;
1410
1411
1412/**
1413 * Writes an array of numbers to the buffer as a packed fixed32 field.
1414 * @param {number} field The field number.
1415 * @param {?Array.<number>} value The array of ints to write.
1416 */
1417jspb.BinaryWriter.prototype.writePackedFixed32 = function(field, value) {
1418  if (value == null || !value.length) return;
1419  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED);
1420  this.encoder_.writeUnsignedVarint32(value.length * 4);
1421  for (var i = 0; i < value.length; i++) {
1422    this.encoder_.writeUint32(value[i]);
1423  }
1424};
1425
1426
1427/**
1428 * Writes an array of numbers to the buffer as a packed fixed64 field.
1429 * @param {number} field The field number.
1430 * @param {?Array.<number>} value The array of ints to write.
1431 */
1432jspb.BinaryWriter.prototype.writePackedFixed64 = function(field, value) {
1433  if (value == null || !value.length) return;
1434  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED);
1435  this.encoder_.writeUnsignedVarint32(value.length * 8);
1436  for (var i = 0; i < value.length; i++) {
1437    this.encoder_.writeUint64(value[i]);
1438  }
1439};
1440
1441
1442/**
1443 * Writes an array of numbers to the buffer as a packed sfixed32 field.
1444 * @param {number} field The field number.
1445 * @param {?Array.<number>} value The array of ints to write.
1446 */
1447jspb.BinaryWriter.prototype.writePackedSfixed32 = function(field, value) {
1448  if (value == null || !value.length) return;
1449  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED);
1450  this.encoder_.writeUnsignedVarint32(value.length * 4);
1451  for (var i = 0; i < value.length; i++) {
1452    this.encoder_.writeInt32(value[i]);
1453  }
1454};
1455
1456
1457/**
1458 * Writes an array of numbers to the buffer as a packed sfixed64 field.
1459 * @param {number} field The field number.
1460 * @param {?Array.<number>} value The array of ints to write.
1461 */
1462jspb.BinaryWriter.prototype.writePackedSfixed64 = function(field, value) {
1463  if (value == null || !value.length) return;
1464  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED);
1465  this.encoder_.writeUnsignedVarint32(value.length * 8);
1466  for (var i = 0; i < value.length; i++) {
1467    this.encoder_.writeInt64(value[i]);
1468  }
1469};
1470
1471
1472/**
1473 * Writes an array of numbers to the buffer as a packed float field.
1474 * @param {number} field The field number.
1475 * @param {?Array.<number>} value The array of ints to write.
1476 */
1477jspb.BinaryWriter.prototype.writePackedFloat = function(field, value) {
1478  if (value == null || !value.length) return;
1479  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED);
1480  this.encoder_.writeUnsignedVarint32(value.length * 4);
1481  for (var i = 0; i < value.length; i++) {
1482    this.encoder_.writeFloat(value[i]);
1483  }
1484};
1485
1486
1487/**
1488 * Writes an array of numbers to the buffer as a packed double field.
1489 * @param {number} field The field number.
1490 * @param {?Array.<number>} value The array of ints to write.
1491 */
1492jspb.BinaryWriter.prototype.writePackedDouble = function(field, value) {
1493  if (value == null || !value.length) return;
1494  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED);
1495  this.encoder_.writeUnsignedVarint32(value.length * 8);
1496  for (var i = 0; i < value.length; i++) {
1497    this.encoder_.writeDouble(value[i]);
1498  }
1499};
1500
1501
1502/**
1503 * Writes an array of booleans to the buffer as a packed bool field.
1504 * @param {number} field The field number.
1505 * @param {?Array.<boolean>} value The array of ints to write.
1506 */
1507jspb.BinaryWriter.prototype.writePackedBool = function(field, value) {
1508  if (value == null || !value.length) return;
1509  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED);
1510  this.encoder_.writeUnsignedVarint32(value.length);
1511  for (var i = 0; i < value.length; i++) {
1512    this.encoder_.writeBool(value[i]);
1513  }
1514};
1515
1516
1517/**
1518 * Writes an array of enums to the buffer as a packed enum field.
1519 * @param {number} field The field number.
1520 * @param {?Array.<number>} value The array of ints to write.
1521 */
1522jspb.BinaryWriter.prototype.writePackedEnum = function(field, value) {
1523  if (value == null || !value.length) return;
1524  var bookmark = this.beginDelimited_(field);
1525  for (var i = 0; i < value.length; i++) {
1526    this.encoder_.writeEnum(value[i]);
1527  }
1528  this.endDelimited_(bookmark);
1529};
1530
1531
1532/**
1533 * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to
1534 * the buffer.
1535 * @param {number} field The field number.
1536 * @param {?Array.<string>} value The array of hashes to write.
1537 */
1538jspb.BinaryWriter.prototype.writePackedFixedHash64 = function(field, value) {
1539  if (value == null || !value.length) return;
1540  this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED);
1541  this.encoder_.writeUnsignedVarint32(value.length * 8);
1542  for (var i = 0; i < value.length; i++) {
1543    this.encoder_.writeFixedHash64(value[i]);
1544  }
1545};
1546
1547
1548/**
1549 * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to
1550 * the buffer.
1551 * @param {number} field The field number.
1552 * @param {?Array.<string>} value The array of hashes to write.
1553 */
1554jspb.BinaryWriter.prototype.writePackedVarintHash64 = function(field, value) {
1555  if (value == null || !value.length) return;
1556  var bookmark = this.beginDelimited_(field);
1557  for (var i = 0; i < value.length; i++) {
1558    this.encoder_.writeVarintHash64(value[i]);
1559  }
1560  this.endDelimited_(bookmark);
1561};
1562