1/// @file 2/// @addtogroup flatbuffers_javascript_api 3/// @{ 4/// @cond FLATBUFFERS_INTERNAL 5 6/** 7 * @fileoverview 8 * 9 * Need to suppress 'global this' error so the Node.js export line doesn't cause 10 * closure compile to error out. 11 * @suppress {globalThis} 12 */ 13 14/** 15 * @const 16 * @namespace 17 */ 18var flatbuffers = {}; 19 20/** 21 * @typedef {number} 22 */ 23flatbuffers.Offset; 24 25/** 26 * @typedef {{ 27 * bb: flatbuffers.ByteBuffer, 28 * bb_pos: number 29 * }} 30 */ 31flatbuffers.Table; 32 33/** 34 * @type {number} 35 * @const 36 */ 37flatbuffers.SIZEOF_SHORT = 2; 38 39/** 40 * @type {number} 41 * @const 42 */ 43flatbuffers.SIZEOF_INT = 4; 44 45/** 46 * @type {number} 47 * @const 48 */ 49flatbuffers.FILE_IDENTIFIER_LENGTH = 4; 50 51/** 52 * @enum {number} 53 */ 54flatbuffers.Encoding = { 55 UTF8_BYTES: 1, 56 UTF16_STRING: 2 57}; 58 59/** 60 * @type {Int32Array} 61 * @const 62 */ 63flatbuffers.int32 = new Int32Array(2); 64 65/** 66 * @type {Float32Array} 67 * @const 68 */ 69flatbuffers.float32 = new Float32Array(flatbuffers.int32.buffer); 70 71/** 72 * @type {Float64Array} 73 * @const 74 */ 75flatbuffers.float64 = new Float64Array(flatbuffers.int32.buffer); 76 77/** 78 * @type {boolean} 79 * @const 80 */ 81flatbuffers.isLittleEndian = new Uint16Array(new Uint8Array([1, 0]).buffer)[0] === 1; 82 83//////////////////////////////////////////////////////////////////////////////// 84 85/** 86 * @constructor 87 * @param {number} low 88 * @param {number} high 89 */ 90flatbuffers.Long = function(low, high) { 91 /** 92 * @type {number} 93 * @const 94 */ 95 this.low = low | 0; 96 97 /** 98 * @type {number} 99 * @const 100 */ 101 this.high = high | 0; 102}; 103 104/** 105 * @param {number} low 106 * @param {number} high 107 * @returns {flatbuffers.Long} 108 */ 109flatbuffers.Long.create = function(low, high) { 110 // Special-case zero to avoid GC overhead for default values 111 return low == 0 && high == 0 ? flatbuffers.Long.ZERO : new flatbuffers.Long(low, high); 112}; 113 114/** 115 * @returns {number} 116 */ 117flatbuffers.Long.prototype.toFloat64 = function() { 118 return (this.low >>> 0) + this.high * 0x100000000; 119}; 120 121/** 122 * @param {flatbuffers.Long} other 123 * @returns {boolean} 124 */ 125flatbuffers.Long.prototype.equals = function(other) { 126 return this.low == other.low && this.high == other.high; 127}; 128 129/** 130 * @type {flatbuffers.Long} 131 * @const 132 */ 133flatbuffers.Long.ZERO = new flatbuffers.Long(0, 0); 134 135/// @endcond 136//////////////////////////////////////////////////////////////////////////////// 137/** 138 * Create a FlatBufferBuilder. 139 * 140 * @constructor 141 * @param {number=} opt_initial_size 142 */ 143flatbuffers.Builder = function(opt_initial_size) { 144 if (!opt_initial_size) { 145 var initial_size = 1024; 146 } else { 147 var initial_size = opt_initial_size; 148 } 149 150 /** 151 * @type {flatbuffers.ByteBuffer} 152 * @private 153 */ 154 this.bb = flatbuffers.ByteBuffer.allocate(initial_size); 155 156 /** 157 * Remaining space in the ByteBuffer. 158 * 159 * @type {number} 160 * @private 161 */ 162 this.space = initial_size; 163 164 /** 165 * Minimum alignment encountered so far. 166 * 167 * @type {number} 168 * @private 169 */ 170 this.minalign = 1; 171 172 /** 173 * The vtable for the current table. 174 * 175 * @type {Array.<number>} 176 * @private 177 */ 178 this.vtable = null; 179 180 /** 181 * The amount of fields we're actually using. 182 * 183 * @type {number} 184 * @private 185 */ 186 this.vtable_in_use = 0; 187 188 /** 189 * Whether we are currently serializing a table. 190 * 191 * @type {boolean} 192 * @private 193 */ 194 this.isNested = false; 195 196 /** 197 * Starting offset of the current struct/table. 198 * 199 * @type {number} 200 * @private 201 */ 202 this.object_start = 0; 203 204 /** 205 * List of offsets of all vtables. 206 * 207 * @type {Array.<number>} 208 * @private 209 */ 210 this.vtables = []; 211 212 /** 213 * For the current vector being built. 214 * 215 * @type {number} 216 * @private 217 */ 218 this.vector_num_elems = 0; 219 220 /** 221 * False omits default values from the serialized data 222 * 223 * @type {boolean} 224 * @private 225 */ 226 this.force_defaults = false; 227}; 228 229/** 230 * In order to save space, fields that are set to their default value 231 * don't get serialized into the buffer. Forcing defaults provides a 232 * way to manually disable this optimization. 233 * 234 * @param {boolean} forceDefaults true always serializes default values 235 */ 236flatbuffers.Builder.prototype.forceDefaults = function(forceDefaults) { 237 this.force_defaults = forceDefaults; 238}; 239 240/** 241 * Get the ByteBuffer representing the FlatBuffer. Only call this after you've 242 * called finish(). The actual data starts at the ByteBuffer's current position, 243 * not necessarily at 0. 244 * 245 * @returns {flatbuffers.ByteBuffer} 246 */ 247flatbuffers.Builder.prototype.dataBuffer = function() { 248 return this.bb; 249}; 250 251/** 252 * Get the bytes representing the FlatBuffer. Only call this after you've 253 * called finish(). 254 * 255 * @returns {Uint8Array} 256 */ 257flatbuffers.Builder.prototype.asUint8Array = function() { 258 return this.bb.bytes().subarray(this.bb.position(), this.bb.position() + this.offset()); 259}; 260 261/// @cond FLATBUFFERS_INTERNAL 262/** 263 * Prepare to write an element of `size` after `additional_bytes` have been 264 * written, e.g. if you write a string, you need to align such the int length 265 * field is aligned to 4 bytes, and the string data follows it directly. If all 266 * you need to do is alignment, `additional_bytes` will be 0. 267 * 268 * @param {number} size This is the of the new element to write 269 * @param {number} additional_bytes The padding size 270 */ 271flatbuffers.Builder.prototype.prep = function(size, additional_bytes) { 272 // Track the biggest thing we've ever aligned to. 273 if (size > this.minalign) { 274 this.minalign = size; 275 } 276 277 // Find the amount of alignment needed such that `size` is properly 278 // aligned after `additional_bytes` 279 var align_size = ((~(this.bb.capacity() - this.space + additional_bytes)) + 1) & (size - 1); 280 281 // Reallocate the buffer if needed. 282 while (this.space < align_size + size + additional_bytes) { 283 var old_buf_size = this.bb.capacity(); 284 this.bb = flatbuffers.Builder.growByteBuffer(this.bb); 285 this.space += this.bb.capacity() - old_buf_size; 286 } 287 288 this.pad(align_size); 289}; 290 291/** 292 * @param {number} byte_size 293 */ 294flatbuffers.Builder.prototype.pad = function(byte_size) { 295 for (var i = 0; i < byte_size; i++) { 296 this.bb.writeInt8(--this.space, 0); 297 } 298}; 299 300/** 301 * @param {number} value 302 */ 303flatbuffers.Builder.prototype.writeInt8 = function(value) { 304 this.bb.writeInt8(this.space -= 1, value); 305}; 306 307/** 308 * @param {number} value 309 */ 310flatbuffers.Builder.prototype.writeInt16 = function(value) { 311 this.bb.writeInt16(this.space -= 2, value); 312}; 313 314/** 315 * @param {number} value 316 */ 317flatbuffers.Builder.prototype.writeInt32 = function(value) { 318 this.bb.writeInt32(this.space -= 4, value); 319}; 320 321/** 322 * @param {flatbuffers.Long} value 323 */ 324flatbuffers.Builder.prototype.writeInt64 = function(value) { 325 this.bb.writeInt64(this.space -= 8, value); 326}; 327 328/** 329 * @param {number} value 330 */ 331flatbuffers.Builder.prototype.writeFloat32 = function(value) { 332 this.bb.writeFloat32(this.space -= 4, value); 333}; 334 335/** 336 * @param {number} value 337 */ 338flatbuffers.Builder.prototype.writeFloat64 = function(value) { 339 this.bb.writeFloat64(this.space -= 8, value); 340}; 341/// @endcond 342 343/** 344 * Add an `int8` to the buffer, properly aligned, and grows the buffer (if necessary). 345 * @param {number} value The `int8` to add the the buffer. 346 */ 347flatbuffers.Builder.prototype.addInt8 = function(value) { 348 this.prep(1, 0); 349 this.writeInt8(value); 350}; 351 352/** 353 * Add an `int16` to the buffer, properly aligned, and grows the buffer (if necessary). 354 * @param {number} value The `int16` to add the the buffer. 355 */ 356flatbuffers.Builder.prototype.addInt16 = function(value) { 357 this.prep(2, 0); 358 this.writeInt16(value); 359}; 360 361/** 362 * Add an `int32` to the buffer, properly aligned, and grows the buffer (if necessary). 363 * @param {number} value The `int32` to add the the buffer. 364 */ 365flatbuffers.Builder.prototype.addInt32 = function(value) { 366 this.prep(4, 0); 367 this.writeInt32(value); 368}; 369 370/** 371 * Add an `int64` to the buffer, properly aligned, and grows the buffer (if necessary). 372 * @param {flatbuffers.Long} value The `int64` to add the the buffer. 373 */ 374flatbuffers.Builder.prototype.addInt64 = function(value) { 375 this.prep(8, 0); 376 this.writeInt64(value); 377}; 378 379/** 380 * Add a `float32` to the buffer, properly aligned, and grows the buffer (if necessary). 381 * @param {number} value The `float32` to add the the buffer. 382 */ 383flatbuffers.Builder.prototype.addFloat32 = function(value) { 384 this.prep(4, 0); 385 this.writeFloat32(value); 386}; 387 388/** 389 * Add a `float64` to the buffer, properly aligned, and grows the buffer (if necessary). 390 * @param {number} value The `float64` to add the the buffer. 391 */ 392flatbuffers.Builder.prototype.addFloat64 = function(value) { 393 this.prep(8, 0); 394 this.writeFloat64(value); 395}; 396 397/// @cond FLATBUFFERS_INTERNAL 398/** 399 * @param {number} voffset 400 * @param {number} value 401 * @param {number} defaultValue 402 */ 403flatbuffers.Builder.prototype.addFieldInt8 = function(voffset, value, defaultValue) { 404 if (this.force_defaults || value != defaultValue) { 405 this.addInt8(value); 406 this.slot(voffset); 407 } 408}; 409 410/** 411 * @param {number} voffset 412 * @param {number} value 413 * @param {number} defaultValue 414 */ 415flatbuffers.Builder.prototype.addFieldInt16 = function(voffset, value, defaultValue) { 416 if (this.force_defaults || value != defaultValue) { 417 this.addInt16(value); 418 this.slot(voffset); 419 } 420}; 421 422/** 423 * @param {number} voffset 424 * @param {number} value 425 * @param {number} defaultValue 426 */ 427flatbuffers.Builder.prototype.addFieldInt32 = function(voffset, value, defaultValue) { 428 if (this.force_defaults || value != defaultValue) { 429 this.addInt32(value); 430 this.slot(voffset); 431 } 432}; 433 434/** 435 * @param {number} voffset 436 * @param {flatbuffers.Long} value 437 * @param {flatbuffers.Long} defaultValue 438 */ 439flatbuffers.Builder.prototype.addFieldInt64 = function(voffset, value, defaultValue) { 440 if (this.force_defaults || !value.equals(defaultValue)) { 441 this.addInt64(value); 442 this.slot(voffset); 443 } 444}; 445 446/** 447 * @param {number} voffset 448 * @param {number} value 449 * @param {number} defaultValue 450 */ 451flatbuffers.Builder.prototype.addFieldFloat32 = function(voffset, value, defaultValue) { 452 if (this.force_defaults || value != defaultValue) { 453 this.addFloat32(value); 454 this.slot(voffset); 455 } 456}; 457 458/** 459 * @param {number} voffset 460 * @param {number} value 461 * @param {number} defaultValue 462 */ 463flatbuffers.Builder.prototype.addFieldFloat64 = function(voffset, value, defaultValue) { 464 if (this.force_defaults || value != defaultValue) { 465 this.addFloat64(value); 466 this.slot(voffset); 467 } 468}; 469 470/** 471 * @param {number} voffset 472 * @param {flatbuffers.Offset} value 473 * @param {flatbuffers.Offset} defaultValue 474 */ 475flatbuffers.Builder.prototype.addFieldOffset = function(voffset, value, defaultValue) { 476 if (this.force_defaults || value != defaultValue) { 477 this.addOffset(value); 478 this.slot(voffset); 479 } 480}; 481 482/** 483 * Structs are stored inline, so nothing additional is being added. `d` is always 0. 484 * 485 * @param {number} voffset 486 * @param {flatbuffers.Offset} value 487 * @param {flatbuffers.Offset} defaultValue 488 */ 489flatbuffers.Builder.prototype.addFieldStruct = function(voffset, value, defaultValue) { 490 if (value != defaultValue) { 491 this.nested(value); 492 this.slot(voffset); 493 } 494}; 495 496/** 497 * Structures are always stored inline, they need to be created right 498 * where they're used. You'll get this assertion failure if you 499 * created it elsewhere. 500 * 501 * @param {flatbuffers.Offset} obj The offset of the created object 502 */ 503flatbuffers.Builder.prototype.nested = function(obj) { 504 if (obj != this.offset()) { 505 throw new Error('FlatBuffers: struct must be serialized inline.'); 506 } 507}; 508 509/** 510 * Should not be creating any other object, string or vector 511 * while an object is being constructed 512 */ 513flatbuffers.Builder.prototype.notNested = function() { 514 if (this.isNested) { 515 throw new Error('FlatBuffers: object serialization must not be nested.'); 516 } 517}; 518 519/** 520 * Set the current vtable at `voffset` to the current location in the buffer. 521 * 522 * @param {number} voffset 523 */ 524flatbuffers.Builder.prototype.slot = function(voffset) { 525 this.vtable[voffset] = this.offset(); 526}; 527 528/** 529 * @returns {flatbuffers.Offset} Offset relative to the end of the buffer. 530 */ 531flatbuffers.Builder.prototype.offset = function() { 532 return this.bb.capacity() - this.space; 533}; 534 535/** 536 * Doubles the size of the backing ByteBuffer and copies the old data towards 537 * the end of the new buffer (since we build the buffer backwards). 538 * 539 * @param {flatbuffers.ByteBuffer} bb The current buffer with the existing data 540 * @returns {flatbuffers.ByteBuffer} A new byte buffer with the old data copied 541 * to it. The data is located at the end of the buffer. 542 * 543 * uint8Array.set() formally takes {Array<number>|ArrayBufferView}, so to pass 544 * it a uint8Array we need to suppress the type check: 545 * @suppress {checkTypes} 546 */ 547flatbuffers.Builder.growByteBuffer = function(bb) { 548 var old_buf_size = bb.capacity(); 549 550 // Ensure we don't grow beyond what fits in an int. 551 if (old_buf_size & 0xC0000000) { 552 throw new Error('FlatBuffers: cannot grow buffer beyond 2 gigabytes.'); 553 } 554 555 var new_buf_size = old_buf_size << 1; 556 var nbb = flatbuffers.ByteBuffer.allocate(new_buf_size); 557 nbb.setPosition(new_buf_size - old_buf_size); 558 nbb.bytes().set(bb.bytes(), new_buf_size - old_buf_size); 559 return nbb; 560}; 561/// @endcond 562 563/** 564 * Adds on offset, relative to where it will be written. 565 * 566 * @param {flatbuffers.Offset} offset The offset to add. 567 */ 568flatbuffers.Builder.prototype.addOffset = function(offset) { 569 this.prep(flatbuffers.SIZEOF_INT, 0); // Ensure alignment is already done. 570 this.writeInt32(this.offset() - offset + flatbuffers.SIZEOF_INT); 571}; 572 573/// @cond FLATBUFFERS_INTERNAL 574/** 575 * Start encoding a new object in the buffer. Users will not usually need to 576 * call this directly. The FlatBuffers compiler will generate helper methods 577 * that call this method internally. 578 * 579 * @param {number} numfields 580 */ 581flatbuffers.Builder.prototype.startObject = function(numfields) { 582 this.notNested(); 583 if (this.vtable == null) { 584 this.vtable = []; 585 } 586 this.vtable_in_use = numfields; 587 for (var i = 0; i < numfields; i++) { 588 this.vtable[i] = 0; // This will push additional elements as needed 589 } 590 this.isNested = true; 591 this.object_start = this.offset(); 592}; 593 594/** 595 * Finish off writing the object that is under construction. 596 * 597 * @returns {flatbuffers.Offset} The offset to the object inside `dataBuffer` 598 */ 599flatbuffers.Builder.prototype.endObject = function() { 600 if (this.vtable == null || !this.isNested) { 601 throw new Error('FlatBuffers: endObject called without startObject'); 602 } 603 604 this.addInt32(0); 605 var vtableloc = this.offset(); 606 607 // Trim trailing zeroes. 608 var i = this.vtable_in_use - 1; 609 for (; i >= 0 && this.vtable[i] == 0; i--) {} 610 var trimmed_size = i + 1; 611 612 // Write out the current vtable. 613 for (; i >= 0; i--) { 614 // Offset relative to the start of the table. 615 this.addInt16(this.vtable[i] != 0 ? vtableloc - this.vtable[i] : 0); 616 } 617 618 var standard_fields = 2; // The fields below: 619 this.addInt16(vtableloc - this.object_start); 620 var len = (trimmed_size + standard_fields) * flatbuffers.SIZEOF_SHORT; 621 this.addInt16(len); 622 623 // Search for an existing vtable that matches the current one. 624 var existing_vtable = 0; 625 var vt1 = this.space; 626outer_loop: 627 for (i = 0; i < this.vtables.length; i++) { 628 var vt2 = this.bb.capacity() - this.vtables[i]; 629 if (len == this.bb.readInt16(vt2)) { 630 for (var j = flatbuffers.SIZEOF_SHORT; j < len; j += flatbuffers.SIZEOF_SHORT) { 631 if (this.bb.readInt16(vt1 + j) != this.bb.readInt16(vt2 + j)) { 632 continue outer_loop; 633 } 634 } 635 existing_vtable = this.vtables[i]; 636 break; 637 } 638 } 639 640 if (existing_vtable) { 641 // Found a match: 642 // Remove the current vtable. 643 this.space = this.bb.capacity() - vtableloc; 644 645 // Point table to existing vtable. 646 this.bb.writeInt32(this.space, existing_vtable - vtableloc); 647 } else { 648 // No match: 649 // Add the location of the current vtable to the list of vtables. 650 this.vtables.push(this.offset()); 651 652 // Point table to current vtable. 653 this.bb.writeInt32(this.bb.capacity() - vtableloc, this.offset() - vtableloc); 654 } 655 656 this.isNested = false; 657 return vtableloc; 658}; 659/// @endcond 660 661/** 662 * Finalize a buffer, poiting to the given `root_table`. 663 * 664 * @param {flatbuffers.Offset} root_table 665 * @param {string=} opt_file_identifier 666 */ 667flatbuffers.Builder.prototype.finish = function(root_table, opt_file_identifier) { 668 if (opt_file_identifier) { 669 var file_identifier = opt_file_identifier; 670 this.prep(this.minalign, flatbuffers.SIZEOF_INT + 671 flatbuffers.FILE_IDENTIFIER_LENGTH); 672 if (file_identifier.length != flatbuffers.FILE_IDENTIFIER_LENGTH) { 673 throw new Error('FlatBuffers: file identifier must be length ' + 674 flatbuffers.FILE_IDENTIFIER_LENGTH); 675 } 676 for (var i = flatbuffers.FILE_IDENTIFIER_LENGTH - 1; i >= 0; i--) { 677 this.writeInt8(file_identifier.charCodeAt(i)); 678 } 679 } 680 this.prep(this.minalign, flatbuffers.SIZEOF_INT); 681 this.addOffset(root_table); 682 this.bb.setPosition(this.space); 683}; 684 685/// @cond FLATBUFFERS_INTERNAL 686/** 687 * This checks a required field has been set in a given table that has 688 * just been constructed. 689 * 690 * @param {flatbuffers.Offset} table 691 * @param {number} field 692 */ 693flatbuffers.Builder.prototype.requiredField = function(table, field) { 694 var table_start = this.bb.capacity() - table; 695 var vtable_start = table_start - this.bb.readInt32(table_start); 696 var ok = this.bb.readInt16(vtable_start + field) != 0; 697 698 // If this fails, the caller will show what field needs to be set. 699 if (!ok) { 700 throw new Error('FlatBuffers: field ' + field + ' must be set'); 701 } 702}; 703 704/** 705 * Start a new array/vector of objects. Users usually will not call 706 * this directly. The FlatBuffers compiler will create a start/end 707 * method for vector types in generated code. 708 * 709 * @param {number} elem_size The size of each element in the array 710 * @param {number} num_elems The number of elements in the array 711 * @param {number} alignment The alignment of the array 712 */ 713flatbuffers.Builder.prototype.startVector = function(elem_size, num_elems, alignment) { 714 this.notNested(); 715 this.vector_num_elems = num_elems; 716 this.prep(flatbuffers.SIZEOF_INT, elem_size * num_elems); 717 this.prep(alignment, elem_size * num_elems); // Just in case alignment > int. 718}; 719 720/** 721 * Finish off the creation of an array and all its elements. The array must be 722 * created with `startVector`. 723 * 724 * @returns {flatbuffers.Offset} The offset at which the newly created array 725 * starts. 726 */ 727flatbuffers.Builder.prototype.endVector = function() { 728 this.writeInt32(this.vector_num_elems); 729 return this.offset(); 730}; 731/// @endcond 732 733/** 734 * Encode the string `s` in the buffer using UTF-8. If a Uint8Array is passed 735 * instead of a string, it is assumed to contain valid UTF-8 encoded data. 736 * 737 * @param {string|Uint8Array} s The string to encode 738 * @return {flatbuffers.Offset} The offset in the buffer where the encoded string starts 739 */ 740flatbuffers.Builder.prototype.createString = function(s) { 741 if (s instanceof Uint8Array) { 742 var utf8 = s; 743 } else { 744 var utf8 = []; 745 var i = 0; 746 747 while (i < s.length) { 748 var codePoint; 749 750 // Decode UTF-16 751 var a = s.charCodeAt(i++); 752 if (a < 0xD800 || a >= 0xDC00) { 753 codePoint = a; 754 } else { 755 var b = s.charCodeAt(i++); 756 codePoint = (a << 10) + b + (0x10000 - (0xD800 << 10) - 0xDC00); 757 } 758 759 // Encode UTF-8 760 if (codePoint < 0x80) { 761 utf8.push(codePoint); 762 } else { 763 if (codePoint < 0x800) { 764 utf8.push(((codePoint >> 6) & 0x1F) | 0xC0); 765 } else { 766 if (codePoint < 0x10000) { 767 utf8.push(((codePoint >> 12) & 0x0F) | 0xE0); 768 } else { 769 utf8.push( 770 ((codePoint >> 18) & 0x07) | 0xF0, 771 ((codePoint >> 12) & 0x3F) | 0x80); 772 } 773 utf8.push(((codePoint >> 6) & 0x3F) | 0x80); 774 } 775 utf8.push((codePoint & 0x3F) | 0x80); 776 } 777 } 778 } 779 780 this.addInt8(0); 781 this.startVector(1, utf8.length, 1); 782 this.bb.setPosition(this.space -= utf8.length); 783 for (var i = 0, offset = this.space, bytes = this.bb.bytes(); i < utf8.length; i++) { 784 bytes[offset++] = utf8[i]; 785 } 786 return this.endVector(); 787}; 788 789/** 790 * A helper function to avoid generated code depending on this file directly. 791 * 792 * @param {number} low 793 * @param {number} high 794 * @returns {flatbuffers.Long} 795 */ 796flatbuffers.Builder.prototype.createLong = function(low, high) { 797 return flatbuffers.Long.create(low, high); 798}; 799//////////////////////////////////////////////////////////////////////////////// 800/// @cond FLATBUFFERS_INTERNAL 801/** 802 * Create a new ByteBuffer with a given array of bytes (`Uint8Array`). 803 * 804 * @constructor 805 * @param {Uint8Array} bytes 806 */ 807flatbuffers.ByteBuffer = function(bytes) { 808 /** 809 * @type {Uint8Array} 810 * @private 811 */ 812 this.bytes_ = bytes; 813 814 /** 815 * @type {number} 816 * @private 817 */ 818 this.position_ = 0; 819}; 820 821/** 822 * Create and allocate a new ByteBuffer with a given size. 823 * 824 * @param {number} byte_size 825 * @returns {flatbuffers.ByteBuffer} 826 */ 827flatbuffers.ByteBuffer.allocate = function(byte_size) { 828 return new flatbuffers.ByteBuffer(new Uint8Array(byte_size)); 829}; 830 831/** 832 * Get the underlying `Uint8Array`. 833 * 834 * @returns {Uint8Array} 835 */ 836flatbuffers.ByteBuffer.prototype.bytes = function() { 837 return this.bytes_; 838}; 839 840/** 841 * Get the buffer's position. 842 * 843 * @returns {number} 844 */ 845flatbuffers.ByteBuffer.prototype.position = function() { 846 return this.position_; 847}; 848 849/** 850 * Set the buffer's position. 851 * 852 * @param {number} position 853 */ 854flatbuffers.ByteBuffer.prototype.setPosition = function(position) { 855 this.position_ = position; 856}; 857 858/** 859 * Get the buffer's capacity. 860 * 861 * @returns {number} 862 */ 863flatbuffers.ByteBuffer.prototype.capacity = function() { 864 return this.bytes_.length; 865}; 866 867/** 868 * @param {number} offset 869 * @returns {number} 870 */ 871flatbuffers.ByteBuffer.prototype.readInt8 = function(offset) { 872 return this.readUint8(offset) << 24 >> 24; 873}; 874 875/** 876 * @param {number} offset 877 * @returns {number} 878 */ 879flatbuffers.ByteBuffer.prototype.readUint8 = function(offset) { 880 return this.bytes_[offset]; 881}; 882 883/** 884 * @param {number} offset 885 * @returns {number} 886 */ 887flatbuffers.ByteBuffer.prototype.readInt16 = function(offset) { 888 return this.readUint16(offset) << 16 >> 16; 889}; 890 891/** 892 * @param {number} offset 893 * @returns {number} 894 */ 895flatbuffers.ByteBuffer.prototype.readUint16 = function(offset) { 896 return this.bytes_[offset] | this.bytes_[offset + 1] << 8; 897}; 898 899/** 900 * @param {number} offset 901 * @returns {number} 902 */ 903flatbuffers.ByteBuffer.prototype.readInt32 = function(offset) { 904 return this.bytes_[offset] | this.bytes_[offset + 1] << 8 | this.bytes_[offset + 2] << 16 | this.bytes_[offset + 3] << 24; 905}; 906 907/** 908 * @param {number} offset 909 * @returns {number} 910 */ 911flatbuffers.ByteBuffer.prototype.readUint32 = function(offset) { 912 return this.readInt32(offset) >>> 0; 913}; 914 915/** 916 * @param {number} offset 917 * @returns {flatbuffers.Long} 918 */ 919flatbuffers.ByteBuffer.prototype.readInt64 = function(offset) { 920 return new flatbuffers.Long(this.readInt32(offset), this.readInt32(offset + 4)); 921}; 922 923/** 924 * @param {number} offset 925 * @returns {flatbuffers.Long} 926 */ 927flatbuffers.ByteBuffer.prototype.readUint64 = function(offset) { 928 return new flatbuffers.Long(this.readUint32(offset), this.readUint32(offset + 4)); 929}; 930 931/** 932 * @param {number} offset 933 * @returns {number} 934 */ 935flatbuffers.ByteBuffer.prototype.readFloat32 = function(offset) { 936 flatbuffers.int32[0] = this.readInt32(offset); 937 return flatbuffers.float32[0]; 938}; 939 940/** 941 * @param {number} offset 942 * @returns {number} 943 */ 944flatbuffers.ByteBuffer.prototype.readFloat64 = function(offset) { 945 flatbuffers.int32[flatbuffers.isLittleEndian ? 0 : 1] = this.readInt32(offset); 946 flatbuffers.int32[flatbuffers.isLittleEndian ? 1 : 0] = this.readInt32(offset + 4); 947 return flatbuffers.float64[0]; 948}; 949 950/** 951 * @param {number} offset 952 * @param {number|boolean} value 953 */ 954flatbuffers.ByteBuffer.prototype.writeInt8 = function(offset, value) { 955 this.bytes_[offset] = /** @type {number} */(value); 956}; 957 958/** 959 * @param {number} offset 960 * @param {number} value 961 */ 962flatbuffers.ByteBuffer.prototype.writeUint8 = function(offset, value) { 963 this.bytes_[offset] = value; 964}; 965 966/** 967 * @param {number} offset 968 * @param {number} value 969 */ 970flatbuffers.ByteBuffer.prototype.writeInt16 = function(offset, value) { 971 this.bytes_[offset] = value; 972 this.bytes_[offset + 1] = value >> 8; 973}; 974 975/** 976 * @param {number} offset 977 * @param {number} value 978 */ 979flatbuffers.ByteBuffer.prototype.writeUint16 = function(offset, value) { 980 this.bytes_[offset] = value; 981 this.bytes_[offset + 1] = value >> 8; 982}; 983 984/** 985 * @param {number} offset 986 * @param {number} value 987 */ 988flatbuffers.ByteBuffer.prototype.writeInt32 = function(offset, value) { 989 this.bytes_[offset] = value; 990 this.bytes_[offset + 1] = value >> 8; 991 this.bytes_[offset + 2] = value >> 16; 992 this.bytes_[offset + 3] = value >> 24; 993}; 994 995/** 996 * @param {number} offset 997 * @param {number} value 998 */ 999flatbuffers.ByteBuffer.prototype.writeUint32 = function(offset, value) { 1000 this.bytes_[offset] = value; 1001 this.bytes_[offset + 1] = value >> 8; 1002 this.bytes_[offset + 2] = value >> 16; 1003 this.bytes_[offset + 3] = value >> 24; 1004}; 1005 1006/** 1007 * @param {number} offset 1008 * @param {flatbuffers.Long} value 1009 */ 1010flatbuffers.ByteBuffer.prototype.writeInt64 = function(offset, value) { 1011 this.writeInt32(offset, value.low); 1012 this.writeInt32(offset + 4, value.high); 1013}; 1014 1015/** 1016 * @param {number} offset 1017 * @param {flatbuffers.Long} value 1018 */ 1019flatbuffers.ByteBuffer.prototype.writeUint64 = function(offset, value) { 1020 this.writeUint32(offset, value.low); 1021 this.writeUint32(offset + 4, value.high); 1022}; 1023 1024/** 1025 * @param {number} offset 1026 * @param {number} value 1027 */ 1028flatbuffers.ByteBuffer.prototype.writeFloat32 = function(offset, value) { 1029 flatbuffers.float32[0] = value; 1030 this.writeInt32(offset, flatbuffers.int32[0]); 1031}; 1032 1033/** 1034 * @param {number} offset 1035 * @param {number} value 1036 */ 1037flatbuffers.ByteBuffer.prototype.writeFloat64 = function(offset, value) { 1038 flatbuffers.float64[0] = value; 1039 this.writeInt32(offset, flatbuffers.int32[flatbuffers.isLittleEndian ? 0 : 1]); 1040 this.writeInt32(offset + 4, flatbuffers.int32[flatbuffers.isLittleEndian ? 1 : 0]); 1041}; 1042 1043/** 1044 * Look up a field in the vtable, return an offset into the object, or 0 if the 1045 * field is not present. 1046 * 1047 * @param {number} bb_pos 1048 * @param {number} vtable_offset 1049 * @returns {number} 1050 */ 1051flatbuffers.ByteBuffer.prototype.__offset = function(bb_pos, vtable_offset) { 1052 var vtable = bb_pos - this.readInt32(bb_pos); 1053 return vtable_offset < this.readInt16(vtable) ? this.readInt16(vtable + vtable_offset) : 0; 1054}; 1055 1056/** 1057 * Initialize any Table-derived type to point to the union at the given offset. 1058 * 1059 * @param {flatbuffers.Table} t 1060 * @param {number} offset 1061 * @returns {flatbuffers.Table} 1062 */ 1063flatbuffers.ByteBuffer.prototype.__union = function(t, offset) { 1064 t.bb_pos = offset + this.readInt32(offset); 1065 t.bb = this; 1066 return t; 1067}; 1068 1069/** 1070 * Create a JavaScript string from UTF-8 data stored inside the FlatBuffer. 1071 * This allocates a new string and converts to wide chars upon each access. 1072 * 1073 * To avoid the conversion to UTF-16, pass flatbuffers.Encoding.UTF8_BYTES as 1074 * the "optionalEncoding" argument. This is useful for avoiding conversion to 1075 * and from UTF-16 when the data will just be packaged back up in another 1076 * FlatBuffer later on. 1077 * 1078 * @param {number} offset 1079 * @param {flatbuffers.Encoding=} opt_encoding Defaults to UTF16_STRING 1080 * @returns {string|Uint8Array} 1081 */ 1082flatbuffers.ByteBuffer.prototype.__string = function(offset, opt_encoding) { 1083 offset += this.readInt32(offset); 1084 1085 var length = this.readInt32(offset); 1086 var result = ''; 1087 var i = 0; 1088 1089 offset += flatbuffers.SIZEOF_INT; 1090 1091 if (opt_encoding === flatbuffers.Encoding.UTF8_BYTES) { 1092 return this.bytes_.subarray(offset, offset + length); 1093 } 1094 1095 while (i < length) { 1096 var codePoint; 1097 1098 // Decode UTF-8 1099 var a = this.readUint8(offset + i++); 1100 if (a < 0xC0) { 1101 codePoint = a; 1102 } else { 1103 var b = this.readUint8(offset + i++); 1104 if (a < 0xE0) { 1105 codePoint = 1106 ((a & 0x1F) << 6) | 1107 (b & 0x3F); 1108 } else { 1109 var c = this.readUint8(offset + i++); 1110 if (a < 0xF0) { 1111 codePoint = 1112 ((a & 0x0F) << 12) | 1113 ((b & 0x3F) << 6) | 1114 (c & 0x3F); 1115 } else { 1116 var d = this.readUint8(offset + i++); 1117 codePoint = 1118 ((a & 0x07) << 18) | 1119 ((b & 0x3F) << 12) | 1120 ((c & 0x3F) << 6) | 1121 (d & 0x3F); 1122 } 1123 } 1124 } 1125 1126 // Encode UTF-16 1127 if (codePoint < 0x10000) { 1128 result += String.fromCharCode(codePoint); 1129 } else { 1130 codePoint -= 0x10000; 1131 result += String.fromCharCode( 1132 (codePoint >> 10) + 0xD800, 1133 (codePoint & ((1 << 10) - 1)) + 0xDC00); 1134 } 1135 } 1136 1137 return result; 1138}; 1139 1140/** 1141 * Retrieve the relative offset stored at "offset" 1142 * @param {number} offset 1143 * @returns {number} 1144 */ 1145flatbuffers.ByteBuffer.prototype.__indirect = function(offset) { 1146 return offset + this.readInt32(offset); 1147}; 1148 1149/** 1150 * Get the start of data of a vector whose offset is stored at "offset" in this object. 1151 * 1152 * @param {number} offset 1153 * @returns {number} 1154 */ 1155flatbuffers.ByteBuffer.prototype.__vector = function(offset) { 1156 return offset + this.readInt32(offset) + flatbuffers.SIZEOF_INT; // data starts after the length 1157}; 1158 1159/** 1160 * Get the length of a vector whose offset is stored at "offset" in this object. 1161 * 1162 * @param {number} offset 1163 * @returns {number} 1164 */ 1165flatbuffers.ByteBuffer.prototype.__vector_len = function(offset) { 1166 return this.readInt32(offset + this.readInt32(offset)); 1167}; 1168 1169/** 1170 * @param {string} ident 1171 * @returns {boolean} 1172 */ 1173flatbuffers.ByteBuffer.prototype.__has_identifier = function(ident) { 1174 if (ident.length != flatbuffers.FILE_IDENTIFIER_LENGTH) { 1175 throw new Error('FlatBuffers: file identifier must be length ' + 1176 flatbuffers.FILE_IDENTIFIER_LENGTH); 1177 } 1178 for (var i = 0; i < flatbuffers.FILE_IDENTIFIER_LENGTH; i++) { 1179 if (ident.charCodeAt(i) != this.readInt8(this.position_ + flatbuffers.SIZEOF_INT + i)) { 1180 return false; 1181 } 1182 } 1183 return true; 1184}; 1185 1186/** 1187 * A helper function to avoid generated code depending on this file directly. 1188 * 1189 * @param {number} low 1190 * @param {number} high 1191 * @returns {flatbuffers.Long} 1192 */ 1193flatbuffers.ByteBuffer.prototype.createLong = function(low, high) { 1194 return flatbuffers.Long.create(low, high); 1195}; 1196 1197// Exports for Node.js and RequireJS 1198this.flatbuffers = flatbuffers; 1199 1200/// @endcond 1201/// @} 1202