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('Invalid wire type'); 294 this.error_ = true; 295 return false; 296 } 297 298 this.nextField_ = nextField; 299 this.nextWireType_ = nextWireType; 300 301 return true; 302}; 303 304 305/** 306 * Winds the reader back to just before this field's header. 307 */ 308jspb.BinaryReader.prototype.unskipHeader = function() { 309 this.decoder_.unskipVarint((this.nextField_ << 3) | this.nextWireType_); 310}; 311 312 313/** 314 * Skips all contiguous fields whose header matches the one we just read. 315 */ 316jspb.BinaryReader.prototype.skipMatchingFields = function() { 317 var field = this.nextField_; 318 this.unskipHeader(); 319 320 while (this.nextField() && (this.getFieldNumber() == field)) { 321 this.skipField(); 322 } 323 324 if (!this.decoder_.atEnd()) { 325 this.unskipHeader(); 326 } 327}; 328 329 330/** 331 * Skips over the next varint field in the binary stream. 332 */ 333jspb.BinaryReader.prototype.skipVarintField = function() { 334 if (this.nextWireType_ != jspb.BinaryConstants.WireType.VARINT) { 335 goog.asserts.fail('Invalid wire type for skipVarintField'); 336 this.skipField(); 337 return; 338 } 339 340 this.decoder_.skipVarint(); 341}; 342 343 344/** 345 * Skips over the next delimited field in the binary stream. 346 */ 347jspb.BinaryReader.prototype.skipDelimitedField = function() { 348 if (this.nextWireType_ != jspb.BinaryConstants.WireType.DELIMITED) { 349 goog.asserts.fail('Invalid wire type for skipDelimitedField'); 350 this.skipField(); 351 return; 352 } 353 354 var length = this.decoder_.readUnsignedVarint32(); 355 this.decoder_.advance(length); 356}; 357 358 359/** 360 * Skips over the next fixed32 field in the binary stream. 361 */ 362jspb.BinaryReader.prototype.skipFixed32Field = function() { 363 if (this.nextWireType_ != jspb.BinaryConstants.WireType.FIXED32) { 364 goog.asserts.fail('Invalid wire type for skipFixed32Field'); 365 this.skipField(); 366 return; 367 } 368 369 this.decoder_.advance(4); 370}; 371 372 373/** 374 * Skips over the next fixed64 field in the binary stream. 375 */ 376jspb.BinaryReader.prototype.skipFixed64Field = function() { 377 if (this.nextWireType_ != jspb.BinaryConstants.WireType.FIXED64) { 378 goog.asserts.fail('Invalid wire type for skipFixed64Field'); 379 this.skipField(); 380 return; 381 } 382 383 this.decoder_.advance(8); 384}; 385 386 387/** 388 * Skips over the next group field in the binary stream. 389 */ 390jspb.BinaryReader.prototype.skipGroup = function() { 391 // Keep a stack of start-group tags that must be matched by end-group tags. 392 var nestedGroups = [this.nextField_]; 393 do { 394 if (!this.nextField()) { 395 goog.asserts.fail('Unmatched start-group tag: stream EOF'); 396 this.error_ = true; 397 return; 398 } 399 if (this.nextWireType_ == 400 jspb.BinaryConstants.WireType.START_GROUP) { 401 // Nested group start. 402 nestedGroups.push(this.nextField_); 403 } else if (this.nextWireType_ == 404 jspb.BinaryConstants.WireType.END_GROUP) { 405 // Group end: check that it matches top-of-stack. 406 if (this.nextField_ != nestedGroups.pop()) { 407 goog.asserts.fail('Unmatched end-group tag'); 408 this.error_ = true; 409 return; 410 } 411 } 412 } while (nestedGroups.length > 0); 413}; 414 415 416/** 417 * Skips over the next field in the binary stream - this is useful if we're 418 * decoding a message that contain unknown fields. 419 */ 420jspb.BinaryReader.prototype.skipField = function() { 421 switch (this.nextWireType_) { 422 case jspb.BinaryConstants.WireType.VARINT: 423 this.skipVarintField(); 424 break; 425 case jspb.BinaryConstants.WireType.FIXED64: 426 this.skipFixed64Field(); 427 break; 428 case jspb.BinaryConstants.WireType.DELIMITED: 429 this.skipDelimitedField(); 430 break; 431 case jspb.BinaryConstants.WireType.FIXED32: 432 this.skipFixed32Field(); 433 break; 434 case jspb.BinaryConstants.WireType.START_GROUP: 435 this.skipGroup(); 436 break; 437 default: 438 goog.asserts.fail('Invalid wire encoding for field.'); 439 } 440}; 441 442 443/** 444 * Registers a user-defined read callback. 445 * @param {string} callbackName 446 * @param {function(!jspb.BinaryReader):*} callback 447 */ 448jspb.BinaryReader.prototype.registerReadCallback = 449 function(callbackName, callback) { 450 if (goog.isNull(this.readCallbacks_)) { 451 this.readCallbacks_ = {}; 452 } 453 goog.asserts.assert(!this.readCallbacks_[callbackName]); 454 this.readCallbacks_[callbackName] = callback; 455}; 456 457 458/** 459 * Runs a registered read callback. 460 * @param {string} callbackName The name the callback is registered under. 461 * @return {*} The value returned by the callback. 462 */ 463jspb.BinaryReader.prototype.runReadCallback = function(callbackName) { 464 goog.asserts.assert(!goog.isNull(this.readCallbacks_)); 465 var callback = this.readCallbacks_[callbackName]; 466 goog.asserts.assert(callback); 467 return callback(this); 468}; 469 470 471/** 472 * Reads a field of any valid non-message type from the binary stream. 473 * @param {jspb.BinaryConstants.FieldType} fieldType 474 * @return {jspb.AnyFieldType} 475 */ 476jspb.BinaryReader.prototype.readAny = function(fieldType) { 477 this.nextWireType_ = jspb.BinaryConstants.FieldTypeToWireType(fieldType); 478 var fieldTypes = jspb.BinaryConstants.FieldType; 479 switch (fieldType) { 480 case fieldTypes.DOUBLE: 481 return this.readDouble(); 482 case fieldTypes.FLOAT: 483 return this.readFloat(); 484 case fieldTypes.INT64: 485 return this.readInt64(); 486 case fieldTypes.UINT64: 487 return this.readUint64(); 488 case fieldTypes.INT32: 489 return this.readInt32(); 490 case fieldTypes.FIXED64: 491 return this.readFixed64(); 492 case fieldTypes.FIXED32: 493 return this.readFixed32(); 494 case fieldTypes.BOOL: 495 return this.readBool(); 496 case fieldTypes.STRING: 497 return this.readString(); 498 case fieldTypes.GROUP: 499 goog.asserts.fail('Group field type not supported in readAny()'); 500 case fieldTypes.MESSAGE: 501 goog.asserts.fail('Message field type not supported in readAny()'); 502 case fieldTypes.BYTES: 503 return this.readBytes(); 504 case fieldTypes.UINT32: 505 return this.readUint32(); 506 case fieldTypes.ENUM: 507 return this.readEnum(); 508 case fieldTypes.SFIXED32: 509 return this.readSfixed32(); 510 case fieldTypes.SFIXED64: 511 return this.readSfixed64(); 512 case fieldTypes.SINT32: 513 return this.readSint32(); 514 case fieldTypes.SINT64: 515 return this.readSint64(); 516 case fieldTypes.FHASH64: 517 return this.readFixedHash64(); 518 case fieldTypes.VHASH64: 519 return this.readVarintHash64(); 520 default: 521 goog.asserts.fail('Invalid field type in readAny()'); 522 } 523 return 0; 524}; 525 526 527/** 528 * Deserialize a proto into the provided message object using the provided 529 * reader function. This function is templated as we currently have one client 530 * who is using manual deserialization instead of the code-generated versions. 531 * @template T 532 * @param {T} message 533 * @param {function(T, !jspb.BinaryReader)} reader 534 */ 535jspb.BinaryReader.prototype.readMessage = function(message, reader) { 536 goog.asserts.assert( 537 this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED); 538 539 // Save the current endpoint of the decoder and move it to the end of the 540 // embedded message. 541 var oldEnd = this.decoder_.getEnd(); 542 var length = this.decoder_.readUnsignedVarint32(); 543 var newEnd = this.decoder_.getCursor() + length; 544 this.decoder_.setEnd(newEnd); 545 546 // Deserialize the embedded message. 547 reader(message, this); 548 549 // Advance the decoder past the embedded message and restore the endpoint. 550 this.decoder_.setCursor(newEnd); 551 this.decoder_.setEnd(oldEnd); 552}; 553 554 555/** 556 * Deserialize a proto into the provided message object using the provided 557 * reader function, assuming that the message is serialized as a group 558 * with the given tag. 559 * @template T 560 * @param {number} field 561 * @param {T} message 562 * @param {function(T, !jspb.BinaryReader)} reader 563 */ 564jspb.BinaryReader.prototype.readGroup = 565 function(field, message, reader) { 566 // Ensure that the wire type is correct. 567 goog.asserts.assert( 568 this.nextWireType_ == jspb.BinaryConstants.WireType.START_GROUP); 569 // Ensure that the field number is correct. 570 goog.asserts.assert(this.nextField_ == field); 571 572 // Deserialize the message. The deserialization will stop at an END_GROUP tag. 573 reader(message, this); 574 575 if (!this.error_ && 576 this.nextWireType_ != jspb.BinaryConstants.WireType.END_GROUP) { 577 goog.asserts.fail('Group submessage did not end with an END_GROUP tag'); 578 this.error_ = true; 579 } 580}; 581 582 583/** 584 * Return a decoder that wraps the current delimited field. 585 * @return {!jspb.BinaryDecoder} 586 */ 587jspb.BinaryReader.prototype.getFieldDecoder = function() { 588 goog.asserts.assert( 589 this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED); 590 591 var length = this.decoder_.readUnsignedVarint32(); 592 var start = this.decoder_.getCursor(); 593 var end = start + length; 594 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 an unsigned 32-bit fixed-length integer fiield from the binary stream, 748 * or throws an error if the next field in the stream is not of the correct 749 * wire type. 750 * 751 * @return {number} The value of the double field. 752 */ 753jspb.BinaryReader.prototype.readFixed32 = function() { 754 goog.asserts.assert( 755 this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED32); 756 return this.decoder_.readUint32(); 757}; 758 759 760/** 761 * Reads an unsigned 64-bit fixed-length integer fiield from the binary stream, 762 * or throws an error if the next field in the stream is not of the correct 763 * wire type. 764 * 765 * @return {number} The value of the float field. 766 */ 767jspb.BinaryReader.prototype.readFixed64 = function() { 768 goog.asserts.assert( 769 this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64); 770 return this.decoder_.readUint64(); 771}; 772 773 774/** 775 * Reads a signed 32-bit fixed-length integer fiield from the binary stream, or 776 * throws an error if the next field in the stream is not of the correct wire 777 * type. 778 * 779 * @return {number} The value of the double field. 780 */ 781jspb.BinaryReader.prototype.readSfixed32 = function() { 782 goog.asserts.assert( 783 this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED32); 784 return this.decoder_.readInt32(); 785}; 786 787 788/** 789 * Reads a signed 64-bit fixed-length integer fiield from the binary stream, or 790 * throws an error if the next field in the stream is not of the correct wire 791 * type. 792 * 793 * @return {number} The value of the float field. 794 */ 795jspb.BinaryReader.prototype.readSfixed64 = function() { 796 goog.asserts.assert( 797 this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64); 798 return this.decoder_.readInt64(); 799}; 800 801 802/** 803 * Reads a 32-bit floating-point field from the binary stream, or throws an 804 * error if the next field in the stream is not of the correct wire type. 805 * 806 * @return {number} The value of the float field. 807 */ 808jspb.BinaryReader.prototype.readFloat = function() { 809 goog.asserts.assert( 810 this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED32); 811 return this.decoder_.readFloat(); 812}; 813 814 815/** 816 * Reads a 64-bit floating-point field from the binary stream, or throws an 817 * error if the next field in the stream is not of the correct wire type. 818 * 819 * @return {number} The value of the double field. 820 */ 821jspb.BinaryReader.prototype.readDouble = function() { 822 goog.asserts.assert( 823 this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64); 824 return this.decoder_.readDouble(); 825}; 826 827 828/** 829 * Reads a boolean field from the binary stream, or throws an error if the next 830 * field in the stream is not of the correct wire type. 831 * 832 * @return {boolean} The value of the boolean field. 833 */ 834jspb.BinaryReader.prototype.readBool = function() { 835 goog.asserts.assert( 836 this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); 837 return !!this.decoder_.readUnsignedVarint32(); 838}; 839 840 841/** 842 * Reads an enum field from the binary stream, or throws an error if the next 843 * field in the stream is not of the correct wire type. 844 * 845 * @return {number} The value of the enum field. 846 */ 847jspb.BinaryReader.prototype.readEnum = function() { 848 goog.asserts.assert( 849 this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); 850 return this.decoder_.readSignedVarint64(); 851}; 852 853 854/** 855 * Reads a string field from the binary stream, or throws an error if the next 856 * field in the stream is not of the correct wire type. 857 * 858 * @return {string} The value of the string field. 859 */ 860jspb.BinaryReader.prototype.readString = function() { 861 goog.asserts.assert( 862 this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED); 863 var length = this.decoder_.readUnsignedVarint32(); 864 return this.decoder_.readString(length); 865}; 866 867 868/** 869 * Reads a length-prefixed block of bytes from the binary stream, or returns 870 * null if the next field in the stream has an invalid length value. 871 * 872 * @return {!Uint8Array} The block of bytes. 873 */ 874jspb.BinaryReader.prototype.readBytes = function() { 875 goog.asserts.assert( 876 this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED); 877 var length = this.decoder_.readUnsignedVarint32(); 878 return this.decoder_.readBytes(length); 879}; 880 881 882/** 883 * Reads a 64-bit varint or fixed64 field from the stream and returns it as a 884 * 8-character Unicode string for use as a hash table key, or throws an error 885 * if the next field in the stream is not of the correct wire type. 886 * 887 * @return {string} The hash value. 888 */ 889jspb.BinaryReader.prototype.readVarintHash64 = function() { 890 goog.asserts.assert( 891 this.nextWireType_ == jspb.BinaryConstants.WireType.VARINT); 892 return this.decoder_.readVarintHash64(); 893}; 894 895 896/** 897 * Reads a 64-bit varint or fixed64 field from the stream and returns it as a 898 * 8-character Unicode string for use as a hash table key, or throws an error 899 * if the next field in the stream is not of the correct wire type. 900 * 901 * @return {string} The hash value. 902 */ 903jspb.BinaryReader.prototype.readFixedHash64 = function() { 904 goog.asserts.assert( 905 this.nextWireType_ == jspb.BinaryConstants.WireType.FIXED64); 906 return this.decoder_.readFixedHash64(); 907}; 908 909 910/** 911 * Reads a packed scalar field using the supplied raw reader function. 912 * @param {function()} decodeMethod 913 * @return {!Array} 914 * @private 915 */ 916jspb.BinaryReader.prototype.readPackedField_ = function(decodeMethod) { 917 goog.asserts.assert( 918 this.nextWireType_ == jspb.BinaryConstants.WireType.DELIMITED); 919 var length = this.decoder_.readUnsignedVarint32(); 920 var end = this.decoder_.getCursor() + length; 921 var result = []; 922 while (this.decoder_.getCursor() < end) { 923 // TODO(aappleby): .call is slow 924 result.push(decodeMethod.call(this.decoder_)); 925 } 926 return result; 927}; 928 929 930/** 931 * Reads a packed int32 field, which consists of a length header and a list of 932 * signed varints. 933 * @return {!Array.<number>} 934 */ 935jspb.BinaryReader.prototype.readPackedInt32 = function() { 936 return this.readPackedField_(this.decoder_.readSignedVarint32); 937}; 938 939 940/** 941 * Reads a packed int32 field, which consists of a length header and a list of 942 * signed varints. Returns a list of strings. 943 * @return {!Array.<string>} 944 */ 945jspb.BinaryReader.prototype.readPackedInt32String = function() { 946 return this.readPackedField_(this.decoder_.readSignedVarint32String); 947}; 948 949 950/** 951 * Reads a packed int64 field, which consists of a length header and a list of 952 * signed varints. 953 * @return {!Array.<number>} 954 */ 955jspb.BinaryReader.prototype.readPackedInt64 = function() { 956 return this.readPackedField_(this.decoder_.readSignedVarint64); 957}; 958 959 960/** 961 * Reads a packed int64 field, which consists of a length header and a list of 962 * signed varints. Returns a list of strings. 963 * @return {!Array.<string>} 964 */ 965jspb.BinaryReader.prototype.readPackedInt64String = function() { 966 return this.readPackedField_(this.decoder_.readSignedVarint64String); 967}; 968 969 970/** 971 * Reads a packed uint32 field, which consists of a length header and a list of 972 * unsigned varints. 973 * @return {!Array.<number>} 974 */ 975jspb.BinaryReader.prototype.readPackedUint32 = function() { 976 return this.readPackedField_(this.decoder_.readUnsignedVarint32); 977}; 978 979 980/** 981 * Reads a packed uint32 field, which consists of a length header and a list of 982 * unsigned varints. Returns a list of strings. 983 * @return {!Array.<string>} 984 */ 985jspb.BinaryReader.prototype.readPackedUint32String = function() { 986 return this.readPackedField_(this.decoder_.readUnsignedVarint32String); 987}; 988 989 990/** 991 * Reads a packed uint64 field, which consists of a length header and a list of 992 * unsigned varints. 993 * @return {!Array.<number>} 994 */ 995jspb.BinaryReader.prototype.readPackedUint64 = function() { 996 return this.readPackedField_(this.decoder_.readUnsignedVarint64); 997}; 998 999 1000/** 1001 * Reads a packed uint64 field, which consists of a length header and a list of 1002 * unsigned varints. Returns a list of strings. 1003 * @return {!Array.<string>} 1004 */ 1005jspb.BinaryReader.prototype.readPackedUint64String = function() { 1006 return this.readPackedField_(this.decoder_.readUnsignedVarint64String); 1007}; 1008 1009 1010/** 1011 * Reads a packed sint32 field, which consists of a length header and a list of 1012 * zigzag varints. 1013 * @return {!Array.<number>} 1014 */ 1015jspb.BinaryReader.prototype.readPackedSint32 = function() { 1016 return this.readPackedField_(this.decoder_.readZigzagVarint32); 1017}; 1018 1019 1020/** 1021 * Reads a packed sint64 field, which consists of a length header and a list of 1022 * zigzag varints. 1023 * @return {!Array.<number>} 1024 */ 1025jspb.BinaryReader.prototype.readPackedSint64 = function() { 1026 return this.readPackedField_(this.decoder_.readZigzagVarint64); 1027}; 1028 1029 1030/** 1031 * Reads a packed fixed32 field, which consists of a length header and a list 1032 * of unsigned 32-bit ints. 1033 * @return {!Array.<number>} 1034 */ 1035jspb.BinaryReader.prototype.readPackedFixed32 = function() { 1036 return this.readPackedField_(this.decoder_.readUint32); 1037}; 1038 1039 1040/** 1041 * Reads a packed fixed64 field, which consists of a length header and a list 1042 * of unsigned 64-bit ints. 1043 * @return {!Array.<number>} 1044 */ 1045jspb.BinaryReader.prototype.readPackedFixed64 = function() { 1046 return this.readPackedField_(this.decoder_.readUint64); 1047}; 1048 1049 1050/** 1051 * Reads a packed sfixed32 field, which consists of a length header and a list 1052 * of 32-bit ints. 1053 * @return {!Array.<number>} 1054 */ 1055jspb.BinaryReader.prototype.readPackedSfixed32 = function() { 1056 return this.readPackedField_(this.decoder_.readInt32); 1057}; 1058 1059 1060/** 1061 * Reads a packed sfixed64 field, which consists of a length header and a list 1062 * of 64-bit ints. 1063 * @return {!Array.<number>} 1064 */ 1065jspb.BinaryReader.prototype.readPackedSfixed64 = function() { 1066 return this.readPackedField_(this.decoder_.readInt64); 1067}; 1068 1069 1070/** 1071 * Reads a packed float field, which consists of a length header and a list of 1072 * floats. 1073 * @return {!Array.<number>} 1074 */ 1075jspb.BinaryReader.prototype.readPackedFloat = function() { 1076 return this.readPackedField_(this.decoder_.readFloat); 1077}; 1078 1079 1080/** 1081 * Reads a packed double field, which consists of a length header and a list of 1082 * doubles. 1083 * @return {!Array.<number>} 1084 */ 1085jspb.BinaryReader.prototype.readPackedDouble = function() { 1086 return this.readPackedField_(this.decoder_.readDouble); 1087}; 1088 1089 1090/** 1091 * Reads a packed bool field, which consists of a length header and a list of 1092 * unsigned varints. 1093 * @return {!Array.<boolean>} 1094 */ 1095jspb.BinaryReader.prototype.readPackedBool = function() { 1096 return this.readPackedField_(this.decoder_.readBool); 1097}; 1098 1099 1100/** 1101 * Reads a packed enum field, which consists of a length header and a list of 1102 * unsigned varints. 1103 * @return {!Array.<number>} 1104 */ 1105jspb.BinaryReader.prototype.readPackedEnum = function() { 1106 return this.readPackedField_(this.decoder_.readEnum); 1107}; 1108 1109 1110/** 1111 * Reads a packed varint hash64 field, which consists of a length header and a 1112 * list of varint hash64s. 1113 * @return {!Array.<string>} 1114 */ 1115jspb.BinaryReader.prototype.readPackedVarintHash64 = function() { 1116 return this.readPackedField_(this.decoder_.readVarintHash64); 1117}; 1118 1119 1120/** 1121 * Reads a packed fixed hash64 field, which consists of a length header and a 1122 * list of fixed hash64s. 1123 * @return {!Array.<string>} 1124 */ 1125jspb.BinaryReader.prototype.readPackedFixedHash64 = function() { 1126 return this.readPackedField_(this.decoder_.readFixedHash64); 1127}; 1128