blob: 15f90432d89ee440279b25ba97a56f1bdf5aa1bd [file] [log] [blame]
Feng Xiaoe841bac2015-12-11 17:09:20 -08001// 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.
Jisi Liu3b3c8ab2016-03-30 11:39:59 -0700183 * @return {?Uint8Array} The raw buffer.
Feng Xiaoe841bac2015-12-11 17:09:20 -0800184 */
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('Invalid wire type');
294 this.error_ = true;
295 return false;
296 }
297
298 this.nextField_ = nextField;
299 this.nextWireType_ = nextWireType;
300
301 return true;
302};
303
304
305/**
306 * Winds the reader back to just before this field's header.
307 */
308jspb.BinaryReader.prototype.unskipHeader = function() {
309 this.decoder_.unskipVarint((this.nextField_ << 3) | this.nextWireType_);
310};
311
312
313/**
314 * Skips all contiguous fields whose header matches the one we just read.
315 */
316jspb.BinaryReader.prototype.skipMatchingFields = function() {
317 var field = this.nextField_;
318 this.unskipHeader();
319
320 while (this.nextField() && (this.getFieldNumber() == field)) {
321 this.skipField();
322 }
323
324 if (!this.decoder_.atEnd()) {
325 this.unskipHeader();
326 }
327};
328
329
330/**
331 * Skips over the next varint field in the binary stream.
332 */
333jspb.BinaryReader.prototype.skipVarintField = function() {
334 if (this.nextWireType_ != jspb.BinaryConstants.WireType.VARINT) {
335 goog.asserts.fail('Invalid wire type for skipVarintField');
336 this.skipField();
337 return;
338 }
339
340 this.decoder_.skipVarint();
341};
342
343
344/**
345 * Skips over the next delimited field in the binary stream.
346 */
347jspb.BinaryReader.prototype.skipDelimitedField = function() {
348 if (this.nextWireType_ != jspb.BinaryConstants.WireType.DELIMITED) {
349 goog.asserts.fail('Invalid wire type for skipDelimitedField');
350 this.skipField();
351 return;
352 }
353
354 var length = this.decoder_.readUnsignedVarint32();
355 this.decoder_.advance(length);
356};
357
358
359/**
360 * Skips over the next fixed32 field in the binary stream.
361 */
362jspb.BinaryReader.prototype.skipFixed32Field = function() {
363 if (this.nextWireType_ != jspb.BinaryConstants.WireType.FIXED32) {
364 goog.asserts.fail('Invalid wire type for skipFixed32Field');
365 this.skipField();
366 return;
367 }
368
369 this.decoder_.advance(4);
370};
371
372
373/**
374 * Skips over the next fixed64 field in the binary stream.
375 */
376jspb.BinaryReader.prototype.skipFixed64Field = function() {
377 if (this.nextWireType_ != jspb.BinaryConstants.WireType.FIXED64) {
378 goog.asserts.fail('Invalid wire type for skipFixed64Field');
379 this.skipField();
380 return;
381 }
382
383 this.decoder_.advance(8);
384};
385
386
387/**
388 * Skips over the next group field in the binary stream.
389 */
390jspb.BinaryReader.prototype.skipGroup = function() {
391 // Keep a stack of start-group tags that must be matched by end-group tags.
392 var nestedGroups = [this.nextField_];
393 do {
394 if (!this.nextField()) {
395 goog.asserts.fail('Unmatched start-group tag: stream EOF');
396 this.error_ = true;
397 return;
398 }
399 if (this.nextWireType_ ==
400 jspb.BinaryConstants.WireType.START_GROUP) {
401 // Nested group start.
402 nestedGroups.push(this.nextField_);
403 } else if (this.nextWireType_ ==
404 jspb.BinaryConstants.WireType.END_GROUP) {
405 // Group end: check that it matches top-of-stack.
406 if (this.nextField_ != nestedGroups.pop()) {
407 goog.asserts.fail('Unmatched end-group tag');
408 this.error_ = true;
409 return;
410 }
411 }
412 } while (nestedGroups.length > 0);
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 =
449 function(callbackName, callback) {
450 if (goog.isNull(this.readCallbacks_)) {
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(!goog.isNull(this.readCallbacks_));
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
Jisi Liu3b3c8ab2016-03-30 11:39:59 -0700595 var innerDecoder =
596 jspb.BinaryDecoder.alloc(this.decoder_.getBuffer(), start, length);
Feng Xiaoe841bac2015-12-11 17:09:20 -0800597 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 an unsigned 32-bit fixed-length integer fiield 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 {number} The value of the double field.
752 */
753jspb.BinaryReader.prototype.readFixed32 = function() {
754 goog.asserts.assert(
755 this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED32);
756 return this.decoder_.readUint32();
757};
758
759
760/**
761 * Reads an unsigned 64-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 float field.
766 */
767jspb.BinaryReader.prototype.readFixed64 = function() {
768 goog.asserts.assert(
769 this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64);
770 return this.decoder_.readUint64();
771};
772
773
774/**
775 * Reads a signed 32-bit fixed-length integer fiield from the binary stream, or
776 * throws an error if the next field in the stream is not of the correct wire
777 * type.
778 *
779 * @return {number} The value of the double field.
780 */
781jspb.BinaryReader.prototype.readSfixed32 = function() {
782 goog.asserts.assert(
783 this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED32);
784 return this.decoder_.readInt32();
785};
786
787
788/**
789 * Reads a signed 64-bit fixed-length integer fiield from the binary stream, or
790 * throws an error if the next field in the stream is not of the correct wire
791 * type.
792 *
793 * @return {number} The value of the float field.
794 */
795jspb.BinaryReader.prototype.readSfixed64 = function() {
796 goog.asserts.assert(
797 this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64);
798 return this.decoder_.readInt64();
799};
800
801
802/**
803 * Reads a 32-bit floating-point field from the binary stream, or throws an
804 * error if the next field in the stream is not of the correct wire type.
805 *
806 * @return {number} The value of the float field.
807 */
808jspb.BinaryReader.prototype.readFloat = function() {
809 goog.asserts.assert(
810 this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED32);
811 return this.decoder_.readFloat();
812};
813
814
815/**
816 * Reads a 64-bit floating-point field from the binary stream, or throws an
817 * error if the next field in the stream is not of the correct wire type.
818 *
819 * @return {number} The value of the double field.
820 */
821jspb.BinaryReader.prototype.readDouble = function() {
822 goog.asserts.assert(
823 this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64);
824 return this.decoder_.readDouble();
825};
826
827
828/**
829 * Reads a boolean field from the binary stream, or throws an error if the next
830 * field in the stream is not of the correct wire type.
831 *
832 * @return {boolean} The value of the boolean field.
833 */
834jspb.BinaryReader.prototype.readBool = function() {
835 goog.asserts.assert(
836 this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
837 return !!this.decoder_.readUnsignedVarint32();
838};
839
840
841/**
842 * Reads an enum field from the binary stream, or throws an error if the next
843 * field in the stream is not of the correct wire type.
844 *
845 * @return {number} The value of the enum field.
846 */
847jspb.BinaryReader.prototype.readEnum = function() {
848 goog.asserts.assert(
849 this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
850 return this.decoder_.readSignedVarint64();
851};
852
853
854/**
855 * Reads a string field from the binary stream, or throws an error if the next
856 * field in the stream is not of the correct wire type.
857 *
858 * @return {string} The value of the string field.
859 */
860jspb.BinaryReader.prototype.readString = function() {
861 goog.asserts.assert(
862 this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED);
863 var length = this.decoder_.readUnsignedVarint32();
864 return this.decoder_.readString(length);
865};
866
867
868/**
869 * Reads a length-prefixed block of bytes from the binary stream, or returns
870 * null if the next field in the stream has an invalid length value.
871 *
Jisi Liu3b3c8ab2016-03-30 11:39:59 -0700872 * @return {!Uint8Array} The block of bytes.
Feng Xiaoe841bac2015-12-11 17:09:20 -0800873 */
874jspb.BinaryReader.prototype.readBytes = function() {
875 goog.asserts.assert(
876 this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED);
877 var length = this.decoder_.readUnsignedVarint32();
878 return this.decoder_.readBytes(length);
879};
880
881
882/**
883 * Reads a 64-bit varint or fixed64 field from the stream and returns it as a
884 * 8-character Unicode string for use as a hash table key, or throws an error
885 * if the next field in the stream is not of the correct wire type.
886 *
887 * @return {string} The hash value.
888 */
889jspb.BinaryReader.prototype.readVarintHash64 = function() {
890 goog.asserts.assert(
891 this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT);
892 return this.decoder_.readVarintHash64();
893};
894
895
896/**
897 * Reads a 64-bit varint or fixed64 field from the stream and returns it as a
898 * 8-character Unicode string for use as a hash table key, or throws an error
899 * if the next field in the stream is not of the correct wire type.
900 *
901 * @return {string} The hash value.
902 */
903jspb.BinaryReader.prototype.readFixedHash64 = function() {
904 goog.asserts.assert(
905 this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64);
906 return this.decoder_.readFixedHash64();
907};
908
909
910/**
911 * Reads a packed scalar field using the supplied raw reader function.
912 * @param {function()} decodeMethod
913 * @return {!Array}
914 * @private
915 */
916jspb.BinaryReader.prototype.readPackedField_ = function(decodeMethod) {
917 goog.asserts.assert(
918 this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED);
919 var length = this.decoder_.readUnsignedVarint32();
920 var end = this.decoder_.getCursor() + length;
921 var result = [];
922 while (this.decoder_.getCursor() < end) {
923 // TODO(aappleby): .call is slow
924 result.push(decodeMethod.call(this.decoder_));
925 }
926 return result;
927};
928
929
930/**
931 * Reads a packed int32 field, which consists of a length header and a list of
932 * signed varints.
933 * @return {!Array.<number>}
934 */
935jspb.BinaryReader.prototype.readPackedInt32 = function() {
936 return this.readPackedField_(this.decoder_.readSignedVarint32);
937};
938
939
940/**
941 * Reads a packed int32 field, which consists of a length header and a list of
942 * signed varints. Returns a list of strings.
943 * @return {!Array.<string>}
944 */
945jspb.BinaryReader.prototype.readPackedInt32String = function() {
946 return this.readPackedField_(this.decoder_.readSignedVarint32String);
947};
948
949
950/**
951 * Reads a packed int64 field, which consists of a length header and a list of
952 * signed varints.
953 * @return {!Array.<number>}
954 */
955jspb.BinaryReader.prototype.readPackedInt64 = function() {
956 return this.readPackedField_(this.decoder_.readSignedVarint64);
957};
958
959
960/**
961 * Reads a packed int64 field, which consists of a length header and a list of
962 * signed varints. Returns a list of strings.
963 * @return {!Array.<string>}
964 */
965jspb.BinaryReader.prototype.readPackedInt64String = function() {
966 return this.readPackedField_(this.decoder_.readSignedVarint64String);
967};
968
969
970/**
971 * Reads a packed uint32 field, which consists of a length header and a list of
972 * unsigned varints.
973 * @return {!Array.<number>}
974 */
975jspb.BinaryReader.prototype.readPackedUint32 = function() {
976 return this.readPackedField_(this.decoder_.readUnsignedVarint32);
977};
978
979
980/**
981 * Reads a packed uint32 field, which consists of a length header and a list of
982 * unsigned varints. Returns a list of strings.
983 * @return {!Array.<string>}
984 */
985jspb.BinaryReader.prototype.readPackedUint32String = function() {
986 return this.readPackedField_(this.decoder_.readUnsignedVarint32String);
987};
988
989
990/**
991 * Reads a packed uint64 field, which consists of a length header and a list of
992 * unsigned varints.
993 * @return {!Array.<number>}
994 */
995jspb.BinaryReader.prototype.readPackedUint64 = function() {
996 return this.readPackedField_(this.decoder_.readUnsignedVarint64);
997};
998
999
1000/**
1001 * Reads a packed uint64 field, which consists of a length header and a list of
1002 * unsigned varints. Returns a list of strings.
1003 * @return {!Array.<string>}
1004 */
1005jspb.BinaryReader.prototype.readPackedUint64String = function() {
1006 return this.readPackedField_(this.decoder_.readUnsignedVarint64String);
1007};
1008
1009
1010/**
1011 * Reads a packed sint32 field, which consists of a length header and a list of
1012 * zigzag varints.
1013 * @return {!Array.<number>}
1014 */
1015jspb.BinaryReader.prototype.readPackedSint32 = function() {
1016 return this.readPackedField_(this.decoder_.readZigzagVarint32);
1017};
1018
1019
1020/**
1021 * Reads a packed sint64 field, which consists of a length header and a list of
1022 * zigzag varints.
1023 * @return {!Array.<number>}
1024 */
1025jspb.BinaryReader.prototype.readPackedSint64 = function() {
1026 return this.readPackedField_(this.decoder_.readZigzagVarint64);
1027};
1028
1029
1030/**
1031 * Reads a packed fixed32 field, which consists of a length header and a list
1032 * of unsigned 32-bit ints.
1033 * @return {!Array.<number>}
1034 */
1035jspb.BinaryReader.prototype.readPackedFixed32 = function() {
1036 return this.readPackedField_(this.decoder_.readUint32);
1037};
1038
1039
1040/**
1041 * Reads a packed fixed64 field, which consists of a length header and a list
1042 * of unsigned 64-bit ints.
1043 * @return {!Array.<number>}
1044 */
1045jspb.BinaryReader.prototype.readPackedFixed64 = function() {
1046 return this.readPackedField_(this.decoder_.readUint64);
1047};
1048
1049
1050/**
1051 * Reads a packed sfixed32 field, which consists of a length header and a list
1052 * of 32-bit ints.
1053 * @return {!Array.<number>}
1054 */
1055jspb.BinaryReader.prototype.readPackedSfixed32 = function() {
1056 return this.readPackedField_(this.decoder_.readInt32);
1057};
1058
1059
1060/**
1061 * Reads a packed sfixed64 field, which consists of a length header and a list
1062 * of 64-bit ints.
1063 * @return {!Array.<number>}
1064 */
1065jspb.BinaryReader.prototype.readPackedSfixed64 = function() {
1066 return this.readPackedField_(this.decoder_.readInt64);
1067};
1068
1069
1070/**
1071 * Reads a packed float field, which consists of a length header and a list of
1072 * floats.
1073 * @return {!Array.<number>}
1074 */
1075jspb.BinaryReader.prototype.readPackedFloat = function() {
1076 return this.readPackedField_(this.decoder_.readFloat);
1077};
1078
1079
1080/**
1081 * Reads a packed double field, which consists of a length header and a list of
1082 * doubles.
1083 * @return {!Array.<number>}
1084 */
1085jspb.BinaryReader.prototype.readPackedDouble = function() {
1086 return this.readPackedField_(this.decoder_.readDouble);
1087};
1088
1089
1090/**
1091 * Reads a packed bool field, which consists of a length header and a list of
1092 * unsigned varints.
1093 * @return {!Array.<boolean>}
1094 */
1095jspb.BinaryReader.prototype.readPackedBool = function() {
1096 return this.readPackedField_(this.decoder_.readBool);
1097};
1098
1099
1100/**
1101 * Reads a packed enum field, which consists of a length header and a list of
1102 * unsigned varints.
1103 * @return {!Array.<number>}
1104 */
1105jspb.BinaryReader.prototype.readPackedEnum = function() {
1106 return this.readPackedField_(this.decoder_.readEnum);
1107};
1108
1109
1110/**
1111 * Reads a packed varint hash64 field, which consists of a length header and a
1112 * list of varint hash64s.
1113 * @return {!Array.<string>}
1114 */
1115jspb.BinaryReader.prototype.readPackedVarintHash64 = function() {
1116 return this.readPackedField_(this.decoder_.readVarintHash64);
1117};
1118
1119
1120/**
1121 * Reads a packed fixed hash64 field, which consists of a length header and a
1122 * list of fixed hash64s.
1123 * @return {!Array.<string>}
1124 */
1125jspb.BinaryReader.prototype.readPackedFixedHash64 = function() {
1126 return this.readPackedField_(this.decoder_.readFixedHash64);
1127};