252 lines
8.5 KiB
JavaScript
252 lines
8.5 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.ByteBuffer = void 0;
|
|
const constants_js_1 = require("./constants.js");
|
|
const utils_js_1 = require("./utils.js");
|
|
const encoding_js_1 = require("./encoding.js");
|
|
class ByteBuffer {
|
|
/**
|
|
* Create a new ByteBuffer with a given array of bytes (`Uint8Array`)
|
|
*/
|
|
constructor(bytes_) {
|
|
this.bytes_ = bytes_;
|
|
this.position_ = 0;
|
|
this.text_decoder_ = new TextDecoder();
|
|
}
|
|
/**
|
|
* Create and allocate a new ByteBuffer with a given size.
|
|
*/
|
|
static allocate(byte_size) {
|
|
return new ByteBuffer(new Uint8Array(byte_size));
|
|
}
|
|
clear() {
|
|
this.position_ = 0;
|
|
}
|
|
/**
|
|
* Get the underlying `Uint8Array`.
|
|
*/
|
|
bytes() {
|
|
return this.bytes_;
|
|
}
|
|
/**
|
|
* Get the buffer's position.
|
|
*/
|
|
position() {
|
|
return this.position_;
|
|
}
|
|
/**
|
|
* Set the buffer's position.
|
|
*/
|
|
setPosition(position) {
|
|
this.position_ = position;
|
|
}
|
|
/**
|
|
* Get the buffer's capacity.
|
|
*/
|
|
capacity() {
|
|
return this.bytes_.length;
|
|
}
|
|
readInt8(offset) {
|
|
return this.readUint8(offset) << 24 >> 24;
|
|
}
|
|
readUint8(offset) {
|
|
return this.bytes_[offset];
|
|
}
|
|
readInt16(offset) {
|
|
return this.readUint16(offset) << 16 >> 16;
|
|
}
|
|
readUint16(offset) {
|
|
return this.bytes_[offset] | this.bytes_[offset + 1] << 8;
|
|
}
|
|
readInt32(offset) {
|
|
return this.bytes_[offset] | this.bytes_[offset + 1] << 8 | this.bytes_[offset + 2] << 16 | this.bytes_[offset + 3] << 24;
|
|
}
|
|
readUint32(offset) {
|
|
return this.readInt32(offset) >>> 0;
|
|
}
|
|
readInt64(offset) {
|
|
return BigInt.asIntN(64, BigInt(this.readUint32(offset)) + (BigInt(this.readUint32(offset + 4)) << BigInt(32)));
|
|
}
|
|
readUint64(offset) {
|
|
return BigInt.asUintN(64, BigInt(this.readUint32(offset)) + (BigInt(this.readUint32(offset + 4)) << BigInt(32)));
|
|
}
|
|
readFloat32(offset) {
|
|
utils_js_1.int32[0] = this.readInt32(offset);
|
|
return utils_js_1.float32[0];
|
|
}
|
|
readFloat64(offset) {
|
|
utils_js_1.int32[utils_js_1.isLittleEndian ? 0 : 1] = this.readInt32(offset);
|
|
utils_js_1.int32[utils_js_1.isLittleEndian ? 1 : 0] = this.readInt32(offset + 4);
|
|
return utils_js_1.float64[0];
|
|
}
|
|
writeInt8(offset, value) {
|
|
this.bytes_[offset] = value;
|
|
}
|
|
writeUint8(offset, value) {
|
|
this.bytes_[offset] = value;
|
|
}
|
|
writeInt16(offset, value) {
|
|
this.bytes_[offset] = value;
|
|
this.bytes_[offset + 1] = value >> 8;
|
|
}
|
|
writeUint16(offset, value) {
|
|
this.bytes_[offset] = value;
|
|
this.bytes_[offset + 1] = value >> 8;
|
|
}
|
|
writeInt32(offset, value) {
|
|
this.bytes_[offset] = value;
|
|
this.bytes_[offset + 1] = value >> 8;
|
|
this.bytes_[offset + 2] = value >> 16;
|
|
this.bytes_[offset + 3] = value >> 24;
|
|
}
|
|
writeUint32(offset, value) {
|
|
this.bytes_[offset] = value;
|
|
this.bytes_[offset + 1] = value >> 8;
|
|
this.bytes_[offset + 2] = value >> 16;
|
|
this.bytes_[offset + 3] = value >> 24;
|
|
}
|
|
writeInt64(offset, value) {
|
|
this.writeInt32(offset, Number(BigInt.asIntN(32, value)));
|
|
this.writeInt32(offset + 4, Number(BigInt.asIntN(32, value >> BigInt(32))));
|
|
}
|
|
writeUint64(offset, value) {
|
|
this.writeUint32(offset, Number(BigInt.asUintN(32, value)));
|
|
this.writeUint32(offset + 4, Number(BigInt.asUintN(32, value >> BigInt(32))));
|
|
}
|
|
writeFloat32(offset, value) {
|
|
utils_js_1.float32[0] = value;
|
|
this.writeInt32(offset, utils_js_1.int32[0]);
|
|
}
|
|
writeFloat64(offset, value) {
|
|
utils_js_1.float64[0] = value;
|
|
this.writeInt32(offset, utils_js_1.int32[utils_js_1.isLittleEndian ? 0 : 1]);
|
|
this.writeInt32(offset + 4, utils_js_1.int32[utils_js_1.isLittleEndian ? 1 : 0]);
|
|
}
|
|
/**
|
|
* Return the file identifier. Behavior is undefined for FlatBuffers whose
|
|
* schema does not include a file_identifier (likely points at padding or the
|
|
* start of a the root vtable).
|
|
*/
|
|
getBufferIdentifier() {
|
|
if (this.bytes_.length < this.position_ + constants_js_1.SIZEOF_INT +
|
|
constants_js_1.FILE_IDENTIFIER_LENGTH) {
|
|
throw new Error('FlatBuffers: ByteBuffer is too short to contain an identifier.');
|
|
}
|
|
let result = "";
|
|
for (let i = 0; i < constants_js_1.FILE_IDENTIFIER_LENGTH; i++) {
|
|
result += String.fromCharCode(this.readInt8(this.position_ + constants_js_1.SIZEOF_INT + i));
|
|
}
|
|
return result;
|
|
}
|
|
/**
|
|
* Look up a field in the vtable, return an offset into the object, or 0 if the
|
|
* field is not present.
|
|
*/
|
|
__offset(bb_pos, vtable_offset) {
|
|
const vtable = bb_pos - this.readInt32(bb_pos);
|
|
return vtable_offset < this.readInt16(vtable) ? this.readInt16(vtable + vtable_offset) : 0;
|
|
}
|
|
/**
|
|
* Initialize any Table-derived type to point to the union at the given offset.
|
|
*/
|
|
__union(t, offset) {
|
|
t.bb_pos = offset + this.readInt32(offset);
|
|
t.bb = this;
|
|
return t;
|
|
}
|
|
/**
|
|
* Create a JavaScript string from UTF-8 data stored inside the FlatBuffer.
|
|
* This allocates a new string and converts to wide chars upon each access.
|
|
*
|
|
* To avoid the conversion to string, pass Encoding.UTF8_BYTES as the
|
|
* "optionalEncoding" argument. This is useful for avoiding conversion when
|
|
* the data will just be packaged back up in another FlatBuffer later on.
|
|
*
|
|
* @param offset
|
|
* @param opt_encoding Defaults to UTF16_STRING
|
|
*/
|
|
__string(offset, opt_encoding) {
|
|
offset += this.readInt32(offset);
|
|
const length = this.readInt32(offset);
|
|
offset += constants_js_1.SIZEOF_INT;
|
|
const utf8bytes = this.bytes_.subarray(offset, offset + length);
|
|
if (opt_encoding === encoding_js_1.Encoding.UTF8_BYTES)
|
|
return utf8bytes;
|
|
else
|
|
return this.text_decoder_.decode(utf8bytes);
|
|
}
|
|
/**
|
|
* Handle unions that can contain string as its member, if a Table-derived type then initialize it,
|
|
* if a string then return a new one
|
|
*
|
|
* WARNING: strings are immutable in JS so we can't change the string that the user gave us, this
|
|
* makes the behaviour of __union_with_string different compared to __union
|
|
*/
|
|
__union_with_string(o, offset) {
|
|
if (typeof o === 'string') {
|
|
return this.__string(offset);
|
|
}
|
|
return this.__union(o, offset);
|
|
}
|
|
/**
|
|
* Retrieve the relative offset stored at "offset"
|
|
*/
|
|
__indirect(offset) {
|
|
return offset + this.readInt32(offset);
|
|
}
|
|
/**
|
|
* Get the start of data of a vector whose offset is stored at "offset" in this object.
|
|
*/
|
|
__vector(offset) {
|
|
return offset + this.readInt32(offset) + constants_js_1.SIZEOF_INT; // data starts after the length
|
|
}
|
|
/**
|
|
* Get the length of a vector whose offset is stored at "offset" in this object.
|
|
*/
|
|
__vector_len(offset) {
|
|
return this.readInt32(offset + this.readInt32(offset));
|
|
}
|
|
__has_identifier(ident) {
|
|
if (ident.length != constants_js_1.FILE_IDENTIFIER_LENGTH) {
|
|
throw new Error('FlatBuffers: file identifier must be length ' +
|
|
constants_js_1.FILE_IDENTIFIER_LENGTH);
|
|
}
|
|
for (let i = 0; i < constants_js_1.FILE_IDENTIFIER_LENGTH; i++) {
|
|
if (ident.charCodeAt(i) != this.readInt8(this.position() + constants_js_1.SIZEOF_INT + i)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
/**
|
|
* A helper function for generating list for obj api
|
|
*/
|
|
createScalarList(listAccessor, listLength) {
|
|
const ret = [];
|
|
for (let i = 0; i < listLength; ++i) {
|
|
const val = listAccessor(i);
|
|
if (val !== null) {
|
|
ret.push(val);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
/**
|
|
* A helper function for generating list for obj api
|
|
* @param listAccessor function that accepts an index and return data at that index
|
|
* @param listLength listLength
|
|
* @param res result list
|
|
*/
|
|
createObjList(listAccessor, listLength) {
|
|
const ret = [];
|
|
for (let i = 0; i < listLength; ++i) {
|
|
const val = listAccessor(i);
|
|
if (val !== null) {
|
|
ret.push(val.unpack());
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
}
|
|
exports.ByteBuffer = ByteBuffer;
|