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