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 * @suppress {missingRequire} TODO(b/152540451): this shouldn't be needed 56 * @author aappleby@google.com (Austin Appleby) 57 */ 58 59goog.provide('jspb.BinaryWriter'); 60 61goog.require('goog.asserts'); 62goog.require('goog.crypt.base64'); 63goog.require('jspb.BinaryConstants'); 64goog.require('jspb.BinaryEncoder'); 65goog.require('jspb.arith.Int64'); 66goog.require('jspb.arith.UInt64'); 67goog.require('jspb.utils'); 68 69 70 71/** 72 * BinaryWriter implements encoders for all the wire types specified in 73 * https://developers.google.com/protocol-buffers/docs/encoding. 74 * 75 * @constructor 76 * @struct 77 */ 78jspb.BinaryWriter = function() { 79 /** 80 * Blocks of serialized data that will be concatenated once all messages have 81 * been written. 82 * @private {!Array<!Uint8Array|!Array<number>>} 83 */ 84 this.blocks_ = []; 85 86 /** 87 * Total number of bytes in the blocks_ array. Does _not_ include bytes in 88 * the encoder below. 89 * @private {number} 90 */ 91 this.totalLength_ = 0; 92 93 /** 94 * Binary encoder holding pieces of a message that we're still serializing. 95 * When we get to a stopping point (either the start of a new submessage, or 96 * when we need to append a raw Uint8Array), the encoder's buffer will be 97 * added to the block array above and the encoder will be reset. 98 * @private {!jspb.BinaryEncoder} 99 */ 100 this.encoder_ = new jspb.BinaryEncoder(); 101 102 /** 103 * A stack of bookmarks containing the parent blocks for each message started 104 * via beginSubMessage(), needed as bookkeeping for endSubMessage(). 105 * TODO(aappleby): Deprecated, users should be calling writeMessage(). 106 * @private {!Array<!Array<number>>} 107 */ 108 this.bookmarks_ = []; 109}; 110 111 112/** 113 * Append a typed array of bytes onto the buffer. 114 * 115 * @param {!Uint8Array} arr The byte array to append. 116 * @private 117 */ 118jspb.BinaryWriter.prototype.appendUint8Array_ = function(arr) { 119 var temp = this.encoder_.end(); 120 this.blocks_.push(temp); 121 this.blocks_.push(arr); 122 this.totalLength_ += temp.length + arr.length; 123}; 124 125 126/** 127 * Begins a new message by writing the field header and returning a bookmark 128 * which we will use to patch in the message length to in endDelimited_ below. 129 * @param {number} field 130 * @return {!Array<number>} 131 * @private 132 */ 133jspb.BinaryWriter.prototype.beginDelimited_ = function(field) { 134 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 135 var bookmark = this.encoder_.end(); 136 this.blocks_.push(bookmark); 137 this.totalLength_ += bookmark.length; 138 bookmark.push(this.totalLength_); 139 return bookmark; 140}; 141 142 143/** 144 * Ends a message by encoding the _change_ in length of the buffer to the 145 * parent block and adds the number of bytes needed to encode that length to 146 * the total byte length. 147 * @param {!Array<number>} bookmark 148 * @private 149 */ 150jspb.BinaryWriter.prototype.endDelimited_ = function(bookmark) { 151 var oldLength = bookmark.pop(); 152 var messageLength = this.totalLength_ + this.encoder_.length() - oldLength; 153 goog.asserts.assert(messageLength >= 0); 154 155 while (messageLength > 127) { 156 bookmark.push((messageLength & 0x7f) | 0x80); 157 messageLength = messageLength >>> 7; 158 this.totalLength_++; 159 } 160 161 bookmark.push(messageLength); 162 this.totalLength_++; 163}; 164 165 166/** 167 * Writes a pre-serialized message to the buffer. 168 * @param {!Uint8Array} bytes The array of bytes to write. 169 * @param {number} start The start of the range to write. 170 * @param {number} end The end of the range to write. 171 */ 172jspb.BinaryWriter.prototype.writeSerializedMessage = function( 173 bytes, start, end) { 174 this.appendUint8Array_(bytes.subarray(start, end)); 175}; 176 177 178/** 179 * Writes a pre-serialized message to the buffer if the message and endpoints 180 * are non-null. 181 * @param {?Uint8Array} bytes The array of bytes to write. 182 * @param {?number} start The start of the range to write. 183 * @param {?number} end The end of the range to write. 184 */ 185jspb.BinaryWriter.prototype.maybeWriteSerializedMessage = function( 186 bytes, start, end) { 187 if (bytes != null && start != null && end != null) { 188 this.writeSerializedMessage(bytes, start, end); 189 } 190}; 191 192 193/** 194 * Resets the writer, throwing away any accumulated buffers. 195 */ 196jspb.BinaryWriter.prototype.reset = function() { 197 this.blocks_ = []; 198 this.encoder_.end(); 199 this.totalLength_ = 0; 200 this.bookmarks_ = []; 201}; 202 203 204/** 205 * Converts the encoded data into a Uint8Array. 206 * @return {!Uint8Array} 207 */ 208jspb.BinaryWriter.prototype.getResultBuffer = function() { 209 goog.asserts.assert(this.bookmarks_.length == 0); 210 211 var flat = new Uint8Array(this.totalLength_ + this.encoder_.length()); 212 213 var blocks = this.blocks_; 214 var blockCount = blocks.length; 215 var offset = 0; 216 217 for (var i = 0; i < blockCount; i++) { 218 var block = blocks[i]; 219 flat.set(block, offset); 220 offset += block.length; 221 } 222 223 var tail = this.encoder_.end(); 224 flat.set(tail, offset); 225 offset += tail.length; 226 227 // Post condition: `flattened` must have had every byte written. 228 goog.asserts.assert(offset == flat.length); 229 230 // Replace our block list with the flattened block, which lets GC reclaim 231 // the temp blocks sooner. 232 this.blocks_ = [flat]; 233 234 return flat; 235}; 236 237 238/** 239 * Converts the encoded data into a base64-encoded string. 240 * @param {!goog.crypt.base64.Alphabet=} alphabet Which flavor of base64 to use. 241 * @return {string} 242 */ 243jspb.BinaryWriter.prototype.getResultBase64String = function(alphabet) { 244 return goog.crypt.base64.encodeByteArray(this.getResultBuffer(), alphabet); 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 a zigzag varint field to the buffer without range checking. 455 * @param {number} field The field number. 456 * @param {string?} value The value to write. 457 * @private 458 */ 459jspb.BinaryWriter.prototype.writeZigzagVarintHash64_ = function(field, value) { 460 if (value == null) return; 461 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 462 this.encoder_.writeZigzagVarintHash64(value); 463}; 464 465 466/** 467 * Writes an int32 field to the buffer. Numbers outside the range [-2^31,2^31) 468 * will be truncated. 469 * @param {number} field The field number. 470 * @param {number?} value The value to write. 471 */ 472jspb.BinaryWriter.prototype.writeInt32 = function(field, value) { 473 if (value == null) return; 474 goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) && 475 (value < jspb.BinaryConstants.TWO_TO_31)); 476 this.writeSignedVarint32_(field, value); 477}; 478 479 480/** 481 * Writes an int32 field represented as a string to the buffer. Numbers outside 482 * the range [-2^31,2^31) will be truncated. 483 * @param {number} field The field number. 484 * @param {string?} value The value to write. 485 */ 486jspb.BinaryWriter.prototype.writeInt32String = function(field, value) { 487 if (value == null) return; 488 var intValue = /** {number} */ parseInt(value, 10); 489 goog.asserts.assert((intValue >= -jspb.BinaryConstants.TWO_TO_31) && 490 (intValue < jspb.BinaryConstants.TWO_TO_31)); 491 this.writeSignedVarint32_(field, intValue); 492}; 493 494 495/** 496 * Writes an int64 field to the buffer. Numbers outside the range [-2^63,2^63) 497 * will be truncated. 498 * @param {number} field The field number. 499 * @param {number?} value The value to write. 500 */ 501jspb.BinaryWriter.prototype.writeInt64 = function(field, value) { 502 if (value == null) return; 503 goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_63) && 504 (value < jspb.BinaryConstants.TWO_TO_63)); 505 this.writeSignedVarint64_(field, value); 506}; 507 508 509/** 510 * Writes a int64 field (with value as a string) to the buffer. 511 * @param {number} field The field number. 512 * @param {string?} value The value to write. 513 */ 514jspb.BinaryWriter.prototype.writeInt64String = function(field, value) { 515 if (value == null) return; 516 var num = jspb.arith.Int64.fromString(value); 517 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 518 this.encoder_.writeSplitVarint64(num.lo, num.hi); 519}; 520 521 522/** 523 * Writes a uint32 field to the buffer. Numbers outside the range [0,2^32) 524 * will be truncated. 525 * @param {number} field The field number. 526 * @param {number?} value The value to write. 527 */ 528jspb.BinaryWriter.prototype.writeUint32 = function(field, value) { 529 if (value == null) return; 530 goog.asserts.assert((value >= 0) && 531 (value < jspb.BinaryConstants.TWO_TO_32)); 532 this.writeUnsignedVarint32_(field, value); 533}; 534 535 536/** 537 * Writes a uint32 field represented as a string to the buffer. Numbers outside 538 * the range [0,2^32) will be truncated. 539 * @param {number} field The field number. 540 * @param {string?} value The value to write. 541 */ 542jspb.BinaryWriter.prototype.writeUint32String = function(field, value) { 543 if (value == null) return; 544 var intValue = /** {number} */ parseInt(value, 10); 545 goog.asserts.assert((intValue >= 0) && 546 (intValue < jspb.BinaryConstants.TWO_TO_32)); 547 this.writeUnsignedVarint32_(field, intValue); 548}; 549 550 551/** 552 * Writes a uint64 field to the buffer. Numbers outside the range [0,2^64) 553 * will be truncated. 554 * @param {number} field The field number. 555 * @param {number?} value The value to write. 556 */ 557jspb.BinaryWriter.prototype.writeUint64 = function(field, value) { 558 if (value == null) return; 559 goog.asserts.assert((value >= 0) && 560 (value < jspb.BinaryConstants.TWO_TO_64)); 561 this.writeUnsignedVarint64_(field, value); 562}; 563 564 565/** 566 * Writes a uint64 field (with value as a string) to the buffer. 567 * @param {number} field The field number. 568 * @param {string?} value The value to write. 569 */ 570jspb.BinaryWriter.prototype.writeUint64String = function(field, value) { 571 if (value == null) return; 572 var num = jspb.arith.UInt64.fromString(value); 573 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 574 this.encoder_.writeSplitVarint64(num.lo, num.hi); 575}; 576 577 578/** 579 * Writes an sint32 field to the buffer. Numbers outside the range [-2^31,2^31) 580 * will be truncated. 581 * @param {number} field The field number. 582 * @param {number?} value The value to write. 583 */ 584jspb.BinaryWriter.prototype.writeSint32 = function(field, value) { 585 if (value == null) return; 586 goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) && 587 (value < jspb.BinaryConstants.TWO_TO_31)); 588 this.writeZigzagVarint32_(field, value); 589}; 590 591 592/** 593 * Writes an sint64 field to the buffer. Numbers outside the range [-2^63,2^63) 594 * will be truncated. 595 * @param {number} field The field number. 596 * @param {number?} value The value to write. 597 */ 598jspb.BinaryWriter.prototype.writeSint64 = function(field, value) { 599 if (value == null) return; 600 goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_63) && 601 (value < jspb.BinaryConstants.TWO_TO_63)); 602 this.writeZigzagVarint64_(field, value); 603}; 604 605 606/** 607 * Writes an sint64 field to the buffer from a hash64 encoded value. Numbers 608 * outside the range [-2^63,2^63) will be truncated. 609 * @param {number} field The field number. 610 * @param {string?} value The hash64 string to write. 611 */ 612jspb.BinaryWriter.prototype.writeSintHash64 = function(field, value) { 613 if (value == null) return; 614 this.writeZigzagVarintHash64_(field, value); 615}; 616 617 618/** 619 * Writes an sint64 field to the buffer. Numbers outside the range [-2^63,2^63) 620 * will be truncated. 621 * @param {number} field The field number. 622 * @param {string?} value The decimal string to write. 623 */ 624jspb.BinaryWriter.prototype.writeSint64String = function(field, value) { 625 if (value == null) return; 626 this.writeZigzagVarint64String_(field, value); 627}; 628 629 630/** 631 * Writes a fixed32 field to the buffer. Numbers outside the range [0,2^32) 632 * will be truncated. 633 * @param {number} field The field number. 634 * @param {number?} value The value to write. 635 */ 636jspb.BinaryWriter.prototype.writeFixed32 = function(field, value) { 637 if (value == null) return; 638 goog.asserts.assert((value >= 0) && 639 (value < jspb.BinaryConstants.TWO_TO_32)); 640 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED32); 641 this.encoder_.writeUint32(value); 642}; 643 644 645/** 646 * Writes a fixed64 field to the buffer. Numbers outside the range [0,2^64) 647 * will be truncated. 648 * @param {number} field The field number. 649 * @param {number?} value The value to write. 650 */ 651jspb.BinaryWriter.prototype.writeFixed64 = function(field, value) { 652 if (value == null) return; 653 goog.asserts.assert((value >= 0) && 654 (value < jspb.BinaryConstants.TWO_TO_64)); 655 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); 656 this.encoder_.writeUint64(value); 657}; 658 659 660/** 661 * Writes a fixed64 field (with value as a string) to the buffer. 662 * @param {number} field The field number. 663 * @param {string?} value The value to write. 664 */ 665jspb.BinaryWriter.prototype.writeFixed64String = function(field, value) { 666 if (value == null) return; 667 var num = jspb.arith.UInt64.fromString(value); 668 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); 669 this.encoder_.writeSplitFixed64(num.lo, num.hi); 670}; 671 672 673/** 674 * Writes a sfixed32 field to the buffer. Numbers outside the range 675 * [-2^31,2^31) will be truncated. 676 * @param {number} field The field number. 677 * @param {number?} value The value to write. 678 */ 679jspb.BinaryWriter.prototype.writeSfixed32 = function(field, value) { 680 if (value == null) return; 681 goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) && 682 (value < jspb.BinaryConstants.TWO_TO_31)); 683 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED32); 684 this.encoder_.writeInt32(value); 685}; 686 687 688/** 689 * Writes a sfixed64 field to the buffer. Numbers outside the range 690 * [-2^63,2^63) will be truncated. 691 * @param {number} field The field number. 692 * @param {number?} value The value to write. 693 */ 694jspb.BinaryWriter.prototype.writeSfixed64 = function(field, value) { 695 if (value == null) return; 696 goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_63) && 697 (value < jspb.BinaryConstants.TWO_TO_63)); 698 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); 699 this.encoder_.writeInt64(value); 700}; 701 702 703/** 704 * Writes a sfixed64 string field to the buffer. Numbers outside the range 705 * [-2^63,2^63) will be truncated. 706 * @param {number} field The field number. 707 * @param {string?} value The value to write. 708 */ 709jspb.BinaryWriter.prototype.writeSfixed64String = function(field, value) { 710 if (value == null) return; 711 var num = jspb.arith.Int64.fromString(value); 712 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); 713 this.encoder_.writeSplitFixed64(num.lo, num.hi); 714}; 715 716 717/** 718 * Writes a single-precision floating point field to the buffer. Numbers 719 * requiring more than 32 bits of precision will be truncated. 720 * @param {number} field The field number. 721 * @param {number?} value The value to write. 722 */ 723jspb.BinaryWriter.prototype.writeFloat = function(field, value) { 724 if (value == null) return; 725 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED32); 726 this.encoder_.writeFloat(value); 727}; 728 729 730/** 731 * Writes a double-precision floating point field to the buffer. As this is the 732 * native format used by JavaScript, no precision will be lost. 733 * @param {number} field The field number. 734 * @param {number?} value The value to write. 735 */ 736jspb.BinaryWriter.prototype.writeDouble = function(field, value) { 737 if (value == null) return; 738 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); 739 this.encoder_.writeDouble(value); 740}; 741 742 743/** 744 * Writes a boolean field to the buffer. We allow numbers as input 745 * because the JSPB code generator uses 0/1 instead of true/false to save space 746 * in the string representation of the proto. 747 * @param {number} field The field number. 748 * @param {boolean?|number?} value The value to write. 749 */ 750jspb.BinaryWriter.prototype.writeBool = function(field, value) { 751 if (value == null) return; 752 goog.asserts.assert(typeof value === 'boolean' || typeof value === 'number'); 753 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 754 this.encoder_.writeBool(value); 755}; 756 757 758/** 759 * Writes an enum field to the buffer. 760 * @param {number} field The field number. 761 * @param {number?} value The value to write. 762 */ 763jspb.BinaryWriter.prototype.writeEnum = function(field, value) { 764 if (value == null) return; 765 goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) && 766 (value < jspb.BinaryConstants.TWO_TO_31)); 767 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 768 this.encoder_.writeSignedVarint32(value); 769}; 770 771 772/** 773 * Writes a string field to the buffer. 774 * @param {number} field The field number. 775 * @param {string?} value The string to write. 776 */ 777jspb.BinaryWriter.prototype.writeString = function(field, value) { 778 if (value == null) return; 779 var bookmark = this.beginDelimited_(field); 780 this.encoder_.writeString(value); 781 this.endDelimited_(bookmark); 782}; 783 784 785/** 786 * Writes an arbitrary byte field to the buffer. Note - to match the behavior 787 * of the C++ implementation, empty byte arrays _are_ serialized. 788 * @param {number} field The field number. 789 * @param {?jspb.ByteSource} value The array of bytes to write. 790 */ 791jspb.BinaryWriter.prototype.writeBytes = function(field, value) { 792 if (value == null) return; 793 var bytes = jspb.utils.byteSourceToUint8Array(value); 794 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 795 this.encoder_.writeUnsignedVarint32(bytes.length); 796 this.appendUint8Array_(bytes); 797}; 798 799 800/** 801 * Writes a message to the buffer. 802 * @param {number} field The field number. 803 * @param {?MessageType} value The message to write. 804 * @param {function(MessageTypeNonNull, !jspb.BinaryWriter)} writerCallback 805 * Will be invoked with the value to write and the writer to write it with. 806 * @template MessageType 807 * Use go/closure-ttl to declare a non-nullable version of MessageType. Replace 808 * the null in blah|null with none. This is necessary because the compiler will 809 * infer MessageType to be nullable if the value parameter is nullable. 810 * @template MessageTypeNonNull := 811 * cond(isUnknown(MessageType), unknown(), 812 * mapunion(MessageType, (X) => 813 * cond(eq(X, 'null'), none(), X))) 814 * =: 815 */ 816jspb.BinaryWriter.prototype.writeMessage = function( 817 field, value, writerCallback) { 818 if (value == null) return; 819 var bookmark = this.beginDelimited_(field); 820 writerCallback(value, this); 821 this.endDelimited_(bookmark); 822}; 823 824 825/** 826 * Writes a message set extension to the buffer. 827 * @param {number} field The field number for the extension. 828 * @param {?MessageType} value The extension message object to write. Note that 829 * message set can only have extensions with type of optional message. 830 * @param {function(!MessageTypeNonNull, !jspb.BinaryWriter)} writerCallback 831 * Will be invoked with the value to write and the writer to write it with. 832 * @template MessageType 833 * Use go/closure-ttl to declare a non-nullable version of MessageType. Replace 834 * the null in blah|null with none. This is necessary because the compiler will 835 * infer MessageType to be nullable if the value parameter is nullable. 836 * @template MessageTypeNonNull := 837 * cond(isUnknown(MessageType), unknown(), 838 * mapunion(MessageType, (X) => 839 * cond(eq(X, 'null'), none(), X))) 840 * =: 841 */ 842jspb.BinaryWriter.prototype.writeMessageSet = function( 843 field, value, writerCallback) { 844 if (value == null) return; 845 // The wire format for a message set is defined by 846 // google3/net/proto/message_set.proto 847 this.writeFieldHeader_(1, jspb.BinaryConstants.WireType.START_GROUP); 848 this.writeFieldHeader_(2, jspb.BinaryConstants.WireType.VARINT); 849 this.encoder_.writeSignedVarint32(field); 850 var bookmark = this.beginDelimited_(3); 851 writerCallback(value, this); 852 this.endDelimited_(bookmark); 853 this.writeFieldHeader_(1, jspb.BinaryConstants.WireType.END_GROUP); 854}; 855 856 857/** 858 * Writes a group message to the buffer. 859 * 860 * @param {number} field The field number. 861 * @param {?MessageType} value The message to write, wrapped with START_GROUP / 862 * END_GROUP tags. Will be a no-op if 'value' is null. 863 * @param {function(MessageTypeNonNull, !jspb.BinaryWriter)} writerCallback 864 * Will be invoked with the value to write and the writer to write it with. 865 * @template MessageType 866 * Use go/closure-ttl to declare a non-nullable version of MessageType. Replace 867 * the null in blah|null with none. This is necessary because the compiler will 868 * infer MessageType to be nullable if the value parameter is nullable. 869 * @template MessageTypeNonNull := 870 * cond(isUnknown(MessageType), unknown(), 871 * mapunion(MessageType, (X) => 872 * cond(eq(X, 'null'), none(), X))) 873 * =: 874 */ 875jspb.BinaryWriter.prototype.writeGroup = function( 876 field, value, writerCallback) { 877 if (value == null) return; 878 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.START_GROUP); 879 writerCallback(value, this); 880 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.END_GROUP); 881}; 882 883 884/** 885 * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to 886 * the buffer. 887 * @param {number} field The field number. 888 * @param {string?} value The hash string. 889 */ 890jspb.BinaryWriter.prototype.writeFixedHash64 = function(field, value) { 891 if (value == null) return; 892 goog.asserts.assert(value.length == 8); 893 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); 894 this.encoder_.writeFixedHash64(value); 895}; 896 897 898/** 899 * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to 900 * the buffer. 901 * @param {number} field The field number. 902 * @param {string?} value The hash string. 903 */ 904jspb.BinaryWriter.prototype.writeVarintHash64 = function(field, value) { 905 if (value == null) return; 906 goog.asserts.assert(value.length == 8); 907 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 908 this.encoder_.writeVarintHash64(value); 909}; 910 911 912/** 913 * Writes a 64-bit field to the buffer as a fixed64. 914 * @param {number} field The field number. 915 * @param {number} lowBits The low 32 bits. 916 * @param {number} highBits The high 32 bits. 917 */ 918jspb.BinaryWriter.prototype.writeSplitFixed64 = function( 919 field, lowBits, highBits) { 920 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); 921 this.encoder_.writeSplitFixed64(lowBits, highBits); 922}; 923 924 925/** 926 * Writes a 64-bit field to the buffer as a varint. 927 * @param {number} field The field number. 928 * @param {number} lowBits The low 32 bits. 929 * @param {number} highBits The high 32 bits. 930 */ 931jspb.BinaryWriter.prototype.writeSplitVarint64 = function( 932 field, lowBits, highBits) { 933 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 934 this.encoder_.writeSplitVarint64(lowBits, highBits); 935}; 936 937 938/** 939 * Writes a 64-bit field to the buffer as a zigzag encoded varint. 940 * @param {number} field The field number. 941 * @param {number} lowBits The low 32 bits. 942 * @param {number} highBits The high 32 bits. 943 */ 944jspb.BinaryWriter.prototype.writeSplitZigzagVarint64 = function( 945 field, lowBits, highBits) { 946 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 947 var encoder = this.encoder_; 948 jspb.utils.toZigzag64(lowBits, highBits, function(lowBits, highBits) { 949 encoder.writeSplitVarint64(lowBits >>> 0, highBits >>> 0); 950 }); 951}; 952 953 954/** 955 * Writes an array of numbers to the buffer as a repeated 32-bit int field. 956 * @param {number} field The field number. 957 * @param {?Array<number>} value The array of ints to write. 958 */ 959jspb.BinaryWriter.prototype.writeRepeatedInt32 = function(field, value) { 960 if (value == null) return; 961 for (var i = 0; i < value.length; i++) { 962 this.writeSignedVarint32_(field, value[i]); 963 } 964}; 965 966 967/** 968 * Writes an array of numbers formatted as strings to the buffer as a repeated 969 * 32-bit int field. 970 * @param {number} field The field number. 971 * @param {?Array<string>} value The array of ints to write. 972 */ 973jspb.BinaryWriter.prototype.writeRepeatedInt32String = function(field, value) { 974 if (value == null) return; 975 for (var i = 0; i < value.length; i++) { 976 this.writeInt32String(field, value[i]); 977 } 978}; 979 980 981/** 982 * Writes an array of numbers to the buffer as a repeated 64-bit int field. 983 * @param {number} field The field number. 984 * @param {?Array<number>} value The array of ints to write. 985 */ 986jspb.BinaryWriter.prototype.writeRepeatedInt64 = function(field, value) { 987 if (value == null) return; 988 for (var i = 0; i < value.length; i++) { 989 this.writeSignedVarint64_(field, value[i]); 990 } 991}; 992 993 994/** 995 * Writes an array of 64-bit values to the buffer as a fixed64. 996 * @param {number} field The field number. 997 * @param {?Array<T>} value The value. 998 * @param {function(T): number} lo Function to get low bits. 999 * @param {function(T): number} hi Function to get high bits. 1000 * @template T 1001 */ 1002jspb.BinaryWriter.prototype.writeRepeatedSplitFixed64 = function( 1003 field, value, lo, hi) { 1004 if (value == null) return; 1005 for (var i = 0; i < value.length; i++) { 1006 this.writeSplitFixed64(field, lo(value[i]), hi(value[i])); 1007 } 1008}; 1009 1010 1011/** 1012 * Writes an array of 64-bit values to the buffer as a varint. 1013 * @param {number} field The field number. 1014 * @param {?Array<T>} value The value. 1015 * @param {function(T): number} lo Function to get low bits. 1016 * @param {function(T): number} hi Function to get high bits. 1017 * @template T 1018 */ 1019jspb.BinaryWriter.prototype.writeRepeatedSplitVarint64 = function( 1020 field, value, lo, hi) { 1021 if (value == null) return; 1022 for (var i = 0; i < value.length; i++) { 1023 this.writeSplitVarint64(field, lo(value[i]), hi(value[i])); 1024 } 1025}; 1026 1027 1028/** 1029 * Writes an array of 64-bit values to the buffer as a zigzag varint. 1030 * @param {number} field The field number. 1031 * @param {?Array<T>} value The value. 1032 * @param {function(T): number} lo Function to get low bits. 1033 * @param {function(T): number} hi Function to get high bits. 1034 * @template T 1035 */ 1036jspb.BinaryWriter.prototype.writeRepeatedSplitZigzagVarint64 = function( 1037 field, value, lo, hi) { 1038 if (value == null) return; 1039 for (var i = 0; i < value.length; i++) { 1040 this.writeSplitZigzagVarint64(field, lo(value[i]), hi(value[i])); 1041 } 1042}; 1043 1044 1045/** 1046 * Writes an array of numbers formatted as strings to the buffer as a repeated 1047 * 64-bit int field. 1048 * @param {number} field The field number. 1049 * @param {?Array<string>} value The array of ints to write. 1050 */ 1051jspb.BinaryWriter.prototype.writeRepeatedInt64String = function(field, value) { 1052 if (value == null) return; 1053 for (var i = 0; i < value.length; i++) { 1054 this.writeInt64String(field, value[i]); 1055 } 1056}; 1057 1058 1059/** 1060 * Writes an array numbers to the buffer as a repeated unsigned 32-bit int 1061 * field. 1062 * @param {number} field The field number. 1063 * @param {?Array<number>} value The array of ints to write. 1064 */ 1065jspb.BinaryWriter.prototype.writeRepeatedUint32 = function(field, value) { 1066 if (value == null) return; 1067 for (var i = 0; i < value.length; i++) { 1068 this.writeUnsignedVarint32_(field, value[i]); 1069 } 1070}; 1071 1072 1073/** 1074 * Writes an array of numbers formatted as strings to the buffer as a repeated 1075 * unsigned 32-bit int field. 1076 * @param {number} field The field number. 1077 * @param {?Array<string>} value The array of ints to write. 1078 */ 1079jspb.BinaryWriter.prototype.writeRepeatedUint32String = function(field, value) { 1080 if (value == null) return; 1081 for (var i = 0; i < value.length; i++) { 1082 this.writeUint32String(field, value[i]); 1083 } 1084}; 1085 1086 1087/** 1088 * Writes an array numbers to the buffer as a repeated unsigned 64-bit int 1089 * field. 1090 * @param {number} field The field number. 1091 * @param {?Array<number>} value The array of ints to write. 1092 */ 1093jspb.BinaryWriter.prototype.writeRepeatedUint64 = function(field, value) { 1094 if (value == null) return; 1095 for (var i = 0; i < value.length; i++) { 1096 this.writeUnsignedVarint64_(field, value[i]); 1097 } 1098}; 1099 1100 1101/** 1102 * Writes an array of numbers formatted as strings to the buffer as a repeated 1103 * unsigned 64-bit int field. 1104 * @param {number} field The field number. 1105 * @param {?Array<string>} value The array of ints to write. 1106 */ 1107jspb.BinaryWriter.prototype.writeRepeatedUint64String = function(field, value) { 1108 if (value == null) return; 1109 for (var i = 0; i < value.length; i++) { 1110 this.writeUint64String(field, value[i]); 1111 } 1112}; 1113 1114 1115/** 1116 * Writes an array numbers to the buffer as a repeated signed 32-bit int field. 1117 * @param {number} field The field number. 1118 * @param {?Array<number>} value The array of ints to write. 1119 */ 1120jspb.BinaryWriter.prototype.writeRepeatedSint32 = function(field, value) { 1121 if (value == null) return; 1122 for (var i = 0; i < value.length; i++) { 1123 this.writeZigzagVarint32_(field, value[i]); 1124 } 1125}; 1126 1127 1128/** 1129 * Writes an array numbers to the buffer as a repeated signed 64-bit int field. 1130 * @param {number} field The field number. 1131 * @param {?Array<number>} value The array of ints to write. 1132 */ 1133jspb.BinaryWriter.prototype.writeRepeatedSint64 = function(field, value) { 1134 if (value == null) return; 1135 for (var i = 0; i < value.length; i++) { 1136 this.writeZigzagVarint64_(field, value[i]); 1137 } 1138}; 1139 1140 1141/** 1142 * Writes an array numbers to the buffer as a repeated signed 64-bit int field. 1143 * @param {number} field The field number. 1144 * @param {?Array<string>} value The array of ints to write. 1145 */ 1146jspb.BinaryWriter.prototype.writeRepeatedSint64String = function(field, value) { 1147 if (value == null) return; 1148 for (var i = 0; i < value.length; i++) { 1149 this.writeZigzagVarint64String_(field, value[i]); 1150 } 1151}; 1152 1153 1154/** 1155 * Writes an array of hash64 strings to the buffer as a repeated signed 64-bit 1156 * int field. 1157 * @param {number} field The field number. 1158 * @param {?Array<string>} value The array of ints to write. 1159 */ 1160jspb.BinaryWriter.prototype.writeRepeatedSintHash64 = function(field, value) { 1161 if (value == null) return; 1162 for (var i = 0; i < value.length; i++) { 1163 this.writeZigzagVarintHash64_(field, value[i]); 1164 } 1165}; 1166 1167 1168/** 1169 * Writes an array of numbers to the buffer as a repeated fixed32 field. This 1170 * works for both signed and unsigned fixed32s. 1171 * @param {number} field The field number. 1172 * @param {?Array<number>} value The array of ints to write. 1173 */ 1174jspb.BinaryWriter.prototype.writeRepeatedFixed32 = function(field, value) { 1175 if (value == null) return; 1176 for (var i = 0; i < value.length; i++) { 1177 this.writeFixed32(field, value[i]); 1178 } 1179}; 1180 1181 1182/** 1183 * Writes an array of numbers to the buffer as a repeated fixed64 field. This 1184 * works for both signed and unsigned fixed64s. 1185 * @param {number} field The field number. 1186 * @param {?Array<number>} value The array of ints to write. 1187 */ 1188jspb.BinaryWriter.prototype.writeRepeatedFixed64 = function(field, value) { 1189 if (value == null) return; 1190 for (var i = 0; i < value.length; i++) { 1191 this.writeFixed64(field, value[i]); 1192 } 1193}; 1194 1195 1196/** 1197 * Writes an array of numbers to the buffer as a repeated fixed64 field. This 1198 * works for both signed and unsigned fixed64s. 1199 * @param {number} field The field number. 1200 * @param {?Array<string>} value The array of decimal strings to write. 1201 */ 1202jspb.BinaryWriter.prototype.writeRepeatedFixed64String = function( 1203 field, value) { 1204 if (value == null) return; 1205 for (var i = 0; i < value.length; i++) { 1206 this.writeFixed64String(field, value[i]); 1207 } 1208}; 1209 1210 1211/** 1212 * Writes an array of numbers to the buffer as a repeated sfixed32 field. 1213 * @param {number} field The field number. 1214 * @param {?Array<number>} value The array of ints to write. 1215 */ 1216jspb.BinaryWriter.prototype.writeRepeatedSfixed32 = function(field, value) { 1217 if (value == null) return; 1218 for (var i = 0; i < value.length; i++) { 1219 this.writeSfixed32(field, value[i]); 1220 } 1221}; 1222 1223 1224/** 1225 * Writes an array of numbers to the buffer as a repeated sfixed64 field. 1226 * @param {number} field The field number. 1227 * @param {?Array<number>} value The array of ints to write. 1228 */ 1229jspb.BinaryWriter.prototype.writeRepeatedSfixed64 = function(field, value) { 1230 if (value == null) return; 1231 for (var i = 0; i < value.length; i++) { 1232 this.writeSfixed64(field, value[i]); 1233 } 1234}; 1235 1236 1237/** 1238 * Writes an array of decimal strings to the buffer as a repeated sfixed64 1239 * field. 1240 * @param {number} field The field number. 1241 * @param {?Array<string>} value The array of decimal strings to write. 1242 */ 1243jspb.BinaryWriter.prototype.writeRepeatedSfixed64String = function(field, value) { 1244 if (value == null) return; 1245 for (var i = 0; i < value.length; i++) { 1246 this.writeSfixed64String(field, value[i]); 1247 } 1248}; 1249 1250 1251/** 1252 * Writes an array of numbers to the buffer as a repeated float field. 1253 * @param {number} field The field number. 1254 * @param {?Array<number>} value The array of ints to write. 1255 */ 1256jspb.BinaryWriter.prototype.writeRepeatedFloat = function(field, value) { 1257 if (value == null) return; 1258 for (var i = 0; i < value.length; i++) { 1259 this.writeFloat(field, value[i]); 1260 } 1261}; 1262 1263 1264/** 1265 * Writes an array of numbers to the buffer as a repeated double field. 1266 * @param {number} field The field number. 1267 * @param {?Array<number>} value The array of ints to write. 1268 */ 1269jspb.BinaryWriter.prototype.writeRepeatedDouble = function(field, value) { 1270 if (value == null) return; 1271 for (var i = 0; i < value.length; i++) { 1272 this.writeDouble(field, value[i]); 1273 } 1274}; 1275 1276 1277/** 1278 * Writes an array of booleans to the buffer as a repeated bool field. 1279 * @param {number} field The field number. 1280 * @param {?Array<boolean>} value The array of ints to write. 1281 */ 1282jspb.BinaryWriter.prototype.writeRepeatedBool = function(field, value) { 1283 if (value == null) return; 1284 for (var i = 0; i < value.length; i++) { 1285 this.writeBool(field, value[i]); 1286 } 1287}; 1288 1289 1290/** 1291 * Writes an array of enums to the buffer as a repeated enum field. 1292 * @param {number} field The field number. 1293 * @param {?Array<number>} value The array of ints to write. 1294 */ 1295jspb.BinaryWriter.prototype.writeRepeatedEnum = function(field, value) { 1296 if (value == null) return; 1297 for (var i = 0; i < value.length; i++) { 1298 this.writeEnum(field, value[i]); 1299 } 1300}; 1301 1302 1303/** 1304 * Writes an array of strings to the buffer as a repeated string field. 1305 * @param {number} field The field number. 1306 * @param {?Array<string>} value The array of strings to write. 1307 */ 1308jspb.BinaryWriter.prototype.writeRepeatedString = function(field, value) { 1309 if (value == null) return; 1310 for (var i = 0; i < value.length; i++) { 1311 this.writeString(field, value[i]); 1312 } 1313}; 1314 1315 1316/** 1317 * Writes an array of arbitrary byte fields to the buffer. 1318 * @param {number} field The field number. 1319 * @param {?Array<!jspb.ByteSource>} value The arrays of arrays of bytes to 1320 * write. 1321 */ 1322jspb.BinaryWriter.prototype.writeRepeatedBytes = function(field, value) { 1323 if (value == null) return; 1324 for (var i = 0; i < value.length; i++) { 1325 this.writeBytes(field, value[i]); 1326 } 1327}; 1328 1329 1330/** 1331 * Writes an array of messages to the buffer. 1332 * @template MessageType 1333 * @param {number} field The field number. 1334 * @param {?Array<MessageType>} value The array of messages to 1335 * write. 1336 * @param {function(MessageType, !jspb.BinaryWriter)} writerCallback 1337 * Will be invoked with the value to write and the writer to write it with. 1338 */ 1339jspb.BinaryWriter.prototype.writeRepeatedMessage = function( 1340 field, value, writerCallback) { 1341 if (value == null) return; 1342 for (var i = 0; i < value.length; i++) { 1343 var bookmark = this.beginDelimited_(field); 1344 writerCallback(value[i], this); 1345 this.endDelimited_(bookmark); 1346 } 1347}; 1348 1349 1350/** 1351 * Writes an array of group messages to the buffer. 1352 * @template MessageType 1353 * @param {number} field The field number. 1354 * @param {?Array<MessageType>} value The array of messages to 1355 * write. 1356 * @param {function(MessageType, !jspb.BinaryWriter)} writerCallback 1357 * Will be invoked with the value to write and the writer to write it with. 1358 */ 1359jspb.BinaryWriter.prototype.writeRepeatedGroup = function( 1360 field, value, writerCallback) { 1361 if (value == null) return; 1362 for (var i = 0; i < value.length; i++) { 1363 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.START_GROUP); 1364 writerCallback(value[i], this); 1365 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.END_GROUP); 1366 } 1367}; 1368 1369 1370/** 1371 * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to 1372 * the buffer. 1373 * @param {number} field The field number. 1374 * @param {?Array<string>} value The array of hashes to write. 1375 */ 1376jspb.BinaryWriter.prototype.writeRepeatedFixedHash64 = 1377 function(field, value) { 1378 if (value == null) return; 1379 for (var i = 0; i < value.length; i++) { 1380 this.writeFixedHash64(field, value[i]); 1381 } 1382}; 1383 1384 1385/** 1386 * Writes a repeated 64-bit hash string field (8 characters @ 8 bits of data 1387 * each) to the buffer. 1388 * @param {number} field The field number. 1389 * @param {?Array<string>} value The array of hashes to write. 1390 */ 1391jspb.BinaryWriter.prototype.writeRepeatedVarintHash64 = 1392 function(field, value) { 1393 if (value == null) return; 1394 for (var i = 0; i < value.length; i++) { 1395 this.writeVarintHash64(field, value[i]); 1396 } 1397}; 1398 1399 1400/** 1401 * Writes an array of numbers to the buffer as a packed 32-bit int field. 1402 * @param {number} field The field number. 1403 * @param {?Array<number>} value The array of ints to write. 1404 */ 1405jspb.BinaryWriter.prototype.writePackedInt32 = function(field, value) { 1406 if (value == null || !value.length) return; 1407 var bookmark = this.beginDelimited_(field); 1408 for (var i = 0; i < value.length; i++) { 1409 this.encoder_.writeSignedVarint32(value[i]); 1410 } 1411 this.endDelimited_(bookmark); 1412}; 1413 1414 1415/** 1416 * Writes an array of numbers represented as strings to the buffer as a packed 1417 * 32-bit int field. 1418 * @param {number} field 1419 * @param {?Array<string>} value 1420 */ 1421jspb.BinaryWriter.prototype.writePackedInt32String = function(field, value) { 1422 if (value == null || !value.length) return; 1423 var bookmark = this.beginDelimited_(field); 1424 for (var i = 0; i < value.length; i++) { 1425 this.encoder_.writeSignedVarint32(parseInt(value[i], 10)); 1426 } 1427 this.endDelimited_(bookmark); 1428}; 1429 1430 1431/** 1432 * Writes an array of numbers to the buffer as a packed 64-bit int field. 1433 * @param {number} field The field number. 1434 * @param {?Array<number>} value The array of ints to write. 1435 */ 1436jspb.BinaryWriter.prototype.writePackedInt64 = function(field, value) { 1437 if (value == null || !value.length) return; 1438 var bookmark = this.beginDelimited_(field); 1439 for (var i = 0; i < value.length; i++) { 1440 this.encoder_.writeSignedVarint64(value[i]); 1441 } 1442 this.endDelimited_(bookmark); 1443}; 1444 1445 1446/** 1447 * Writes an array of 64-bit values to the buffer as a fixed64. 1448 * @param {number} field The field number. 1449 * @param {?Array<T>} value The value. 1450 * @param {function(T): number} lo Function to get low bits. 1451 * @param {function(T): number} hi Function to get high bits. 1452 * @template T 1453 */ 1454jspb.BinaryWriter.prototype.writePackedSplitFixed64 = function( 1455 field, value, lo, hi) { 1456 if (value == null) return; 1457 var bookmark = this.beginDelimited_(field); 1458 for (var i = 0; i < value.length; i++) { 1459 this.encoder_.writeSplitFixed64(lo(value[i]), hi(value[i])); 1460 } 1461 this.endDelimited_(bookmark); 1462}; 1463 1464 1465/** 1466 * Writes an array of 64-bit values to the buffer as a varint. 1467 * @param {number} field The field number. 1468 * @param {?Array<T>} value The value. 1469 * @param {function(T): number} lo Function to get low bits. 1470 * @param {function(T): number} hi Function to get high bits. 1471 * @template T 1472 */ 1473jspb.BinaryWriter.prototype.writePackedSplitVarint64 = function( 1474 field, value, lo, hi) { 1475 if (value == null) return; 1476 var bookmark = this.beginDelimited_(field); 1477 for (var i = 0; i < value.length; i++) { 1478 this.encoder_.writeSplitVarint64(lo(value[i]), hi(value[i])); 1479 } 1480 this.endDelimited_(bookmark); 1481}; 1482 1483 1484/** 1485 * Writes an array of 64-bit values to the buffer as a zigzag varint. 1486 * @param {number} field The field number. 1487 * @param {?Array<T>} value The value. 1488 * @param {function(T): number} lo Function to get low bits. 1489 * @param {function(T): number} hi Function to get high bits. 1490 * @template T 1491 */ 1492jspb.BinaryWriter.prototype.writePackedSplitZigzagVarint64 = function( 1493 field, value, lo, hi) { 1494 if (value == null) return; 1495 var bookmark = this.beginDelimited_(field); 1496 var encoder = this.encoder_; 1497 for (var i = 0; i < value.length; i++) { 1498 jspb.utils.toZigzag64( 1499 lo(value[i]), hi(value[i]), function(bitsLow, bitsHigh) { 1500 encoder.writeSplitVarint64(bitsLow >>> 0, bitsHigh >>> 0); 1501 }); 1502 } 1503 this.endDelimited_(bookmark); 1504}; 1505 1506 1507/** 1508 * Writes an array of numbers represented as strings to the buffer as a packed 1509 * 64-bit int field. 1510 * @param {number} field 1511 * @param {?Array<string>} value 1512 */ 1513jspb.BinaryWriter.prototype.writePackedInt64String = function(field, value) { 1514 if (value == null || !value.length) return; 1515 var bookmark = this.beginDelimited_(field); 1516 for (var i = 0; i < value.length; i++) { 1517 var num = jspb.arith.Int64.fromString(value[i]); 1518 this.encoder_.writeSplitVarint64(num.lo, num.hi); 1519 } 1520 this.endDelimited_(bookmark); 1521}; 1522 1523 1524/** 1525 * Writes an array numbers to the buffer as a packed unsigned 32-bit int field. 1526 * @param {number} field The field number. 1527 * @param {?Array<number>} value The array of ints to write. 1528 */ 1529jspb.BinaryWriter.prototype.writePackedUint32 = function(field, value) { 1530 if (value == null || !value.length) return; 1531 var bookmark = this.beginDelimited_(field); 1532 for (var i = 0; i < value.length; i++) { 1533 this.encoder_.writeUnsignedVarint32(value[i]); 1534 } 1535 this.endDelimited_(bookmark); 1536}; 1537 1538 1539/** 1540 * Writes an array of numbers represented as strings to the buffer as a packed 1541 * unsigned 32-bit int field. 1542 * @param {number} field 1543 * @param {?Array<string>} value 1544 */ 1545jspb.BinaryWriter.prototype.writePackedUint32String = 1546 function(field, value) { 1547 if (value == null || !value.length) return; 1548 var bookmark = this.beginDelimited_(field); 1549 for (var i = 0; i < value.length; i++) { 1550 this.encoder_.writeUnsignedVarint32(parseInt(value[i], 10)); 1551 } 1552 this.endDelimited_(bookmark); 1553}; 1554 1555 1556/** 1557 * Writes an array numbers to the buffer as a packed unsigned 64-bit int field. 1558 * @param {number} field The field number. 1559 * @param {?Array<number>} value The array of ints to write. 1560 */ 1561jspb.BinaryWriter.prototype.writePackedUint64 = function(field, value) { 1562 if (value == null || !value.length) return; 1563 var bookmark = this.beginDelimited_(field); 1564 for (var i = 0; i < value.length; i++) { 1565 this.encoder_.writeUnsignedVarint64(value[i]); 1566 } 1567 this.endDelimited_(bookmark); 1568}; 1569 1570 1571/** 1572 * Writes an array of numbers represented as strings to the buffer as a packed 1573 * unsigned 64-bit int field. 1574 * @param {number} field 1575 * @param {?Array<string>} value 1576 */ 1577jspb.BinaryWriter.prototype.writePackedUint64String = 1578 function(field, value) { 1579 if (value == null || !value.length) return; 1580 var bookmark = this.beginDelimited_(field); 1581 for (var i = 0; i < value.length; i++) { 1582 var num = jspb.arith.UInt64.fromString(value[i]); 1583 this.encoder_.writeSplitVarint64(num.lo, num.hi); 1584 } 1585 this.endDelimited_(bookmark); 1586}; 1587 1588 1589/** 1590 * Writes an array numbers to the buffer as a packed signed 32-bit int field. 1591 * @param {number} field The field number. 1592 * @param {?Array<number>} value The array of ints to write. 1593 */ 1594jspb.BinaryWriter.prototype.writePackedSint32 = function(field, value) { 1595 if (value == null || !value.length) return; 1596 var bookmark = this.beginDelimited_(field); 1597 for (var i = 0; i < value.length; i++) { 1598 this.encoder_.writeZigzagVarint32(value[i]); 1599 } 1600 this.endDelimited_(bookmark); 1601}; 1602 1603 1604/** 1605 * Writes an array of numbers to the buffer as a packed signed 64-bit int field. 1606 * @param {number} field The field number. 1607 * @param {?Array<number>} value The array of ints to write. 1608 */ 1609jspb.BinaryWriter.prototype.writePackedSint64 = function(field, value) { 1610 if (value == null || !value.length) return; 1611 var bookmark = this.beginDelimited_(field); 1612 for (var i = 0; i < value.length; i++) { 1613 this.encoder_.writeZigzagVarint64(value[i]); 1614 } 1615 this.endDelimited_(bookmark); 1616}; 1617 1618 1619/** 1620 * Writes an array of decimal strings to the buffer as a packed signed 64-bit 1621 * int field. 1622 * @param {number} field The field number. 1623 * @param {?Array<string>} value The array of decimal strings to write. 1624 */ 1625jspb.BinaryWriter.prototype.writePackedSint64String = function(field, value) { 1626 if (value == null || !value.length) return; 1627 var bookmark = this.beginDelimited_(field); 1628 for (var i = 0; i < value.length; i++) { 1629 this.encoder_.writeZigzagVarintHash64( 1630 jspb.utils.decimalStringToHash64(value[i])); 1631 } 1632 this.endDelimited_(bookmark); 1633}; 1634 1635 1636/** 1637 * Writes an array of hash 64 strings to the buffer as a packed signed 64-bit 1638 * int field. 1639 * @param {number} field The field number. 1640 * @param {?Array<string>} value The array of decimal strings to write. 1641 */ 1642jspb.BinaryWriter.prototype.writePackedSintHash64 = function(field, value) { 1643 if (value == null || !value.length) return; 1644 var bookmark = this.beginDelimited_(field); 1645 for (var i = 0; i < value.length; i++) { 1646 this.encoder_.writeZigzagVarintHash64(value[i]); 1647 } 1648 this.endDelimited_(bookmark); 1649}; 1650 1651 1652/** 1653 * Writes an array of numbers to the buffer as a packed fixed32 field. 1654 * @param {number} field The field number. 1655 * @param {?Array<number>} value The array of ints to write. 1656 */ 1657jspb.BinaryWriter.prototype.writePackedFixed32 = function(field, value) { 1658 if (value == null || !value.length) return; 1659 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 1660 this.encoder_.writeUnsignedVarint32(value.length * 4); 1661 for (var i = 0; i < value.length; i++) { 1662 this.encoder_.writeUint32(value[i]); 1663 } 1664}; 1665 1666 1667/** 1668 * Writes an array of numbers to the buffer as a packed fixed64 field. 1669 * @param {number} field The field number. 1670 * @param {?Array<number>} value The array of ints to write. 1671 */ 1672jspb.BinaryWriter.prototype.writePackedFixed64 = function(field, value) { 1673 if (value == null || !value.length) return; 1674 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 1675 this.encoder_.writeUnsignedVarint32(value.length * 8); 1676 for (var i = 0; i < value.length; i++) { 1677 this.encoder_.writeUint64(value[i]); 1678 } 1679}; 1680 1681 1682/** 1683 * Writes an array of numbers represented as strings to the buffer as a packed 1684 * fixed64 field. 1685 * @param {number} field The field number. 1686 * @param {?Array<string>} value The array of strings to write. 1687 */ 1688jspb.BinaryWriter.prototype.writePackedFixed64String = function(field, value) { 1689 if (value == null || !value.length) return; 1690 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 1691 this.encoder_.writeUnsignedVarint32(value.length * 8); 1692 for (var i = 0; i < value.length; i++) { 1693 var num = jspb.arith.UInt64.fromString(value[i]); 1694 this.encoder_.writeSplitFixed64(num.lo, num.hi); 1695 } 1696}; 1697 1698 1699/** 1700 * Writes an array of numbers to the buffer as a packed sfixed32 field. 1701 * @param {number} field The field number. 1702 * @param {?Array<number>} value The array of ints to write. 1703 */ 1704jspb.BinaryWriter.prototype.writePackedSfixed32 = function(field, value) { 1705 if (value == null || !value.length) return; 1706 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 1707 this.encoder_.writeUnsignedVarint32(value.length * 4); 1708 for (var i = 0; i < value.length; i++) { 1709 this.encoder_.writeInt32(value[i]); 1710 } 1711}; 1712 1713 1714/** 1715 * Writes an array of numbers to the buffer as a packed sfixed64 field. 1716 * @param {number} field The field number. 1717 * @param {?Array<number>} value The array of ints to write. 1718 */ 1719jspb.BinaryWriter.prototype.writePackedSfixed64 = function(field, value) { 1720 if (value == null || !value.length) return; 1721 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 1722 this.encoder_.writeUnsignedVarint32(value.length * 8); 1723 for (var i = 0; i < value.length; i++) { 1724 this.encoder_.writeInt64(value[i]); 1725 } 1726}; 1727 1728 1729/** 1730 * Writes an array of numbers to the buffer as a packed sfixed64 field. 1731 * @param {number} field The field number. 1732 * @param {?Array<string>} value The array of decimal strings to write. 1733 */ 1734jspb.BinaryWriter.prototype.writePackedSfixed64String = function(field, value) { 1735 if (value == null || !value.length) return; 1736 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 1737 this.encoder_.writeUnsignedVarint32(value.length * 8); 1738 for (var i = 0; i < value.length; i++) { 1739 this.encoder_.writeInt64String(value[i]); 1740 } 1741}; 1742 1743 1744/** 1745 * Writes an array of numbers to the buffer as a packed float field. 1746 * @param {number} field The field number. 1747 * @param {?Array<number>} value The array of ints to write. 1748 */ 1749jspb.BinaryWriter.prototype.writePackedFloat = function(field, value) { 1750 if (value == null || !value.length) return; 1751 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 1752 this.encoder_.writeUnsignedVarint32(value.length * 4); 1753 for (var i = 0; i < value.length; i++) { 1754 this.encoder_.writeFloat(value[i]); 1755 } 1756}; 1757 1758 1759/** 1760 * Writes an array of numbers to the buffer as a packed double field. 1761 * @param {number} field The field number. 1762 * @param {?Array<number>} value The array of ints to write. 1763 */ 1764jspb.BinaryWriter.prototype.writePackedDouble = function(field, value) { 1765 if (value == null || !value.length) return; 1766 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 1767 this.encoder_.writeUnsignedVarint32(value.length * 8); 1768 for (var i = 0; i < value.length; i++) { 1769 this.encoder_.writeDouble(value[i]); 1770 } 1771}; 1772 1773 1774/** 1775 * Writes an array of booleans to the buffer as a packed bool field. 1776 * @param {number} field The field number. 1777 * @param {?Array<boolean>} value The array of ints to write. 1778 */ 1779jspb.BinaryWriter.prototype.writePackedBool = function(field, value) { 1780 if (value == null || !value.length) return; 1781 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 1782 this.encoder_.writeUnsignedVarint32(value.length); 1783 for (var i = 0; i < value.length; i++) { 1784 this.encoder_.writeBool(value[i]); 1785 } 1786}; 1787 1788 1789/** 1790 * Writes an array of enums to the buffer as a packed enum field. 1791 * @param {number} field The field number. 1792 * @param {?Array<number>} value The array of ints to write. 1793 */ 1794jspb.BinaryWriter.prototype.writePackedEnum = function(field, value) { 1795 if (value == null || !value.length) return; 1796 var bookmark = this.beginDelimited_(field); 1797 for (var i = 0; i < value.length; i++) { 1798 this.encoder_.writeEnum(value[i]); 1799 } 1800 this.endDelimited_(bookmark); 1801}; 1802 1803 1804/** 1805 * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to 1806 * the buffer. 1807 * @param {number} field The field number. 1808 * @param {?Array<string>} value The array of hashes to write. 1809 */ 1810jspb.BinaryWriter.prototype.writePackedFixedHash64 = function(field, value) { 1811 if (value == null || !value.length) return; 1812 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 1813 this.encoder_.writeUnsignedVarint32(value.length * 8); 1814 for (var i = 0; i < value.length; i++) { 1815 this.encoder_.writeFixedHash64(value[i]); 1816 } 1817}; 1818 1819 1820/** 1821 * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to 1822 * the buffer. 1823 * @param {number} field The field number. 1824 * @param {?Array<string>} value The array of hashes to write. 1825 */ 1826jspb.BinaryWriter.prototype.writePackedVarintHash64 = function(field, value) { 1827 if (value == null || !value.length) return; 1828 var bookmark = this.beginDelimited_(field); 1829 for (var i = 0; i < value.length; i++) { 1830 this.encoder_.writeVarintHash64(value[i]); 1831 } 1832 this.endDelimited_(bookmark); 1833}; 1834