flatbuffers/ts/byte-buffer.ts

337 lines
9.9 KiB
TypeScript
Raw Normal View History

import { FILE_IDENTIFIER_LENGTH, SIZEOF_INT } from "./constants";
import { int32, isLittleEndian, float32, float64 } from "./utils";
import { Offset, Table, IGeneratedObject } from "./types";
import { Encoding } from "./encoding";
export class ByteBuffer {
private position_ = 0;
/**
* Create a new ByteBuffer with a given array of bytes (`Uint8Array`)
*/
constructor(private bytes_: Uint8Array) { }
/**
* Create and allocate a new ByteBuffer with a given size.
*/
static allocate(byte_size: number): ByteBuffer {
return new ByteBuffer(new Uint8Array(byte_size));
}
clear(): void {
this.position_ = 0;
}
/**
* Get the underlying `Uint8Array`.
*/
bytes(): Uint8Array {
return this.bytes_;
}
/**
* Get the buffer's position.
*/
position(): number {
return this.position_;
}
/**
* Set the buffer's position.
*/
setPosition(position: number): void {
this.position_ = position;
}
/**
* Get the buffer's capacity.
*/
capacity(): number {
return this.bytes_.length;
}
readInt8(offset: number): number {
return this.readUint8(offset) << 24 >> 24;
}
readUint8(offset: number): number {
return this.bytes_[offset];
}
readInt16(offset: number): number {
return this.readUint16(offset) << 16 >> 16;
}
readUint16(offset: number): number {
return this.bytes_[offset] | this.bytes_[offset + 1] << 8;
}
readInt32(offset: number): number {
return this.bytes_[offset] | this.bytes_[offset + 1] << 8 | this.bytes_[offset + 2] << 16 | this.bytes_[offset + 3] << 24;
}
readUint32(offset: number): number {
return this.readInt32(offset) >>> 0;
}
readInt64(offset: number): bigint {
return BigInt.asIntN(64, BigInt(this.readUint32(offset)) + (BigInt(this.readUint32(offset + 4)) << BigInt(32)));
}
readUint64(offset: number): bigint {
return BigInt.asUintN(64, BigInt(this.readUint32(offset)) + (BigInt(this.readUint32(offset + 4)) << BigInt(32)));
}
readFloat32(offset: number): number {
int32[0] = this.readInt32(offset);
return float32[0];
}
readFloat64(offset: number): number {
int32[isLittleEndian ? 0 : 1] = this.readInt32(offset);
int32[isLittleEndian ? 1 : 0] = this.readInt32(offset + 4);
return float64[0];
}
writeInt8(offset: number, value: number): void {
this.bytes_[offset] = value;
}
writeUint8(offset: number, value: number): void {
this.bytes_[offset] = value;
}
writeInt16(offset: number, value: number): void {
this.bytes_[offset] = value;
this.bytes_[offset + 1] = value >> 8;
}
writeUint16(offset: number, value: number): void {
this.bytes_[offset] = value;
this.bytes_[offset + 1] = value >> 8;
}
writeInt32(offset: number, value: number): void {
this.bytes_[offset] = value;
this.bytes_[offset + 1] = value >> 8;
this.bytes_[offset + 2] = value >> 16;
this.bytes_[offset + 3] = value >> 24;
}
writeUint32(offset: number, value: number): void {
this.bytes_[offset] = value;
this.bytes_[offset + 1] = value >> 8;
this.bytes_[offset + 2] = value >> 16;
this.bytes_[offset + 3] = value >> 24;
}
writeInt64(offset: number, value: bigint): void {
this.writeInt32(offset, Number(BigInt.asIntN(32, value)));
this.writeInt32(offset + 4, Number(BigInt.asIntN(32, value >> BigInt(32))));
}
writeUint64(offset: number, value: bigint): void {
this.writeUint32(offset, Number(BigInt.asUintN(32, value)));
this.writeUint32(offset + 4, Number(BigInt.asUintN(32, value >> BigInt(32))));
}
writeFloat32(offset: number, value: number): void {
float32[0] = value;
this.writeInt32(offset, int32[0]);
}
writeFloat64(offset: number, value: number): void {
float64[0] = value;
this.writeInt32(offset, int32[isLittleEndian ? 0 : 1]);
this.writeInt32(offset + 4, int32[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(): string {
if (this.bytes_.length < this.position_ + SIZEOF_INT +
FILE_IDENTIFIER_LENGTH) {
throw new Error(
'FlatBuffers: ByteBuffer is too short to contain an identifier.');
}
let result = "";
for (let i = 0; i < FILE_IDENTIFIER_LENGTH; i++) {
result += String.fromCharCode(
this.readInt8(this.position_ + 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: number, vtable_offset: number): 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: Table, offset: number): Table {
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 UTF-16, pass Encoding.UTF8_BYTES as
* the "optionalEncoding" argument. This is useful for avoiding conversion to
* and from UTF-16 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: number, opt_encoding?: Encoding): string | Uint8Array {
offset += this.readInt32(offset);
const length = this.readInt32(offset);
let result = '';
let i = 0;
offset += SIZEOF_INT;
if (opt_encoding === Encoding.UTF8_BYTES) {
return this.bytes_.subarray(offset, offset + length);
}
while (i < length) {
let codePoint;
// Decode UTF-8
const a = this.readUint8(offset + i++);
if (a < 0xC0) {
codePoint = a;
} else {
const b = this.readUint8(offset + i++);
if (a < 0xE0) {
codePoint =
((a & 0x1F) << 6) |
(b & 0x3F);
} else {
const c = this.readUint8(offset + i++);
if (a < 0xF0) {
codePoint =
((a & 0x0F) << 12) |
((b & 0x3F) << 6) |
(c & 0x3F);
} else {
const d = this.readUint8(offset + i++);
codePoint =
((a & 0x07) << 18) |
((b & 0x3F) << 12) |
((c & 0x3F) << 6) |
(d & 0x3F);
}
}
}
// Encode UTF-16
if (codePoint < 0x10000) {
result += String.fromCharCode(codePoint);
} else {
codePoint -= 0x10000;
result += String.fromCharCode(
(codePoint >> 10) + 0xD800,
(codePoint & ((1 << 10) - 1)) + 0xDC00);
}
}
return result;
}
/**
* 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: Table | string, offset: number) : Table | string {
if(typeof o === 'string') {
return this.__string(offset) as string;
}
return this.__union(o, offset);
}
/**
* Retrieve the relative offset stored at "offset"
*/
__indirect(offset: Offset): 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: Offset): Offset {
return offset + this.readInt32(offset) + 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: Offset): Offset {
return this.readInt32(offset + this.readInt32(offset));
}
__has_identifier(ident: string): boolean {
if (ident.length != FILE_IDENTIFIER_LENGTH) {
throw new Error('FlatBuffers: file identifier must be length ' +
FILE_IDENTIFIER_LENGTH);
}
for (let i = 0; i < FILE_IDENTIFIER_LENGTH; i++) {
if (ident.charCodeAt(i) != this.readInt8(this.position() + SIZEOF_INT + i)) {
return false;
}
}
return true;
}
/**
* A helper function for generating list for obj api
*/
[TS/JS] New gen TS code gen (#6302) * TS/ES6 modules spike iteration 1 * Initial modularized dasherized output * Remove obsoleted parts and namespace wrapping * Use _flatbuffers_ prefix * First part of imports logic * Second part of imports logic * Fix TS/JS code removal mixup * Alias imported symbols if same name from different namespaces and some fixes * Use star import for bare imports * Fix messed up string concat * var to const and remove not needed semi * Remove some cases of ns prefixing * Add missing space * Cleanups * Completed initial import tracking logic * Compilable output * Adjust TypeScriptTest and dependents to work * Use local flatbuffers package for tests * Refactor away use of any * Remove obsolete imported_fileset and reexport_map * Still need any and fix JavaScriptTest.sh * Fix test runs out of the box * Temp add generated files * TypeScriptTest replaces JavaScriptTest and cleanups * Also remove reference to JavaScriptTest in TestAll.sh * Remove old generated ts/js files * Remove use of --js in generate_code scripts * idl_gen_js_ts to idl_gen_ts and removal of js gen * Remove obsoleted options * Fix obsolete ts test detection * Tweak ts compilation be as strict as possible * Remove jsdoc type annotation generation * Generated test ts files * Fix search and replace messup * Regenerated ts test output * Use CharToLower * Use normal for loop * Rework namespacedir * Revert "Rework namespacedir" This reverts commit 6f4eb0104ceeb86011bb076ebca901138c48e068. * Revert "Use normal for loop" This reverts commit 676b2135bfaa1853dfbb06c92b5c16a0d81bb13a. * Revert "Use CharToLower" This reverts commit 2d08648d0d72d0af201fad80d54cdc76412b35e9. * Again do rework but correct * Avoid runtime cast * Fix test runs * Also add npm install to get tsc * Bump node test versions * for range to std for loop * Clang format * Missed one clang format * Move accessor to later * Attempt to make windows version of TypeScriptTest * Want to see the output * Try to get newer node at appveyor * Style changes
2021-01-19 20:51:13 +00:00
createScalarList(listAccessor: (i: number) => unknown, listLength: number): any[] {
const ret: any[] = [];
for(let i = 0; i < listLength; ++i) {
if(listAccessor(i) !== null) {
ret.push(listAccessor(i));
}
}
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
*/
[TS/JS] New gen TS code gen (#6302) * TS/ES6 modules spike iteration 1 * Initial modularized dasherized output * Remove obsoleted parts and namespace wrapping * Use _flatbuffers_ prefix * First part of imports logic * Second part of imports logic * Fix TS/JS code removal mixup * Alias imported symbols if same name from different namespaces and some fixes * Use star import for bare imports * Fix messed up string concat * var to const and remove not needed semi * Remove some cases of ns prefixing * Add missing space * Cleanups * Completed initial import tracking logic * Compilable output * Adjust TypeScriptTest and dependents to work * Use local flatbuffers package for tests * Refactor away use of any * Remove obsolete imported_fileset and reexport_map * Still need any and fix JavaScriptTest.sh * Fix test runs out of the box * Temp add generated files * TypeScriptTest replaces JavaScriptTest and cleanups * Also remove reference to JavaScriptTest in TestAll.sh * Remove old generated ts/js files * Remove use of --js in generate_code scripts * idl_gen_js_ts to idl_gen_ts and removal of js gen * Remove obsoleted options * Fix obsolete ts test detection * Tweak ts compilation be as strict as possible * Remove jsdoc type annotation generation * Generated test ts files * Fix search and replace messup * Regenerated ts test output * Use CharToLower * Use normal for loop * Rework namespacedir * Revert "Rework namespacedir" This reverts commit 6f4eb0104ceeb86011bb076ebca901138c48e068. * Revert "Use normal for loop" This reverts commit 676b2135bfaa1853dfbb06c92b5c16a0d81bb13a. * Revert "Use CharToLower" This reverts commit 2d08648d0d72d0af201fad80d54cdc76412b35e9. * Again do rework but correct * Avoid runtime cast * Fix test runs * Also add npm install to get tsc * Bump node test versions * for range to std for loop * Clang format * Missed one clang format * Move accessor to later * Attempt to make windows version of TypeScriptTest * Want to see the output * Try to get newer node at appveyor * Style changes
2021-01-19 20:51:13 +00:00
createObjList(listAccessor: (i: number) => unknown, listLength: number): any[] {
const ret: any[] = [];
for(let i = 0; i < listLength; ++i) {
const val = listAccessor(i);
if(val !== null) {
[TS/JS] New gen TS code gen (#6302) * TS/ES6 modules spike iteration 1 * Initial modularized dasherized output * Remove obsoleted parts and namespace wrapping * Use _flatbuffers_ prefix * First part of imports logic * Second part of imports logic * Fix TS/JS code removal mixup * Alias imported symbols if same name from different namespaces and some fixes * Use star import for bare imports * Fix messed up string concat * var to const and remove not needed semi * Remove some cases of ns prefixing * Add missing space * Cleanups * Completed initial import tracking logic * Compilable output * Adjust TypeScriptTest and dependents to work * Use local flatbuffers package for tests * Refactor away use of any * Remove obsolete imported_fileset and reexport_map * Still need any and fix JavaScriptTest.sh * Fix test runs out of the box * Temp add generated files * TypeScriptTest replaces JavaScriptTest and cleanups * Also remove reference to JavaScriptTest in TestAll.sh * Remove old generated ts/js files * Remove use of --js in generate_code scripts * idl_gen_js_ts to idl_gen_ts and removal of js gen * Remove obsoleted options * Fix obsolete ts test detection * Tweak ts compilation be as strict as possible * Remove jsdoc type annotation generation * Generated test ts files * Fix search and replace messup * Regenerated ts test output * Use CharToLower * Use normal for loop * Rework namespacedir * Revert "Rework namespacedir" This reverts commit 6f4eb0104ceeb86011bb076ebca901138c48e068. * Revert "Use normal for loop" This reverts commit 676b2135bfaa1853dfbb06c92b5c16a0d81bb13a. * Revert "Use CharToLower" This reverts commit 2d08648d0d72d0af201fad80d54cdc76412b35e9. * Again do rework but correct * Avoid runtime cast * Fix test runs * Also add npm install to get tsc * Bump node test versions * for range to std for loop * Clang format * Missed one clang format * Move accessor to later * Attempt to make windows version of TypeScriptTest * Want to see the output * Try to get newer node at appveyor * Style changes
2021-01-19 20:51:13 +00:00
ret.push((val as IGeneratedObject).unpack());
}
}
return ret;
}
}