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