OLD | NEW |
(Empty) | |
| 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 |
| 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 = jspb.BinaryDecoder.alloc(this.decoder_.getBuffer(), |
| 596 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 }; |
OLD | NEW |