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 encoding Javascript objects 33 * into binary, wire-format protocol buffers (in the form of Uint8Arrays) that 34 * a server can consume directly. 35 * 36 * jspb's BinaryWriter class defines methods for efficiently encoding 37 * Javascript objects into binary, wire-format protocol buffers and supports 38 * all the fundamental field types used in protocol buffers. 39 * 40 * Major caveat 1 - Users of this library _must_ keep their Javascript proto 41 * parsing code in sync with the original .proto file - presumably you'll be 42 * using the typed jspb code generator, but if you bypass that you'll need 43 * to keep things in sync by hand. 44 * 45 * Major caveat 2 - Javascript is unable to accurately represent integers 46 * larger than 2^53 due to its use of a double-precision floating point format 47 * for all numbers. BinaryWriter does not make any special effort to preserve 48 * precision for values above this limit - if you need to pass 64-bit integers 49 * (hash codes, for example) between the client and server without precision 50 * loss, do _not_ use this library. 51 * 52 * Major caveat 3 - This class uses typed arrays and must not be used on older 53 * browsers that do not support them. 54 * 55 * @author aappleby@google.com (Austin Appleby) 56 */ 57 58goog.provide('jspb.BinaryWriter'); 59 60goog.require('goog.asserts'); 61goog.require('goog.crypt.base64'); 62goog.require('jspb.BinaryConstants'); 63goog.require('jspb.BinaryEncoder'); 64goog.require('jspb.arith.Int64'); 65goog.require('jspb.arith.UInt64'); 66goog.require('jspb.utils'); 67 68 69 70/** 71 * BinaryWriter implements encoders for all the wire types specified in 72 * https://developers.google.com/protocol-buffers/docs/encoding. 73 * 74 * @constructor 75 * @struct 76 */ 77jspb.BinaryWriter = function() { 78 /** 79 * Blocks of serialized data that will be concatenated once all messages have 80 * been written. 81 * @private {!Array<!Uint8Array|!Array<number>>} 82 */ 83 this.blocks_ = []; 84 85 /** 86 * Total number of bytes in the blocks_ array. Does _not_ include bytes in 87 * the encoder below. 88 * @private {number} 89 */ 90 this.totalLength_ = 0; 91 92 /** 93 * Binary encoder holding pieces of a message that we're still serializing. 94 * When we get to a stopping point (either the start of a new submessage, or 95 * when we need to append a raw Uint8Array), the encoder's buffer will be 96 * added to the block array above and the encoder will be reset. 97 * @private {!jspb.BinaryEncoder} 98 */ 99 this.encoder_ = new jspb.BinaryEncoder(); 100 101 /** 102 * A stack of bookmarks containing the parent blocks for each message started 103 * via beginSubMessage(), needed as bookkeeping for endSubMessage(). 104 * TODO(aappleby): Deprecated, users should be calling writeMessage(). 105 * @private {!Array<!Array<number>>} 106 */ 107 this.bookmarks_ = []; 108}; 109 110 111/** 112 * Append a typed array of bytes onto the buffer. 113 * 114 * @param {!Uint8Array} arr The byte array to append. 115 * @private 116 */ 117jspb.BinaryWriter.prototype.appendUint8Array_ = function(arr) { 118 var temp = this.encoder_.end(); 119 this.blocks_.push(temp); 120 this.blocks_.push(arr); 121 this.totalLength_ += temp.length + arr.length; 122}; 123 124 125/** 126 * Begins a new message by writing the field header and returning a bookmark 127 * which we will use to patch in the message length to in endDelimited_ below. 128 * @param {number} field 129 * @return {!Array<number>} 130 * @private 131 */ 132jspb.BinaryWriter.prototype.beginDelimited_ = function(field) { 133 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 134 var bookmark = this.encoder_.end(); 135 this.blocks_.push(bookmark); 136 this.totalLength_ += bookmark.length; 137 bookmark.push(this.totalLength_); 138 return bookmark; 139}; 140 141 142/** 143 * Ends a message by encoding the _change_ in length of the buffer to the 144 * parent block and adds the number of bytes needed to encode that length to 145 * the total byte length. 146 * @param {!Array<number>} bookmark 147 * @private 148 */ 149jspb.BinaryWriter.prototype.endDelimited_ = function(bookmark) { 150 var oldLength = bookmark.pop(); 151 var messageLength = this.totalLength_ + this.encoder_.length() - oldLength; 152 goog.asserts.assert(messageLength >= 0); 153 154 while (messageLength > 127) { 155 bookmark.push((messageLength & 0x7f) | 0x80); 156 messageLength = messageLength >>> 7; 157 this.totalLength_++; 158 } 159 160 bookmark.push(messageLength); 161 this.totalLength_++; 162}; 163 164 165/** 166 * Writes a pre-serialized message to the buffer. 167 * @param {!Uint8Array} bytes The array of bytes to write. 168 * @param {number} start The start of the range to write. 169 * @param {number} end The end of the range to write. 170 */ 171jspb.BinaryWriter.prototype.writeSerializedMessage = function( 172 bytes, start, end) { 173 this.appendUint8Array_(bytes.subarray(start, end)); 174}; 175 176 177/** 178 * Writes a pre-serialized message to the buffer if the message and endpoints 179 * are non-null. 180 * @param {?Uint8Array} bytes The array of bytes to write. 181 * @param {?number} start The start of the range to write. 182 * @param {?number} end The end of the range to write. 183 */ 184jspb.BinaryWriter.prototype.maybeWriteSerializedMessage = function( 185 bytes, start, end) { 186 if (bytes != null && start != null && end != null) { 187 this.writeSerializedMessage(bytes, start, end); 188 } 189}; 190 191 192/** 193 * Resets the writer, throwing away any accumulated buffers. 194 */ 195jspb.BinaryWriter.prototype.reset = function() { 196 this.blocks_ = []; 197 this.encoder_.end(); 198 this.totalLength_ = 0; 199 this.bookmarks_ = []; 200}; 201 202 203/** 204 * Converts the encoded data into a Uint8Array. 205 * @return {!Uint8Array} 206 */ 207jspb.BinaryWriter.prototype.getResultBuffer = function() { 208 goog.asserts.assert(this.bookmarks_.length == 0); 209 210 var flat = new Uint8Array(this.totalLength_ + this.encoder_.length()); 211 212 var blocks = this.blocks_; 213 var blockCount = blocks.length; 214 var offset = 0; 215 216 for (var i = 0; i < blockCount; i++) { 217 var block = blocks[i]; 218 flat.set(block, offset); 219 offset += block.length; 220 } 221 222 var tail = this.encoder_.end(); 223 flat.set(tail, offset); 224 offset += tail.length; 225 226 // Post condition: `flattened` must have had every byte written. 227 goog.asserts.assert(offset == flat.length); 228 229 // Replace our block list with the flattened block, which lets GC reclaim 230 // the temp blocks sooner. 231 this.blocks_ = [flat]; 232 233 return flat; 234}; 235 236 237/** 238 * Converts the encoded data into a base64-encoded string. 239 * @param {boolean=} opt_webSafe True indicates we should use a websafe 240 * alphabet, which does not require escaping for use in URLs. 241 * @return {string} 242 */ 243jspb.BinaryWriter.prototype.getResultBase64String = function(opt_webSafe) { 244 return goog.crypt.base64.encodeByteArray(this.getResultBuffer(), opt_webSafe); 245}; 246 247 248/** 249 * Begins a new sub-message. The client must call endSubMessage() when they're 250 * done. 251 * TODO(aappleby): Deprecated. Move callers to writeMessage(). 252 * @param {number} field The field number of the sub-message. 253 */ 254jspb.BinaryWriter.prototype.beginSubMessage = function(field) { 255 this.bookmarks_.push(this.beginDelimited_(field)); 256}; 257 258 259/** 260 * Finishes a sub-message and packs it into the parent messages' buffer. 261 * TODO(aappleby): Deprecated. Move callers to writeMessage(). 262 */ 263jspb.BinaryWriter.prototype.endSubMessage = function() { 264 goog.asserts.assert(this.bookmarks_.length >= 0); 265 this.endDelimited_(this.bookmarks_.pop()); 266}; 267 268 269/** 270 * Encodes a (field number, wire type) tuple into a wire-format field header 271 * and stores it in the buffer as a varint. 272 * @param {number} field The field number. 273 * @param {number} wireType The wire-type of the field, as specified in the 274 * protocol buffer documentation. 275 * @private 276 */ 277jspb.BinaryWriter.prototype.writeFieldHeader_ = 278 function(field, wireType) { 279 goog.asserts.assert(field >= 1 && field == Math.floor(field)); 280 var x = field * 8 + wireType; 281 this.encoder_.writeUnsignedVarint32(x); 282}; 283 284 285/** 286 * Writes a field of any valid scalar type to the binary stream. 287 * @param {jspb.BinaryConstants.FieldType} fieldType 288 * @param {number} field 289 * @param {jspb.AnyFieldType} value 290 */ 291jspb.BinaryWriter.prototype.writeAny = function(fieldType, field, value) { 292 var fieldTypes = jspb.BinaryConstants.FieldType; 293 switch (fieldType) { 294 case fieldTypes.DOUBLE: 295 this.writeDouble(field, /** @type {number} */(value)); 296 return; 297 case fieldTypes.FLOAT: 298 this.writeFloat(field, /** @type {number} */(value)); 299 return; 300 case fieldTypes.INT64: 301 this.writeInt64(field, /** @type {number} */(value)); 302 return; 303 case fieldTypes.UINT64: 304 this.writeUint64(field, /** @type {number} */(value)); 305 return; 306 case fieldTypes.INT32: 307 this.writeInt32(field, /** @type {number} */(value)); 308 return; 309 case fieldTypes.FIXED64: 310 this.writeFixed64(field, /** @type {number} */(value)); 311 return; 312 case fieldTypes.FIXED32: 313 this.writeFixed32(field, /** @type {number} */(value)); 314 return; 315 case fieldTypes.BOOL: 316 this.writeBool(field, /** @type {boolean} */(value)); 317 return; 318 case fieldTypes.STRING: 319 this.writeString(field, /** @type {string} */(value)); 320 return; 321 case fieldTypes.GROUP: 322 goog.asserts.fail('Group field type not supported in writeAny()'); 323 return; 324 case fieldTypes.MESSAGE: 325 goog.asserts.fail('Message field type not supported in writeAny()'); 326 return; 327 case fieldTypes.BYTES: 328 this.writeBytes(field, /** @type {?Uint8Array} */(value)); 329 return; 330 case fieldTypes.UINT32: 331 this.writeUint32(field, /** @type {number} */(value)); 332 return; 333 case fieldTypes.ENUM: 334 this.writeEnum(field, /** @type {number} */(value)); 335 return; 336 case fieldTypes.SFIXED32: 337 this.writeSfixed32(field, /** @type {number} */(value)); 338 return; 339 case fieldTypes.SFIXED64: 340 this.writeSfixed64(field, /** @type {number} */(value)); 341 return; 342 case fieldTypes.SINT32: 343 this.writeSint32(field, /** @type {number} */(value)); 344 return; 345 case fieldTypes.SINT64: 346 this.writeSint64(field, /** @type {number} */(value)); 347 return; 348 case fieldTypes.FHASH64: 349 this.writeFixedHash64(field, /** @type {string} */(value)); 350 return; 351 case fieldTypes.VHASH64: 352 this.writeVarintHash64(field, /** @type {string} */(value)); 353 return; 354 default: 355 goog.asserts.fail('Invalid field type in writeAny()'); 356 return; 357 } 358}; 359 360 361/** 362 * Writes a varint field to the buffer without range checking. 363 * @param {number} field The field number. 364 * @param {number?} value The value to write. 365 * @private 366 */ 367jspb.BinaryWriter.prototype.writeUnsignedVarint32_ = function(field, value) { 368 if (value == null) return; 369 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 370 this.encoder_.writeUnsignedVarint32(value); 371}; 372 373 374/** 375 * Writes a varint field to the buffer without range checking. 376 * @param {number} field The field number. 377 * @param {number?} value The value to write. 378 * @private 379 */ 380jspb.BinaryWriter.prototype.writeSignedVarint32_ = function(field, value) { 381 if (value == null) return; 382 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 383 this.encoder_.writeSignedVarint32(value); 384}; 385 386 387/** 388 * Writes a varint field to the buffer without range checking. 389 * @param {number} field The field number. 390 * @param {number?} value The value to write. 391 * @private 392 */ 393jspb.BinaryWriter.prototype.writeUnsignedVarint64_ = function(field, value) { 394 if (value == null) return; 395 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 396 this.encoder_.writeUnsignedVarint64(value); 397}; 398 399 400/** 401 * Writes a varint field to the buffer without range checking. 402 * @param {number} field The field number. 403 * @param {number?} value The value to write. 404 * @private 405 */ 406jspb.BinaryWriter.prototype.writeSignedVarint64_ = function(field, value) { 407 if (value == null) return; 408 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 409 this.encoder_.writeSignedVarint64(value); 410}; 411 412 413/** 414 * Writes a zigzag varint field to the buffer without range checking. 415 * @param {number} field The field number. 416 * @param {number?} value The value to write. 417 * @private 418 */ 419jspb.BinaryWriter.prototype.writeZigzagVarint32_ = function(field, value) { 420 if (value == null) return; 421 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 422 this.encoder_.writeZigzagVarint32(value); 423}; 424 425 426/** 427 * Writes a zigzag varint field to the buffer without range checking. 428 * @param {number} field The field number. 429 * @param {number?} value The value to write. 430 * @private 431 */ 432jspb.BinaryWriter.prototype.writeZigzagVarint64_ = function(field, value) { 433 if (value == null) return; 434 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 435 this.encoder_.writeZigzagVarint64(value); 436}; 437 438 439/** 440 * Writes a zigzag varint field to the buffer without range checking. 441 * @param {number} field The field number. 442 * @param {string?} value The value to write. 443 * @private 444 */ 445jspb.BinaryWriter.prototype.writeZigzagVarint64String_ = function( 446 field, value) { 447 if (value == null) return; 448 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 449 this.encoder_.writeZigzagVarint64String(value); 450}; 451 452 453/** 454 * Writes an int32 field to the buffer. Numbers outside the range [-2^31,2^31) 455 * will be truncated. 456 * @param {number} field The field number. 457 * @param {number?} value The value to write. 458 */ 459jspb.BinaryWriter.prototype.writeInt32 = function(field, value) { 460 if (value == null) return; 461 goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) && 462 (value < jspb.BinaryConstants.TWO_TO_31)); 463 this.writeSignedVarint32_(field, value); 464}; 465 466 467/** 468 * Writes an int32 field represented as a string to the buffer. Numbers outside 469 * the range [-2^31,2^31) will be truncated. 470 * @param {number} field The field number. 471 * @param {string?} value The value to write. 472 */ 473jspb.BinaryWriter.prototype.writeInt32String = function(field, value) { 474 if (value == null) return; 475 var intValue = /** {number} */ parseInt(value, 10); 476 goog.asserts.assert((intValue >= -jspb.BinaryConstants.TWO_TO_31) && 477 (intValue < jspb.BinaryConstants.TWO_TO_31)); 478 this.writeSignedVarint32_(field, intValue); 479}; 480 481 482/** 483 * Writes an int64 field to the buffer. Numbers outside the range [-2^63,2^63) 484 * will be truncated. 485 * @param {number} field The field number. 486 * @param {number?} value The value to write. 487 */ 488jspb.BinaryWriter.prototype.writeInt64 = function(field, value) { 489 if (value == null) return; 490 goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_63) && 491 (value < jspb.BinaryConstants.TWO_TO_63)); 492 this.writeSignedVarint64_(field, value); 493}; 494 495 496/** 497 * Writes a int64 field (with value as a string) to the buffer. 498 * @param {number} field The field number. 499 * @param {string?} value The value to write. 500 */ 501jspb.BinaryWriter.prototype.writeInt64String = function(field, value) { 502 if (value == null) return; 503 var num = jspb.arith.Int64.fromString(value); 504 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 505 this.encoder_.writeSplitVarint64(num.lo, num.hi); 506}; 507 508 509/** 510 * Writes a uint32 field to the buffer. Numbers outside the range [0,2^32) 511 * will be truncated. 512 * @param {number} field The field number. 513 * @param {number?} value The value to write. 514 */ 515jspb.BinaryWriter.prototype.writeUint32 = function(field, value) { 516 if (value == null) return; 517 goog.asserts.assert((value >= 0) && 518 (value < jspb.BinaryConstants.TWO_TO_32)); 519 this.writeUnsignedVarint32_(field, value); 520}; 521 522 523/** 524 * Writes a uint32 field represented as a string to the buffer. Numbers outside 525 * the range [0,2^32) will be truncated. 526 * @param {number} field The field number. 527 * @param {string?} value The value to write. 528 */ 529jspb.BinaryWriter.prototype.writeUint32String = function(field, value) { 530 if (value == null) return; 531 var intValue = /** {number} */ parseInt(value, 10); 532 goog.asserts.assert((intValue >= 0) && 533 (intValue < jspb.BinaryConstants.TWO_TO_32)); 534 this.writeUnsignedVarint32_(field, intValue); 535}; 536 537 538/** 539 * Writes a uint64 field to the buffer. Numbers outside the range [0,2^64) 540 * will be truncated. 541 * @param {number} field The field number. 542 * @param {number?} value The value to write. 543 */ 544jspb.BinaryWriter.prototype.writeUint64 = function(field, value) { 545 if (value == null) return; 546 goog.asserts.assert((value >= 0) && 547 (value < jspb.BinaryConstants.TWO_TO_64)); 548 this.writeUnsignedVarint64_(field, value); 549}; 550 551 552/** 553 * Writes a uint64 field (with value as a string) to the buffer. 554 * @param {number} field The field number. 555 * @param {string?} value The value to write. 556 */ 557jspb.BinaryWriter.prototype.writeUint64String = function(field, value) { 558 if (value == null) return; 559 var num = jspb.arith.UInt64.fromString(value); 560 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 561 this.encoder_.writeSplitVarint64(num.lo, num.hi); 562}; 563 564 565/** 566 * Writes a sint32 field to the buffer. Numbers outside the range [-2^31,2^31) 567 * will be truncated. 568 * @param {number} field The field number. 569 * @param {number?} value The value to write. 570 */ 571jspb.BinaryWriter.prototype.writeSint32 = function(field, value) { 572 if (value == null) return; 573 goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) && 574 (value < jspb.BinaryConstants.TWO_TO_31)); 575 this.writeZigzagVarint32_(field, value); 576}; 577 578 579/** 580 * Writes a sint64 field to the buffer. Numbers outside the range [-2^63,2^63) 581 * will be truncated. 582 * @param {number} field The field number. 583 * @param {number?} value The value to write. 584 */ 585jspb.BinaryWriter.prototype.writeSint64 = function(field, value) { 586 if (value == null) return; 587 goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_63) && 588 (value < jspb.BinaryConstants.TWO_TO_63)); 589 this.writeZigzagVarint64_(field, value); 590}; 591 592 593/** 594 * Writes a sint64 field to the buffer. Numbers outside the range [-2^63,2^63) 595 * will be truncated. 596 * @param {number} field The field number. 597 * @param {string?} value The decimal string to write. 598 */ 599jspb.BinaryWriter.prototype.writeSint64String = function(field, value) { 600 if (value == null) return; 601 goog.asserts.assert((+value >= -jspb.BinaryConstants.TWO_TO_63) && 602 (+value < jspb.BinaryConstants.TWO_TO_63)); 603 this.writeZigzagVarint64String_(field, value); 604}; 605 606 607/** 608 * Writes a fixed32 field to the buffer. Numbers outside the range [0,2^32) 609 * will be truncated. 610 * @param {number} field The field number. 611 * @param {number?} value The value to write. 612 */ 613jspb.BinaryWriter.prototype.writeFixed32 = function(field, value) { 614 if (value == null) return; 615 goog.asserts.assert((value >= 0) && 616 (value < jspb.BinaryConstants.TWO_TO_32)); 617 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED32); 618 this.encoder_.writeUint32(value); 619}; 620 621 622/** 623 * Writes a fixed64 field to the buffer. Numbers outside the range [0,2^64) 624 * will be truncated. 625 * @param {number} field The field number. 626 * @param {number?} value The value to write. 627 */ 628jspb.BinaryWriter.prototype.writeFixed64 = function(field, value) { 629 if (value == null) return; 630 goog.asserts.assert((value >= 0) && 631 (value < jspb.BinaryConstants.TWO_TO_64)); 632 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); 633 this.encoder_.writeUint64(value); 634}; 635 636 637/** 638 * Writes a fixed64 field (with value as a string) to the buffer. 639 * @param {number} field The field number. 640 * @param {string?} value The value to write. 641 */ 642jspb.BinaryWriter.prototype.writeFixed64String = function(field, value) { 643 if (value == null) return; 644 var num = jspb.arith.UInt64.fromString(value); 645 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); 646 this.encoder_.writeSplitFixed64(num.lo, num.hi); 647}; 648 649 650/** 651 * Writes a sfixed32 field to the buffer. Numbers outside the range 652 * [-2^31,2^31) will be truncated. 653 * @param {number} field The field number. 654 * @param {number?} value The value to write. 655 */ 656jspb.BinaryWriter.prototype.writeSfixed32 = function(field, value) { 657 if (value == null) return; 658 goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) && 659 (value < jspb.BinaryConstants.TWO_TO_31)); 660 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED32); 661 this.encoder_.writeInt32(value); 662}; 663 664 665/** 666 * Writes a sfixed64 field to the buffer. Numbers outside the range 667 * [-2^63,2^63) will be truncated. 668 * @param {number} field The field number. 669 * @param {number?} value The value to write. 670 */ 671jspb.BinaryWriter.prototype.writeSfixed64 = function(field, value) { 672 if (value == null) return; 673 goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_63) && 674 (value < jspb.BinaryConstants.TWO_TO_63)); 675 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); 676 this.encoder_.writeInt64(value); 677}; 678 679 680/** 681 * Writes a sfixed64 string field to the buffer. Numbers outside the range 682 * [-2^63,2^63) will be truncated. 683 * @param {number} field The field number. 684 * @param {string?} value The value to write. 685 */ 686jspb.BinaryWriter.prototype.writeSfixed64String = function(field, value) { 687 if (value == null) return; 688 var num = jspb.arith.Int64.fromString(value); 689 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); 690 this.encoder_.writeSplitFixed64(num.lo, num.hi); 691}; 692 693 694/** 695 * Writes a single-precision floating point field to the buffer. Numbers 696 * requiring more than 32 bits of precision will be truncated. 697 * @param {number} field The field number. 698 * @param {number?} value The value to write. 699 */ 700jspb.BinaryWriter.prototype.writeFloat = function(field, value) { 701 if (value == null) return; 702 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED32); 703 this.encoder_.writeFloat(value); 704}; 705 706 707/** 708 * Writes a double-precision floating point field to the buffer. As this is the 709 * native format used by JavaScript, no precision will be lost. 710 * @param {number} field The field number. 711 * @param {number?} value The value to write. 712 */ 713jspb.BinaryWriter.prototype.writeDouble = function(field, value) { 714 if (value == null) return; 715 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); 716 this.encoder_.writeDouble(value); 717}; 718 719 720/** 721 * Writes a boolean field to the buffer. We allow numbers as input 722 * because the JSPB code generator uses 0/1 instead of true/false to save space 723 * in the string representation of the proto. 724 * @param {number} field The field number. 725 * @param {boolean?|number?} value The value to write. 726 */ 727jspb.BinaryWriter.prototype.writeBool = function(field, value) { 728 if (value == null) return; 729 goog.asserts.assert(goog.isBoolean(value) || goog.isNumber(value)); 730 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 731 this.encoder_.writeBool(value); 732}; 733 734 735/** 736 * Writes an enum field to the buffer. 737 * @param {number} field The field number. 738 * @param {number?} value The value to write. 739 */ 740jspb.BinaryWriter.prototype.writeEnum = function(field, value) { 741 if (value == null) return; 742 goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) && 743 (value < jspb.BinaryConstants.TWO_TO_31)); 744 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 745 this.encoder_.writeSignedVarint32(value); 746}; 747 748 749/** 750 * Writes a string field to the buffer. 751 * @param {number} field The field number. 752 * @param {string?} value The string to write. 753 */ 754jspb.BinaryWriter.prototype.writeString = function(field, value) { 755 if (value == null) return; 756 var bookmark = this.beginDelimited_(field); 757 this.encoder_.writeString(value); 758 this.endDelimited_(bookmark); 759}; 760 761 762/** 763 * Writes an arbitrary byte field to the buffer. Note - to match the behavior 764 * of the C++ implementation, empty byte arrays _are_ serialized. 765 * @param {number} field The field number. 766 * @param {?jspb.ByteSource} value The array of bytes to write. 767 */ 768jspb.BinaryWriter.prototype.writeBytes = function(field, value) { 769 if (value == null) return; 770 var bytes = jspb.utils.byteSourceToUint8Array(value); 771 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 772 this.encoder_.writeUnsignedVarint32(bytes.length); 773 this.appendUint8Array_(bytes); 774}; 775 776 777/** 778 * Writes a message to the buffer. 779 * @param {number} field The field number. 780 * @param {?MessageType} value The message to write. 781 * @param {function(MessageTypeNonNull, !jspb.BinaryWriter)} writerCallback 782 * Will be invoked with the value to write and the writer to write it with. 783 * @template MessageType 784 * Use go/closure-ttl to declare a non-nullable version of MessageType. Replace 785 * the null in blah|null with none. This is necessary because the compiler will 786 * infer MessageType to be nullable if the value parameter is nullable. 787 * @template MessageTypeNonNull := 788 * cond(isUnknown(MessageType), unknown(), 789 * mapunion(MessageType, (X) => 790 * cond(eq(X, 'null'), none(), X))) 791 * =: 792 */ 793jspb.BinaryWriter.prototype.writeMessage = function( 794 field, value, writerCallback) { 795 if (value == null) return; 796 var bookmark = this.beginDelimited_(field); 797 writerCallback(value, this); 798 this.endDelimited_(bookmark); 799}; 800 801 802/** 803 * Writes a message set extension to the buffer. 804 * @param {number} field The field number for the extension. 805 * @param {?MessageType} value The extension message object to write. Note that 806 * message set can only have extensions with type of optional message. 807 * @param {function(!MessageTypeNonNull, !jspb.BinaryWriter)} writerCallback 808 * Will be invoked with the value to write and the writer to write it with. 809 * @template MessageType 810 * Use go/closure-ttl to declare a non-nullable version of MessageType. Replace 811 * the null in blah|null with none. This is necessary because the compiler will 812 * infer MessageType to be nullable if the value parameter is nullable. 813 * @template MessageTypeNonNull := 814 * cond(isUnknown(MessageType), unknown(), 815 * mapunion(MessageType, (X) => 816 * cond(eq(X, 'null'), none(), X))) 817 * =: 818 */ 819jspb.BinaryWriter.prototype.writeMessageSet = function( 820 field, value, writerCallback) { 821 if (value == null) return; 822 // The wire format for a message set is defined by 823 // google3/net/proto/message_set.proto 824 this.writeFieldHeader_(1, jspb.BinaryConstants.WireType.START_GROUP); 825 this.writeFieldHeader_(2, jspb.BinaryConstants.WireType.VARINT); 826 this.encoder_.writeSignedVarint32(field); 827 var bookmark = this.beginDelimited_(3); 828 writerCallback(value, this); 829 this.endDelimited_(bookmark); 830 this.writeFieldHeader_(1, jspb.BinaryConstants.WireType.END_GROUP); 831}; 832 833 834/** 835 * Writes a group message to the buffer. 836 * 837 * @param {number} field The field number. 838 * @param {?MessageType} value The message to write, wrapped with START_GROUP / 839 * END_GROUP tags. Will be a no-op if 'value' is null. 840 * @param {function(MessageTypeNonNull, !jspb.BinaryWriter)} writerCallback 841 * Will be invoked with the value to write and the writer to write it with. 842 * @template MessageType 843 * Use go/closure-ttl to declare a non-nullable version of MessageType. Replace 844 * the null in blah|null with none. This is necessary because the compiler will 845 * infer MessageType to be nullable if the value parameter is nullable. 846 * @template MessageTypeNonNull := 847 * cond(isUnknown(MessageType), unknown(), 848 * mapunion(MessageType, (X) => 849 * cond(eq(X, 'null'), none(), X))) 850 * =: 851 */ 852jspb.BinaryWriter.prototype.writeGroup = function( 853 field, value, writerCallback) { 854 if (value == null) return; 855 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.START_GROUP); 856 writerCallback(value, this); 857 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.END_GROUP); 858}; 859 860 861/** 862 * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to 863 * the buffer. 864 * @param {number} field The field number. 865 * @param {string?} value The hash string. 866 */ 867jspb.BinaryWriter.prototype.writeFixedHash64 = function(field, value) { 868 if (value == null) return; 869 goog.asserts.assert(value.length == 8); 870 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); 871 this.encoder_.writeFixedHash64(value); 872}; 873 874 875/** 876 * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to 877 * the buffer. 878 * @param {number} field The field number. 879 * @param {string?} value The hash string. 880 */ 881jspb.BinaryWriter.prototype.writeVarintHash64 = function(field, value) { 882 if (value == null) return; 883 goog.asserts.assert(value.length == 8); 884 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 885 this.encoder_.writeVarintHash64(value); 886}; 887 888 889/** 890 * Writes an array of numbers to the buffer as a repeated 32-bit int field. 891 * @param {number} field The field number. 892 * @param {?Array<number>} value The array of ints to write. 893 */ 894jspb.BinaryWriter.prototype.writeRepeatedInt32 = function(field, value) { 895 if (value == null) return; 896 for (var i = 0; i < value.length; i++) { 897 this.writeSignedVarint32_(field, value[i]); 898 } 899}; 900 901 902/** 903 * Writes an array of numbers formatted as strings to the buffer as a repeated 904 * 32-bit int field. 905 * @param {number} field The field number. 906 * @param {?Array<string>} value The array of ints to write. 907 */ 908jspb.BinaryWriter.prototype.writeRepeatedInt32String = function(field, value) { 909 if (value == null) return; 910 for (var i = 0; i < value.length; i++) { 911 this.writeInt32String(field, value[i]); 912 } 913}; 914 915 916/** 917 * Writes an array of numbers to the buffer as a repeated 64-bit int field. 918 * @param {number} field The field number. 919 * @param {?Array<number>} value The array of ints to write. 920 */ 921jspb.BinaryWriter.prototype.writeRepeatedInt64 = function(field, value) { 922 if (value == null) return; 923 for (var i = 0; i < value.length; i++) { 924 this.writeSignedVarint64_(field, value[i]); 925 } 926}; 927 928 929/** 930 * Writes an array of numbers formatted as strings to the buffer as a repeated 931 * 64-bit int field. 932 * @param {number} field The field number. 933 * @param {?Array<string>} value The array of ints to write. 934 */ 935jspb.BinaryWriter.prototype.writeRepeatedInt64String = function(field, value) { 936 if (value == null) return; 937 for (var i = 0; i < value.length; i++) { 938 this.writeInt64String(field, value[i]); 939 } 940}; 941 942 943/** 944 * Writes an array numbers to the buffer as a repeated unsigned 32-bit int 945 * field. 946 * @param {number} field The field number. 947 * @param {?Array<number>} value The array of ints to write. 948 */ 949jspb.BinaryWriter.prototype.writeRepeatedUint32 = function(field, value) { 950 if (value == null) return; 951 for (var i = 0; i < value.length; i++) { 952 this.writeUnsignedVarint32_(field, value[i]); 953 } 954}; 955 956 957/** 958 * Writes an array of numbers formatted as strings to the buffer as a repeated 959 * unsigned 32-bit int field. 960 * @param {number} field The field number. 961 * @param {?Array<string>} value The array of ints to write. 962 */ 963jspb.BinaryWriter.prototype.writeRepeatedUint32String = function(field, value) { 964 if (value == null) return; 965 for (var i = 0; i < value.length; i++) { 966 this.writeUint32String(field, value[i]); 967 } 968}; 969 970 971/** 972 * Writes an array numbers to the buffer as a repeated unsigned 64-bit int 973 * field. 974 * @param {number} field The field number. 975 * @param {?Array<number>} value The array of ints to write. 976 */ 977jspb.BinaryWriter.prototype.writeRepeatedUint64 = function(field, value) { 978 if (value == null) return; 979 for (var i = 0; i < value.length; i++) { 980 this.writeUnsignedVarint64_(field, value[i]); 981 } 982}; 983 984 985/** 986 * Writes an array of numbers formatted as strings to the buffer as a repeated 987 * unsigned 64-bit int field. 988 * @param {number} field The field number. 989 * @param {?Array<string>} value The array of ints to write. 990 */ 991jspb.BinaryWriter.prototype.writeRepeatedUint64String = function(field, value) { 992 if (value == null) return; 993 for (var i = 0; i < value.length; i++) { 994 this.writeUint64String(field, value[i]); 995 } 996}; 997 998 999/** 1000 * Writes an array numbers to the buffer as a repeated signed 32-bit int field. 1001 * @param {number} field The field number. 1002 * @param {?Array<number>} value The array of ints to write. 1003 */ 1004jspb.BinaryWriter.prototype.writeRepeatedSint32 = function(field, value) { 1005 if (value == null) return; 1006 for (var i = 0; i < value.length; i++) { 1007 this.writeZigzagVarint32_(field, value[i]); 1008 } 1009}; 1010 1011 1012/** 1013 * Writes an array numbers to the buffer as a repeated signed 64-bit int field. 1014 * @param {number} field The field number. 1015 * @param {?Array<number>} value The array of ints to write. 1016 */ 1017jspb.BinaryWriter.prototype.writeRepeatedSint64 = function(field, value) { 1018 if (value == null) return; 1019 for (var i = 0; i < value.length; i++) { 1020 this.writeZigzagVarint64_(field, value[i]); 1021 } 1022}; 1023 1024 1025/** 1026 * Writes an array numbers to the buffer as a repeated signed 64-bit int field. 1027 * @param {number} field The field number. 1028 * @param {?Array<string>} value The array of ints to write. 1029 */ 1030jspb.BinaryWriter.prototype.writeRepeatedSint64String = function(field, value) { 1031 if (value == null) return; 1032 for (var i = 0; i < value.length; i++) { 1033 this.writeZigzagVarint64String_(field, value[i]); 1034 } 1035}; 1036 1037 1038/** 1039 * Writes an array of numbers to the buffer as a repeated fixed32 field. This 1040 * works for both signed and unsigned fixed32s. 1041 * @param {number} field The field number. 1042 * @param {?Array<number>} value The array of ints to write. 1043 */ 1044jspb.BinaryWriter.prototype.writeRepeatedFixed32 = function(field, value) { 1045 if (value == null) return; 1046 for (var i = 0; i < value.length; i++) { 1047 this.writeFixed32(field, value[i]); 1048 } 1049}; 1050 1051 1052/** 1053 * Writes an array of numbers to the buffer as a repeated fixed64 field. This 1054 * works for both signed and unsigned fixed64s. 1055 * @param {number} field The field number. 1056 * @param {?Array<number>} value The array of ints to write. 1057 */ 1058jspb.BinaryWriter.prototype.writeRepeatedFixed64 = function(field, value) { 1059 if (value == null) return; 1060 for (var i = 0; i < value.length; i++) { 1061 this.writeFixed64(field, value[i]); 1062 } 1063}; 1064 1065 1066/** 1067 * Writes an array of numbers to the buffer as a repeated fixed64 field. This 1068 * works for both signed and unsigned fixed64s. 1069 * @param {number} field The field number. 1070 * @param {?Array<string>} value The array of decimal strings to write. 1071 */ 1072jspb.BinaryWriter.prototype.writeRepeatedFixed64String = function( 1073 field, value) { 1074 if (value == null) return; 1075 for (var i = 0; i < value.length; i++) { 1076 this.writeFixed64String(field, value[i]); 1077 } 1078}; 1079 1080 1081/** 1082 * Writes an array of numbers to the buffer as a repeated sfixed32 field. 1083 * @param {number} field The field number. 1084 * @param {?Array<number>} value The array of ints to write. 1085 */ 1086jspb.BinaryWriter.prototype.writeRepeatedSfixed32 = function(field, value) { 1087 if (value == null) return; 1088 for (var i = 0; i < value.length; i++) { 1089 this.writeSfixed32(field, value[i]); 1090 } 1091}; 1092 1093 1094/** 1095 * Writes an array of numbers to the buffer as a repeated sfixed64 field. 1096 * @param {number} field The field number. 1097 * @param {?Array<number>} value The array of ints to write. 1098 */ 1099jspb.BinaryWriter.prototype.writeRepeatedSfixed64 = function(field, value) { 1100 if (value == null) return; 1101 for (var i = 0; i < value.length; i++) { 1102 this.writeSfixed64(field, value[i]); 1103 } 1104}; 1105 1106 1107/** 1108 * Writes an array of decimal strings to the buffer as a repeated sfixed64 1109 * field. 1110 * @param {number} field The field number. 1111 * @param {?Array<string>} value The array of decimal strings to write. 1112 */ 1113jspb.BinaryWriter.prototype.writeRepeatedSfixed64String = function(field, value) { 1114 if (value == null) return; 1115 for (var i = 0; i < value.length; i++) { 1116 this.writeSfixed64String(field, value[i]); 1117 } 1118}; 1119 1120 1121/** 1122 * Writes an array of numbers to the buffer as a repeated float field. 1123 * @param {number} field The field number. 1124 * @param {?Array<number>} value The array of ints to write. 1125 */ 1126jspb.BinaryWriter.prototype.writeRepeatedFloat = function(field, value) { 1127 if (value == null) return; 1128 for (var i = 0; i < value.length; i++) { 1129 this.writeFloat(field, value[i]); 1130 } 1131}; 1132 1133 1134/** 1135 * Writes an array of numbers to the buffer as a repeated double field. 1136 * @param {number} field The field number. 1137 * @param {?Array<number>} value The array of ints to write. 1138 */ 1139jspb.BinaryWriter.prototype.writeRepeatedDouble = function(field, value) { 1140 if (value == null) return; 1141 for (var i = 0; i < value.length; i++) { 1142 this.writeDouble(field, value[i]); 1143 } 1144}; 1145 1146 1147/** 1148 * Writes an array of booleans to the buffer as a repeated bool field. 1149 * @param {number} field The field number. 1150 * @param {?Array<boolean>} value The array of ints to write. 1151 */ 1152jspb.BinaryWriter.prototype.writeRepeatedBool = function(field, value) { 1153 if (value == null) return; 1154 for (var i = 0; i < value.length; i++) { 1155 this.writeBool(field, value[i]); 1156 } 1157}; 1158 1159 1160/** 1161 * Writes an array of enums to the buffer as a repeated enum field. 1162 * @param {number} field The field number. 1163 * @param {?Array<number>} value The array of ints to write. 1164 */ 1165jspb.BinaryWriter.prototype.writeRepeatedEnum = function(field, value) { 1166 if (value == null) return; 1167 for (var i = 0; i < value.length; i++) { 1168 this.writeEnum(field, value[i]); 1169 } 1170}; 1171 1172 1173/** 1174 * Writes an array of strings to the buffer as a repeated string field. 1175 * @param {number} field The field number. 1176 * @param {?Array<string>} value The array of strings to write. 1177 */ 1178jspb.BinaryWriter.prototype.writeRepeatedString = function(field, value) { 1179 if (value == null) return; 1180 for (var i = 0; i < value.length; i++) { 1181 this.writeString(field, value[i]); 1182 } 1183}; 1184 1185 1186/** 1187 * Writes an array of arbitrary byte fields to the buffer. 1188 * @param {number} field The field number. 1189 * @param {?Array<!jspb.ByteSource>} value The arrays of arrays of bytes to 1190 * write. 1191 */ 1192jspb.BinaryWriter.prototype.writeRepeatedBytes = function(field, value) { 1193 if (value == null) return; 1194 for (var i = 0; i < value.length; i++) { 1195 this.writeBytes(field, value[i]); 1196 } 1197}; 1198 1199 1200/** 1201 * Writes an array of messages to the buffer. 1202 * @template MessageType 1203 * @param {number} field The field number. 1204 * @param {?Array<MessageType>} value The array of messages to 1205 * write. 1206 * @param {function(MessageType, !jspb.BinaryWriter)} writerCallback 1207 * Will be invoked with the value to write and the writer to write it with. 1208 */ 1209jspb.BinaryWriter.prototype.writeRepeatedMessage = function( 1210 field, value, writerCallback) { 1211 if (value == null) return; 1212 for (var i = 0; i < value.length; i++) { 1213 var bookmark = this.beginDelimited_(field); 1214 writerCallback(value[i], this); 1215 this.endDelimited_(bookmark); 1216 } 1217}; 1218 1219 1220/** 1221 * Writes an array of group messages to the buffer. 1222 * @template MessageType 1223 * @param {number} field The field number. 1224 * @param {?Array<MessageType>} value The array of messages to 1225 * write. 1226 * @param {function(MessageType, !jspb.BinaryWriter)} writerCallback 1227 * Will be invoked with the value to write and the writer to write it with. 1228 */ 1229jspb.BinaryWriter.prototype.writeRepeatedGroup = function( 1230 field, value, writerCallback) { 1231 if (value == null) return; 1232 for (var i = 0; i < value.length; i++) { 1233 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.START_GROUP); 1234 writerCallback(value[i], this); 1235 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.END_GROUP); 1236 } 1237}; 1238 1239 1240/** 1241 * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to 1242 * the buffer. 1243 * @param {number} field The field number. 1244 * @param {?Array<string>} value The array of hashes to write. 1245 */ 1246jspb.BinaryWriter.prototype.writeRepeatedFixedHash64 = 1247 function(field, value) { 1248 if (value == null) return; 1249 for (var i = 0; i < value.length; i++) { 1250 this.writeFixedHash64(field, value[i]); 1251 } 1252}; 1253 1254 1255/** 1256 * Writes a repeated 64-bit hash string field (8 characters @ 8 bits of data 1257 * each) to the buffer. 1258 * @param {number} field The field number. 1259 * @param {?Array<string>} value The array of hashes to write. 1260 */ 1261jspb.BinaryWriter.prototype.writeRepeatedVarintHash64 = 1262 function(field, value) { 1263 if (value == null) return; 1264 for (var i = 0; i < value.length; i++) { 1265 this.writeVarintHash64(field, value[i]); 1266 } 1267}; 1268 1269 1270/** 1271 * Writes an array of numbers to the buffer as a packed 32-bit int field. 1272 * @param {number} field The field number. 1273 * @param {?Array<number>} value The array of ints to write. 1274 */ 1275jspb.BinaryWriter.prototype.writePackedInt32 = function(field, value) { 1276 if (value == null || !value.length) return; 1277 var bookmark = this.beginDelimited_(field); 1278 for (var i = 0; i < value.length; i++) { 1279 this.encoder_.writeSignedVarint32(value[i]); 1280 } 1281 this.endDelimited_(bookmark); 1282}; 1283 1284 1285/** 1286 * Writes an array of numbers represented as strings to the buffer as a packed 1287 * 32-bit int field. 1288 * @param {number} field 1289 * @param {?Array<string>} value 1290 */ 1291jspb.BinaryWriter.prototype.writePackedInt32String = function(field, value) { 1292 if (value == null || !value.length) return; 1293 var bookmark = this.beginDelimited_(field); 1294 for (var i = 0; i < value.length; i++) { 1295 this.encoder_.writeSignedVarint32(parseInt(value[i], 10)); 1296 } 1297 this.endDelimited_(bookmark); 1298}; 1299 1300 1301/** 1302 * Writes an array of numbers to the buffer as a packed 64-bit int field. 1303 * @param {number} field The field number. 1304 * @param {?Array<number>} value The array of ints to write. 1305 */ 1306jspb.BinaryWriter.prototype.writePackedInt64 = function(field, value) { 1307 if (value == null || !value.length) return; 1308 var bookmark = this.beginDelimited_(field); 1309 for (var i = 0; i < value.length; i++) { 1310 this.encoder_.writeSignedVarint64(value[i]); 1311 } 1312 this.endDelimited_(bookmark); 1313}; 1314 1315 1316/** 1317 * Writes an array of numbers represented as strings to the buffer as a packed 1318 * 64-bit int field. 1319 * @param {number} field 1320 * @param {?Array<string>} value 1321 */ 1322jspb.BinaryWriter.prototype.writePackedInt64String = function(field, value) { 1323 if (value == null || !value.length) return; 1324 var bookmark = this.beginDelimited_(field); 1325 for (var i = 0; i < value.length; i++) { 1326 var num = jspb.arith.Int64.fromString(value[i]); 1327 this.encoder_.writeSplitVarint64(num.lo, num.hi); 1328 } 1329 this.endDelimited_(bookmark); 1330}; 1331 1332 1333/** 1334 * Writes an array numbers to the buffer as a packed unsigned 32-bit int field. 1335 * @param {number} field The field number. 1336 * @param {?Array<number>} value The array of ints to write. 1337 */ 1338jspb.BinaryWriter.prototype.writePackedUint32 = function(field, value) { 1339 if (value == null || !value.length) return; 1340 var bookmark = this.beginDelimited_(field); 1341 for (var i = 0; i < value.length; i++) { 1342 this.encoder_.writeUnsignedVarint32(value[i]); 1343 } 1344 this.endDelimited_(bookmark); 1345}; 1346 1347 1348/** 1349 * Writes an array of numbers represented as strings to the buffer as a packed 1350 * unsigned 32-bit int field. 1351 * @param {number} field 1352 * @param {?Array<string>} value 1353 */ 1354jspb.BinaryWriter.prototype.writePackedUint32String = 1355 function(field, value) { 1356 if (value == null || !value.length) return; 1357 var bookmark = this.beginDelimited_(field); 1358 for (var i = 0; i < value.length; i++) { 1359 this.encoder_.writeUnsignedVarint32(parseInt(value[i], 10)); 1360 } 1361 this.endDelimited_(bookmark); 1362}; 1363 1364 1365/** 1366 * Writes an array numbers to the buffer as a packed unsigned 64-bit int field. 1367 * @param {number} field The field number. 1368 * @param {?Array<number>} value The array of ints to write. 1369 */ 1370jspb.BinaryWriter.prototype.writePackedUint64 = function(field, value) { 1371 if (value == null || !value.length) return; 1372 var bookmark = this.beginDelimited_(field); 1373 for (var i = 0; i < value.length; i++) { 1374 this.encoder_.writeUnsignedVarint64(value[i]); 1375 } 1376 this.endDelimited_(bookmark); 1377}; 1378 1379 1380/** 1381 * Writes an array of numbers represented as strings to the buffer as a packed 1382 * unsigned 64-bit int field. 1383 * @param {number} field 1384 * @param {?Array<string>} value 1385 */ 1386jspb.BinaryWriter.prototype.writePackedUint64String = 1387 function(field, value) { 1388 if (value == null || !value.length) return; 1389 var bookmark = this.beginDelimited_(field); 1390 for (var i = 0; i < value.length; i++) { 1391 var num = jspb.arith.UInt64.fromString(value[i]); 1392 this.encoder_.writeSplitVarint64(num.lo, num.hi); 1393 } 1394 this.endDelimited_(bookmark); 1395}; 1396 1397 1398/** 1399 * Writes an array numbers to the buffer as a packed signed 32-bit int field. 1400 * @param {number} field The field number. 1401 * @param {?Array<number>} value The array of ints to write. 1402 */ 1403jspb.BinaryWriter.prototype.writePackedSint32 = function(field, value) { 1404 if (value == null || !value.length) return; 1405 var bookmark = this.beginDelimited_(field); 1406 for (var i = 0; i < value.length; i++) { 1407 this.encoder_.writeZigzagVarint32(value[i]); 1408 } 1409 this.endDelimited_(bookmark); 1410}; 1411 1412 1413/** 1414 * Writes an array of numbers to the buffer as a packed signed 64-bit int field. 1415 * @param {number} field The field number. 1416 * @param {?Array<number>} value The array of ints to write. 1417 */ 1418jspb.BinaryWriter.prototype.writePackedSint64 = function(field, value) { 1419 if (value == null || !value.length) return; 1420 var bookmark = this.beginDelimited_(field); 1421 for (var i = 0; i < value.length; i++) { 1422 this.encoder_.writeZigzagVarint64(value[i]); 1423 } 1424 this.endDelimited_(bookmark); 1425}; 1426 1427 1428/** 1429 * Writes an array of decimal strings to the buffer as a packed signed 64-bit 1430 * int field. 1431 * @param {number} field The field number. 1432 * @param {?Array<string>} value The array of decimal strings to write. 1433 */ 1434jspb.BinaryWriter.prototype.writePackedSint64String = function(field, value) { 1435 if (value == null || !value.length) return; 1436 var bookmark = this.beginDelimited_(field); 1437 for (var i = 0; i < value.length; i++) { 1438 // TODO(haberman): make lossless 1439 this.encoder_.writeZigzagVarint64(parseInt(value[i], 10)); 1440 } 1441 this.endDelimited_(bookmark); 1442}; 1443 1444 1445/** 1446 * Writes an array of numbers to the buffer as a packed fixed32 field. 1447 * @param {number} field The field number. 1448 * @param {?Array<number>} value The array of ints to write. 1449 */ 1450jspb.BinaryWriter.prototype.writePackedFixed32 = function(field, value) { 1451 if (value == null || !value.length) return; 1452 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 1453 this.encoder_.writeUnsignedVarint32(value.length * 4); 1454 for (var i = 0; i < value.length; i++) { 1455 this.encoder_.writeUint32(value[i]); 1456 } 1457}; 1458 1459 1460/** 1461 * Writes an array of numbers to the buffer as a packed fixed64 field. 1462 * @param {number} field The field number. 1463 * @param {?Array<number>} value The array of ints to write. 1464 */ 1465jspb.BinaryWriter.prototype.writePackedFixed64 = function(field, value) { 1466 if (value == null || !value.length) return; 1467 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 1468 this.encoder_.writeUnsignedVarint32(value.length * 8); 1469 for (var i = 0; i < value.length; i++) { 1470 this.encoder_.writeUint64(value[i]); 1471 } 1472}; 1473 1474 1475/** 1476 * Writes an array of numbers represented as strings to the buffer as a packed 1477 * fixed64 field. 1478 * @param {number} field The field number. 1479 * @param {?Array<string>} value The array of strings to write. 1480 */ 1481jspb.BinaryWriter.prototype.writePackedFixed64String = function(field, value) { 1482 if (value == null || !value.length) return; 1483 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 1484 this.encoder_.writeUnsignedVarint32(value.length * 8); 1485 for (var i = 0; i < value.length; i++) { 1486 var num = jspb.arith.UInt64.fromString(value[i]); 1487 this.encoder_.writeSplitFixed64(num.lo, num.hi); 1488 } 1489}; 1490 1491 1492/** 1493 * Writes an array of numbers to the buffer as a packed sfixed32 field. 1494 * @param {number} field The field number. 1495 * @param {?Array<number>} value The array of ints to write. 1496 */ 1497jspb.BinaryWriter.prototype.writePackedSfixed32 = function(field, value) { 1498 if (value == null || !value.length) return; 1499 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 1500 this.encoder_.writeUnsignedVarint32(value.length * 4); 1501 for (var i = 0; i < value.length; i++) { 1502 this.encoder_.writeInt32(value[i]); 1503 } 1504}; 1505 1506 1507/** 1508 * Writes an array of numbers to the buffer as a packed sfixed64 field. 1509 * @param {number} field The field number. 1510 * @param {?Array<number>} value The array of ints to write. 1511 */ 1512jspb.BinaryWriter.prototype.writePackedSfixed64 = function(field, value) { 1513 if (value == null || !value.length) return; 1514 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 1515 this.encoder_.writeUnsignedVarint32(value.length * 8); 1516 for (var i = 0; i < value.length; i++) { 1517 this.encoder_.writeInt64(value[i]); 1518 } 1519}; 1520 1521 1522/** 1523 * Writes an array of numbers to the buffer as a packed sfixed64 field. 1524 * @param {number} field The field number. 1525 * @param {?Array<string>} value The array of decimal strings to write. 1526 */ 1527jspb.BinaryWriter.prototype.writePackedSfixed64String = function(field, value) { 1528 if (value == null || !value.length) return; 1529 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 1530 this.encoder_.writeUnsignedVarint32(value.length * 8); 1531 for (var i = 0; i < value.length; i++) { 1532 this.encoder_.writeInt64String(value[i]); 1533 } 1534}; 1535 1536 1537/** 1538 * Writes an array of numbers to the buffer as a packed float field. 1539 * @param {number} field The field number. 1540 * @param {?Array<number>} value The array of ints to write. 1541 */ 1542jspb.BinaryWriter.prototype.writePackedFloat = function(field, value) { 1543 if (value == null || !value.length) return; 1544 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 1545 this.encoder_.writeUnsignedVarint32(value.length * 4); 1546 for (var i = 0; i < value.length; i++) { 1547 this.encoder_.writeFloat(value[i]); 1548 } 1549}; 1550 1551 1552/** 1553 * Writes an array of numbers to the buffer as a packed double field. 1554 * @param {number} field The field number. 1555 * @param {?Array<number>} value The array of ints to write. 1556 */ 1557jspb.BinaryWriter.prototype.writePackedDouble = function(field, value) { 1558 if (value == null || !value.length) return; 1559 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 1560 this.encoder_.writeUnsignedVarint32(value.length * 8); 1561 for (var i = 0; i < value.length; i++) { 1562 this.encoder_.writeDouble(value[i]); 1563 } 1564}; 1565 1566 1567/** 1568 * Writes an array of booleans to the buffer as a packed bool field. 1569 * @param {number} field The field number. 1570 * @param {?Array<boolean>} value The array of ints to write. 1571 */ 1572jspb.BinaryWriter.prototype.writePackedBool = function(field, value) { 1573 if (value == null || !value.length) return; 1574 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 1575 this.encoder_.writeUnsignedVarint32(value.length); 1576 for (var i = 0; i < value.length; i++) { 1577 this.encoder_.writeBool(value[i]); 1578 } 1579}; 1580 1581 1582/** 1583 * Writes an array of enums to the buffer as a packed enum field. 1584 * @param {number} field The field number. 1585 * @param {?Array<number>} value The array of ints to write. 1586 */ 1587jspb.BinaryWriter.prototype.writePackedEnum = function(field, value) { 1588 if (value == null || !value.length) return; 1589 var bookmark = this.beginDelimited_(field); 1590 for (var i = 0; i < value.length; i++) { 1591 this.encoder_.writeEnum(value[i]); 1592 } 1593 this.endDelimited_(bookmark); 1594}; 1595 1596 1597/** 1598 * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to 1599 * the buffer. 1600 * @param {number} field The field number. 1601 * @param {?Array<string>} value The array of hashes to write. 1602 */ 1603jspb.BinaryWriter.prototype.writePackedFixedHash64 = function(field, value) { 1604 if (value == null || !value.length) return; 1605 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 1606 this.encoder_.writeUnsignedVarint32(value.length * 8); 1607 for (var i = 0; i < value.length; i++) { 1608 this.encoder_.writeFixedHash64(value[i]); 1609 } 1610}; 1611 1612 1613/** 1614 * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to 1615 * the buffer. 1616 * @param {number} field The field number. 1617 * @param {?Array<string>} value The array of hashes to write. 1618 */ 1619jspb.BinaryWriter.prototype.writePackedVarintHash64 = function(field, value) { 1620 if (value == null || !value.length) return; 1621 var bookmark = this.beginDelimited_(field); 1622 for (var i = 0; i < value.length; i++) { 1623 this.encoder_.writeVarintHash64(value[i]); 1624 } 1625 this.endDelimited_(bookmark); 1626}; 1627