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