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