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 (a] google.com (Austin Appleby) 45 */ 46 47 goog.provide('jspb.BinaryReader'); 48 49 goog.require('goog.asserts'); 50 goog.require('jspb.BinaryConstants'); 51 goog.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 */ 66 jspb.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 */ 110 jspb.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 */ 122 jspb.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 */ 144 jspb.BinaryReader.prototype.alloc = jspb.BinaryReader.alloc; 145 146 147 /** 148 * Puts this instance back in the instance cache. 149 */ 150 jspb.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 */ 167 jspb.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 */ 176 jspb.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 */ 185 jspb.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 */ 194 jspb.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 */ 203 jspb.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 */ 212 jspb.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 */ 221 jspb.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 */ 232 jspb.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 */ 243 jspb.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 */ 254 jspb.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 */ 265 jspb.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 */ 308 jspb.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 */ 316 jspb.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 */ 333 jspb.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 */ 347 jspb.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 */ 362 jspb.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 */ 376 jspb.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 */ 390 jspb.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 */ 420 jspb.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 */ 448 jspb.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 */ 463 jspb.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 */ 476 jspb.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 */ 535 jspb.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 */ 564 jspb.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 */ 587 jspb.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 */ 608 jspb.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 */ 624 jspb.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 */ 637 jspb.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 */ 653 jspb.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 */ 666 jspb.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 */ 682 jspb.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 */ 695 jspb.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 */ 711 jspb.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 */ 725 jspb.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 */ 739 jspb.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 */ 753 jspb.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 */ 767 jspb.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 */ 781 jspb.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 */ 795 jspb.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 */ 808 jspb.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 */ 821 jspb.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 */ 834 jspb.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 */ 847 jspb.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 */ 860 jspb.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 */ 874 jspb.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 */ 889 jspb.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 */ 903 jspb.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 */ 916 jspb.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 */ 935 jspb.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 */ 945 jspb.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 */ 955 jspb.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 */ 965 jspb.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 */ 975 jspb.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 */ 985 jspb.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 */ 995 jspb.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 */ 1005 jspb.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 */ 1015 jspb.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 */ 1025 jspb.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 */ 1035 jspb.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 */ 1045 jspb.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 */ 1055 jspb.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 */ 1065 jspb.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 */ 1075 jspb.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 */ 1085 jspb.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 */ 1095 jspb.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 */ 1105 jspb.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 */ 1115 jspb.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 */ 1125 jspb.BinaryReader.prototype.readPackedFixedHash64 = function() { 1126 return this.readPackedField_(this.decoder_.readFixedHash64); 1127 }; 1128