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 {!goog.crypt.base64.Alphabet=} alphabet Which flavor of base64 to use. 240 * @return {string} 241 */ 242jspb.BinaryWriter.prototype.getResultBase64String = function(alphabet) { 243 return goog.crypt.base64.encodeByteArray(this.getResultBuffer(), alphabet); 244}; 245 246 247/** 248 * Begins a new sub-message. The client must call endSubMessage() when they're 249 * done. 250 * TODO(aappleby): Deprecated. Move callers to writeMessage(). 251 * @param {number} field The field number of the sub-message. 252 */ 253jspb.BinaryWriter.prototype.beginSubMessage = function(field) { 254 this.bookmarks_.push(this.beginDelimited_(field)); 255}; 256 257 258/** 259 * Finishes a sub-message and packs it into the parent messages' buffer. 260 * TODO(aappleby): Deprecated. Move callers to writeMessage(). 261 */ 262jspb.BinaryWriter.prototype.endSubMessage = function() { 263 goog.asserts.assert(this.bookmarks_.length >= 0); 264 this.endDelimited_(this.bookmarks_.pop()); 265}; 266 267 268/** 269 * Encodes a (field number, wire type) tuple into a wire-format field header 270 * and stores it in the buffer as a varint. 271 * @param {number} field The field number. 272 * @param {number} wireType The wire-type of the field, as specified in the 273 * protocol buffer documentation. 274 * @private 275 */ 276jspb.BinaryWriter.prototype.writeFieldHeader_ = 277 function(field, wireType) { 278 goog.asserts.assert(field >= 1 && field == Math.floor(field)); 279 var x = field * 8 + wireType; 280 this.encoder_.writeUnsignedVarint32(x); 281}; 282 283 284/** 285 * Writes a field of any valid scalar type to the binary stream. 286 * @param {jspb.BinaryConstants.FieldType} fieldType 287 * @param {number} field 288 * @param {jspb.AnyFieldType} value 289 */ 290jspb.BinaryWriter.prototype.writeAny = function(fieldType, field, value) { 291 var fieldTypes = jspb.BinaryConstants.FieldType; 292 switch (fieldType) { 293 case fieldTypes.DOUBLE: 294 this.writeDouble(field, /** @type {number} */(value)); 295 return; 296 case fieldTypes.FLOAT: 297 this.writeFloat(field, /** @type {number} */(value)); 298 return; 299 case fieldTypes.INT64: 300 this.writeInt64(field, /** @type {number} */(value)); 301 return; 302 case fieldTypes.UINT64: 303 this.writeUint64(field, /** @type {number} */(value)); 304 return; 305 case fieldTypes.INT32: 306 this.writeInt32(field, /** @type {number} */(value)); 307 return; 308 case fieldTypes.FIXED64: 309 this.writeFixed64(field, /** @type {number} */(value)); 310 return; 311 case fieldTypes.FIXED32: 312 this.writeFixed32(field, /** @type {number} */(value)); 313 return; 314 case fieldTypes.BOOL: 315 this.writeBool(field, /** @type {boolean} */(value)); 316 return; 317 case fieldTypes.STRING: 318 this.writeString(field, /** @type {string} */(value)); 319 return; 320 case fieldTypes.GROUP: 321 goog.asserts.fail('Group field type not supported in writeAny()'); 322 return; 323 case fieldTypes.MESSAGE: 324 goog.asserts.fail('Message field type not supported in writeAny()'); 325 return; 326 case fieldTypes.BYTES: 327 this.writeBytes(field, /** @type {?Uint8Array} */(value)); 328 return; 329 case fieldTypes.UINT32: 330 this.writeUint32(field, /** @type {number} */(value)); 331 return; 332 case fieldTypes.ENUM: 333 this.writeEnum(field, /** @type {number} */(value)); 334 return; 335 case fieldTypes.SFIXED32: 336 this.writeSfixed32(field, /** @type {number} */(value)); 337 return; 338 case fieldTypes.SFIXED64: 339 this.writeSfixed64(field, /** @type {number} */(value)); 340 return; 341 case fieldTypes.SINT32: 342 this.writeSint32(field, /** @type {number} */(value)); 343 return; 344 case fieldTypes.SINT64: 345 this.writeSint64(field, /** @type {number} */(value)); 346 return; 347 case fieldTypes.FHASH64: 348 this.writeFixedHash64(field, /** @type {string} */(value)); 349 return; 350 case fieldTypes.VHASH64: 351 this.writeVarintHash64(field, /** @type {string} */(value)); 352 return; 353 default: 354 goog.asserts.fail('Invalid field type in writeAny()'); 355 return; 356 } 357}; 358 359 360/** 361 * Writes a varint field to the buffer without range checking. 362 * @param {number} field The field number. 363 * @param {number?} value The value to write. 364 * @private 365 */ 366jspb.BinaryWriter.prototype.writeUnsignedVarint32_ = function(field, value) { 367 if (value == null) return; 368 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 369 this.encoder_.writeUnsignedVarint32(value); 370}; 371 372 373/** 374 * Writes a varint field to the buffer without range checking. 375 * @param {number} field The field number. 376 * @param {number?} value The value to write. 377 * @private 378 */ 379jspb.BinaryWriter.prototype.writeSignedVarint32_ = function(field, value) { 380 if (value == null) return; 381 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 382 this.encoder_.writeSignedVarint32(value); 383}; 384 385 386/** 387 * Writes a varint field to the buffer without range checking. 388 * @param {number} field The field number. 389 * @param {number?} value The value to write. 390 * @private 391 */ 392jspb.BinaryWriter.prototype.writeUnsignedVarint64_ = function(field, value) { 393 if (value == null) return; 394 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 395 this.encoder_.writeUnsignedVarint64(value); 396}; 397 398 399/** 400 * Writes a varint field to the buffer without range checking. 401 * @param {number} field The field number. 402 * @param {number?} value The value to write. 403 * @private 404 */ 405jspb.BinaryWriter.prototype.writeSignedVarint64_ = function(field, value) { 406 if (value == null) return; 407 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 408 this.encoder_.writeSignedVarint64(value); 409}; 410 411 412/** 413 * Writes a zigzag varint field to the buffer without range checking. 414 * @param {number} field The field number. 415 * @param {number?} value The value to write. 416 * @private 417 */ 418jspb.BinaryWriter.prototype.writeZigzagVarint32_ = function(field, value) { 419 if (value == null) return; 420 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 421 this.encoder_.writeZigzagVarint32(value); 422}; 423 424 425/** 426 * Writes a zigzag varint field to the buffer without range checking. 427 * @param {number} field The field number. 428 * @param {number?} value The value to write. 429 * @private 430 */ 431jspb.BinaryWriter.prototype.writeZigzagVarint64_ = function(field, value) { 432 if (value == null) return; 433 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 434 this.encoder_.writeZigzagVarint64(value); 435}; 436 437 438/** 439 * Writes a zigzag varint field to the buffer without range checking. 440 * @param {number} field The field number. 441 * @param {string?} value The value to write. 442 * @private 443 */ 444jspb.BinaryWriter.prototype.writeZigzagVarint64String_ = function( 445 field, value) { 446 if (value == null) return; 447 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 448 this.encoder_.writeZigzagVarint64String(value); 449}; 450 451 452/** 453 * Writes a zigzag varint field to the buffer without range checking. 454 * @param {number} field The field number. 455 * @param {string?} value The value to write. 456 * @private 457 */ 458jspb.BinaryWriter.prototype.writeZigzagVarintHash64_ = function(field, value) { 459 if (value == null) return; 460 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 461 this.encoder_.writeZigzagVarintHash64(value); 462}; 463 464 465/** 466 * Writes an int32 field to the buffer. Numbers outside the range [-2^31,2^31) 467 * will be truncated. 468 * @param {number} field The field number. 469 * @param {number?} value The value to write. 470 */ 471jspb.BinaryWriter.prototype.writeInt32 = function(field, value) { 472 if (value == null) return; 473 goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) && 474 (value < jspb.BinaryConstants.TWO_TO_31)); 475 this.writeSignedVarint32_(field, value); 476}; 477 478 479/** 480 * Writes an int32 field represented as a string to the buffer. Numbers outside 481 * the range [-2^31,2^31) will be truncated. 482 * @param {number} field The field number. 483 * @param {string?} value The value to write. 484 */ 485jspb.BinaryWriter.prototype.writeInt32String = function(field, value) { 486 if (value == null) return; 487 var intValue = /** {number} */ parseInt(value, 10); 488 goog.asserts.assert((intValue >= -jspb.BinaryConstants.TWO_TO_31) && 489 (intValue < jspb.BinaryConstants.TWO_TO_31)); 490 this.writeSignedVarint32_(field, intValue); 491}; 492 493 494/** 495 * Writes an int64 field to the buffer. Numbers outside the range [-2^63,2^63) 496 * will be truncated. 497 * @param {number} field The field number. 498 * @param {number?} value The value to write. 499 */ 500jspb.BinaryWriter.prototype.writeInt64 = function(field, value) { 501 if (value == null) return; 502 goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_63) && 503 (value < jspb.BinaryConstants.TWO_TO_63)); 504 this.writeSignedVarint64_(field, value); 505}; 506 507 508/** 509 * Writes a int64 field (with value as a string) to the buffer. 510 * @param {number} field The field number. 511 * @param {string?} value The value to write. 512 */ 513jspb.BinaryWriter.prototype.writeInt64String = function(field, value) { 514 if (value == null) return; 515 var num = jspb.arith.Int64.fromString(value); 516 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 517 this.encoder_.writeSplitVarint64(num.lo, num.hi); 518}; 519 520 521/** 522 * Writes a uint32 field to the buffer. Numbers outside the range [0,2^32) 523 * will be truncated. 524 * @param {number} field The field number. 525 * @param {number?} value The value to write. 526 */ 527jspb.BinaryWriter.prototype.writeUint32 = function(field, value) { 528 if (value == null) return; 529 goog.asserts.assert((value >= 0) && 530 (value < jspb.BinaryConstants.TWO_TO_32)); 531 this.writeUnsignedVarint32_(field, value); 532}; 533 534 535/** 536 * Writes a uint32 field represented as a string to the buffer. Numbers outside 537 * the range [0,2^32) will be truncated. 538 * @param {number} field The field number. 539 * @param {string?} value The value to write. 540 */ 541jspb.BinaryWriter.prototype.writeUint32String = function(field, value) { 542 if (value == null) return; 543 var intValue = /** {number} */ parseInt(value, 10); 544 goog.asserts.assert((intValue >= 0) && 545 (intValue < jspb.BinaryConstants.TWO_TO_32)); 546 this.writeUnsignedVarint32_(field, intValue); 547}; 548 549 550/** 551 * Writes a uint64 field to the buffer. Numbers outside the range [0,2^64) 552 * will be truncated. 553 * @param {number} field The field number. 554 * @param {number?} value The value to write. 555 */ 556jspb.BinaryWriter.prototype.writeUint64 = function(field, value) { 557 if (value == null) return; 558 goog.asserts.assert((value >= 0) && 559 (value < jspb.BinaryConstants.TWO_TO_64)); 560 this.writeUnsignedVarint64_(field, value); 561}; 562 563 564/** 565 * Writes a uint64 field (with value as a string) to the buffer. 566 * @param {number} field The field number. 567 * @param {string?} value The value to write. 568 */ 569jspb.BinaryWriter.prototype.writeUint64String = function(field, value) { 570 if (value == null) return; 571 var num = jspb.arith.UInt64.fromString(value); 572 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 573 this.encoder_.writeSplitVarint64(num.lo, num.hi); 574}; 575 576 577/** 578 * Writes an sint32 field to the buffer. Numbers outside the range [-2^31,2^31) 579 * will be truncated. 580 * @param {number} field The field number. 581 * @param {number?} value The value to write. 582 */ 583jspb.BinaryWriter.prototype.writeSint32 = function(field, value) { 584 if (value == null) return; 585 goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) && 586 (value < jspb.BinaryConstants.TWO_TO_31)); 587 this.writeZigzagVarint32_(field, value); 588}; 589 590 591/** 592 * Writes an sint64 field to the buffer. Numbers outside the range [-2^63,2^63) 593 * will be truncated. 594 * @param {number} field The field number. 595 * @param {number?} value The value to write. 596 */ 597jspb.BinaryWriter.prototype.writeSint64 = function(field, value) { 598 if (value == null) return; 599 goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_63) && 600 (value < jspb.BinaryConstants.TWO_TO_63)); 601 this.writeZigzagVarint64_(field, value); 602}; 603 604 605/** 606 * Writes an sint64 field to the buffer from a hash64 encoded value. Numbers 607 * outside the range [-2^63,2^63) will be truncated. 608 * @param {number} field The field number. 609 * @param {string?} value The hash64 string to write. 610 */ 611jspb.BinaryWriter.prototype.writeSintHash64 = function(field, value) { 612 if (value == null) return; 613 this.writeZigzagVarintHash64_(field, value); 614}; 615 616 617/** 618 * Writes an sint64 field to the buffer. Numbers outside the range [-2^63,2^63) 619 * will be truncated. 620 * @param {number} field The field number. 621 * @param {string?} value The decimal string to write. 622 */ 623jspb.BinaryWriter.prototype.writeSint64String = function(field, value) { 624 if (value == null) return; 625 this.writeZigzagVarint64String_(field, value); 626}; 627 628 629/** 630 * Writes a fixed32 field to the buffer. Numbers outside the range [0,2^32) 631 * will be truncated. 632 * @param {number} field The field number. 633 * @param {number?} value The value to write. 634 */ 635jspb.BinaryWriter.prototype.writeFixed32 = function(field, value) { 636 if (value == null) return; 637 goog.asserts.assert((value >= 0) && 638 (value < jspb.BinaryConstants.TWO_TO_32)); 639 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED32); 640 this.encoder_.writeUint32(value); 641}; 642 643 644/** 645 * Writes a fixed64 field to the buffer. Numbers outside the range [0,2^64) 646 * will be truncated. 647 * @param {number} field The field number. 648 * @param {number?} value The value to write. 649 */ 650jspb.BinaryWriter.prototype.writeFixed64 = function(field, value) { 651 if (value == null) return; 652 goog.asserts.assert((value >= 0) && 653 (value < jspb.BinaryConstants.TWO_TO_64)); 654 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); 655 this.encoder_.writeUint64(value); 656}; 657 658 659/** 660 * Writes a fixed64 field (with value as a string) to the buffer. 661 * @param {number} field The field number. 662 * @param {string?} value The value to write. 663 */ 664jspb.BinaryWriter.prototype.writeFixed64String = function(field, value) { 665 if (value == null) return; 666 var num = jspb.arith.UInt64.fromString(value); 667 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); 668 this.encoder_.writeSplitFixed64(num.lo, num.hi); 669}; 670 671 672/** 673 * Writes a sfixed32 field to the buffer. Numbers outside the range 674 * [-2^31,2^31) will be truncated. 675 * @param {number} field The field number. 676 * @param {number?} value The value to write. 677 */ 678jspb.BinaryWriter.prototype.writeSfixed32 = function(field, value) { 679 if (value == null) return; 680 goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) && 681 (value < jspb.BinaryConstants.TWO_TO_31)); 682 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED32); 683 this.encoder_.writeInt32(value); 684}; 685 686 687/** 688 * Writes a sfixed64 field to the buffer. Numbers outside the range 689 * [-2^63,2^63) will be truncated. 690 * @param {number} field The field number. 691 * @param {number?} value The value to write. 692 */ 693jspb.BinaryWriter.prototype.writeSfixed64 = function(field, value) { 694 if (value == null) return; 695 goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_63) && 696 (value < jspb.BinaryConstants.TWO_TO_63)); 697 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); 698 this.encoder_.writeInt64(value); 699}; 700 701 702/** 703 * Writes a sfixed64 string field to the buffer. Numbers outside the range 704 * [-2^63,2^63) will be truncated. 705 * @param {number} field The field number. 706 * @param {string?} value The value to write. 707 */ 708jspb.BinaryWriter.prototype.writeSfixed64String = function(field, value) { 709 if (value == null) return; 710 var num = jspb.arith.Int64.fromString(value); 711 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); 712 this.encoder_.writeSplitFixed64(num.lo, num.hi); 713}; 714 715 716/** 717 * Writes a single-precision floating point field to the buffer. Numbers 718 * requiring more than 32 bits of precision will be truncated. 719 * @param {number} field The field number. 720 * @param {number?} value The value to write. 721 */ 722jspb.BinaryWriter.prototype.writeFloat = function(field, value) { 723 if (value == null) return; 724 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED32); 725 this.encoder_.writeFloat(value); 726}; 727 728 729/** 730 * Writes a double-precision floating point field to the buffer. As this is the 731 * native format used by JavaScript, no precision will be lost. 732 * @param {number} field The field number. 733 * @param {number?} value The value to write. 734 */ 735jspb.BinaryWriter.prototype.writeDouble = function(field, value) { 736 if (value == null) return; 737 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); 738 this.encoder_.writeDouble(value); 739}; 740 741 742/** 743 * Writes a boolean field to the buffer. We allow numbers as input 744 * because the JSPB code generator uses 0/1 instead of true/false to save space 745 * in the string representation of the proto. 746 * @param {number} field The field number. 747 * @param {boolean?|number?} value The value to write. 748 */ 749jspb.BinaryWriter.prototype.writeBool = function(field, value) { 750 if (value == null) return; 751 goog.asserts.assert(typeof value === 'boolean' || typeof value === 'number'); 752 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 753 this.encoder_.writeBool(value); 754}; 755 756 757/** 758 * Writes an enum field to the buffer. 759 * @param {number} field The field number. 760 * @param {number?} value The value to write. 761 */ 762jspb.BinaryWriter.prototype.writeEnum = function(field, value) { 763 if (value == null) return; 764 goog.asserts.assert((value >= -jspb.BinaryConstants.TWO_TO_31) && 765 (value < jspb.BinaryConstants.TWO_TO_31)); 766 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 767 this.encoder_.writeSignedVarint32(value); 768}; 769 770 771/** 772 * Writes a string field to the buffer. 773 * @param {number} field The field number. 774 * @param {string?} value The string to write. 775 */ 776jspb.BinaryWriter.prototype.writeString = function(field, value) { 777 if (value == null) return; 778 var bookmark = this.beginDelimited_(field); 779 this.encoder_.writeString(value); 780 this.endDelimited_(bookmark); 781}; 782 783 784/** 785 * Writes an arbitrary byte field to the buffer. Note - to match the behavior 786 * of the C++ implementation, empty byte arrays _are_ serialized. 787 * @param {number} field The field number. 788 * @param {?jspb.ByteSource} value The array of bytes to write. 789 */ 790jspb.BinaryWriter.prototype.writeBytes = function(field, value) { 791 if (value == null) return; 792 var bytes = jspb.utils.byteSourceToUint8Array(value); 793 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 794 this.encoder_.writeUnsignedVarint32(bytes.length); 795 this.appendUint8Array_(bytes); 796}; 797 798 799/** 800 * Writes a message to the buffer. 801 * @param {number} field The field number. 802 * @param {?MessageType} value The message to write. 803 * @param {function(MessageTypeNonNull, !jspb.BinaryWriter)} writerCallback 804 * Will be invoked with the value to write and the writer to write it with. 805 * @template MessageType 806 * Use go/closure-ttl to declare a non-nullable version of MessageType. Replace 807 * the null in blah|null with none. This is necessary because the compiler will 808 * infer MessageType to be nullable if the value parameter is nullable. 809 * @template MessageTypeNonNull := 810 * cond(isUnknown(MessageType), unknown(), 811 * mapunion(MessageType, (X) => 812 * cond(eq(X, 'null'), none(), X))) 813 * =: 814 */ 815jspb.BinaryWriter.prototype.writeMessage = function( 816 field, value, writerCallback) { 817 if (value == null) return; 818 var bookmark = this.beginDelimited_(field); 819 writerCallback(value, this); 820 this.endDelimited_(bookmark); 821}; 822 823 824/** 825 * Writes a message set extension to the buffer. 826 * @param {number} field The field number for the extension. 827 * @param {?MessageType} value The extension message object to write. Note that 828 * message set can only have extensions with type of optional message. 829 * @param {function(!MessageTypeNonNull, !jspb.BinaryWriter)} writerCallback 830 * Will be invoked with the value to write and the writer to write it with. 831 * @template MessageType 832 * Use go/closure-ttl to declare a non-nullable version of MessageType. Replace 833 * the null in blah|null with none. This is necessary because the compiler will 834 * infer MessageType to be nullable if the value parameter is nullable. 835 * @template MessageTypeNonNull := 836 * cond(isUnknown(MessageType), unknown(), 837 * mapunion(MessageType, (X) => 838 * cond(eq(X, 'null'), none(), X))) 839 * =: 840 */ 841jspb.BinaryWriter.prototype.writeMessageSet = function( 842 field, value, writerCallback) { 843 if (value == null) return; 844 // The wire format for a message set is defined by 845 // google3/net/proto/message_set.proto 846 this.writeFieldHeader_(1, jspb.BinaryConstants.WireType.START_GROUP); 847 this.writeFieldHeader_(2, jspb.BinaryConstants.WireType.VARINT); 848 this.encoder_.writeSignedVarint32(field); 849 var bookmark = this.beginDelimited_(3); 850 writerCallback(value, this); 851 this.endDelimited_(bookmark); 852 this.writeFieldHeader_(1, jspb.BinaryConstants.WireType.END_GROUP); 853}; 854 855 856/** 857 * Writes a group message to the buffer. 858 * 859 * @param {number} field The field number. 860 * @param {?MessageType} value The message to write, wrapped with START_GROUP / 861 * END_GROUP tags. Will be a no-op if 'value' is null. 862 * @param {function(MessageTypeNonNull, !jspb.BinaryWriter)} writerCallback 863 * Will be invoked with the value to write and the writer to write it with. 864 * @template MessageType 865 * Use go/closure-ttl to declare a non-nullable version of MessageType. Replace 866 * the null in blah|null with none. This is necessary because the compiler will 867 * infer MessageType to be nullable if the value parameter is nullable. 868 * @template MessageTypeNonNull := 869 * cond(isUnknown(MessageType), unknown(), 870 * mapunion(MessageType, (X) => 871 * cond(eq(X, 'null'), none(), X))) 872 * =: 873 */ 874jspb.BinaryWriter.prototype.writeGroup = function( 875 field, value, writerCallback) { 876 if (value == null) return; 877 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.START_GROUP); 878 writerCallback(value, this); 879 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.END_GROUP); 880}; 881 882 883/** 884 * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to 885 * the buffer. 886 * @param {number} field The field number. 887 * @param {string?} value The hash string. 888 */ 889jspb.BinaryWriter.prototype.writeFixedHash64 = function(field, value) { 890 if (value == null) return; 891 goog.asserts.assert(value.length == 8); 892 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); 893 this.encoder_.writeFixedHash64(value); 894}; 895 896 897/** 898 * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to 899 * the buffer. 900 * @param {number} field The field number. 901 * @param {string?} value The hash string. 902 */ 903jspb.BinaryWriter.prototype.writeVarintHash64 = function(field, value) { 904 if (value == null) return; 905 goog.asserts.assert(value.length == 8); 906 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 907 this.encoder_.writeVarintHash64(value); 908}; 909 910 911/** 912 * Writes a 64-bit field to the buffer as a fixed64. 913 * @param {number} field The field number. 914 * @param {number} lowBits The low 32 bits. 915 * @param {number} highBits The high 32 bits. 916 */ 917jspb.BinaryWriter.prototype.writeSplitFixed64 = function( 918 field, lowBits, highBits) { 919 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.FIXED64); 920 this.encoder_.writeSplitFixed64(lowBits, highBits); 921}; 922 923 924/** 925 * Writes a 64-bit field to the buffer as a varint. 926 * @param {number} field The field number. 927 * @param {number} lowBits The low 32 bits. 928 * @param {number} highBits The high 32 bits. 929 */ 930jspb.BinaryWriter.prototype.writeSplitVarint64 = function( 931 field, lowBits, highBits) { 932 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 933 this.encoder_.writeSplitVarint64(lowBits, highBits); 934}; 935 936 937/** 938 * Writes a 64-bit field to the buffer as a zigzag encoded varint. 939 * @param {number} field The field number. 940 * @param {number} lowBits The low 32 bits. 941 * @param {number} highBits The high 32 bits. 942 */ 943jspb.BinaryWriter.prototype.writeSplitZigzagVarint64 = function( 944 field, lowBits, highBits) { 945 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.VARINT); 946 var encoder = this.encoder_; 947 jspb.utils.toZigzag64(lowBits, highBits, function(lowBits, highBits) { 948 encoder.writeSplitVarint64(lowBits >>> 0, highBits >>> 0); 949 }); 950}; 951 952 953/** 954 * Writes an array of numbers to the buffer as a repeated 32-bit int field. 955 * @param {number} field The field number. 956 * @param {?Array<number>} value The array of ints to write. 957 */ 958jspb.BinaryWriter.prototype.writeRepeatedInt32 = function(field, value) { 959 if (value == null) return; 960 for (var i = 0; i < value.length; i++) { 961 this.writeSignedVarint32_(field, value[i]); 962 } 963}; 964 965 966/** 967 * Writes an array of numbers formatted as strings to the buffer as a repeated 968 * 32-bit int field. 969 * @param {number} field The field number. 970 * @param {?Array<string>} value The array of ints to write. 971 */ 972jspb.BinaryWriter.prototype.writeRepeatedInt32String = function(field, value) { 973 if (value == null) return; 974 for (var i = 0; i < value.length; i++) { 975 this.writeInt32String(field, value[i]); 976 } 977}; 978 979 980/** 981 * Writes an array of numbers to the buffer as a repeated 64-bit int field. 982 * @param {number} field The field number. 983 * @param {?Array<number>} value The array of ints to write. 984 */ 985jspb.BinaryWriter.prototype.writeRepeatedInt64 = function(field, value) { 986 if (value == null) return; 987 for (var i = 0; i < value.length; i++) { 988 this.writeSignedVarint64_(field, value[i]); 989 } 990}; 991 992 993/** 994 * Writes an array of 64-bit values to the buffer as a fixed64. 995 * @param {number} field The field number. 996 * @param {?Array<T>} value The value. 997 * @param {function(T): number} lo Function to get low bits. 998 * @param {function(T): number} hi Function to get high bits. 999 * @template T 1000 */ 1001jspb.BinaryWriter.prototype.writeRepeatedSplitFixed64 = function( 1002 field, value, lo, hi) { 1003 if (value == null) return; 1004 for (var i = 0; i < value.length; i++) { 1005 this.writeSplitFixed64(field, lo(value[i]), hi(value[i])); 1006 } 1007}; 1008 1009 1010/** 1011 * Writes an array of 64-bit values to the buffer as a varint. 1012 * @param {number} field The field number. 1013 * @param {?Array<T>} value The value. 1014 * @param {function(T): number} lo Function to get low bits. 1015 * @param {function(T): number} hi Function to get high bits. 1016 * @template T 1017 */ 1018jspb.BinaryWriter.prototype.writeRepeatedSplitVarint64 = function( 1019 field, value, lo, hi) { 1020 if (value == null) return; 1021 for (var i = 0; i < value.length; i++) { 1022 this.writeSplitVarint64(field, lo(value[i]), hi(value[i])); 1023 } 1024}; 1025 1026 1027/** 1028 * Writes an array of 64-bit values to the buffer as a zigzag varint. 1029 * @param {number} field The field number. 1030 * @param {?Array<T>} value The value. 1031 * @param {function(T): number} lo Function to get low bits. 1032 * @param {function(T): number} hi Function to get high bits. 1033 * @template T 1034 */ 1035jspb.BinaryWriter.prototype.writeRepeatedSplitZigzagVarint64 = function( 1036 field, value, lo, hi) { 1037 if (value == null) return; 1038 for (var i = 0; i < value.length; i++) { 1039 this.writeSplitZigzagVarint64(field, lo(value[i]), hi(value[i])); 1040 } 1041}; 1042 1043 1044/** 1045 * Writes an array of numbers formatted as strings to the buffer as a repeated 1046 * 64-bit int field. 1047 * @param {number} field The field number. 1048 * @param {?Array<string>} value The array of ints to write. 1049 */ 1050jspb.BinaryWriter.prototype.writeRepeatedInt64String = function(field, value) { 1051 if (value == null) return; 1052 for (var i = 0; i < value.length; i++) { 1053 this.writeInt64String(field, value[i]); 1054 } 1055}; 1056 1057 1058/** 1059 * Writes an array numbers to the buffer as a repeated unsigned 32-bit int 1060 * field. 1061 * @param {number} field The field number. 1062 * @param {?Array<number>} value The array of ints to write. 1063 */ 1064jspb.BinaryWriter.prototype.writeRepeatedUint32 = function(field, value) { 1065 if (value == null) return; 1066 for (var i = 0; i < value.length; i++) { 1067 this.writeUnsignedVarint32_(field, value[i]); 1068 } 1069}; 1070 1071 1072/** 1073 * Writes an array of numbers formatted as strings to the buffer as a repeated 1074 * unsigned 32-bit int field. 1075 * @param {number} field The field number. 1076 * @param {?Array<string>} value The array of ints to write. 1077 */ 1078jspb.BinaryWriter.prototype.writeRepeatedUint32String = function(field, value) { 1079 if (value == null) return; 1080 for (var i = 0; i < value.length; i++) { 1081 this.writeUint32String(field, value[i]); 1082 } 1083}; 1084 1085 1086/** 1087 * Writes an array numbers to the buffer as a repeated unsigned 64-bit int 1088 * field. 1089 * @param {number} field The field number. 1090 * @param {?Array<number>} value The array of ints to write. 1091 */ 1092jspb.BinaryWriter.prototype.writeRepeatedUint64 = function(field, value) { 1093 if (value == null) return; 1094 for (var i = 0; i < value.length; i++) { 1095 this.writeUnsignedVarint64_(field, value[i]); 1096 } 1097}; 1098 1099 1100/** 1101 * Writes an array of numbers formatted as strings to the buffer as a repeated 1102 * unsigned 64-bit int field. 1103 * @param {number} field The field number. 1104 * @param {?Array<string>} value The array of ints to write. 1105 */ 1106jspb.BinaryWriter.prototype.writeRepeatedUint64String = function(field, value) { 1107 if (value == null) return; 1108 for (var i = 0; i < value.length; i++) { 1109 this.writeUint64String(field, value[i]); 1110 } 1111}; 1112 1113 1114/** 1115 * Writes an array numbers to the buffer as a repeated signed 32-bit int field. 1116 * @param {number} field The field number. 1117 * @param {?Array<number>} value The array of ints to write. 1118 */ 1119jspb.BinaryWriter.prototype.writeRepeatedSint32 = function(field, value) { 1120 if (value == null) return; 1121 for (var i = 0; i < value.length; i++) { 1122 this.writeZigzagVarint32_(field, value[i]); 1123 } 1124}; 1125 1126 1127/** 1128 * Writes an array numbers to the buffer as a repeated signed 64-bit int field. 1129 * @param {number} field The field number. 1130 * @param {?Array<number>} value The array of ints to write. 1131 */ 1132jspb.BinaryWriter.prototype.writeRepeatedSint64 = function(field, value) { 1133 if (value == null) return; 1134 for (var i = 0; i < value.length; i++) { 1135 this.writeZigzagVarint64_(field, value[i]); 1136 } 1137}; 1138 1139 1140/** 1141 * Writes an array numbers to the buffer as a repeated signed 64-bit int field. 1142 * @param {number} field The field number. 1143 * @param {?Array<string>} value The array of ints to write. 1144 */ 1145jspb.BinaryWriter.prototype.writeRepeatedSint64String = function(field, value) { 1146 if (value == null) return; 1147 for (var i = 0; i < value.length; i++) { 1148 this.writeZigzagVarint64String_(field, value[i]); 1149 } 1150}; 1151 1152 1153/** 1154 * Writes an array of hash64 strings to the buffer as a repeated signed 64-bit 1155 * int field. 1156 * @param {number} field The field number. 1157 * @param {?Array<string>} value The array of ints to write. 1158 */ 1159jspb.BinaryWriter.prototype.writeRepeatedSintHash64 = function(field, value) { 1160 if (value == null) return; 1161 for (var i = 0; i < value.length; i++) { 1162 this.writeZigzagVarintHash64_(field, value[i]); 1163 } 1164}; 1165 1166 1167/** 1168 * Writes an array of numbers to the buffer as a repeated fixed32 field. This 1169 * works for both signed and unsigned fixed32s. 1170 * @param {number} field The field number. 1171 * @param {?Array<number>} value The array of ints to write. 1172 */ 1173jspb.BinaryWriter.prototype.writeRepeatedFixed32 = function(field, value) { 1174 if (value == null) return; 1175 for (var i = 0; i < value.length; i++) { 1176 this.writeFixed32(field, value[i]); 1177 } 1178}; 1179 1180 1181/** 1182 * Writes an array of numbers to the buffer as a repeated fixed64 field. This 1183 * works for both signed and unsigned fixed64s. 1184 * @param {number} field The field number. 1185 * @param {?Array<number>} value The array of ints to write. 1186 */ 1187jspb.BinaryWriter.prototype.writeRepeatedFixed64 = function(field, value) { 1188 if (value == null) return; 1189 for (var i = 0; i < value.length; i++) { 1190 this.writeFixed64(field, value[i]); 1191 } 1192}; 1193 1194 1195/** 1196 * Writes an array of numbers to the buffer as a repeated fixed64 field. This 1197 * works for both signed and unsigned fixed64s. 1198 * @param {number} field The field number. 1199 * @param {?Array<string>} value The array of decimal strings to write. 1200 */ 1201jspb.BinaryWriter.prototype.writeRepeatedFixed64String = function( 1202 field, value) { 1203 if (value == null) return; 1204 for (var i = 0; i < value.length; i++) { 1205 this.writeFixed64String(field, value[i]); 1206 } 1207}; 1208 1209 1210/** 1211 * Writes an array of numbers to the buffer as a repeated sfixed32 field. 1212 * @param {number} field The field number. 1213 * @param {?Array<number>} value The array of ints to write. 1214 */ 1215jspb.BinaryWriter.prototype.writeRepeatedSfixed32 = function(field, value) { 1216 if (value == null) return; 1217 for (var i = 0; i < value.length; i++) { 1218 this.writeSfixed32(field, value[i]); 1219 } 1220}; 1221 1222 1223/** 1224 * Writes an array of numbers to the buffer as a repeated sfixed64 field. 1225 * @param {number} field The field number. 1226 * @param {?Array<number>} value The array of ints to write. 1227 */ 1228jspb.BinaryWriter.prototype.writeRepeatedSfixed64 = function(field, value) { 1229 if (value == null) return; 1230 for (var i = 0; i < value.length; i++) { 1231 this.writeSfixed64(field, value[i]); 1232 } 1233}; 1234 1235 1236/** 1237 * Writes an array of decimal strings to the buffer as a repeated sfixed64 1238 * field. 1239 * @param {number} field The field number. 1240 * @param {?Array<string>} value The array of decimal strings to write. 1241 */ 1242jspb.BinaryWriter.prototype.writeRepeatedSfixed64String = function(field, value) { 1243 if (value == null) return; 1244 for (var i = 0; i < value.length; i++) { 1245 this.writeSfixed64String(field, value[i]); 1246 } 1247}; 1248 1249 1250/** 1251 * Writes an array of numbers to the buffer as a repeated float field. 1252 * @param {number} field The field number. 1253 * @param {?Array<number>} value The array of ints to write. 1254 */ 1255jspb.BinaryWriter.prototype.writeRepeatedFloat = function(field, value) { 1256 if (value == null) return; 1257 for (var i = 0; i < value.length; i++) { 1258 this.writeFloat(field, value[i]); 1259 } 1260}; 1261 1262 1263/** 1264 * Writes an array of numbers to the buffer as a repeated double field. 1265 * @param {number} field The field number. 1266 * @param {?Array<number>} value The array of ints to write. 1267 */ 1268jspb.BinaryWriter.prototype.writeRepeatedDouble = function(field, value) { 1269 if (value == null) return; 1270 for (var i = 0; i < value.length; i++) { 1271 this.writeDouble(field, value[i]); 1272 } 1273}; 1274 1275 1276/** 1277 * Writes an array of booleans to the buffer as a repeated bool field. 1278 * @param {number} field The field number. 1279 * @param {?Array<boolean>} value The array of ints to write. 1280 */ 1281jspb.BinaryWriter.prototype.writeRepeatedBool = function(field, value) { 1282 if (value == null) return; 1283 for (var i = 0; i < value.length; i++) { 1284 this.writeBool(field, value[i]); 1285 } 1286}; 1287 1288 1289/** 1290 * Writes an array of enums to the buffer as a repeated enum field. 1291 * @param {number} field The field number. 1292 * @param {?Array<number>} value The array of ints to write. 1293 */ 1294jspb.BinaryWriter.prototype.writeRepeatedEnum = function(field, value) { 1295 if (value == null) return; 1296 for (var i = 0; i < value.length; i++) { 1297 this.writeEnum(field, value[i]); 1298 } 1299}; 1300 1301 1302/** 1303 * Writes an array of strings to the buffer as a repeated string field. 1304 * @param {number} field The field number. 1305 * @param {?Array<string>} value The array of strings to write. 1306 */ 1307jspb.BinaryWriter.prototype.writeRepeatedString = function(field, value) { 1308 if (value == null) return; 1309 for (var i = 0; i < value.length; i++) { 1310 this.writeString(field, value[i]); 1311 } 1312}; 1313 1314 1315/** 1316 * Writes an array of arbitrary byte fields to the buffer. 1317 * @param {number} field The field number. 1318 * @param {?Array<!jspb.ByteSource>} value The arrays of arrays of bytes to 1319 * write. 1320 */ 1321jspb.BinaryWriter.prototype.writeRepeatedBytes = function(field, value) { 1322 if (value == null) return; 1323 for (var i = 0; i < value.length; i++) { 1324 this.writeBytes(field, value[i]); 1325 } 1326}; 1327 1328 1329/** 1330 * Writes an array of messages to the buffer. 1331 * @template MessageType 1332 * @param {number} field The field number. 1333 * @param {?Array<MessageType>} value The array of messages to 1334 * write. 1335 * @param {function(MessageType, !jspb.BinaryWriter)} writerCallback 1336 * Will be invoked with the value to write and the writer to write it with. 1337 */ 1338jspb.BinaryWriter.prototype.writeRepeatedMessage = function( 1339 field, value, writerCallback) { 1340 if (value == null) return; 1341 for (var i = 0; i < value.length; i++) { 1342 var bookmark = this.beginDelimited_(field); 1343 writerCallback(value[i], this); 1344 this.endDelimited_(bookmark); 1345 } 1346}; 1347 1348 1349/** 1350 * Writes an array of group messages to the buffer. 1351 * @template MessageType 1352 * @param {number} field The field number. 1353 * @param {?Array<MessageType>} value The array of messages to 1354 * write. 1355 * @param {function(MessageType, !jspb.BinaryWriter)} writerCallback 1356 * Will be invoked with the value to write and the writer to write it with. 1357 */ 1358jspb.BinaryWriter.prototype.writeRepeatedGroup = function( 1359 field, value, writerCallback) { 1360 if (value == null) return; 1361 for (var i = 0; i < value.length; i++) { 1362 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.START_GROUP); 1363 writerCallback(value[i], this); 1364 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.END_GROUP); 1365 } 1366}; 1367 1368 1369/** 1370 * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to 1371 * the buffer. 1372 * @param {number} field The field number. 1373 * @param {?Array<string>} value The array of hashes to write. 1374 */ 1375jspb.BinaryWriter.prototype.writeRepeatedFixedHash64 = 1376 function(field, value) { 1377 if (value == null) return; 1378 for (var i = 0; i < value.length; i++) { 1379 this.writeFixedHash64(field, value[i]); 1380 } 1381}; 1382 1383 1384/** 1385 * Writes a repeated 64-bit hash string field (8 characters @ 8 bits of data 1386 * each) to the buffer. 1387 * @param {number} field The field number. 1388 * @param {?Array<string>} value The array of hashes to write. 1389 */ 1390jspb.BinaryWriter.prototype.writeRepeatedVarintHash64 = 1391 function(field, value) { 1392 if (value == null) return; 1393 for (var i = 0; i < value.length; i++) { 1394 this.writeVarintHash64(field, value[i]); 1395 } 1396}; 1397 1398 1399/** 1400 * Writes an array of numbers to the buffer as a packed 32-bit int field. 1401 * @param {number} field The field number. 1402 * @param {?Array<number>} value The array of ints to write. 1403 */ 1404jspb.BinaryWriter.prototype.writePackedInt32 = function(field, value) { 1405 if (value == null || !value.length) return; 1406 var bookmark = this.beginDelimited_(field); 1407 for (var i = 0; i < value.length; i++) { 1408 this.encoder_.writeSignedVarint32(value[i]); 1409 } 1410 this.endDelimited_(bookmark); 1411}; 1412 1413 1414/** 1415 * Writes an array of numbers represented as strings to the buffer as a packed 1416 * 32-bit int field. 1417 * @param {number} field 1418 * @param {?Array<string>} value 1419 */ 1420jspb.BinaryWriter.prototype.writePackedInt32String = function(field, value) { 1421 if (value == null || !value.length) return; 1422 var bookmark = this.beginDelimited_(field); 1423 for (var i = 0; i < value.length; i++) { 1424 this.encoder_.writeSignedVarint32(parseInt(value[i], 10)); 1425 } 1426 this.endDelimited_(bookmark); 1427}; 1428 1429 1430/** 1431 * Writes an array of numbers to the buffer as a packed 64-bit int field. 1432 * @param {number} field The field number. 1433 * @param {?Array<number>} value The array of ints to write. 1434 */ 1435jspb.BinaryWriter.prototype.writePackedInt64 = function(field, value) { 1436 if (value == null || !value.length) return; 1437 var bookmark = this.beginDelimited_(field); 1438 for (var i = 0; i < value.length; i++) { 1439 this.encoder_.writeSignedVarint64(value[i]); 1440 } 1441 this.endDelimited_(bookmark); 1442}; 1443 1444 1445/** 1446 * Writes an array of 64-bit values to the buffer as a fixed64. 1447 * @param {number} field The field number. 1448 * @param {?Array<T>} value The value. 1449 * @param {function(T): number} lo Function to get low bits. 1450 * @param {function(T): number} hi Function to get high bits. 1451 * @template T 1452 */ 1453jspb.BinaryWriter.prototype.writePackedSplitFixed64 = function( 1454 field, value, lo, hi) { 1455 if (value == null) return; 1456 var bookmark = this.beginDelimited_(field); 1457 for (var i = 0; i < value.length; i++) { 1458 this.encoder_.writeSplitFixed64(lo(value[i]), hi(value[i])); 1459 } 1460 this.endDelimited_(bookmark); 1461}; 1462 1463 1464/** 1465 * Writes an array of 64-bit values to the buffer as a varint. 1466 * @param {number} field The field number. 1467 * @param {?Array<T>} value The value. 1468 * @param {function(T): number} lo Function to get low bits. 1469 * @param {function(T): number} hi Function to get high bits. 1470 * @template T 1471 */ 1472jspb.BinaryWriter.prototype.writePackedSplitVarint64 = function( 1473 field, value, lo, hi) { 1474 if (value == null) return; 1475 var bookmark = this.beginDelimited_(field); 1476 for (var i = 0; i < value.length; i++) { 1477 this.encoder_.writeSplitVarint64(lo(value[i]), hi(value[i])); 1478 } 1479 this.endDelimited_(bookmark); 1480}; 1481 1482 1483/** 1484 * Writes an array of 64-bit values to the buffer as a zigzag varint. 1485 * @param {number} field The field number. 1486 * @param {?Array<T>} value The value. 1487 * @param {function(T): number} lo Function to get low bits. 1488 * @param {function(T): number} hi Function to get high bits. 1489 * @template T 1490 */ 1491jspb.BinaryWriter.prototype.writePackedSplitZigzagVarint64 = function( 1492 field, value, lo, hi) { 1493 if (value == null) return; 1494 var bookmark = this.beginDelimited_(field); 1495 var encoder = this.encoder_; 1496 for (var i = 0; i < value.length; i++) { 1497 jspb.utils.toZigzag64( 1498 lo(value[i]), hi(value[i]), function(bitsLow, bitsHigh) { 1499 encoder.writeSplitVarint64(bitsLow >>> 0, bitsHigh >>> 0); 1500 }); 1501 } 1502 this.endDelimited_(bookmark); 1503}; 1504 1505 1506/** 1507 * Writes an array of numbers represented as strings to the buffer as a packed 1508 * 64-bit int field. 1509 * @param {number} field 1510 * @param {?Array<string>} value 1511 */ 1512jspb.BinaryWriter.prototype.writePackedInt64String = function(field, value) { 1513 if (value == null || !value.length) return; 1514 var bookmark = this.beginDelimited_(field); 1515 for (var i = 0; i < value.length; i++) { 1516 var num = jspb.arith.Int64.fromString(value[i]); 1517 this.encoder_.writeSplitVarint64(num.lo, num.hi); 1518 } 1519 this.endDelimited_(bookmark); 1520}; 1521 1522 1523/** 1524 * Writes an array numbers to the buffer as a packed unsigned 32-bit int field. 1525 * @param {number} field The field number. 1526 * @param {?Array<number>} value The array of ints to write. 1527 */ 1528jspb.BinaryWriter.prototype.writePackedUint32 = function(field, value) { 1529 if (value == null || !value.length) return; 1530 var bookmark = this.beginDelimited_(field); 1531 for (var i = 0; i < value.length; i++) { 1532 this.encoder_.writeUnsignedVarint32(value[i]); 1533 } 1534 this.endDelimited_(bookmark); 1535}; 1536 1537 1538/** 1539 * Writes an array of numbers represented as strings to the buffer as a packed 1540 * unsigned 32-bit int field. 1541 * @param {number} field 1542 * @param {?Array<string>} value 1543 */ 1544jspb.BinaryWriter.prototype.writePackedUint32String = 1545 function(field, value) { 1546 if (value == null || !value.length) return; 1547 var bookmark = this.beginDelimited_(field); 1548 for (var i = 0; i < value.length; i++) { 1549 this.encoder_.writeUnsignedVarint32(parseInt(value[i], 10)); 1550 } 1551 this.endDelimited_(bookmark); 1552}; 1553 1554 1555/** 1556 * Writes an array numbers to the buffer as a packed unsigned 64-bit int field. 1557 * @param {number} field The field number. 1558 * @param {?Array<number>} value The array of ints to write. 1559 */ 1560jspb.BinaryWriter.prototype.writePackedUint64 = function(field, value) { 1561 if (value == null || !value.length) return; 1562 var bookmark = this.beginDelimited_(field); 1563 for (var i = 0; i < value.length; i++) { 1564 this.encoder_.writeUnsignedVarint64(value[i]); 1565 } 1566 this.endDelimited_(bookmark); 1567}; 1568 1569 1570/** 1571 * Writes an array of numbers represented as strings to the buffer as a packed 1572 * unsigned 64-bit int field. 1573 * @param {number} field 1574 * @param {?Array<string>} value 1575 */ 1576jspb.BinaryWriter.prototype.writePackedUint64String = 1577 function(field, value) { 1578 if (value == null || !value.length) return; 1579 var bookmark = this.beginDelimited_(field); 1580 for (var i = 0; i < value.length; i++) { 1581 var num = jspb.arith.UInt64.fromString(value[i]); 1582 this.encoder_.writeSplitVarint64(num.lo, num.hi); 1583 } 1584 this.endDelimited_(bookmark); 1585}; 1586 1587 1588/** 1589 * Writes an array numbers to the buffer as a packed signed 32-bit int field. 1590 * @param {number} field The field number. 1591 * @param {?Array<number>} value The array of ints to write. 1592 */ 1593jspb.BinaryWriter.prototype.writePackedSint32 = function(field, value) { 1594 if (value == null || !value.length) return; 1595 var bookmark = this.beginDelimited_(field); 1596 for (var i = 0; i < value.length; i++) { 1597 this.encoder_.writeZigzagVarint32(value[i]); 1598 } 1599 this.endDelimited_(bookmark); 1600}; 1601 1602 1603/** 1604 * Writes an array of numbers to the buffer as a packed signed 64-bit int field. 1605 * @param {number} field The field number. 1606 * @param {?Array<number>} value The array of ints to write. 1607 */ 1608jspb.BinaryWriter.prototype.writePackedSint64 = function(field, value) { 1609 if (value == null || !value.length) return; 1610 var bookmark = this.beginDelimited_(field); 1611 for (var i = 0; i < value.length; i++) { 1612 this.encoder_.writeZigzagVarint64(value[i]); 1613 } 1614 this.endDelimited_(bookmark); 1615}; 1616 1617 1618/** 1619 * Writes an array of decimal strings to the buffer as a packed signed 64-bit 1620 * int field. 1621 * @param {number} field The field number. 1622 * @param {?Array<string>} value The array of decimal strings to write. 1623 */ 1624jspb.BinaryWriter.prototype.writePackedSint64String = function(field, value) { 1625 if (value == null || !value.length) return; 1626 var bookmark = this.beginDelimited_(field); 1627 for (var i = 0; i < value.length; i++) { 1628 this.encoder_.writeZigzagVarintHash64( 1629 jspb.utils.decimalStringToHash64(value[i])); 1630 } 1631 this.endDelimited_(bookmark); 1632}; 1633 1634 1635/** 1636 * Writes an array of hash 64 strings to the buffer as a packed signed 64-bit 1637 * int field. 1638 * @param {number} field The field number. 1639 * @param {?Array<string>} value The array of decimal strings to write. 1640 */ 1641jspb.BinaryWriter.prototype.writePackedSintHash64 = function(field, value) { 1642 if (value == null || !value.length) return; 1643 var bookmark = this.beginDelimited_(field); 1644 for (var i = 0; i < value.length; i++) { 1645 this.encoder_.writeZigzagVarintHash64(value[i]); 1646 } 1647 this.endDelimited_(bookmark); 1648}; 1649 1650 1651/** 1652 * Writes an array of numbers to the buffer as a packed fixed32 field. 1653 * @param {number} field The field number. 1654 * @param {?Array<number>} value The array of ints to write. 1655 */ 1656jspb.BinaryWriter.prototype.writePackedFixed32 = function(field, value) { 1657 if (value == null || !value.length) return; 1658 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 1659 this.encoder_.writeUnsignedVarint32(value.length * 4); 1660 for (var i = 0; i < value.length; i++) { 1661 this.encoder_.writeUint32(value[i]); 1662 } 1663}; 1664 1665 1666/** 1667 * Writes an array of numbers to the buffer as a packed fixed64 field. 1668 * @param {number} field The field number. 1669 * @param {?Array<number>} value The array of ints to write. 1670 */ 1671jspb.BinaryWriter.prototype.writePackedFixed64 = function(field, value) { 1672 if (value == null || !value.length) return; 1673 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 1674 this.encoder_.writeUnsignedVarint32(value.length * 8); 1675 for (var i = 0; i < value.length; i++) { 1676 this.encoder_.writeUint64(value[i]); 1677 } 1678}; 1679 1680 1681/** 1682 * Writes an array of numbers represented as strings to the buffer as a packed 1683 * fixed64 field. 1684 * @param {number} field The field number. 1685 * @param {?Array<string>} value The array of strings to write. 1686 */ 1687jspb.BinaryWriter.prototype.writePackedFixed64String = function(field, value) { 1688 if (value == null || !value.length) return; 1689 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 1690 this.encoder_.writeUnsignedVarint32(value.length * 8); 1691 for (var i = 0; i < value.length; i++) { 1692 var num = jspb.arith.UInt64.fromString(value[i]); 1693 this.encoder_.writeSplitFixed64(num.lo, num.hi); 1694 } 1695}; 1696 1697 1698/** 1699 * Writes an array of numbers to the buffer as a packed sfixed32 field. 1700 * @param {number} field The field number. 1701 * @param {?Array<number>} value The array of ints to write. 1702 */ 1703jspb.BinaryWriter.prototype.writePackedSfixed32 = function(field, value) { 1704 if (value == null || !value.length) return; 1705 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 1706 this.encoder_.writeUnsignedVarint32(value.length * 4); 1707 for (var i = 0; i < value.length; i++) { 1708 this.encoder_.writeInt32(value[i]); 1709 } 1710}; 1711 1712 1713/** 1714 * Writes an array of numbers to the buffer as a packed sfixed64 field. 1715 * @param {number} field The field number. 1716 * @param {?Array<number>} value The array of ints to write. 1717 */ 1718jspb.BinaryWriter.prototype.writePackedSfixed64 = function(field, value) { 1719 if (value == null || !value.length) return; 1720 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 1721 this.encoder_.writeUnsignedVarint32(value.length * 8); 1722 for (var i = 0; i < value.length; i++) { 1723 this.encoder_.writeInt64(value[i]); 1724 } 1725}; 1726 1727 1728/** 1729 * Writes an array of numbers to the buffer as a packed sfixed64 field. 1730 * @param {number} field The field number. 1731 * @param {?Array<string>} value The array of decimal strings to write. 1732 */ 1733jspb.BinaryWriter.prototype.writePackedSfixed64String = function(field, value) { 1734 if (value == null || !value.length) return; 1735 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 1736 this.encoder_.writeUnsignedVarint32(value.length * 8); 1737 for (var i = 0; i < value.length; i++) { 1738 this.encoder_.writeInt64String(value[i]); 1739 } 1740}; 1741 1742 1743/** 1744 * Writes an array of numbers to the buffer as a packed float field. 1745 * @param {number} field The field number. 1746 * @param {?Array<number>} value The array of ints to write. 1747 */ 1748jspb.BinaryWriter.prototype.writePackedFloat = function(field, value) { 1749 if (value == null || !value.length) return; 1750 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 1751 this.encoder_.writeUnsignedVarint32(value.length * 4); 1752 for (var i = 0; i < value.length; i++) { 1753 this.encoder_.writeFloat(value[i]); 1754 } 1755}; 1756 1757 1758/** 1759 * Writes an array of numbers to the buffer as a packed double field. 1760 * @param {number} field The field number. 1761 * @param {?Array<number>} value The array of ints to write. 1762 */ 1763jspb.BinaryWriter.prototype.writePackedDouble = function(field, value) { 1764 if (value == null || !value.length) return; 1765 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 1766 this.encoder_.writeUnsignedVarint32(value.length * 8); 1767 for (var i = 0; i < value.length; i++) { 1768 this.encoder_.writeDouble(value[i]); 1769 } 1770}; 1771 1772 1773/** 1774 * Writes an array of booleans to the buffer as a packed bool field. 1775 * @param {number} field The field number. 1776 * @param {?Array<boolean>} value The array of ints to write. 1777 */ 1778jspb.BinaryWriter.prototype.writePackedBool = function(field, value) { 1779 if (value == null || !value.length) return; 1780 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 1781 this.encoder_.writeUnsignedVarint32(value.length); 1782 for (var i = 0; i < value.length; i++) { 1783 this.encoder_.writeBool(value[i]); 1784 } 1785}; 1786 1787 1788/** 1789 * Writes an array of enums to the buffer as a packed enum field. 1790 * @param {number} field The field number. 1791 * @param {?Array<number>} value The array of ints to write. 1792 */ 1793jspb.BinaryWriter.prototype.writePackedEnum = function(field, value) { 1794 if (value == null || !value.length) return; 1795 var bookmark = this.beginDelimited_(field); 1796 for (var i = 0; i < value.length; i++) { 1797 this.encoder_.writeEnum(value[i]); 1798 } 1799 this.endDelimited_(bookmark); 1800}; 1801 1802 1803/** 1804 * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to 1805 * the buffer. 1806 * @param {number} field The field number. 1807 * @param {?Array<string>} value The array of hashes to write. 1808 */ 1809jspb.BinaryWriter.prototype.writePackedFixedHash64 = function(field, value) { 1810 if (value == null || !value.length) return; 1811 this.writeFieldHeader_(field, jspb.BinaryConstants.WireType.DELIMITED); 1812 this.encoder_.writeUnsignedVarint32(value.length * 8); 1813 for (var i = 0; i < value.length; i++) { 1814 this.encoder_.writeFixedHash64(value[i]); 1815 } 1816}; 1817 1818 1819/** 1820 * Writes a 64-bit hash string field (8 characters @ 8 bits of data each) to 1821 * the buffer. 1822 * @param {number} field The field number. 1823 * @param {?Array<string>} value The array of hashes to write. 1824 */ 1825jspb.BinaryWriter.prototype.writePackedVarintHash64 = function(field, value) { 1826 if (value == null || !value.length) return; 1827 var bookmark = this.beginDelimited_(field); 1828 for (var i = 0; i < value.length; i++) { 1829 this.encoder_.writeVarintHash64(value[i]); 1830 } 1831 this.endDelimited_(bookmark); 1832}; 1833