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