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 converting binary,
33 * wire-format protocol buffers into Javascript data structures.
34 *
35 * jspb's BinaryReader class wraps the BinaryDecoder class to add methods
36 * that understand the protocol buffer syntax and can do the type checking and
37 * bookkeeping necessary to parse trees of nested messages.
38 *
39 * Major caveat - Users of this library _must_ keep their Javascript proto
40 * parsing code in sync with the original .proto file - presumably you'll be
41 * using the typed jspb code generator, but if you bypass that you'll need
42 * to keep things in sync by hand.
43 *
44 * @author aappleby@google.com (Austin Appleby)
45 */
46
47goog.provide('jspb.BinaryReader');
48
49goog.require('goog.asserts');
50goog.require('jspb.BinaryConstants');
51goog.require('jspb.BinaryDecoder');
52
53
54
55/**
56 * BinaryReader implements the decoders for all the wire types specified in
57 * https://developers.google.com/protocol-buffers/docs/encoding.
58 *
59 * @param {jspb.ByteSource=} opt_bytes The bytes we're reading from.
60 * @param {number=} opt_start The optional offset to start reading at.
61 * @param {number=} opt_length The optional length of the block to read -
62 *     we'll throw an assertion if we go off the end of the block.
63 * @constructor
64 * @struct
65 */
66jspb.BinaryReader = function(opt_bytes, opt_start, opt_length) {
67  /**
68   * Wire-format decoder.
69   * @private {!jspb.BinaryDecoder}
70   */
71  this.decoder_ = jspb.BinaryDecoder.alloc(opt_bytes, opt_start, opt_length);
72
73  /**
74   * Cursor immediately before the field tag.
75   * @private {number}
76   */
77  this.fieldCursor_ = this.decoder_.getCursor();
78
79  /**
80   * Field number of the next field in the buffer, filled in by nextField().
81   * @private {number}
82   */
83  this.nextField_ = jspb.BinaryConstants.INVALID_FIELD_NUMBER;
84
85  /**
86   * Wire type of the next proto field in the buffer, filled in by
87   * nextField().
88   * @private {jspb.BinaryConstants.WireType}
89   */
90  this.nextWireType_ = jspb.BinaryConstants.WireType.INVALID;
91
92  /**
93   * Set to true if this reader encountered an error due to corrupt data.
94   * @private {boolean}
95   */
96  this.error_ = false;
97
98  /**
99   * User-defined reader callbacks.
100   * @private {?Object<string, function(!jspb.BinaryReader):*>}
101   */
102  this.readCallbacks_ = null;
103};
104
105
106/**
107 * Global pool of BinaryReader instances.
108 * @private {!Array<!jspb.BinaryReader>}
109 */
110jspb.BinaryReader.instanceCache_ = [];
111
112
113/**
114 * Pops an instance off the instance cache, or creates one if the cache is
115 * empty.
116 * @param {jspb.ByteSource=} opt_bytes The bytes we're reading from.
117 * @param {number=} opt_start The optional offset to start reading at.
118 * @param {number=} opt_length The optional length of the block to read -
119 *     we'll throw an assertion if we go off the end of the block.
120 * @return {!jspb.BinaryReader}
121 */
122jspb.BinaryReader.alloc =
123    function(opt_bytes, opt_start, opt_length) {
124  if (jspb.BinaryReader.instanceCache_.length) {
125    var newReader = jspb.BinaryReader.instanceCache_.pop();
126    if (opt_bytes) {
127      newReader.decoder_.setBlock(opt_bytes, opt_start, opt_length);
128    }
129    return newReader;
130  } else {
131    return new jspb.BinaryReader(opt_bytes, opt_start, opt_length);
132  }
133};
134
135
136/**
137 * Alias for the above method.
138 * @param {jspb.ByteSource=} opt_bytes The bytes we're reading from.
139 * @param {number=} opt_start The optional offset to start reading at.
140 * @param {number=} opt_length The optional length of the block to read -
141 *     we'll throw an assertion if we go off the end of the block.
142 * @return {!jspb.BinaryReader}
143 */
144jspb.BinaryReader.prototype.alloc = jspb.BinaryReader.alloc;
145
146
147/**
148 * Puts this instance back in the instance cache.
149 */
150jspb.BinaryReader.prototype.free = function() {
151  this.decoder_.clear();
152  this.nextField_ = jspb.BinaryConstants.INVALID_FIELD_NUMBER;
153  this.nextWireType_ = jspb.BinaryConstants.WireType.INVALID;
154  this.error_ = false;
155  this.readCallbacks_ = null;
156
157  if (jspb.BinaryReader.instanceCache_.length < 100) {
158    jspb.BinaryReader.instanceCache_.push(this);
159  }
160};
161
162
163/**
164 * Returns the cursor immediately before the current field's tag.
165 * @return {number} The internal read cursor.
166 */
167jspb.BinaryReader.prototype.getFieldCursor = function() {
168  return this.fieldCursor_;
169};
170
171
172/**
173 * Returns the internal read cursor.
174 * @return {number} The internal read cursor.
175 */
176jspb.BinaryReader.prototype.getCursor = function() {
177  return this.decoder_.getCursor();
178};
179
180
181/**
182 * Returns the raw buffer.
183 * @return {?Uint8Array} The raw buffer.
184 */
185jspb.BinaryReader.prototype.getBuffer = function() {
186  return this.decoder_.getBuffer();
187};
188
189
190/**
191 * @return {number} The field number of the next field in the buffer, or
192 *     INVALID_FIELD_NUMBER if there is no next field.
193 */
194jspb.BinaryReader.prototype.getFieldNumber = function() {
195  return this.nextField_;
196};
197
198
199/**
200 * @return {jspb.BinaryConstants.WireType} The wire type of the next field
201 *     in the stream, or WireType.INVALID if there is no next field.
202 */
203jspb.BinaryReader.prototype.getWireType = function() {
204  return this.nextWireType_;
205};
206
207
208/**
209 * @return {boolean} Whether the current wire type is an end-group tag. Used as
210 * an exit condition in decoder loops in generated code.
211 */
212jspb.BinaryReader.prototype.isEndGroup = function() {
213  return this.nextWireType_ == jspb.BinaryConstants.WireType.END_GROUP;
214};
215
216
217/**
218 * Returns true if this reader hit an error due to corrupt data.
219 * @return {boolean}
220 */
221jspb.BinaryReader.prototype.getError = function() {
222  return this.error_ || this.decoder_.getError();
223};
224
225
226/**
227 * Points this reader at a new block of bytes.
228 * @param {!Uint8Array} bytes The block of bytes we're reading from.
229 * @param {number} start The offset to start reading at.
230 * @param {number} length The length of the block to read.
231 */
232jspb.BinaryReader.prototype.setBlock = function(bytes, start, length) {
233  this.decoder_.setBlock(bytes, start, length);
234  this.nextField_ = jspb.BinaryConstants.INVALID_FIELD_NUMBER;
235  this.nextWireType_ = jspb.BinaryConstants.WireType.INVALID;
236};
237
238
239/**
240 * Rewinds the stream cursor to the beginning of the buffer and resets all
241 * internal state.
242 */
243jspb.BinaryReader.prototype.reset = function() {
244  this.decoder_.reset();
245  this.nextField_ = jspb.BinaryConstants.INVALID_FIELD_NUMBER;
246  this.nextWireType_ = jspb.BinaryConstants.WireType.INVALID;
247};
248
249
250/**
251 * Advances the stream cursor by the given number of bytes.
252 * @param {number} count The number of bytes to advance by.
253 */
254jspb.BinaryReader.prototype.advance = function(count) {
255  this.decoder_.advance(count);
256};
257
258
259/**
260 * Reads the next field header in the stream if there is one, returns true if
261 * we saw a valid field header or false if we've read the whole stream.
262 * Throws an error if we encountered a deprecated START_GROUP/END_GROUP field.
263 * @return {boolean} True if the stream contains more fields.
264 */
265jspb.BinaryReader.prototype.nextField = function() {
266  // If we're at the end of the block, there are no more fields.
267  if (this.decoder_.atEnd()) {
268    return false;
269  }
270
271  // If we hit an error decoding the previous field, stop now before we
272  // try to decode anything else
273  if (this.getError()) {
274    goog.asserts.fail('Decoder hit an error');
275    return false;
276  }
277
278  // Otherwise just read the header of the next field.
279  this.fieldCursor_ = this.decoder_.getCursor();
280  var header = this.decoder_.readUnsignedVarint32();
281
282  var nextField = header >>> 3;
283  var nextWireType = /** @type {jspb.BinaryConstants.WireType} */
284      (header & 0x7);
285
286  // If the wire type isn't one of the valid ones, something's broken.
287  if (nextWireType != jspb.BinaryConstants.WireType.VARINT &&
288      nextWireType != jspb.BinaryConstants.WireType.FIXED32 &&
289      nextWireType != jspb.BinaryConstants.WireType.FIXED64 &&
290      nextWireType != jspb.BinaryConstants.WireType.DELIMITED &&
291      nextWireType != jspb.BinaryConstants.WireType.START_GROUP &&
292      nextWireType != jspb.BinaryConstants.WireType.END_GROUP) {
293    goog.asserts.fail(
294        'Invalid wire type: %s (at position %s)', nextWireType,
295        this.fieldCursor_);
296    this.error_ = true;
297    return false;
298  }
299
300  this.nextField_ = nextField;
301  this.nextWireType_ = nextWireType;
302
303  return true;
304};
305
306
307/**
308 * Winds the reader back to just before this field's header.
309 */
310jspb.BinaryReader.prototype.unskipHeader = function() {
311  this.decoder_.unskipVarint((this.nextField_ << 3) | this.nextWireType_);
312};
313
314
315/**
316 * Skips all contiguous fields whose header matches the one we just read.
317 */
318jspb.BinaryReader.prototype.skipMatchingFields = function() {
319  var field = this.nextField_;
320  this.unskipHeader();
321
322  while (this.nextField() && (this.getFieldNumber() == field)) {
323    this.skipField();
324  }
325
326  if (!this.decoder_.atEnd()) {
327    this.unskipHeader();
328  }
329};
330
331
332/**
333 * Skips over the next varint field in the binary stream.
334 */
335jspb.BinaryReader.prototype.skipVarintField = function() {
336  if (this.nextWireType_ != jspb.BinaryConstants.WireType.VARINT) {
337    goog.asserts.fail('Invalid wire type for skipVarintField');
338    this.skipField();
339    return;
340  }
341
342  this.decoder_.skipVarint();
343};
344
345
346/**
347 * Skips over the next delimited field in the binary stream.
348 */
349jspb.BinaryReader.prototype.skipDelimitedField = function() {
350  if (this.nextWireType_ != jspb.BinaryConstants.WireType.DELIMITED) {
351    goog.asserts.fail('Invalid wire type for skipDelimitedField');
352    this.skipField();
353    return;
354  }
355
356  var length = this.decoder_.readUnsignedVarint32();
357  this.decoder_.advance(length);
358};
359
360
361/**
362 * Skips over the next fixed32 field in the binary stream.
363 */
364jspb.BinaryReader.prototype.skipFixed32Field = function() {
365  if (this.nextWireType_ != jspb.BinaryConstants.WireType.FIXED32) {
366    goog.asserts.fail('Invalid wire type for skipFixed32Field');
367    this.skipField();
368    return;
369  }
370
371  this.decoder_.advance(4);
372};
373
374
375/**
376 * Skips over the next fixed64 field in the binary stream.
377 */
378jspb.BinaryReader.prototype.skipFixed64Field = function() {
379  if (this.nextWireType_ != jspb.BinaryConstants.WireType.FIXED64) {
380    goog.asserts.fail('Invalid wire type for skipFixed64Field');
381    this.skipField();
382    return;
383  }
384
385  this.decoder_.advance(8);
386};
387
388
389/**
390 * Skips over the next group field in the binary stream.
391 */
392jspb.BinaryReader.prototype.skipGroup = function() {
393  var previousField = this.nextField_;
394  do {
395    if (!this.nextField()) {
396      goog.asserts.fail('Unmatched start-group tag: stream EOF');
397      this.error_ = true;
398      return;
399    }
400    if (this.nextWireType_ ==
401               jspb.BinaryConstants.WireType.END_GROUP) {
402      // Group end: check that it matches top-of-stack.
403      if (this.nextField_ != previousField) {
404        goog.asserts.fail('Unmatched end-group tag');
405        this.error_ = true;
406        return;
407      }
408      return;
409    }
410    this.skipField();
411  } while (true);
412};
413
414
415/**
416 * Skips over the next field in the binary stream - this is useful if we're
417 * decoding a message that contain unknown fields.
418 */
419jspb.BinaryReader.prototype.skipField = function() {
420  switch (this.nextWireType_) {
421    case jspb.BinaryConstants.WireType.VARINT:
422      this.skipVarintField();
423      break;
424    case jspb.BinaryConstants.WireType.FIXED64:
425      this.skipFixed64Field();
426      break;
427    case jspb.BinaryConstants.WireType.DELIMITED:
428      this.skipDelimitedField();
429      break;
430    case jspb.BinaryConstants.WireType.FIXED32:
431      this.skipFixed32Field();
432      break;
433    case jspb.BinaryConstants.WireType.START_GROUP:
434      this.skipGroup();
435      break;
436    default:
437      goog.asserts.fail('Invalid wire encoding for field.');
438  }
439};
440
441
442/**
443 * Registers a user-defined read callback.
444 * @param {string} callbackName
445 * @param {function(!jspb.BinaryReader):*} callback
446 */
447jspb.BinaryReader.prototype.registerReadCallback =
448    function(callbackName, callback) {
449  if (goog.isNull(this.readCallbacks_)) {
450    this.readCallbacks_ = {};
451  }
452  goog.asserts.assert(!this.readCallbacks_[callbackName]);
453  this.readCallbacks_[callbackName] = callback;
454};
455
456
457/**
458 * Runs a registered read callback.
459 * @param {string} callbackName The name the callback is registered under.
460 * @return {*} The value returned by the callback.
461 */
462jspb.BinaryReader.prototype.runReadCallback = function(callbackName) {
463  goog.asserts.assert(!goog.isNull(this.readCallbacks_));
464  var callback = this.readCallbacks_[callbackName];
465  goog.asserts.assert(callback);
466  return callback(this);
467};
468
469
470/**
471 * Reads a field of any valid non-message type from the binary stream.
472 * @param {jspb.BinaryConstants.FieldType} fieldType
473 * @return {jspb.AnyFieldType}
474 */
475jspb.BinaryReader.prototype.readAny = function(fieldType) {
476  this.nextWireType_ = jspb.BinaryConstants.FieldTypeToWireType(fieldType);
477  var fieldTypes = jspb.BinaryConstants.FieldType;
478  switch (fieldType) {
479    case fieldTypes.DOUBLE:
480      return this.readDouble();
481    case fieldTypes.FLOAT:
482      return this.readFloat();
483    case fieldTypes.INT64:
484      return this.readInt64();
485    case fieldTypes.UINT64:
486      return this.readUint64();
487    case fieldTypes.INT32:
488      return this.readInt32();
489    case fieldTypes.FIXED64:
490      return this.readFixed64();
491    case fieldTypes.FIXED32:
492      return this.readFixed32();
493    case fieldTypes.BOOL:
494      return this.readBool();
495    case fieldTypes.STRING:
496      return this.readString();
497    case fieldTypes.GROUP:
498      goog.asserts.fail('Group field type not supported in readAny()');
499    case fieldTypes.MESSAGE:
500      goog.asserts.fail('Message field type not supported in readAny()');
501    case fieldTypes.BYTES:
502      return this.readBytes();
503    case fieldTypes.UINT32:
504      return this.readUint32();
505    case fieldTypes.ENUM:
506      return this.readEnum();
507    case fieldTypes.SFIXED32:
508      return this.readSfixed32();
509    case fieldTypes.SFIXED64:
510      return this.readSfixed64();
511    case fieldTypes.SINT32:
512      return this.readSint32();
513    case fieldTypes.SINT64:
514      return this.readSint64();
515    case fieldTypes.FHASH64:
516      return this.readFixedHash64();
517    case fieldTypes.VHASH64:
518      return this.readVarintHash64();
519    default:
520      goog.asserts.fail('Invalid field type in readAny()');
521  }
522  return 0;
523};
524
525
526/**
527 * Deserialize a proto into the provided message object using the provided
528 * reader function. This function is templated as we currently have one client
529 * who is using manual deserialization instead of the code-generated versions.
530 * @template T
531 * @param {T} message
532 * @param {function(T, !jspb.BinaryReader)} reader
533 */
534jspb.BinaryReader.prototype.readMessage = function(message, reader) {
535  goog.asserts.assert(
536      this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED);
537
538  // Save the current endpoint of the decoder and move it to the end of the
539  // embedded message.
540  var oldEnd = this.decoder_.getEnd();
541  var length = this.decoder_.readUnsignedVarint32();
542  var newEnd = this.decoder_.getCursor() + length;
543  this.decoder_.setEnd(newEnd);
544
545  // Deserialize the embedded message.
546  reader(message, this);
547
548  // Advance the decoder past the embedded message and restore the endpoint.
549  this.decoder_.setCursor(newEnd);
550  this.decoder_.setEnd(oldEnd);
551};
552
553
554/**
555 * Deserialize a proto into the provided message object using the provided
556 * reader function, assuming that the message is serialized as a group
557 * with the given tag.
558 * @template T
559 * @param {number} field
560 * @param {T} message
561 * @param {function(T, !jspb.BinaryReader)} reader
562 */
563jspb.BinaryReader.prototype.readGroup =
564    function(field, message, reader) {
565  // Ensure that the wire type is correct.
566  goog.asserts.assert(
567      this.nextWireType_ == jspb.BinaryConstants.WireType.START_GROUP);
568  // Ensure that the field number is correct.
569  goog.asserts.assert(this.nextField_ == field);
570
571  // Deserialize the message. The deserialization will stop at an END_GROUP tag.
572  reader(message, this);
573
574  if (!this.error_ &&
575      this.nextWireType_ != jspb.BinaryConstants.WireType.END_GROUP) {
576    goog.asserts.fail('Group submessage did not end with an END_GROUP tag');
577    this.error_ = true;
578  }
579};
580
581
582/**
583 * Return a decoder that wraps the current delimited field.
584 * @return {!jspb.BinaryDecoder}
585 */
586jspb.BinaryReader.prototype.getFieldDecoder = function() {
587  goog.asserts.assert(
588      this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED);
589
590  var length = this.decoder_.readUnsignedVarint32();
591  var start = this.decoder_.getCursor();
592  var end = start + length;
593
594  var innerDecoder =
595      jspb.BinaryDecoder.alloc(this.decoder_.getBuffer(), start, length);
596  this.decoder_.setCursor(end);
597  return innerDecoder;
598};
599
600
601/**
602 * Reads a signed 32-bit integer field from the binary stream, or throws an
603 * error if the next field in the stream is not of the correct wire type.
604 *
605 * @return {number} The value of the signed 32-bit integer field.
606 */
607jspb.BinaryReader.prototype.readInt32 = function() {
608  goog.asserts.assert(
609      this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
610  return this.decoder_.readSignedVarint32();
611};
612
613
614/**
615 * Reads a signed 32-bit integer field from the binary stream, or throws an
616 * error if the next field in the stream is not of the correct wire type.
617 *
618 * Returns the value as a string.
619 *
620 * @return {string} The value of the signed 32-bit integer field as a decimal
621 * string.
622 */
623jspb.BinaryReader.prototype.readInt32String = function() {
624  goog.asserts.assert(
625      this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
626  return this.decoder_.readSignedVarint32String();
627};
628
629
630/**
631 * Reads a signed 64-bit integer field from the binary stream, or throws an
632 * error if the next field in the stream is not of the correct wire type.
633 *
634 * @return {number} The value of the signed 64-bit integer field.
635 */
636jspb.BinaryReader.prototype.readInt64 = function() {
637  goog.asserts.assert(
638      this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
639  return this.decoder_.readSignedVarint64();
640};
641
642
643/**
644 * Reads a signed 64-bit integer field from the binary stream, or throws an
645 * error if the next field in the stream is not of the correct wire type.
646 *
647 * Returns the value as a string.
648 *
649 * @return {string} The value of the signed 64-bit integer field as a decimal
650 * string.
651 */
652jspb.BinaryReader.prototype.readInt64String = function() {
653  goog.asserts.assert(
654      this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
655  return this.decoder_.readSignedVarint64String();
656};
657
658
659/**
660 * Reads an unsigned 32-bit integer field from the binary stream, or throws an
661 * error if the next field in the stream is not of the correct wire type.
662 *
663 * @return {number} The value of the unsigned 32-bit integer field.
664 */
665jspb.BinaryReader.prototype.readUint32 = function() {
666  goog.asserts.assert(
667      this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
668  return this.decoder_.readUnsignedVarint32();
669};
670
671
672/**
673 * Reads an unsigned 32-bit integer field from the binary stream, or throws an
674 * error if the next field in the stream is not of the correct wire type.
675 *
676 * Returns the value as a string.
677 *
678 * @return {string} The value of the unsigned 32-bit integer field as a decimal
679 * string.
680 */
681jspb.BinaryReader.prototype.readUint32String = function() {
682  goog.asserts.assert(
683      this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
684  return this.decoder_.readUnsignedVarint32String();
685};
686
687
688/**
689 * Reads an unsigned 64-bit integer field from the binary stream, or throws an
690 * error if the next field in the stream is not of the correct wire type.
691 *
692 * @return {number} The value of the unsigned 64-bit integer field.
693 */
694jspb.BinaryReader.prototype.readUint64 = function() {
695  goog.asserts.assert(
696      this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
697  return this.decoder_.readUnsignedVarint64();
698};
699
700
701/**
702 * Reads an unsigned 64-bit integer field from the binary stream, or throws an
703 * error if the next field in the stream is not of the correct wire type.
704 *
705 * Returns the value as a string.
706 *
707 * @return {string} The value of the unsigned 64-bit integer field as a decimal
708 * string.
709 */
710jspb.BinaryReader.prototype.readUint64String = function() {
711  goog.asserts.assert(
712      this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
713  return this.decoder_.readUnsignedVarint64String();
714};
715
716
717/**
718 * Reads a signed zigzag-encoded 32-bit integer field from the binary stream,
719 * or throws an error if the next field in the stream is not of the correct
720 * wire type.
721 *
722 * @return {number} The value of the signed 32-bit integer field.
723 */
724jspb.BinaryReader.prototype.readSint32 = function() {
725  goog.asserts.assert(
726      this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
727  return this.decoder_.readZigzagVarint32();
728};
729
730
731/**
732 * Reads a signed zigzag-encoded 64-bit integer field from the binary stream,
733 * or throws an error if the next field in the stream is not of the correct
734 * wire type.
735 *
736 * @return {number} The value of the signed 64-bit integer field.
737 */
738jspb.BinaryReader.prototype.readSint64 = function() {
739  goog.asserts.assert(
740      this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
741  return this.decoder_.readZigzagVarint64();
742};
743
744
745/**
746 * Reads a signed zigzag-encoded 64-bit integer field from the binary stream,
747 * or throws an error if the next field in the stream is not of the correct
748 * wire type.
749 *
750 * @return {string} The value of the signed 64-bit integer field as a decimal string.
751 */
752jspb.BinaryReader.prototype.readSint64String = function() {
753  goog.asserts.assert(
754      this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
755  return this.decoder_.readZigzagVarint64String();
756};
757
758
759/**
760 * Reads an unsigned 32-bit fixed-length integer fiield from the binary stream,
761 * or throws an error if the next field in the stream is not of the correct
762 * wire type.
763 *
764 * @return {number} The value of the double field.
765 */
766jspb.BinaryReader.prototype.readFixed32 = function() {
767  goog.asserts.assert(
768      this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED32);
769  return this.decoder_.readUint32();
770};
771
772
773/**
774 * Reads an unsigned 64-bit fixed-length integer fiield from the binary stream,
775 * or throws an error if the next field in the stream is not of the correct
776 * wire type.
777 *
778 * @return {number} The value of the float field.
779 */
780jspb.BinaryReader.prototype.readFixed64 = function() {
781  goog.asserts.assert(
782      this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64);
783  return this.decoder_.readUint64();
784};
785
786
787/**
788 * Reads a signed 64-bit integer field from the binary stream as a string, or
789 * throws an error if the next field in the stream is not of the correct wire
790 * type.
791 *
792 * Returns the value as a string.
793 *
794 * @return {string} The value of the unsigned 64-bit integer field as a decimal
795 * string.
796 */
797jspb.BinaryReader.prototype.readFixed64String = function() {
798  goog.asserts.assert(
799      this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64);
800  return this.decoder_.readUint64String();
801};
802
803
804/**
805 * Reads a signed 32-bit fixed-length integer fiield from the binary stream, or
806 * throws an error if the next field in the stream is not of the correct wire
807 * type.
808 *
809 * @return {number} The value of the signed 32-bit integer field.
810 */
811jspb.BinaryReader.prototype.readSfixed32 = function() {
812  goog.asserts.assert(
813      this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED32);
814  return this.decoder_.readInt32();
815};
816
817
818/**
819 * Reads a signed 32-bit fixed-length integer fiield from the binary stream, or
820 * throws an error if the next field in the stream is not of the correct wire
821 * type.
822 *
823 * @return {string} The value of the signed 32-bit integer field as a decimal
824 * string.
825 */
826jspb.BinaryReader.prototype.readSfixed32String = function() {
827  goog.asserts.assert(
828      this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED32);
829  return this.decoder_.readInt32().toString();
830};
831
832
833/**
834 * Reads a signed 64-bit fixed-length integer fiield from the binary stream, or
835 * throws an error if the next field in the stream is not of the correct wire
836 * type.
837 *
838 * @return {number} The value of the sfixed64 field.
839 */
840jspb.BinaryReader.prototype.readSfixed64 = function() {
841  goog.asserts.assert(
842      this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64);
843  return this.decoder_.readInt64();
844};
845
846
847/**
848 * Reads a signed 64-bit fixed-length integer fiield from the binary stream, or
849 * throws an error if the next field in the stream is not of the correct wire
850 * type.
851 *
852 * Returns the value as a string.
853 *
854 * @return {string} The value of the sfixed64 field as a decimal string.
855 */
856jspb.BinaryReader.prototype.readSfixed64String = function() {
857  goog.asserts.assert(
858      this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64);
859  return this.decoder_.readInt64String();
860};
861
862
863/**
864 * Reads a 32-bit floating-point field from the binary stream, or throws an
865 * error if the next field in the stream is not of the correct wire type.
866 *
867 * @return {number} The value of the float field.
868 */
869jspb.BinaryReader.prototype.readFloat = function() {
870  goog.asserts.assert(
871      this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED32);
872  return this.decoder_.readFloat();
873};
874
875
876/**
877 * Reads a 64-bit floating-point field from the binary stream, or throws an
878 * error if the next field in the stream is not of the correct wire type.
879 *
880 * @return {number} The value of the double field.
881 */
882jspb.BinaryReader.prototype.readDouble = function() {
883  goog.asserts.assert(
884      this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64);
885  return this.decoder_.readDouble();
886};
887
888
889/**
890 * Reads a boolean field from the binary stream, or throws an error if the next
891 * field in the stream is not of the correct wire type.
892 *
893 * @return {boolean} The value of the boolean field.
894 */
895jspb.BinaryReader.prototype.readBool = function() {
896  goog.asserts.assert(
897      this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
898  return !!this.decoder_.readUnsignedVarint32();
899};
900
901
902/**
903 * Reads an enum field from the binary stream, or throws an error if the next
904 * field in the stream is not of the correct wire type.
905 *
906 * @return {number} The value of the enum field.
907 */
908jspb.BinaryReader.prototype.readEnum = function() {
909  goog.asserts.assert(
910      this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
911  return this.decoder_.readSignedVarint64();
912};
913
914
915/**
916 * Reads a string field from the binary stream, or throws an error if the next
917 * field in the stream is not of the correct wire type.
918 *
919 * @return {string} The value of the string field.
920 */
921jspb.BinaryReader.prototype.readString = function() {
922  goog.asserts.assert(
923      this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED);
924  var length = this.decoder_.readUnsignedVarint32();
925  return this.decoder_.readString(length);
926};
927
928
929/**
930 * Reads a length-prefixed block of bytes from the binary stream, or returns
931 * null if the next field in the stream has an invalid length value.
932 *
933 * @return {!Uint8Array} The block of bytes.
934 */
935jspb.BinaryReader.prototype.readBytes = function() {
936  goog.asserts.assert(
937      this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED);
938  var length = this.decoder_.readUnsignedVarint32();
939  return this.decoder_.readBytes(length);
940};
941
942
943/**
944 * Reads a 64-bit varint or fixed64 field from the stream and returns it as a
945 * 8-character Unicode string for use as a hash table key, or throws an error
946 * if the next field in the stream is not of the correct wire type.
947 *
948 * @return {string} The hash value.
949 */
950jspb.BinaryReader.prototype.readVarintHash64 = function() {
951  goog.asserts.assert(
952      this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
953  return this.decoder_.readVarintHash64();
954};
955
956
957/**
958 * Reads a 64-bit varint or fixed64 field from the stream and returns it as a
959 * 8-character Unicode string for use as a hash table key, or throws an error
960 * if the next field in the stream is not of the correct wire type.
961 *
962 * @return {string} The hash value.
963 */
964jspb.BinaryReader.prototype.readFixedHash64 = function() {
965  goog.asserts.assert(
966      this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64);
967  return this.decoder_.readFixedHash64();
968};
969
970
971/**
972 * Reads a packed scalar field using the supplied raw reader function.
973 * @param {function(this:jspb.BinaryDecoder)} decodeMethod
974 * @return {!Array}
975 * @private
976 */
977jspb.BinaryReader.prototype.readPackedField_ = function(decodeMethod) {
978  goog.asserts.assert(
979      this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED);
980  var length = this.decoder_.readUnsignedVarint32();
981  var end = this.decoder_.getCursor() + length;
982  var result = [];
983  while (this.decoder_.getCursor() < end) {
984    // TODO(aappleby): .call is slow
985    result.push(decodeMethod.call(this.decoder_));
986  }
987  return result;
988};
989
990
991/**
992 * Reads a packed int32 field, which consists of a length header and a list of
993 * signed varints.
994 * @return {!Array<number>}
995 */
996jspb.BinaryReader.prototype.readPackedInt32 = function() {
997  return this.readPackedField_(this.decoder_.readSignedVarint32);
998};
999
1000
1001/**
1002 * Reads a packed int32 field, which consists of a length header and a list of
1003 * signed varints. Returns a list of strings.
1004 * @return {!Array<string>}
1005 */
1006jspb.BinaryReader.prototype.readPackedInt32String = function() {
1007  return this.readPackedField_(this.decoder_.readSignedVarint32String);
1008};
1009
1010
1011/**
1012 * Reads a packed int64 field, which consists of a length header and a list of
1013 * signed varints.
1014 * @return {!Array<number>}
1015 */
1016jspb.BinaryReader.prototype.readPackedInt64 = function() {
1017  return this.readPackedField_(this.decoder_.readSignedVarint64);
1018};
1019
1020
1021/**
1022 * Reads a packed int64 field, which consists of a length header and a list of
1023 * signed varints. Returns a list of strings.
1024 * @return {!Array<string>}
1025 */
1026jspb.BinaryReader.prototype.readPackedInt64String = function() {
1027  return this.readPackedField_(this.decoder_.readSignedVarint64String);
1028};
1029
1030
1031/**
1032 * Reads a packed uint32 field, which consists of a length header and a list of
1033 * unsigned varints.
1034 * @return {!Array<number>}
1035 */
1036jspb.BinaryReader.prototype.readPackedUint32 = function() {
1037  return this.readPackedField_(this.decoder_.readUnsignedVarint32);
1038};
1039
1040
1041/**
1042 * Reads a packed uint32 field, which consists of a length header and a list of
1043 * unsigned varints. Returns a list of strings.
1044 * @return {!Array<string>}
1045 */
1046jspb.BinaryReader.prototype.readPackedUint32String = function() {
1047  return this.readPackedField_(this.decoder_.readUnsignedVarint32String);
1048};
1049
1050
1051/**
1052 * Reads a packed uint64 field, which consists of a length header and a list of
1053 * unsigned varints.
1054 * @return {!Array<number>}
1055 */
1056jspb.BinaryReader.prototype.readPackedUint64 = function() {
1057  return this.readPackedField_(this.decoder_.readUnsignedVarint64);
1058};
1059
1060
1061/**
1062 * Reads a packed uint64 field, which consists of a length header and a list of
1063 * unsigned varints. Returns a list of strings.
1064 * @return {!Array<string>}
1065 */
1066jspb.BinaryReader.prototype.readPackedUint64String = function() {
1067  return this.readPackedField_(this.decoder_.readUnsignedVarint64String);
1068};
1069
1070
1071/**
1072 * Reads a packed sint32 field, which consists of a length header and a list of
1073 * zigzag varints.
1074 * @return {!Array<number>}
1075 */
1076jspb.BinaryReader.prototype.readPackedSint32 = function() {
1077  return this.readPackedField_(this.decoder_.readZigzagVarint32);
1078};
1079
1080
1081/**
1082 * Reads a packed sint64 field, which consists of a length header and a list of
1083 * zigzag varints.
1084 * @return {!Array<number>}
1085 */
1086jspb.BinaryReader.prototype.readPackedSint64 = function() {
1087  return this.readPackedField_(this.decoder_.readZigzagVarint64);
1088};
1089
1090
1091/**
1092 * Reads a packed sint64 field, which consists of a length header and a list of
1093 * zigzag varints.  Returns a list of strings.
1094 * @return {!Array<string>}
1095 */
1096jspb.BinaryReader.prototype.readPackedSint64String = function() {
1097  return this.readPackedField_(this.decoder_.readZigzagVarint64String);
1098};
1099
1100
1101/**
1102 * Reads a packed fixed32 field, which consists of a length header and a list
1103 * of unsigned 32-bit ints.
1104 * @return {!Array<number>}
1105 */
1106jspb.BinaryReader.prototype.readPackedFixed32 = function() {
1107  return this.readPackedField_(this.decoder_.readUint32);
1108};
1109
1110
1111/**
1112 * Reads a packed fixed64 field, which consists of a length header and a list
1113 * of unsigned 64-bit ints.
1114 * @return {!Array<number>}
1115 */
1116jspb.BinaryReader.prototype.readPackedFixed64 = function() {
1117  return this.readPackedField_(this.decoder_.readUint64);
1118};
1119
1120
1121/**
1122 * Reads a packed fixed64 field, which consists of a length header and a list
1123 * of unsigned 64-bit ints.  Returns a list of strings.
1124 * @return {!Array<number>}
1125 */
1126jspb.BinaryReader.prototype.readPackedFixed64String = function() {
1127  return this.readPackedField_(this.decoder_.readUint64String);
1128};
1129
1130
1131/**
1132 * Reads a packed sfixed32 field, which consists of a length header and a list
1133 * of 32-bit ints.
1134 * @return {!Array<number>}
1135 */
1136jspb.BinaryReader.prototype.readPackedSfixed32 = function() {
1137  return this.readPackedField_(this.decoder_.readInt32);
1138};
1139
1140
1141/**
1142 * Reads a packed sfixed64 field, which consists of a length header and a list
1143 * of 64-bit ints.
1144 * @return {!Array<number>}
1145 */
1146jspb.BinaryReader.prototype.readPackedSfixed64 = function() {
1147  return this.readPackedField_(this.decoder_.readInt64);
1148};
1149
1150
1151/**
1152 * Reads a packed sfixed64 field, which consists of a length header and a list
1153 * of 64-bit ints.  Returns a list of strings.
1154 * @return {!Array<string>}
1155 */
1156jspb.BinaryReader.prototype.readPackedSfixed64String = function() {
1157  return this.readPackedField_(this.decoder_.readInt64String);
1158};
1159
1160
1161/**
1162 * Reads a packed float field, which consists of a length header and a list of
1163 * floats.
1164 * @return {!Array<number>}
1165 */
1166jspb.BinaryReader.prototype.readPackedFloat = function() {
1167  return this.readPackedField_(this.decoder_.readFloat);
1168};
1169
1170
1171/**
1172 * Reads a packed double field, which consists of a length header and a list of
1173 * doubles.
1174 * @return {!Array<number>}
1175 */
1176jspb.BinaryReader.prototype.readPackedDouble = function() {
1177  return this.readPackedField_(this.decoder_.readDouble);
1178};
1179
1180
1181/**
1182 * Reads a packed bool field, which consists of a length header and a list of
1183 * unsigned varints.
1184 * @return {!Array<boolean>}
1185 */
1186jspb.BinaryReader.prototype.readPackedBool = function() {
1187  return this.readPackedField_(this.decoder_.readBool);
1188};
1189
1190
1191/**
1192 * Reads a packed enum field, which consists of a length header and a list of
1193 * unsigned varints.
1194 * @return {!Array<number>}
1195 */
1196jspb.BinaryReader.prototype.readPackedEnum = function() {
1197  return this.readPackedField_(this.decoder_.readEnum);
1198};
1199
1200
1201/**
1202 * Reads a packed varint hash64 field, which consists of a length header and a
1203 * list of varint hash64s.
1204 * @return {!Array<string>}
1205 */
1206jspb.BinaryReader.prototype.readPackedVarintHash64 = function() {
1207  return this.readPackedField_(this.decoder_.readVarintHash64);
1208};
1209
1210
1211/**
1212 * Reads a packed fixed hash64 field, which consists of a length header and a
1213 * list of fixed hash64s.
1214 * @return {!Array<string>}
1215 */
1216jspb.BinaryReader.prototype.readPackedFixedHash64 = function() {
1217  return this.readPackedField_(this.decoder_.readFixedHash64);
1218};
1219