• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 * Create and allocate a new ByteBuffer with a given size.
836 *
837 * @param {number} byte_size
838 * @returns {flatbuffers.ByteBuffer}
839 */
840flatbuffers.ByteBuffer.allocate = function(byte_size) {
841  return new flatbuffers.ByteBuffer(new Uint8Array(byte_size));
842};
843
844flatbuffers.ByteBuffer.prototype.clear = function() {
845  this.position_ = 0;
846};
847
848/**
849 * Get the underlying `Uint8Array`.
850 *
851 * @returns {Uint8Array}
852 */
853flatbuffers.ByteBuffer.prototype.bytes = function() {
854  return this.bytes_;
855};
856
857/**
858 * Get the buffer's position.
859 *
860 * @returns {number}
861 */
862flatbuffers.ByteBuffer.prototype.position = function() {
863  return this.position_;
864};
865
866/**
867 * Set the buffer's position.
868 *
869 * @param {number} position
870 */
871flatbuffers.ByteBuffer.prototype.setPosition = function(position) {
872  this.position_ = position;
873};
874
875/**
876 * Get the buffer's capacity.
877 *
878 * @returns {number}
879 */
880flatbuffers.ByteBuffer.prototype.capacity = function() {
881  return this.bytes_.length;
882};
883
884/**
885 * @param {number} offset
886 * @returns {number}
887 */
888flatbuffers.ByteBuffer.prototype.readInt8 = function(offset) {
889  return this.readUint8(offset) << 24 >> 24;
890};
891
892/**
893 * @param {number} offset
894 * @returns {number}
895 */
896flatbuffers.ByteBuffer.prototype.readUint8 = function(offset) {
897  return this.bytes_[offset];
898};
899
900/**
901 * @param {number} offset
902 * @returns {number}
903 */
904flatbuffers.ByteBuffer.prototype.readInt16 = function(offset) {
905  return this.readUint16(offset) << 16 >> 16;
906};
907
908/**
909 * @param {number} offset
910 * @returns {number}
911 */
912flatbuffers.ByteBuffer.prototype.readUint16 = function(offset) {
913  return this.bytes_[offset] | this.bytes_[offset + 1] << 8;
914};
915
916/**
917 * @param {number} offset
918 * @returns {number}
919 */
920flatbuffers.ByteBuffer.prototype.readInt32 = function(offset) {
921  return this.bytes_[offset] | this.bytes_[offset + 1] << 8 | this.bytes_[offset + 2] << 16 | this.bytes_[offset + 3] << 24;
922};
923
924/**
925 * @param {number} offset
926 * @returns {number}
927 */
928flatbuffers.ByteBuffer.prototype.readUint32 = function(offset) {
929  return this.readInt32(offset) >>> 0;
930};
931
932/**
933 * @param {number} offset
934 * @returns {flatbuffers.Long}
935 */
936flatbuffers.ByteBuffer.prototype.readInt64 = function(offset) {
937  return new flatbuffers.Long(this.readInt32(offset), this.readInt32(offset + 4));
938};
939
940/**
941 * @param {number} offset
942 * @returns {flatbuffers.Long}
943 */
944flatbuffers.ByteBuffer.prototype.readUint64 = function(offset) {
945  return new flatbuffers.Long(this.readUint32(offset), this.readUint32(offset + 4));
946};
947
948/**
949 * @param {number} offset
950 * @returns {number}
951 */
952flatbuffers.ByteBuffer.prototype.readFloat32 = function(offset) {
953  flatbuffers.int32[0] = this.readInt32(offset);
954  return flatbuffers.float32[0];
955};
956
957/**
958 * @param {number} offset
959 * @returns {number}
960 */
961flatbuffers.ByteBuffer.prototype.readFloat64 = function(offset) {
962  flatbuffers.int32[flatbuffers.isLittleEndian ? 0 : 1] = this.readInt32(offset);
963  flatbuffers.int32[flatbuffers.isLittleEndian ? 1 : 0] = this.readInt32(offset + 4);
964  return flatbuffers.float64[0];
965};
966
967/**
968 * @param {number} offset
969 * @param {number|boolean} value
970 */
971flatbuffers.ByteBuffer.prototype.writeInt8 = function(offset, value) {
972  this.bytes_[offset] = /** @type {number} */(value);
973};
974
975/**
976 * @param {number} offset
977 * @param {number} value
978 */
979flatbuffers.ByteBuffer.prototype.writeUint8 = function(offset, value) {
980  this.bytes_[offset] = value;
981};
982
983/**
984 * @param {number} offset
985 * @param {number} value
986 */
987flatbuffers.ByteBuffer.prototype.writeInt16 = function(offset, value) {
988  this.bytes_[offset] = value;
989  this.bytes_[offset + 1] = value >> 8;
990};
991
992/**
993 * @param {number} offset
994 * @param {number} value
995 */
996flatbuffers.ByteBuffer.prototype.writeUint16 = function(offset, value) {
997    this.bytes_[offset] = value;
998    this.bytes_[offset + 1] = value >> 8;
999};
1000
1001/**
1002 * @param {number} offset
1003 * @param {number} value
1004 */
1005flatbuffers.ByteBuffer.prototype.writeInt32 = function(offset, value) {
1006  this.bytes_[offset] = value;
1007  this.bytes_[offset + 1] = value >> 8;
1008  this.bytes_[offset + 2] = value >> 16;
1009  this.bytes_[offset + 3] = value >> 24;
1010};
1011
1012/**
1013 * @param {number} offset
1014 * @param {number} value
1015 */
1016flatbuffers.ByteBuffer.prototype.writeUint32 = function(offset, value) {
1017    this.bytes_[offset] = value;
1018    this.bytes_[offset + 1] = value >> 8;
1019    this.bytes_[offset + 2] = value >> 16;
1020    this.bytes_[offset + 3] = value >> 24;
1021};
1022
1023/**
1024 * @param {number} offset
1025 * @param {flatbuffers.Long} value
1026 */
1027flatbuffers.ByteBuffer.prototype.writeInt64 = function(offset, value) {
1028  this.writeInt32(offset, value.low);
1029  this.writeInt32(offset + 4, value.high);
1030};
1031
1032/**
1033 * @param {number} offset
1034 * @param {flatbuffers.Long} value
1035 */
1036flatbuffers.ByteBuffer.prototype.writeUint64 = function(offset, value) {
1037    this.writeUint32(offset, value.low);
1038    this.writeUint32(offset + 4, value.high);
1039};
1040
1041/**
1042 * @param {number} offset
1043 * @param {number} value
1044 */
1045flatbuffers.ByteBuffer.prototype.writeFloat32 = function(offset, value) {
1046  flatbuffers.float32[0] = value;
1047  this.writeInt32(offset, flatbuffers.int32[0]);
1048};
1049
1050/**
1051 * @param {number} offset
1052 * @param {number} value
1053 */
1054flatbuffers.ByteBuffer.prototype.writeFloat64 = function(offset, value) {
1055  flatbuffers.float64[0] = value;
1056  this.writeInt32(offset, flatbuffers.int32[flatbuffers.isLittleEndian ? 0 : 1]);
1057  this.writeInt32(offset + 4, flatbuffers.int32[flatbuffers.isLittleEndian ? 1 : 0]);
1058};
1059
1060/**
1061 * Return the file identifier.   Behavior is undefined for FlatBuffers whose
1062 * schema does not include a file_identifier (likely points at padding or the
1063 * start of a the root vtable).
1064 * @returns {string}
1065 */
1066flatbuffers.ByteBuffer.prototype.getBufferIdentifier = function() {
1067  if (this.bytes_.length < this.position_ + flatbuffers.SIZEOF_INT +
1068      flatbuffers.FILE_IDENTIFIER_LENGTH) {
1069    throw new Error(
1070        'FlatBuffers: ByteBuffer is too short to contain an identifier.');
1071  }
1072  var result = "";
1073  for (var i = 0; i < flatbuffers.FILE_IDENTIFIER_LENGTH; i++) {
1074    result += String.fromCharCode(
1075        this.readInt8(this.position_ + flatbuffers.SIZEOF_INT + i));
1076  }
1077  return result;
1078};
1079
1080/**
1081 * Look up a field in the vtable, return an offset into the object, or 0 if the
1082 * field is not present.
1083 *
1084 * @param {number} bb_pos
1085 * @param {number} vtable_offset
1086 * @returns {number}
1087 */
1088flatbuffers.ByteBuffer.prototype.__offset = function(bb_pos, vtable_offset) {
1089  var vtable = bb_pos - this.readInt32(bb_pos);
1090  return vtable_offset < this.readInt16(vtable) ? this.readInt16(vtable + vtable_offset) : 0;
1091};
1092
1093/**
1094 * Initialize any Table-derived type to point to the union at the given offset.
1095 *
1096 * @param {flatbuffers.Table} t
1097 * @param {number} offset
1098 * @returns {flatbuffers.Table}
1099 */
1100flatbuffers.ByteBuffer.prototype.__union = function(t, offset) {
1101  t.bb_pos = offset + this.readInt32(offset);
1102  t.bb = this;
1103  return t;
1104};
1105
1106/**
1107 * Create a JavaScript string from UTF-8 data stored inside the FlatBuffer.
1108 * This allocates a new string and converts to wide chars upon each access.
1109 *
1110 * To avoid the conversion to UTF-16, pass flatbuffers.Encoding.UTF8_BYTES as
1111 * the "optionalEncoding" argument. This is useful for avoiding conversion to
1112 * and from UTF-16 when the data will just be packaged back up in another
1113 * FlatBuffer later on.
1114 *
1115 * @param {number} offset
1116 * @param {flatbuffers.Encoding=} opt_encoding Defaults to UTF16_STRING
1117 * @returns {string|Uint8Array}
1118 */
1119flatbuffers.ByteBuffer.prototype.__string = function(offset, opt_encoding) {
1120  offset += this.readInt32(offset);
1121
1122  var length = this.readInt32(offset);
1123  var result = '';
1124  var i = 0;
1125
1126  offset += flatbuffers.SIZEOF_INT;
1127
1128  if (opt_encoding === flatbuffers.Encoding.UTF8_BYTES) {
1129    return this.bytes_.subarray(offset, offset + length);
1130  }
1131
1132  while (i < length) {
1133    var codePoint;
1134
1135    // Decode UTF-8
1136    var a = this.readUint8(offset + i++);
1137    if (a < 0xC0) {
1138      codePoint = a;
1139    } else {
1140      var b = this.readUint8(offset + i++);
1141      if (a < 0xE0) {
1142        codePoint =
1143          ((a & 0x1F) << 6) |
1144          (b & 0x3F);
1145      } else {
1146        var c = this.readUint8(offset + i++);
1147        if (a < 0xF0) {
1148          codePoint =
1149            ((a & 0x0F) << 12) |
1150            ((b & 0x3F) << 6) |
1151            (c & 0x3F);
1152        } else {
1153          var d = this.readUint8(offset + i++);
1154          codePoint =
1155            ((a & 0x07) << 18) |
1156            ((b & 0x3F) << 12) |
1157            ((c & 0x3F) << 6) |
1158            (d & 0x3F);
1159        }
1160      }
1161    }
1162
1163    // Encode UTF-16
1164    if (codePoint < 0x10000) {
1165      result += String.fromCharCode(codePoint);
1166    } else {
1167      codePoint -= 0x10000;
1168      result += String.fromCharCode(
1169        (codePoint >> 10) + 0xD800,
1170        (codePoint & ((1 << 10) - 1)) + 0xDC00);
1171    }
1172  }
1173
1174  return result;
1175};
1176
1177/**
1178 * Retrieve the relative offset stored at "offset"
1179 * @param {number} offset
1180 * @returns {number}
1181 */
1182flatbuffers.ByteBuffer.prototype.__indirect = function(offset) {
1183  return offset + this.readInt32(offset);
1184};
1185
1186/**
1187 * Get the start of data of a vector whose offset is stored at "offset" in this object.
1188 *
1189 * @param {number} offset
1190 * @returns {number}
1191 */
1192flatbuffers.ByteBuffer.prototype.__vector = function(offset) {
1193  return offset + this.readInt32(offset) + flatbuffers.SIZEOF_INT; // data starts after the length
1194};
1195
1196/**
1197 * Get the length of a vector whose offset is stored at "offset" in this object.
1198 *
1199 * @param {number} offset
1200 * @returns {number}
1201 */
1202flatbuffers.ByteBuffer.prototype.__vector_len = function(offset) {
1203  return this.readInt32(offset + this.readInt32(offset));
1204};
1205
1206/**
1207 * @param {string} ident
1208 * @returns {boolean}
1209 */
1210flatbuffers.ByteBuffer.prototype.__has_identifier = function(ident) {
1211  if (ident.length != flatbuffers.FILE_IDENTIFIER_LENGTH) {
1212    throw new Error('FlatBuffers: file identifier must be length ' +
1213                    flatbuffers.FILE_IDENTIFIER_LENGTH);
1214  }
1215  for (var i = 0; i < flatbuffers.FILE_IDENTIFIER_LENGTH; i++) {
1216    if (ident.charCodeAt(i) != this.readInt8(this.position_ + flatbuffers.SIZEOF_INT + i)) {
1217      return false;
1218    }
1219  }
1220  return true;
1221};
1222
1223/**
1224 * A helper function to avoid generated code depending on this file directly.
1225 *
1226 * @param {number} low
1227 * @param {number} high
1228 * @returns {flatbuffers.Long}
1229 */
1230flatbuffers.ByteBuffer.prototype.createLong = function(low, high) {
1231  return flatbuffers.Long.create(low, high);
1232};
1233
1234// Exports for Node.js and RequireJS
1235this.flatbuffers = flatbuffers;
1236
1237/// @endcond
1238/// @}
1239