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'); 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. 183 * @return {?Uint8Array} The raw buffer. 184 */ 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( 294 'Invalid wire type: %s (at position %s)', nextWireType, 295 this.fieldCursor_); 296 this.error_ = true; 297 return false; 298 } 299 300 this.nextField_ = nextField; 301 this.nextWireType_ = nextWireType; 302 303 return true; 304}; 305 306 307/** 308 * Winds the reader back to just before this field's header. 309 */ 310jspb.BinaryReader.prototype.unskipHeader = function() { 311 this.decoder_.unskipVarint((this.nextField_ << 3) | this.nextWireType_); 312}; 313 314 315/** 316 * Skips all contiguous fields whose header matches the one we just read. 317 */ 318jspb.BinaryReader.prototype.skipMatchingFields = function() { 319 var field = this.nextField_; 320 this.unskipHeader(); 321 322 while (this.nextField() && (this.getFieldNumber() == field)) { 323 this.skipField(); 324 } 325 326 if (!this.decoder_.atEnd()) { 327 this.unskipHeader(); 328 } 329}; 330 331 332/** 333 * Skips over the next varint field in the binary stream. 334 */ 335jspb.BinaryReader.prototype.skipVarintField = function() { 336 if (this.nextWireType_ != jspb.BinaryConstants.WireType.VARINT) { 337 goog.asserts.fail('Invalid wire type for skipVarintField'); 338 this.skipField(); 339 return; 340 } 341 342 this.decoder_.skipVarint(); 343}; 344 345 346/** 347 * Skips over the next delimited field in the binary stream. 348 */ 349jspb.BinaryReader.prototype.skipDelimitedField = function() { 350 if (this.nextWireType_ != jspb.BinaryConstants.WireType.DELIMITED) { 351 goog.asserts.fail('Invalid wire type for skipDelimitedField'); 352 this.skipField(); 353 return; 354 } 355 356 var length = this.decoder_.readUnsignedVarint32(); 357 this.decoder_.advance(length); 358}; 359 360 361/** 362 * Skips over the next fixed32 field in the binary stream. 363 */ 364jspb.BinaryReader.prototype.skipFixed32Field = function() { 365 if (this.nextWireType_ != jspb.BinaryConstants.WireType.FIXED32) { 366 goog.asserts.fail('Invalid wire type for skipFixed32Field'); 367 this.skipField(); 368 return; 369 } 370 371 this.decoder_.advance(4); 372}; 373 374 375/** 376 * Skips over the next fixed64 field in the binary stream. 377 */ 378jspb.BinaryReader.prototype.skipFixed64Field = function() { 379 if (this.nextWireType_ != jspb.BinaryConstants.WireType.FIXED64) { 380 goog.asserts.fail('Invalid wire type for skipFixed64Field'); 381 this.skipField(); 382 return; 383 } 384 385 this.decoder_.advance(8); 386}; 387 388 389/** 390 * Skips over the next group field in the binary stream. 391 */ 392jspb.BinaryReader.prototype.skipGroup = function() { 393 var previousField = this.nextField_; 394 do { 395 if (!this.nextField()) { 396 goog.asserts.fail('Unmatched start-group tag: stream EOF'); 397 this.error_ = true; 398 return; 399 } 400 if (this.nextWireType_ == 401 jspb.BinaryConstants.WireType.END_GROUP) { 402 // Group end: check that it matches top-of-stack. 403 if (this.nextField_ != previousField) { 404 goog.asserts.fail('Unmatched end-group tag'); 405 this.error_ = true; 406 return; 407 } 408 return; 409 } 410 this.skipField(); 411 } while (true); 412}; 413 414 415/** 416 * Skips over the next field in the binary stream - this is useful if we're 417 * decoding a message that contain unknown fields. 418 */ 419jspb.BinaryReader.prototype.skipField = function() { 420 switch (this.nextWireType_) { 421 case jspb.BinaryConstants.WireType.VARINT: 422 this.skipVarintField(); 423 break; 424 case jspb.BinaryConstants.WireType.FIXED64: 425 this.skipFixed64Field(); 426 break; 427 case jspb.BinaryConstants.WireType.DELIMITED: 428 this.skipDelimitedField(); 429 break; 430 case jspb.BinaryConstants.WireType.FIXED32: 431 this.skipFixed32Field(); 432 break; 433 case jspb.BinaryConstants.WireType.START_GROUP: 434 this.skipGroup(); 435 break; 436 default: 437 goog.asserts.fail('Invalid wire encoding for field.'); 438 } 439}; 440 441 442/** 443 * Registers a user-defined read callback. 444 * @param {string} callbackName 445 * @param {function(!jspb.BinaryReader):*} callback 446 */ 447jspb.BinaryReader.prototype.registerReadCallback = 448 function(callbackName, callback) { 449 if (goog.isNull(this.readCallbacks_)) { 450 this.readCallbacks_ = {}; 451 } 452 goog.asserts.assert(!this.readCallbacks_[callbackName]); 453 this.readCallbacks_[callbackName] = callback; 454}; 455 456 457/** 458 * Runs a registered read callback. 459 * @param {string} callbackName The name the callback is registered under. 460 * @return {*} The value returned by the callback. 461 */ 462jspb.BinaryReader.prototype.runReadCallback = function(callbackName) { 463 goog.asserts.assert(!goog.isNull(this.readCallbacks_)); 464 var callback = this.readCallbacks_[callbackName]; 465 goog.asserts.assert(callback); 466 return callback(this); 467}; 468 469 470/** 471 * Reads a field of any valid non-message type from the binary stream. 472 * @param {jspb.BinaryConstants.FieldType} fieldType 473 * @return {jspb.AnyFieldType} 474 */ 475jspb.BinaryReader.prototype.readAny = function(fieldType) { 476 this.nextWireType_ = jspb.BinaryConstants.FieldTypeToWireType(fieldType); 477 var fieldTypes = jspb.BinaryConstants.FieldType; 478 switch (fieldType) { 479 case fieldTypes.DOUBLE: 480 return this.readDouble(); 481 case fieldTypes.FLOAT: 482 return this.readFloat(); 483 case fieldTypes.INT64: 484 return this.readInt64(); 485 case fieldTypes.UINT64: 486 return this.readUint64(); 487 case fieldTypes.INT32: 488 return this.readInt32(); 489 case fieldTypes.FIXED64: 490 return this.readFixed64(); 491 case fieldTypes.FIXED32: 492 return this.readFixed32(); 493 case fieldTypes.BOOL: 494 return this.readBool(); 495 case fieldTypes.STRING: 496 return this.readString(); 497 case fieldTypes.GROUP: 498 goog.asserts.fail('Group field type not supported in readAny()'); 499 case fieldTypes.MESSAGE: 500 goog.asserts.fail('Message field type not supported in readAny()'); 501 case fieldTypes.BYTES: 502 return this.readBytes(); 503 case fieldTypes.UINT32: 504 return this.readUint32(); 505 case fieldTypes.ENUM: 506 return this.readEnum(); 507 case fieldTypes.SFIXED32: 508 return this.readSfixed32(); 509 case fieldTypes.SFIXED64: 510 return this.readSfixed64(); 511 case fieldTypes.SINT32: 512 return this.readSint32(); 513 case fieldTypes.SINT64: 514 return this.readSint64(); 515 case fieldTypes.FHASH64: 516 return this.readFixedHash64(); 517 case fieldTypes.VHASH64: 518 return this.readVarintHash64(); 519 default: 520 goog.asserts.fail('Invalid field type in readAny()'); 521 } 522 return 0; 523}; 524 525 526/** 527 * Deserialize a proto into the provided message object using the provided 528 * reader function. This function is templated as we currently have one client 529 * who is using manual deserialization instead of the code-generated versions. 530 * @template T 531 * @param {T} message 532 * @param {function(T, !jspb.BinaryReader)} reader 533 */ 534jspb.BinaryReader.prototype.readMessage = function(message, reader) { 535 goog.asserts.assert( 536 this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED); 537 538 // Save the current endpoint of the decoder and move it to the end of the 539 // embedded message. 540 var oldEnd = this.decoder_.getEnd(); 541 var length = this.decoder_.readUnsignedVarint32(); 542 var newEnd = this.decoder_.getCursor() + length; 543 this.decoder_.setEnd(newEnd); 544 545 // Deserialize the embedded message. 546 reader(message, this); 547 548 // Advance the decoder past the embedded message and restore the endpoint. 549 this.decoder_.setCursor(newEnd); 550 this.decoder_.setEnd(oldEnd); 551}; 552 553 554/** 555 * Deserialize a proto into the provided message object using the provided 556 * reader function, assuming that the message is serialized as a group 557 * with the given tag. 558 * @template T 559 * @param {number} field 560 * @param {T} message 561 * @param {function(T, !jspb.BinaryReader)} reader 562 */ 563jspb.BinaryReader.prototype.readGroup = 564 function(field, message, reader) { 565 // Ensure that the wire type is correct. 566 goog.asserts.assert( 567 this.nextWireType_ == jspb.BinaryConstants.WireType.START_GROUP); 568 // Ensure that the field number is correct. 569 goog.asserts.assert(this.nextField_ == field); 570 571 // Deserialize the message. The deserialization will stop at an END_GROUP tag. 572 reader(message, this); 573 574 if (!this.error_ && 575 this.nextWireType_ != jspb.BinaryConstants.WireType.END_GROUP) { 576 goog.asserts.fail('Group submessage did not end with an END_GROUP tag'); 577 this.error_ = true; 578 } 579}; 580 581 582/** 583 * Return a decoder that wraps the current delimited field. 584 * @return {!jspb.BinaryDecoder} 585 */ 586jspb.BinaryReader.prototype.getFieldDecoder = function() { 587 goog.asserts.assert( 588 this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED); 589 590 var length = this.decoder_.readUnsignedVarint32(); 591 var start = this.decoder_.getCursor(); 592 var end = start + length; 593 594 var innerDecoder = 595 jspb.BinaryDecoder.alloc(this.decoder_.getBuffer(), start, length); 596 this.decoder_.setCursor(end); 597 return innerDecoder; 598}; 599 600 601/** 602 * Reads a signed 32-bit integer field from the binary stream, or throws an 603 * error if the next field in the stream is not of the correct wire type. 604 * 605 * @return {number} The value of the signed 32-bit integer field. 606 */ 607jspb.BinaryReader.prototype.readInt32 = function() { 608 goog.asserts.assert( 609 this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); 610 return this.decoder_.readSignedVarint32(); 611}; 612 613 614/** 615 * Reads a signed 32-bit integer field from the binary stream, or throws an 616 * error if the next field in the stream is not of the correct wire type. 617 * 618 * Returns the value as a string. 619 * 620 * @return {string} The value of the signed 32-bit integer field as a decimal 621 * string. 622 */ 623jspb.BinaryReader.prototype.readInt32String = function() { 624 goog.asserts.assert( 625 this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); 626 return this.decoder_.readSignedVarint32String(); 627}; 628 629 630/** 631 * Reads a signed 64-bit integer field from the binary stream, or throws an 632 * error if the next field in the stream is not of the correct wire type. 633 * 634 * @return {number} The value of the signed 64-bit integer field. 635 */ 636jspb.BinaryReader.prototype.readInt64 = function() { 637 goog.asserts.assert( 638 this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); 639 return this.decoder_.readSignedVarint64(); 640}; 641 642 643/** 644 * Reads a signed 64-bit integer field from the binary stream, or throws an 645 * error if the next field in the stream is not of the correct wire type. 646 * 647 * Returns the value as a string. 648 * 649 * @return {string} The value of the signed 64-bit integer field as a decimal 650 * string. 651 */ 652jspb.BinaryReader.prototype.readInt64String = function() { 653 goog.asserts.assert( 654 this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); 655 return this.decoder_.readSignedVarint64String(); 656}; 657 658 659/** 660 * Reads an unsigned 32-bit integer field from the binary stream, or throws an 661 * error if the next field in the stream is not of the correct wire type. 662 * 663 * @return {number} The value of the unsigned 32-bit integer field. 664 */ 665jspb.BinaryReader.prototype.readUint32 = function() { 666 goog.asserts.assert( 667 this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); 668 return this.decoder_.readUnsignedVarint32(); 669}; 670 671 672/** 673 * Reads an unsigned 32-bit integer field from the binary stream, or throws an 674 * error if the next field in the stream is not of the correct wire type. 675 * 676 * Returns the value as a string. 677 * 678 * @return {string} The value of the unsigned 32-bit integer field as a decimal 679 * string. 680 */ 681jspb.BinaryReader.prototype.readUint32String = function() { 682 goog.asserts.assert( 683 this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); 684 return this.decoder_.readUnsignedVarint32String(); 685}; 686 687 688/** 689 * Reads an unsigned 64-bit integer field from the binary stream, or throws an 690 * error if the next field in the stream is not of the correct wire type. 691 * 692 * @return {number} The value of the unsigned 64-bit integer field. 693 */ 694jspb.BinaryReader.prototype.readUint64 = function() { 695 goog.asserts.assert( 696 this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); 697 return this.decoder_.readUnsignedVarint64(); 698}; 699 700 701/** 702 * Reads an unsigned 64-bit integer field from the binary stream, or throws an 703 * error if the next field in the stream is not of the correct wire type. 704 * 705 * Returns the value as a string. 706 * 707 * @return {string} The value of the unsigned 64-bit integer field as a decimal 708 * string. 709 */ 710jspb.BinaryReader.prototype.readUint64String = function() { 711 goog.asserts.assert( 712 this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); 713 return this.decoder_.readUnsignedVarint64String(); 714}; 715 716 717/** 718 * Reads a signed zigzag-encoded 32-bit integer field from the binary stream, 719 * or throws an error if the next field in the stream is not of the correct 720 * wire type. 721 * 722 * @return {number} The value of the signed 32-bit integer field. 723 */ 724jspb.BinaryReader.prototype.readSint32 = function() { 725 goog.asserts.assert( 726 this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); 727 return this.decoder_.readZigzagVarint32(); 728}; 729 730 731/** 732 * Reads a signed zigzag-encoded 64-bit integer field from the binary stream, 733 * or throws an error if the next field in the stream is not of the correct 734 * wire type. 735 * 736 * @return {number} The value of the signed 64-bit integer field. 737 */ 738jspb.BinaryReader.prototype.readSint64 = function() { 739 goog.asserts.assert( 740 this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); 741 return this.decoder_.readZigzagVarint64(); 742}; 743 744 745/** 746 * Reads a signed zigzag-encoded 64-bit integer field from the binary stream, 747 * or throws an error if the next field in the stream is not of the correct 748 * wire type. 749 * 750 * @return {string} The value of the signed 64-bit integer field as a decimal string. 751 */ 752jspb.BinaryReader.prototype.readSint64String = function() { 753 goog.asserts.assert( 754 this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); 755 return this.decoder_.readZigzagVarint64String(); 756}; 757 758 759/** 760 * Reads an unsigned 32-bit fixed-length integer fiield from the binary stream, 761 * or throws an error if the next field in the stream is not of the correct 762 * wire type. 763 * 764 * @return {number} The value of the double field. 765 */ 766jspb.BinaryReader.prototype.readFixed32 = function() { 767 goog.asserts.assert( 768 this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED32); 769 return this.decoder_.readUint32(); 770}; 771 772 773/** 774 * Reads an unsigned 64-bit fixed-length integer fiield from the binary stream, 775 * or throws an error if the next field in the stream is not of the correct 776 * wire type. 777 * 778 * @return {number} The value of the float field. 779 */ 780jspb.BinaryReader.prototype.readFixed64 = function() { 781 goog.asserts.assert( 782 this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64); 783 return this.decoder_.readUint64(); 784}; 785 786 787/** 788 * Reads a signed 64-bit integer field from the binary stream as a string, or 789 * throws an error if the next field in the stream is not of the correct wire 790 * type. 791 * 792 * Returns the value as a string. 793 * 794 * @return {string} The value of the unsigned 64-bit integer field as a decimal 795 * string. 796 */ 797jspb.BinaryReader.prototype.readFixed64String = function() { 798 goog.asserts.assert( 799 this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64); 800 return this.decoder_.readUint64String(); 801}; 802 803 804/** 805 * Reads a signed 32-bit fixed-length integer fiield from the binary stream, or 806 * throws an error if the next field in the stream is not of the correct wire 807 * type. 808 * 809 * @return {number} The value of the signed 32-bit integer field. 810 */ 811jspb.BinaryReader.prototype.readSfixed32 = function() { 812 goog.asserts.assert( 813 this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED32); 814 return this.decoder_.readInt32(); 815}; 816 817 818/** 819 * Reads a signed 32-bit fixed-length integer fiield from the binary stream, or 820 * throws an error if the next field in the stream is not of the correct wire 821 * type. 822 * 823 * @return {string} The value of the signed 32-bit integer field as a decimal 824 * string. 825 */ 826jspb.BinaryReader.prototype.readSfixed32String = function() { 827 goog.asserts.assert( 828 this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED32); 829 return this.decoder_.readInt32().toString(); 830}; 831 832 833/** 834 * Reads a signed 64-bit fixed-length integer fiield from the binary stream, or 835 * throws an error if the next field in the stream is not of the correct wire 836 * type. 837 * 838 * @return {number} The value of the sfixed64 field. 839 */ 840jspb.BinaryReader.prototype.readSfixed64 = function() { 841 goog.asserts.assert( 842 this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64); 843 return this.decoder_.readInt64(); 844}; 845 846 847/** 848 * Reads a signed 64-bit fixed-length integer fiield from the binary stream, or 849 * throws an error if the next field in the stream is not of the correct wire 850 * type. 851 * 852 * Returns the value as a string. 853 * 854 * @return {string} The value of the sfixed64 field as a decimal string. 855 */ 856jspb.BinaryReader.prototype.readSfixed64String = function() { 857 goog.asserts.assert( 858 this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64); 859 return this.decoder_.readInt64String(); 860}; 861 862 863/** 864 * Reads a 32-bit floating-point field from the binary stream, or throws an 865 * error if the next field in the stream is not of the correct wire type. 866 * 867 * @return {number} The value of the float field. 868 */ 869jspb.BinaryReader.prototype.readFloat = function() { 870 goog.asserts.assert( 871 this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED32); 872 return this.decoder_.readFloat(); 873}; 874 875 876/** 877 * Reads a 64-bit floating-point field from the binary stream, or throws an 878 * error if the next field in the stream is not of the correct wire type. 879 * 880 * @return {number} The value of the double field. 881 */ 882jspb.BinaryReader.prototype.readDouble = function() { 883 goog.asserts.assert( 884 this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64); 885 return this.decoder_.readDouble(); 886}; 887 888 889/** 890 * Reads a boolean field from the binary stream, or throws an error if the next 891 * field in the stream is not of the correct wire type. 892 * 893 * @return {boolean} The value of the boolean field. 894 */ 895jspb.BinaryReader.prototype.readBool = function() { 896 goog.asserts.assert( 897 this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); 898 return !!this.decoder_.readUnsignedVarint32(); 899}; 900 901 902/** 903 * Reads an enum field from the binary stream, or throws an error if the next 904 * field in the stream is not of the correct wire type. 905 * 906 * @return {number} The value of the enum field. 907 */ 908jspb.BinaryReader.prototype.readEnum = function() { 909 goog.asserts.assert( 910 this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); 911 return this.decoder_.readSignedVarint64(); 912}; 913 914 915/** 916 * Reads a string field from the binary stream, or throws an error if the next 917 * field in the stream is not of the correct wire type. 918 * 919 * @return {string} The value of the string field. 920 */ 921jspb.BinaryReader.prototype.readString = function() { 922 goog.asserts.assert( 923 this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED); 924 var length = this.decoder_.readUnsignedVarint32(); 925 return this.decoder_.readString(length); 926}; 927 928 929/** 930 * Reads a length-prefixed block of bytes from the binary stream, or returns 931 * null if the next field in the stream has an invalid length value. 932 * 933 * @return {!Uint8Array} The block of bytes. 934 */ 935jspb.BinaryReader.prototype.readBytes = function() { 936 goog.asserts.assert( 937 this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED); 938 var length = this.decoder_.readUnsignedVarint32(); 939 return this.decoder_.readBytes(length); 940}; 941 942 943/** 944 * Reads a 64-bit varint or fixed64 field from the stream and returns it as a 945 * 8-character Unicode string for use as a hash table key, or throws an error 946 * if the next field in the stream is not of the correct wire type. 947 * 948 * @return {string} The hash value. 949 */ 950jspb.BinaryReader.prototype.readVarintHash64 = function() { 951 goog.asserts.assert( 952 this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); 953 return this.decoder_.readVarintHash64(); 954}; 955 956 957/** 958 * Reads a 64-bit varint or fixed64 field from the stream and returns it as a 959 * 8-character Unicode string for use as a hash table key, or throws an error 960 * if the next field in the stream is not of the correct wire type. 961 * 962 * @return {string} The hash value. 963 */ 964jspb.BinaryReader.prototype.readFixedHash64 = function() { 965 goog.asserts.assert( 966 this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64); 967 return this.decoder_.readFixedHash64(); 968}; 969 970 971/** 972 * Reads a packed scalar field using the supplied raw reader function. 973 * @param {function(this:jspb.BinaryDecoder)} decodeMethod 974 * @return {!Array} 975 * @private 976 */ 977jspb.BinaryReader.prototype.readPackedField_ = function(decodeMethod) { 978 goog.asserts.assert( 979 this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED); 980 var length = this.decoder_.readUnsignedVarint32(); 981 var end = this.decoder_.getCursor() + length; 982 var result = []; 983 while (this.decoder_.getCursor() < end) { 984 // TODO(aappleby): .call is slow 985 result.push(decodeMethod.call(this.decoder_)); 986 } 987 return result; 988}; 989 990 991/** 992 * Reads a packed int32 field, which consists of a length header and a list of 993 * signed varints. 994 * @return {!Array<number>} 995 */ 996jspb.BinaryReader.prototype.readPackedInt32 = function() { 997 return this.readPackedField_(this.decoder_.readSignedVarint32); 998}; 999 1000 1001/** 1002 * Reads a packed int32 field, which consists of a length header and a list of 1003 * signed varints. Returns a list of strings. 1004 * @return {!Array<string>} 1005 */ 1006jspb.BinaryReader.prototype.readPackedInt32String = function() { 1007 return this.readPackedField_(this.decoder_.readSignedVarint32String); 1008}; 1009 1010 1011/** 1012 * Reads a packed int64 field, which consists of a length header and a list of 1013 * signed varints. 1014 * @return {!Array<number>} 1015 */ 1016jspb.BinaryReader.prototype.readPackedInt64 = function() { 1017 return this.readPackedField_(this.decoder_.readSignedVarint64); 1018}; 1019 1020 1021/** 1022 * Reads a packed int64 field, which consists of a length header and a list of 1023 * signed varints. Returns a list of strings. 1024 * @return {!Array<string>} 1025 */ 1026jspb.BinaryReader.prototype.readPackedInt64String = function() { 1027 return this.readPackedField_(this.decoder_.readSignedVarint64String); 1028}; 1029 1030 1031/** 1032 * Reads a packed uint32 field, which consists of a length header and a list of 1033 * unsigned varints. 1034 * @return {!Array<number>} 1035 */ 1036jspb.BinaryReader.prototype.readPackedUint32 = function() { 1037 return this.readPackedField_(this.decoder_.readUnsignedVarint32); 1038}; 1039 1040 1041/** 1042 * Reads a packed uint32 field, which consists of a length header and a list of 1043 * unsigned varints. Returns a list of strings. 1044 * @return {!Array<string>} 1045 */ 1046jspb.BinaryReader.prototype.readPackedUint32String = function() { 1047 return this.readPackedField_(this.decoder_.readUnsignedVarint32String); 1048}; 1049 1050 1051/** 1052 * Reads a packed uint64 field, which consists of a length header and a list of 1053 * unsigned varints. 1054 * @return {!Array<number>} 1055 */ 1056jspb.BinaryReader.prototype.readPackedUint64 = function() { 1057 return this.readPackedField_(this.decoder_.readUnsignedVarint64); 1058}; 1059 1060 1061/** 1062 * Reads a packed uint64 field, which consists of a length header and a list of 1063 * unsigned varints. Returns a list of strings. 1064 * @return {!Array<string>} 1065 */ 1066jspb.BinaryReader.prototype.readPackedUint64String = function() { 1067 return this.readPackedField_(this.decoder_.readUnsignedVarint64String); 1068}; 1069 1070 1071/** 1072 * Reads a packed sint32 field, which consists of a length header and a list of 1073 * zigzag varints. 1074 * @return {!Array<number>} 1075 */ 1076jspb.BinaryReader.prototype.readPackedSint32 = function() { 1077 return this.readPackedField_(this.decoder_.readZigzagVarint32); 1078}; 1079 1080 1081/** 1082 * Reads a packed sint64 field, which consists of a length header and a list of 1083 * zigzag varints. 1084 * @return {!Array<number>} 1085 */ 1086jspb.BinaryReader.prototype.readPackedSint64 = function() { 1087 return this.readPackedField_(this.decoder_.readZigzagVarint64); 1088}; 1089 1090 1091/** 1092 * Reads a packed sint64 field, which consists of a length header and a list of 1093 * zigzag varints. Returns a list of strings. 1094 * @return {!Array<string>} 1095 */ 1096jspb.BinaryReader.prototype.readPackedSint64String = function() { 1097 return this.readPackedField_(this.decoder_.readZigzagVarint64String); 1098}; 1099 1100 1101/** 1102 * Reads a packed fixed32 field, which consists of a length header and a list 1103 * of unsigned 32-bit ints. 1104 * @return {!Array<number>} 1105 */ 1106jspb.BinaryReader.prototype.readPackedFixed32 = function() { 1107 return this.readPackedField_(this.decoder_.readUint32); 1108}; 1109 1110 1111/** 1112 * Reads a packed fixed64 field, which consists of a length header and a list 1113 * of unsigned 64-bit ints. 1114 * @return {!Array<number>} 1115 */ 1116jspb.BinaryReader.prototype.readPackedFixed64 = function() { 1117 return this.readPackedField_(this.decoder_.readUint64); 1118}; 1119 1120 1121/** 1122 * Reads a packed fixed64 field, which consists of a length header and a list 1123 * of unsigned 64-bit ints. Returns a list of strings. 1124 * @return {!Array<number>} 1125 */ 1126jspb.BinaryReader.prototype.readPackedFixed64String = function() { 1127 return this.readPackedField_(this.decoder_.readUint64String); 1128}; 1129 1130 1131/** 1132 * Reads a packed sfixed32 field, which consists of a length header and a list 1133 * of 32-bit ints. 1134 * @return {!Array<number>} 1135 */ 1136jspb.BinaryReader.prototype.readPackedSfixed32 = function() { 1137 return this.readPackedField_(this.decoder_.readInt32); 1138}; 1139 1140 1141/** 1142 * Reads a packed sfixed64 field, which consists of a length header and a list 1143 * of 64-bit ints. 1144 * @return {!Array<number>} 1145 */ 1146jspb.BinaryReader.prototype.readPackedSfixed64 = function() { 1147 return this.readPackedField_(this.decoder_.readInt64); 1148}; 1149 1150 1151/** 1152 * Reads a packed sfixed64 field, which consists of a length header and a list 1153 * of 64-bit ints. Returns a list of strings. 1154 * @return {!Array<string>} 1155 */ 1156jspb.BinaryReader.prototype.readPackedSfixed64String = function() { 1157 return this.readPackedField_(this.decoder_.readInt64String); 1158}; 1159 1160 1161/** 1162 * Reads a packed float field, which consists of a length header and a list of 1163 * floats. 1164 * @return {!Array<number>} 1165 */ 1166jspb.BinaryReader.prototype.readPackedFloat = function() { 1167 return this.readPackedField_(this.decoder_.readFloat); 1168}; 1169 1170 1171/** 1172 * Reads a packed double field, which consists of a length header and a list of 1173 * doubles. 1174 * @return {!Array<number>} 1175 */ 1176jspb.BinaryReader.prototype.readPackedDouble = function() { 1177 return this.readPackedField_(this.decoder_.readDouble); 1178}; 1179 1180 1181/** 1182 * Reads a packed bool field, which consists of a length header and a list of 1183 * unsigned varints. 1184 * @return {!Array<boolean>} 1185 */ 1186jspb.BinaryReader.prototype.readPackedBool = function() { 1187 return this.readPackedField_(this.decoder_.readBool); 1188}; 1189 1190 1191/** 1192 * Reads a packed enum field, which consists of a length header and a list of 1193 * unsigned varints. 1194 * @return {!Array<number>} 1195 */ 1196jspb.BinaryReader.prototype.readPackedEnum = function() { 1197 return this.readPackedField_(this.decoder_.readEnum); 1198}; 1199 1200 1201/** 1202 * Reads a packed varint hash64 field, which consists of a length header and a 1203 * list of varint hash64s. 1204 * @return {!Array<string>} 1205 */ 1206jspb.BinaryReader.prototype.readPackedVarintHash64 = function() { 1207 return this.readPackedField_(this.decoder_.readVarintHash64); 1208}; 1209 1210 1211/** 1212 * Reads a packed fixed hash64 field, which consists of a length header and a 1213 * list of fixed hash64s. 1214 * @return {!Array<string>} 1215 */ 1216jspb.BinaryReader.prototype.readPackedFixedHash64 = function() { 1217 return this.readPackedField_(this.decoder_.readFixedHash64); 1218}; 1219