mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-12 07:50:59 +00:00
bulk code format fix (#8707)
This commit is contained in:
1245
ts/builder.ts
1245
ts/builder.ts
File diff suppressed because it is too large
Load Diff
@@ -1,287 +1,316 @@
|
||||
import { FILE_IDENTIFIER_LENGTH, SIZEOF_INT } from "./constants.js";
|
||||
import { int32, isLittleEndian, float32, float64 } from "./utils.js";
|
||||
import { Offset, Table, IGeneratedObject, IUnpackableObject } from "./types.js";
|
||||
import { Encoding } from "./encoding.js";
|
||||
import {FILE_IDENTIFIER_LENGTH, SIZEOF_INT} from './constants.js';
|
||||
import {Encoding} from './encoding.js';
|
||||
import {IGeneratedObject, IUnpackableObject, Offset, Table} from './types.js';
|
||||
import {float32, float64, int32, isLittleEndian} from './utils.js';
|
||||
|
||||
export class ByteBuffer {
|
||||
private position_ = 0;
|
||||
private text_decoder_ = new TextDecoder();
|
||||
|
||||
/**
|
||||
* 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 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: number, opt_encoding?: Encoding): string | Uint8Array {
|
||||
offset += this.readInt32(offset);
|
||||
const length = this.readInt32(offset);
|
||||
offset += SIZEOF_INT;
|
||||
const utf8bytes = this.bytes_.subarray(offset, offset + length);
|
||||
if (opt_encoding === 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: 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;
|
||||
}
|
||||
private position_ = 0;
|
||||
private text_decoder_ = new TextDecoder();
|
||||
|
||||
/**
|
||||
* A helper function for generating list for obj api
|
||||
*/
|
||||
createScalarList<T>(listAccessor: (i: number) => T | null, listLength: number): T[] {
|
||||
const ret: T[] = [];
|
||||
for(let i = 0; i < listLength; ++i) {
|
||||
const val = listAccessor(i);
|
||||
if(val !== null) {
|
||||
ret.push(val);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* Create a new ByteBuffer with a given array of bytes (`Uint8Array`)
|
||||
*/
|
||||
constructor(private bytes_: Uint8Array) {}
|
||||
|
||||
/**
|
||||
* 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<T1 extends IUnpackableObject<T2>, T2 extends IGeneratedObject>(listAccessor: (i: number) => T1 | null, listLength: number): T2[] {
|
||||
const ret: T2[] = [];
|
||||
for(let i = 0; i < listLength; ++i) {
|
||||
const val = listAccessor(i);
|
||||
if(val !== null) {
|
||||
ret.push(val.unpack());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* 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 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: number, opt_encoding?: Encoding): string | Uint8Array {
|
||||
offset += this.readInt32(offset);
|
||||
const length = this.readInt32(offset);
|
||||
offset += SIZEOF_INT;
|
||||
const utf8bytes = this.bytes_.subarray(offset, offset + length);
|
||||
if (opt_encoding === 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: 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
|
||||
*/
|
||||
createScalarList<T>(
|
||||
listAccessor: (i: number) => T | null,
|
||||
listLength: number,
|
||||
): T[] {
|
||||
const ret: T[] = [];
|
||||
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<T1 extends IUnpackableObject<T2>, T2 extends IGeneratedObject>(
|
||||
listAccessor: (i: number) => T1 | null,
|
||||
listLength: number,
|
||||
): T2[] {
|
||||
const ret: T2[] = [];
|
||||
for (let i = 0; i < listLength; ++i) {
|
||||
const val = listAccessor(i);
|
||||
if (val !== null) {
|
||||
ret.push(val.unpack());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export const SIZEOF_SHORT = 2;
|
||||
export const SIZEOF_INT = 4;
|
||||
export const FILE_IDENTIFIER_LENGTH = 4;
|
||||
export const SIZE_PREFIX_LENGTH = 4;
|
||||
export const SIZE_PREFIX_LENGTH = 4;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export enum Encoding {
|
||||
UTF8_BYTES = 1,
|
||||
UTF16_STRING = 2
|
||||
}
|
||||
UTF8_BYTES = 1,
|
||||
UTF16_STRING = 2,
|
||||
}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
export { SIZEOF_SHORT } from './constants.js'
|
||||
export { SIZEOF_INT } from './constants.js'
|
||||
export { FILE_IDENTIFIER_LENGTH } from './constants.js'
|
||||
export { SIZE_PREFIX_LENGTH } from './constants.js'
|
||||
export {
|
||||
FILE_IDENTIFIER_LENGTH,
|
||||
SIZEOF_INT,
|
||||
SIZEOF_SHORT,
|
||||
SIZE_PREFIX_LENGTH,
|
||||
} from './constants.js';
|
||||
|
||||
export { Table, Offset, IGeneratedObject, IUnpackableObject } from './types.js'
|
||||
export {IGeneratedObject, IUnpackableObject, Offset, Table} from './types.js';
|
||||
|
||||
export { int32, float32, float64, isLittleEndian } from './utils.js'
|
||||
export {float32, float64, int32, isLittleEndian} from './utils.js';
|
||||
|
||||
export { Encoding } from './encoding.js'
|
||||
export { Builder } from './builder.js'
|
||||
export { ByteBuffer } from './byte-buffer.js'
|
||||
export {Builder} from './builder.js';
|
||||
export {ByteBuffer} from './byte-buffer.js';
|
||||
export {Encoding} from './encoding.js';
|
||||
|
||||
@@ -1,18 +1,29 @@
|
||||
/* eslint-disable @typescript-eslint/no-namespace */
|
||||
import { Builder } from './flexbuffers/builder.js'
|
||||
import { toReference } from './flexbuffers/reference.js'
|
||||
export { toReference } from './flexbuffers/reference.js'
|
||||
import {Builder} from './flexbuffers/builder.js';
|
||||
import {toReference} from './flexbuffers/reference.js';
|
||||
export {toReference} from './flexbuffers/reference.js';
|
||||
|
||||
export function builder(): Builder {
|
||||
return new Builder();
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
export function toObject(buffer: ArrayBuffer): unknown {
|
||||
return toReference(buffer).toObject();
|
||||
return toReference(buffer).toObject();
|
||||
}
|
||||
|
||||
export function encode(object: unknown, size = 2048, deduplicateStrings = true, deduplicateKeys = true, deduplicateKeyVectors = true): Uint8Array {
|
||||
const builder = new Builder(size > 0 ? size : 2048, deduplicateStrings, deduplicateKeys, deduplicateKeyVectors);
|
||||
builder.add(object);
|
||||
return builder.finish();
|
||||
export function encode(
|
||||
object: unknown,
|
||||
size = 2048,
|
||||
deduplicateStrings = true,
|
||||
deduplicateKeys = true,
|
||||
deduplicateKeyVectors = true,
|
||||
): Uint8Array {
|
||||
const builder = new Builder(
|
||||
size > 0 ? size : 2048,
|
||||
deduplicateStrings,
|
||||
deduplicateKeys,
|
||||
deduplicateKeyVectors,
|
||||
);
|
||||
builder.add(object);
|
||||
return builder.finish();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { BitWidth } from './bit-width.js'
|
||||
import {BitWidth} from './bit-width.js';
|
||||
|
||||
export function toByteWidth(bitWidth: BitWidth): number {
|
||||
return 1 << bitWidth;
|
||||
@@ -31,4 +31,4 @@ export function fromByteWidth(value: number): BitWidth {
|
||||
|
||||
export function paddingSize(bufSize: number, scalarSize: number): number {
|
||||
return (~bufSize + 1) & (scalarSize - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,4 +3,4 @@ export enum BitWidth {
|
||||
WIDTH16 = 1,
|
||||
WIDTH32 = 2,
|
||||
WIDTH64 = 3,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,30 @@
|
||||
import { BitWidth } from './bit-width.js'
|
||||
import { paddingSize, iwidth, uwidth, fwidth, toByteWidth, fromByteWidth } from './bit-width-util.js'
|
||||
import { toUTF8Array } from './flexbuffers-util.js'
|
||||
import { ValueType } from './value-type.js'
|
||||
import { isNumber, isTypedVectorElement, toTypedVector } from './value-type-util.js'
|
||||
import { StackValue } from './stack-value.js'
|
||||
import {
|
||||
fromByteWidth,
|
||||
fwidth,
|
||||
iwidth,
|
||||
paddingSize,
|
||||
toByteWidth,
|
||||
uwidth,
|
||||
} from './bit-width-util.js';
|
||||
import {BitWidth} from './bit-width.js';
|
||||
import {toUTF8Array} from './flexbuffers-util.js';
|
||||
import {StackValue} from './stack-value.js';
|
||||
import {
|
||||
isNumber,
|
||||
isTypedVectorElement,
|
||||
toTypedVector,
|
||||
} from './value-type-util.js';
|
||||
import {ValueType} from './value-type.js';
|
||||
|
||||
interface StackPointer {
|
||||
stackPosition: number,
|
||||
isVector: boolean
|
||||
presorted?: boolean
|
||||
stackPosition: number;
|
||||
isVector: boolean;
|
||||
presorted?: boolean;
|
||||
}
|
||||
|
||||
export class Builder {
|
||||
buffer: ArrayBuffer
|
||||
view: DataView
|
||||
buffer: ArrayBuffer;
|
||||
view: DataView;
|
||||
|
||||
readonly stack: Array<StackValue> = [];
|
||||
readonly stackPointers: Array<StackPointer> = [];
|
||||
@@ -26,7 +37,12 @@ export class Builder {
|
||||
readonly indirectUIntLookup: Record<number, StackValue> = {};
|
||||
readonly indirectFloatLookup: Record<number, StackValue> = {};
|
||||
|
||||
constructor(size = 2048, private dedupStrings = true, private dedupKeys = true, private dedupKeyVectors = true) {
|
||||
constructor(
|
||||
size = 2048,
|
||||
private dedupStrings = true,
|
||||
private dedupKeys = true,
|
||||
private dedupKeyVectors = true,
|
||||
) {
|
||||
this.buffer = new ArrayBuffer(size > 0 ? size : 2048);
|
||||
this.view = new DataView(this.buffer);
|
||||
}
|
||||
@@ -101,12 +117,17 @@ export class Builder {
|
||||
const blobOffset = this.offset;
|
||||
const newOffset = this.computeOffset(length);
|
||||
new Uint8Array(this.buffer).set(new Uint8Array(arrayBuffer), blobOffset);
|
||||
this.stack.push(this.offsetStackValue(blobOffset, ValueType.BLOB, bitWidth));
|
||||
this.stack.push(
|
||||
this.offsetStackValue(blobOffset, ValueType.BLOB, bitWidth),
|
||||
);
|
||||
this.offset = newOffset;
|
||||
}
|
||||
|
||||
private writeString(str: string): void {
|
||||
if (this.dedupStrings && Object.prototype.hasOwnProperty.call(this.stringLookup, str)) {
|
||||
if (
|
||||
this.dedupStrings &&
|
||||
Object.prototype.hasOwnProperty.call(this.stringLookup, str)
|
||||
) {
|
||||
this.stack.push(this.stringLookup[str]);
|
||||
return;
|
||||
}
|
||||
@@ -118,7 +139,11 @@ export class Builder {
|
||||
const stringOffset = this.offset;
|
||||
const newOffset = this.computeOffset(length + 1);
|
||||
new Uint8Array(this.buffer).set(utf8, stringOffset);
|
||||
const stackValue = this.offsetStackValue(stringOffset, ValueType.STRING, bitWidth);
|
||||
const stackValue = this.offsetStackValue(
|
||||
stringOffset,
|
||||
ValueType.STRING,
|
||||
bitWidth,
|
||||
);
|
||||
this.stack.push(stackValue);
|
||||
if (this.dedupStrings) {
|
||||
this.stringLookup[str] = stackValue;
|
||||
@@ -127,7 +152,10 @@ export class Builder {
|
||||
}
|
||||
|
||||
private writeKey(str: string): void {
|
||||
if (this.dedupKeys && Object.prototype.hasOwnProperty.call(this.keyLookup, str)) {
|
||||
if (
|
||||
this.dedupKeys &&
|
||||
Object.prototype.hasOwnProperty.call(this.keyLookup, str)
|
||||
) {
|
||||
this.stack.push(this.keyLookup[str]);
|
||||
return;
|
||||
}
|
||||
@@ -135,7 +163,11 @@ export class Builder {
|
||||
const length = utf8.length;
|
||||
const newOffset = this.computeOffset(length + 1);
|
||||
new Uint8Array(this.buffer).set(utf8, this.offset);
|
||||
const stackValue = this.offsetStackValue(this.offset, ValueType.KEY, BitWidth.WIDTH8);
|
||||
const stackValue = this.offsetStackValue(
|
||||
this.offset,
|
||||
ValueType.KEY,
|
||||
BitWidth.WIDTH8,
|
||||
);
|
||||
this.stack.push(stackValue);
|
||||
if (this.dedupKeys) {
|
||||
this.keyLookup[str] = stackValue;
|
||||
@@ -147,10 +179,13 @@ export class Builder {
|
||||
const newOffset = this.computeOffset(byteWidth);
|
||||
if (value.isOffset()) {
|
||||
const relativeOffset = this.offset - value.offset;
|
||||
if (byteWidth === 8 || BigInt(relativeOffset) < (BigInt(1) << BigInt(byteWidth * 8))) {
|
||||
if (
|
||||
byteWidth === 8 ||
|
||||
BigInt(relativeOffset) < BigInt(1) << BigInt(byteWidth * 8)
|
||||
) {
|
||||
this.writeUInt(relativeOffset, byteWidth);
|
||||
} else {
|
||||
throw `Unexpected size ${byteWidth}. This might be a bug. Please create an issue https://github.com/google/flatbuffers/issues/new`
|
||||
throw `Unexpected size ${byteWidth}. This might be a bug. Please create an issue https://github.com/google/flatbuffers/issues/new`;
|
||||
}
|
||||
} else {
|
||||
value.writeToBuffer(byteWidth);
|
||||
@@ -160,30 +195,40 @@ export class Builder {
|
||||
|
||||
private integrityCheckOnValueAddition() {
|
||||
if (this.finished) {
|
||||
throw "Adding values after finish is prohibited";
|
||||
throw 'Adding values after finish is prohibited';
|
||||
}
|
||||
if (this.stackPointers.length !== 0 && this.stackPointers[this.stackPointers.length - 1].isVector === false) {
|
||||
if (
|
||||
this.stackPointers.length !== 0 &&
|
||||
this.stackPointers[this.stackPointers.length - 1].isVector === false
|
||||
) {
|
||||
if (this.stack[this.stack.length - 1].type !== ValueType.KEY) {
|
||||
throw "Adding value to a map before adding a key is prohibited";
|
||||
throw 'Adding value to a map before adding a key is prohibited';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private integrityCheckOnKeyAddition() {
|
||||
if (this.finished) {
|
||||
throw "Adding values after finish is prohibited";
|
||||
throw 'Adding values after finish is prohibited';
|
||||
}
|
||||
if (this.stackPointers.length === 0 || this.stackPointers[this.stackPointers.length - 1].isVector) {
|
||||
throw "Adding key before starting a map is prohibited";
|
||||
if (
|
||||
this.stackPointers.length === 0 ||
|
||||
this.stackPointers[this.stackPointers.length - 1].isVector
|
||||
) {
|
||||
throw 'Adding key before starting a map is prohibited';
|
||||
}
|
||||
}
|
||||
|
||||
startVector(): void {
|
||||
this.stackPointers.push({ stackPosition: this.stack.length, isVector: true });
|
||||
this.stackPointers.push({stackPosition: this.stack.length, isVector: true});
|
||||
}
|
||||
|
||||
startMap(presorted = false): void {
|
||||
this.stackPointers.push({ stackPosition: this.stack.length, isVector: false, presorted: presorted });
|
||||
this.stackPointers.push({
|
||||
stackPosition: this.stack.length,
|
||||
isVector: false,
|
||||
presorted: presorted,
|
||||
});
|
||||
}
|
||||
|
||||
private endVector(stackPointer: StackPointer) {
|
||||
@@ -197,28 +242,42 @@ export class Builder {
|
||||
if (!stackPointer.presorted) {
|
||||
this.sort(stackPointer);
|
||||
}
|
||||
let keyVectorHash = "";
|
||||
let keyVectorHash = '';
|
||||
for (let i = stackPointer.stackPosition; i < this.stack.length; i += 2) {
|
||||
keyVectorHash += `,${this.stack[i].offset}`;
|
||||
}
|
||||
const vecLength = (this.stack.length - stackPointer.stackPosition) >> 1;
|
||||
|
||||
if (this.dedupKeyVectors && !Object.prototype.hasOwnProperty.call(this.keyVectorLookup, keyVectorHash)) {
|
||||
this.keyVectorLookup[keyVectorHash] = this.createVector(stackPointer.stackPosition, vecLength, 2);
|
||||
if (
|
||||
this.dedupKeyVectors &&
|
||||
!Object.prototype.hasOwnProperty.call(this.keyVectorLookup, keyVectorHash)
|
||||
) {
|
||||
this.keyVectorLookup[keyVectorHash] = this.createVector(
|
||||
stackPointer.stackPosition,
|
||||
vecLength,
|
||||
2,
|
||||
);
|
||||
}
|
||||
const keysStackValue = this.dedupKeyVectors ? this.keyVectorLookup[keyVectorHash] : this.createVector(stackPointer.stackPosition, vecLength, 2);
|
||||
const valuesStackValue = this.createVector(stackPointer.stackPosition + 1, vecLength, 2, keysStackValue);
|
||||
const keysStackValue = this.dedupKeyVectors
|
||||
? this.keyVectorLookup[keyVectorHash]
|
||||
: this.createVector(stackPointer.stackPosition, vecLength, 2);
|
||||
const valuesStackValue = this.createVector(
|
||||
stackPointer.stackPosition + 1,
|
||||
vecLength,
|
||||
2,
|
||||
keysStackValue,
|
||||
);
|
||||
this.stack.splice(stackPointer.stackPosition, vecLength << 1);
|
||||
this.stack.push(valuesStackValue);
|
||||
}
|
||||
|
||||
private sort(stackPointer: StackPointer) {
|
||||
const view = this.view
|
||||
const stack = this.stack
|
||||
const view = this.view;
|
||||
const stack = this.stack;
|
||||
|
||||
function shouldFlip(v1: StackValue, v2: StackValue) {
|
||||
if (v1.type !== ValueType.KEY || v2.type !== ValueType.KEY) {
|
||||
throw `Stack values are not keys ${v1} | ${v2}. Check if you combined [addKey] with add... method calls properly.`
|
||||
throw `Stack values are not keys ${v1} | ${v2}. Check if you combined [addKey] with add... method calls properly.`;
|
||||
}
|
||||
let c1, c2;
|
||||
let index = 0;
|
||||
@@ -258,7 +317,7 @@ export class Builder {
|
||||
|
||||
function smaller(v1: StackValue, v2: StackValue) {
|
||||
if (v1.type !== ValueType.KEY || v2.type !== ValueType.KEY) {
|
||||
throw `Stack values are not keys ${v1} | ${v2}. Check if you combined [addKey] with add... method calls properly.`
|
||||
throw `Stack values are not keys ${v1} | ${v2}. Check if you combined [addKey] with add... method calls properly.`;
|
||||
}
|
||||
if (v1.offset === v2.offset) {
|
||||
return false;
|
||||
@@ -276,9 +335,8 @@ export class Builder {
|
||||
}
|
||||
|
||||
function quickSort(left: number, right: number) {
|
||||
|
||||
if (left < right) {
|
||||
const mid = left + (((right - left) >> 2)) * 2;
|
||||
const mid = left + ((right - left) >> 2) * 2;
|
||||
const pivot = stack[mid];
|
||||
let left_new = left;
|
||||
let right_new = right;
|
||||
@@ -299,12 +357,15 @@ export class Builder {
|
||||
|
||||
quickSort(left, right_new);
|
||||
quickSort(left_new, right);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
let sorted = true;
|
||||
for (let i = stackPointer.stackPosition; i < this.stack.length - 2; i += 2) {
|
||||
for (
|
||||
let i = stackPointer.stackPosition;
|
||||
i < this.stack.length - 2;
|
||||
i += 2
|
||||
) {
|
||||
if (shouldFlip(this.stack[i], this.stack[i + 2])) {
|
||||
sorted = false;
|
||||
break;
|
||||
@@ -330,7 +391,12 @@ export class Builder {
|
||||
}
|
||||
}
|
||||
|
||||
private createVector(start: number, vecLength: number, step: number, keys: StackValue | null = null) {
|
||||
private createVector(
|
||||
start: number,
|
||||
vecLength: number,
|
||||
step: number,
|
||||
keys: StackValue | null = null,
|
||||
) {
|
||||
let bitWidth = uwidth(vecLength);
|
||||
let prefixElements = 1;
|
||||
if (keys !== null) {
|
||||
@@ -343,7 +409,10 @@ export class Builder {
|
||||
let vectorType = ValueType.KEY;
|
||||
let typed = keys === null;
|
||||
for (let i = start; i < this.stack.length; i += step) {
|
||||
const elementWidth = this.stack[i].elementWidth(this.offset, i + prefixElements);
|
||||
const elementWidth = this.stack[i].elementWidth(
|
||||
this.offset,
|
||||
i + prefixElements,
|
||||
);
|
||||
if (elementWidth > bitWidth) {
|
||||
bitWidth = elementWidth;
|
||||
}
|
||||
@@ -357,7 +426,8 @@ export class Builder {
|
||||
}
|
||||
}
|
||||
const byteWidth = this.align(bitWidth);
|
||||
const fix = typed && isNumber(vectorType) && vecLength >= 2 && vecLength <= 4;
|
||||
const fix =
|
||||
typed && isNumber(vectorType) && vecLength >= 2 && vecLength <= 4;
|
||||
if (keys !== null) {
|
||||
this.writeStackValue(keys, byteWidth);
|
||||
this.writeUInt(1 << keys.width, byteWidth);
|
||||
@@ -404,7 +474,11 @@ export class Builder {
|
||||
return new StackValue(this, ValueType.FLOAT, fwidth(value), value);
|
||||
}
|
||||
|
||||
private offsetStackValue(offset: number, valueType: ValueType, bitWidth: BitWidth): StackValue {
|
||||
private offsetStackValue(
|
||||
offset: number,
|
||||
valueType: ValueType,
|
||||
bitWidth: BitWidth,
|
||||
): StackValue {
|
||||
return new StackValue(this, valueType, bitWidth, null, offset);
|
||||
}
|
||||
|
||||
@@ -420,16 +494,28 @@ export class Builder {
|
||||
this.finished = true;
|
||||
}
|
||||
|
||||
add(value: undefined | null | boolean | bigint | number | DataView | string | Array<unknown> | Record<string, unknown> | unknown): void {
|
||||
add(
|
||||
value:
|
||||
| undefined
|
||||
| null
|
||||
| boolean
|
||||
| bigint
|
||||
| number
|
||||
| DataView
|
||||
| string
|
||||
| Array<unknown>
|
||||
| Record<string, unknown>
|
||||
| unknown,
|
||||
): void {
|
||||
this.integrityCheckOnValueAddition();
|
||||
if (typeof value === 'undefined') {
|
||||
throw "You need to provide a value";
|
||||
throw 'You need to provide a value';
|
||||
}
|
||||
if (value === null) {
|
||||
this.stack.push(this.nullStackValue());
|
||||
} else if (typeof value === "boolean") {
|
||||
} else if (typeof value === 'boolean') {
|
||||
this.stack.push(this.boolStackValue(value));
|
||||
} else if (typeof value === "bigint") {
|
||||
} else if (typeof value === 'bigint') {
|
||||
this.stack.push(this.intStackValue(value));
|
||||
} else if (typeof value == 'number') {
|
||||
if (Number.isInteger(value)) {
|
||||
@@ -484,7 +570,10 @@ export class Builder {
|
||||
this.stack.push(this.intStackValue(value));
|
||||
return;
|
||||
}
|
||||
if (deduplicate && Object.prototype.hasOwnProperty.call(this.indirectIntLookup, value)) {
|
||||
if (
|
||||
deduplicate &&
|
||||
Object.prototype.hasOwnProperty.call(this.indirectIntLookup, value)
|
||||
) {
|
||||
this.stack.push(this.indirectIntLookup[value]);
|
||||
return;
|
||||
}
|
||||
@@ -493,7 +582,11 @@ export class Builder {
|
||||
const newOffset = this.computeOffset(byteWidth);
|
||||
const valueOffset = this.offset;
|
||||
stackValue.writeToBuffer(byteWidth);
|
||||
const stackOffset = this.offsetStackValue(valueOffset, ValueType.INDIRECT_INT, stackValue.width);
|
||||
const stackOffset = this.offsetStackValue(
|
||||
valueOffset,
|
||||
ValueType.INDIRECT_INT,
|
||||
stackValue.width,
|
||||
);
|
||||
this.stack.push(stackOffset);
|
||||
this.offset = newOffset;
|
||||
if (deduplicate) {
|
||||
@@ -507,7 +600,10 @@ export class Builder {
|
||||
this.stack.push(this.uintStackValue(value));
|
||||
return;
|
||||
}
|
||||
if (deduplicate && Object.prototype.hasOwnProperty.call(this.indirectUIntLookup, value)) {
|
||||
if (
|
||||
deduplicate &&
|
||||
Object.prototype.hasOwnProperty.call(this.indirectUIntLookup, value)
|
||||
) {
|
||||
this.stack.push(this.indirectUIntLookup[value]);
|
||||
return;
|
||||
}
|
||||
@@ -516,7 +612,11 @@ export class Builder {
|
||||
const newOffset = this.computeOffset(byteWidth);
|
||||
const valueOffset = this.offset;
|
||||
stackValue.writeToBuffer(byteWidth);
|
||||
const stackOffset = this.offsetStackValue(valueOffset, ValueType.INDIRECT_UINT, stackValue.width);
|
||||
const stackOffset = this.offsetStackValue(
|
||||
valueOffset,
|
||||
ValueType.INDIRECT_UINT,
|
||||
stackValue.width,
|
||||
);
|
||||
this.stack.push(stackOffset);
|
||||
this.offset = newOffset;
|
||||
if (deduplicate) {
|
||||
@@ -530,7 +630,10 @@ export class Builder {
|
||||
this.stack.push(this.floatStackValue(value));
|
||||
return;
|
||||
}
|
||||
if (deduplicate && Object.prototype.hasOwnProperty.call(this.indirectFloatLookup, value)) {
|
||||
if (
|
||||
deduplicate &&
|
||||
Object.prototype.hasOwnProperty.call(this.indirectFloatLookup, value)
|
||||
) {
|
||||
this.stack.push(this.indirectFloatLookup[value]);
|
||||
return;
|
||||
}
|
||||
@@ -539,7 +642,11 @@ export class Builder {
|
||||
const newOffset = this.computeOffset(byteWidth);
|
||||
const valueOffset = this.offset;
|
||||
stackValue.writeToBuffer(byteWidth);
|
||||
const stackOffset = this.offsetStackValue(valueOffset, ValueType.INDIRECT_FLOAT, stackValue.width);
|
||||
const stackOffset = this.offsetStackValue(
|
||||
valueOffset,
|
||||
ValueType.INDIRECT_FLOAT,
|
||||
stackValue.width,
|
||||
);
|
||||
this.stack.push(stackOffset);
|
||||
this.offset = newOffset;
|
||||
if (deduplicate) {
|
||||
|
||||
@@ -3,7 +3,7 @@ export function fromUTF8Array(data: BufferSource): string {
|
||||
return decoder.decode(data);
|
||||
}
|
||||
|
||||
export function toUTF8Array(str: string) : Uint8Array {
|
||||
export function toUTF8Array(str: string): Uint8Array {
|
||||
const encoder = new TextEncoder();
|
||||
return encoder.encode(str);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,25 @@
|
||||
import { BitWidth } from './bit-width.js'
|
||||
import { toByteWidth, fromByteWidth } from './bit-width-util.js'
|
||||
import { toUTF8Array, fromUTF8Array } from './flexbuffers-util.js'
|
||||
import {fromByteWidth, toByteWidth} from './bit-width-util.js';
|
||||
import {BitWidth} from './bit-width.js';
|
||||
import {fromUTF8Array, toUTF8Array} from './flexbuffers-util.js';
|
||||
|
||||
export function validateOffset(dataView: DataView, offset: number, width: number): void {
|
||||
if (dataView.byteLength <= offset + width || (offset & (toByteWidth(width) - 1)) !== 0) {
|
||||
throw "Bad offset: " + offset + ", width: " + width;
|
||||
export function validateOffset(
|
||||
dataView: DataView,
|
||||
offset: number,
|
||||
width: number,
|
||||
): void {
|
||||
if (
|
||||
dataView.byteLength <= offset + width ||
|
||||
(offset & (toByteWidth(width) - 1)) !== 0
|
||||
) {
|
||||
throw 'Bad offset: ' + offset + ', width: ' + width;
|
||||
}
|
||||
}
|
||||
|
||||
export function readInt(dataView: DataView, offset: number, width: number): number | bigint {
|
||||
export function readInt(
|
||||
dataView: DataView,
|
||||
offset: number,
|
||||
width: number,
|
||||
): number | bigint {
|
||||
if (width < 2) {
|
||||
if (width < 1) {
|
||||
return dataView.getInt8(offset);
|
||||
@@ -17,17 +28,24 @@ export function readInt(dataView: DataView, offset: number, width: number): numb
|
||||
}
|
||||
} else {
|
||||
if (width < 3) {
|
||||
return dataView.getInt32(offset, true)
|
||||
return dataView.getInt32(offset, true);
|
||||
} else {
|
||||
if (dataView.setBigInt64 === undefined) {
|
||||
return BigInt(dataView.getUint32(offset, true)) + (BigInt(dataView.getUint32(offset + 4, true)) << BigInt(32));
|
||||
return (
|
||||
BigInt(dataView.getUint32(offset, true)) +
|
||||
(BigInt(dataView.getUint32(offset + 4, true)) << BigInt(32))
|
||||
);
|
||||
}
|
||||
return dataView.getBigInt64(offset, true)
|
||||
return dataView.getBigInt64(offset, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function readUInt(dataView: DataView, offset: number, width: number): number | bigint {
|
||||
export function readUInt(
|
||||
dataView: DataView,
|
||||
offset: number,
|
||||
width: number,
|
||||
): number | bigint {
|
||||
if (width < 2) {
|
||||
if (width < 1) {
|
||||
return dataView.getUint8(offset);
|
||||
@@ -36,19 +54,26 @@ export function readUInt(dataView: DataView, offset: number, width: number): num
|
||||
}
|
||||
} else {
|
||||
if (width < 3) {
|
||||
return dataView.getUint32(offset, true)
|
||||
return dataView.getUint32(offset, true);
|
||||
} else {
|
||||
if (dataView.getBigUint64 === undefined) {
|
||||
return BigInt(dataView.getUint32(offset, true)) + (BigInt(dataView.getUint32(offset + 4, true)) << BigInt(32));
|
||||
return (
|
||||
BigInt(dataView.getUint32(offset, true)) +
|
||||
(BigInt(dataView.getUint32(offset + 4, true)) << BigInt(32))
|
||||
);
|
||||
}
|
||||
return dataView.getBigUint64(offset, true)
|
||||
return dataView.getBigUint64(offset, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function readFloat(dataView: DataView, offset: number, width: number): number {
|
||||
export function readFloat(
|
||||
dataView: DataView,
|
||||
offset: number,
|
||||
width: number,
|
||||
): number {
|
||||
if (width < BitWidth.WIDTH32) {
|
||||
throw "Bad width: " + width;
|
||||
throw 'Bad width: ' + width;
|
||||
}
|
||||
if (width === BitWidth.WIDTH32) {
|
||||
return dataView.getFloat32(offset, true);
|
||||
@@ -56,17 +81,32 @@ export function readFloat(dataView: DataView, offset: number, width: number): nu
|
||||
return dataView.getFloat64(offset, true);
|
||||
}
|
||||
|
||||
export function indirect(dataView: DataView, offset: number, width: number): number {
|
||||
export function indirect(
|
||||
dataView: DataView,
|
||||
offset: number,
|
||||
width: number,
|
||||
): number {
|
||||
const step = readUInt(dataView, offset, width) as number;
|
||||
return offset - step;
|
||||
}
|
||||
|
||||
export function keyIndex(key: string, dataView: DataView, offset: number, parentWidth: number, byteWidth: number, length: number): number | null {
|
||||
export function keyIndex(
|
||||
key: string,
|
||||
dataView: DataView,
|
||||
offset: number,
|
||||
parentWidth: number,
|
||||
byteWidth: number,
|
||||
length: number,
|
||||
): number | null {
|
||||
const input = toUTF8Array(key);
|
||||
const keysVectorOffset = indirect(dataView, offset, parentWidth) - byteWidth * 3;
|
||||
const keysVectorOffset =
|
||||
indirect(dataView, offset, parentWidth) - byteWidth * 3;
|
||||
const bitWidth = fromByteWidth(byteWidth);
|
||||
const indirectOffset = keysVectorOffset - Number(readUInt(dataView, keysVectorOffset, bitWidth));
|
||||
const _byteWidth = Number(readUInt(dataView, keysVectorOffset + byteWidth, bitWidth));
|
||||
const indirectOffset =
|
||||
keysVectorOffset - Number(readUInt(dataView, keysVectorOffset, bitWidth));
|
||||
const _byteWidth = Number(
|
||||
readUInt(dataView, keysVectorOffset + byteWidth, bitWidth),
|
||||
);
|
||||
let low = 0;
|
||||
let high = length - 1;
|
||||
while (low <= high) {
|
||||
@@ -82,9 +122,16 @@ export function keyIndex(key: string, dataView: DataView, offset: number, parent
|
||||
return null;
|
||||
}
|
||||
|
||||
export function diffKeys(input: Uint8Array, index: number, dataView: DataView, offset: number, width: number): number {
|
||||
export function diffKeys(
|
||||
input: Uint8Array,
|
||||
index: number,
|
||||
dataView: DataView,
|
||||
offset: number,
|
||||
width: number,
|
||||
): number {
|
||||
const keyOffset = offset + index * width;
|
||||
const keyIndirectOffset = keyOffset - Number(readUInt(dataView, keyOffset, fromByteWidth(width)));
|
||||
const keyIndirectOffset =
|
||||
keyOffset - Number(readUInt(dataView, keyOffset, fromByteWidth(width)));
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
const dif = input[i] - dataView.getUint8(keyIndirectOffset + i);
|
||||
if (dif !== 0) {
|
||||
@@ -94,16 +141,30 @@ export function diffKeys(input: Uint8Array, index: number, dataView: DataView, o
|
||||
return dataView.getUint8(keyIndirectOffset + input.length) === 0 ? 0 : -1;
|
||||
}
|
||||
|
||||
export function keyForIndex(index: number, dataView: DataView, offset: number, parentWidth: number, byteWidth: number): string {
|
||||
const keysVectorOffset = indirect(dataView, offset, parentWidth) - byteWidth * 3;
|
||||
export function keyForIndex(
|
||||
index: number,
|
||||
dataView: DataView,
|
||||
offset: number,
|
||||
parentWidth: number,
|
||||
byteWidth: number,
|
||||
): string {
|
||||
const keysVectorOffset =
|
||||
indirect(dataView, offset, parentWidth) - byteWidth * 3;
|
||||
const bitWidth = fromByteWidth(byteWidth);
|
||||
const indirectOffset = keysVectorOffset - Number(readUInt(dataView, keysVectorOffset, bitWidth));
|
||||
const _byteWidth = Number(readUInt(dataView, keysVectorOffset + byteWidth, bitWidth));
|
||||
const indirectOffset =
|
||||
keysVectorOffset - Number(readUInt(dataView, keysVectorOffset, bitWidth));
|
||||
const _byteWidth = Number(
|
||||
readUInt(dataView, keysVectorOffset + byteWidth, bitWidth),
|
||||
);
|
||||
const keyOffset = indirectOffset + index * _byteWidth;
|
||||
const keyIndirectOffset = keyOffset - Number(readUInt(dataView, keyOffset, fromByteWidth(_byteWidth)));
|
||||
const keyIndirectOffset =
|
||||
keyOffset -
|
||||
Number(readUInt(dataView, keyOffset, fromByteWidth(_byteWidth)));
|
||||
let length = 0;
|
||||
while (dataView.getUint8(keyIndirectOffset + length) !== 0) {
|
||||
length++;
|
||||
}
|
||||
return fromUTF8Array(new Uint8Array(dataView.buffer, keyIndirectOffset, length));
|
||||
return fromUTF8Array(
|
||||
new Uint8Array(dataView.buffer, keyIndirectOffset, length),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,15 +1,32 @@
|
||||
import { fromByteWidth } from './bit-width-util.js'
|
||||
import { ValueType } from './value-type.js'
|
||||
import { isNumber, isIndirectNumber, isAVector, fixedTypedVectorElementSize, isFixedTypedVector, isTypedVector, typedVectorElementType, packedType, fixedTypedVectorElementType } from './value-type-util.js'
|
||||
import { indirect, keyForIndex, keyIndex, readFloat, readInt, readUInt } from './reference-util.js'
|
||||
import { fromUTF8Array } from './flexbuffers-util.js';
|
||||
import { BitWidth } from './bit-width.js';
|
||||
import {fromByteWidth} from './bit-width-util.js';
|
||||
import {BitWidth} from './bit-width.js';
|
||||
import {fromUTF8Array} from './flexbuffers-util.js';
|
||||
import {
|
||||
indirect,
|
||||
keyForIndex,
|
||||
keyIndex,
|
||||
readFloat,
|
||||
readInt,
|
||||
readUInt,
|
||||
} from './reference-util.js';
|
||||
import {
|
||||
fixedTypedVectorElementSize,
|
||||
fixedTypedVectorElementType,
|
||||
isAVector,
|
||||
isFixedTypedVector,
|
||||
isIndirectNumber,
|
||||
isNumber,
|
||||
isTypedVector,
|
||||
packedType,
|
||||
typedVectorElementType,
|
||||
} from './value-type-util.js';
|
||||
import {ValueType} from './value-type.js';
|
||||
|
||||
export function toReference(buffer: ArrayBuffer): Reference {
|
||||
const len = buffer.byteLength;
|
||||
|
||||
if (len < 3) {
|
||||
throw "Buffer needs to be bigger than 3";
|
||||
throw 'Buffer needs to be bigger than 3';
|
||||
}
|
||||
|
||||
const dataView = new DataView(buffer);
|
||||
@@ -18,34 +35,78 @@ export function toReference(buffer: ArrayBuffer): Reference {
|
||||
const parentWidth = fromByteWidth(byteWidth);
|
||||
const offset = len - byteWidth - 2;
|
||||
|
||||
return new Reference(dataView, offset, parentWidth, packedType, "/")
|
||||
return new Reference(dataView, offset, parentWidth, packedType, '/');
|
||||
}
|
||||
|
||||
function valueForIndexWithKey(index: number, key: string, dataView: DataView, offset: number, parentWidth: number, byteWidth: number, length: number, path: string): Reference {
|
||||
function valueForIndexWithKey(
|
||||
index: number,
|
||||
key: string,
|
||||
dataView: DataView,
|
||||
offset: number,
|
||||
parentWidth: number,
|
||||
byteWidth: number,
|
||||
length: number,
|
||||
path: string,
|
||||
): Reference {
|
||||
const _indirect = indirect(dataView, offset, parentWidth);
|
||||
const elementOffset = _indirect + index * byteWidth;
|
||||
const packedType = dataView.getUint8(_indirect + length * byteWidth + index);
|
||||
return new Reference(dataView, elementOffset, fromByteWidth(byteWidth), packedType, `${path}/${key}`)
|
||||
return new Reference(
|
||||
dataView,
|
||||
elementOffset,
|
||||
fromByteWidth(byteWidth),
|
||||
packedType,
|
||||
`${path}/${key}`,
|
||||
);
|
||||
}
|
||||
|
||||
export class Reference {
|
||||
private readonly byteWidth: number
|
||||
private readonly valueType: ValueType
|
||||
private _length = -1
|
||||
constructor(private dataView: DataView, private offset: number, private parentWidth: number, private packedType: ValueType, private path: string) {
|
||||
this.byteWidth = 1 << (packedType & 3)
|
||||
this.valueType = packedType >> 2
|
||||
private readonly byteWidth: number;
|
||||
private readonly valueType: ValueType;
|
||||
private _length = -1;
|
||||
constructor(
|
||||
private dataView: DataView,
|
||||
private offset: number,
|
||||
private parentWidth: number,
|
||||
private packedType: ValueType,
|
||||
private path: string,
|
||||
) {
|
||||
this.byteWidth = 1 << (packedType & 3);
|
||||
this.valueType = packedType >> 2;
|
||||
}
|
||||
|
||||
isNull(): boolean { return this.valueType === ValueType.NULL; }
|
||||
isNumber(): boolean { return isNumber(this.valueType) || isIndirectNumber(this.valueType); }
|
||||
isFloat(): boolean { return ValueType.FLOAT === this.valueType || ValueType.INDIRECT_FLOAT === this.valueType; }
|
||||
isInt(): boolean { return this.isNumber() && !this.isFloat(); }
|
||||
isString(): boolean { return ValueType.STRING === this.valueType || ValueType.KEY === this.valueType; }
|
||||
isBool(): boolean { return ValueType.BOOL === this.valueType; }
|
||||
isBlob(): boolean { return ValueType.BLOB === this.valueType; }
|
||||
isVector(): boolean { return isAVector(this.valueType); }
|
||||
isMap(): boolean { return ValueType.MAP === this.valueType; }
|
||||
isNull(): boolean {
|
||||
return this.valueType === ValueType.NULL;
|
||||
}
|
||||
isNumber(): boolean {
|
||||
return isNumber(this.valueType) || isIndirectNumber(this.valueType);
|
||||
}
|
||||
isFloat(): boolean {
|
||||
return (
|
||||
ValueType.FLOAT === this.valueType ||
|
||||
ValueType.INDIRECT_FLOAT === this.valueType
|
||||
);
|
||||
}
|
||||
isInt(): boolean {
|
||||
return this.isNumber() && !this.isFloat();
|
||||
}
|
||||
isString(): boolean {
|
||||
return (
|
||||
ValueType.STRING === this.valueType || ValueType.KEY === this.valueType
|
||||
);
|
||||
}
|
||||
isBool(): boolean {
|
||||
return ValueType.BOOL === this.valueType;
|
||||
}
|
||||
isBlob(): boolean {
|
||||
return ValueType.BLOB === this.valueType;
|
||||
}
|
||||
isVector(): boolean {
|
||||
return isAVector(this.valueType);
|
||||
}
|
||||
isMap(): boolean {
|
||||
return ValueType.MAP === this.valueType;
|
||||
}
|
||||
|
||||
boolValue(): boolean | null {
|
||||
if (this.isBool()) {
|
||||
@@ -62,10 +123,18 @@ export class Reference {
|
||||
return readUInt(this.dataView, this.offset, this.parentWidth);
|
||||
}
|
||||
if (this.valueType === ValueType.INDIRECT_INT) {
|
||||
return readInt(this.dataView, indirect(this.dataView, this.offset, this.parentWidth), fromByteWidth(this.byteWidth));
|
||||
return readInt(
|
||||
this.dataView,
|
||||
indirect(this.dataView, this.offset, this.parentWidth),
|
||||
fromByteWidth(this.byteWidth),
|
||||
);
|
||||
}
|
||||
if (this.valueType === ValueType.INDIRECT_UINT) {
|
||||
return readUInt(this.dataView, indirect(this.dataView, this.offset, this.parentWidth), fromByteWidth(this.byteWidth));
|
||||
return readUInt(
|
||||
this.dataView,
|
||||
indirect(this.dataView, this.offset, this.parentWidth),
|
||||
fromByteWidth(this.byteWidth),
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -75,17 +144,28 @@ export class Reference {
|
||||
return readFloat(this.dataView, this.offset, this.parentWidth);
|
||||
}
|
||||
if (this.valueType === ValueType.INDIRECT_FLOAT) {
|
||||
return readFloat(this.dataView, indirect(this.dataView, this.offset, this.parentWidth), fromByteWidth(this.byteWidth));
|
||||
return readFloat(
|
||||
this.dataView,
|
||||
indirect(this.dataView, this.offset, this.parentWidth),
|
||||
fromByteWidth(this.byteWidth),
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
numericValue(): number | bigint | null { return this.floatValue() || this.intValue()}
|
||||
numericValue(): number | bigint | null {
|
||||
return this.floatValue() || this.intValue();
|
||||
}
|
||||
|
||||
stringValue(): string | null {
|
||||
if (this.valueType === ValueType.STRING || this.valueType === ValueType.KEY) {
|
||||
if (
|
||||
this.valueType === ValueType.STRING ||
|
||||
this.valueType === ValueType.KEY
|
||||
) {
|
||||
const begin = indirect(this.dataView, this.offset, this.parentWidth);
|
||||
return fromUTF8Array(new Uint8Array(this.dataView.buffer, begin, this.length()));
|
||||
return fromUTF8Array(
|
||||
new Uint8Array(this.dataView.buffer, begin, this.length()),
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -106,7 +186,9 @@ export class Reference {
|
||||
}
|
||||
const _indirect = indirect(this.dataView, this.offset, this.parentWidth);
|
||||
const elementOffset = _indirect + key * this.byteWidth;
|
||||
let _packedType = this.dataView.getUint8(_indirect + length * this.byteWidth + key);
|
||||
let _packedType = this.dataView.getUint8(
|
||||
_indirect + length * this.byteWidth + key,
|
||||
);
|
||||
if (isTypedVector(this.valueType)) {
|
||||
const _valueType = typedVectorElementType(this.valueType);
|
||||
_packedType = packedType(_valueType, BitWidth.WIDTH8);
|
||||
@@ -114,12 +196,34 @@ export class Reference {
|
||||
const _valueType = fixedTypedVectorElementType(this.valueType);
|
||||
_packedType = packedType(_valueType, BitWidth.WIDTH8);
|
||||
}
|
||||
return new Reference(this.dataView, elementOffset, fromByteWidth(this.byteWidth), _packedType, `${this.path}[${key}]`);
|
||||
return new Reference(
|
||||
this.dataView,
|
||||
elementOffset,
|
||||
fromByteWidth(this.byteWidth),
|
||||
_packedType,
|
||||
`${this.path}[${key}]`,
|
||||
);
|
||||
}
|
||||
if (typeof key === 'string') {
|
||||
const index = keyIndex(key, this.dataView, this.offset, this.parentWidth, this.byteWidth, length);
|
||||
const index = keyIndex(
|
||||
key,
|
||||
this.dataView,
|
||||
this.offset,
|
||||
this.parentWidth,
|
||||
this.byteWidth,
|
||||
length,
|
||||
);
|
||||
if (index !== null) {
|
||||
return valueForIndexWithKey(index, key, this.dataView, this.offset, this.parentWidth, this.byteWidth, length, this.path)
|
||||
return valueForIndexWithKey(
|
||||
index,
|
||||
key,
|
||||
this.dataView,
|
||||
this.offset,
|
||||
this.parentWidth,
|
||||
this.byteWidth,
|
||||
length,
|
||||
this.path,
|
||||
);
|
||||
}
|
||||
}
|
||||
throw `Key [${key}] is not applicable on ${this.path} of ${this.valueType}`;
|
||||
@@ -132,19 +236,33 @@ export class Reference {
|
||||
}
|
||||
if (isFixedTypedVector(this.valueType)) {
|
||||
this._length = fixedTypedVectorElementSize(this.valueType);
|
||||
} else if (this.valueType === ValueType.BLOB
|
||||
|| this.valueType === ValueType.MAP
|
||||
|| isAVector(this.valueType)) {
|
||||
this._length = readUInt(this.dataView, indirect(this.dataView, this.offset, this.parentWidth) - this.byteWidth, fromByteWidth(this.byteWidth)) as number
|
||||
} else if (
|
||||
this.valueType === ValueType.BLOB ||
|
||||
this.valueType === ValueType.MAP ||
|
||||
isAVector(this.valueType)
|
||||
) {
|
||||
this._length = readUInt(
|
||||
this.dataView,
|
||||
indirect(this.dataView, this.offset, this.parentWidth) - this.byteWidth,
|
||||
fromByteWidth(this.byteWidth),
|
||||
) as number;
|
||||
} else if (this.valueType === ValueType.NULL) {
|
||||
this._length = 0;
|
||||
} else if (this.valueType === ValueType.STRING) {
|
||||
const _indirect = indirect(this.dataView, this.offset, this.parentWidth);
|
||||
let sizeByteWidth = this.byteWidth;
|
||||
size = readUInt(this.dataView, _indirect - sizeByteWidth, fromByteWidth(this.byteWidth));
|
||||
size = readUInt(
|
||||
this.dataView,
|
||||
_indirect - sizeByteWidth,
|
||||
fromByteWidth(this.byteWidth),
|
||||
);
|
||||
while (this.dataView.getInt8(_indirect + (size as number)) !== 0) {
|
||||
sizeByteWidth <<= 1;
|
||||
size = readUInt(this.dataView, _indirect - sizeByteWidth, fromByteWidth(this.byteWidth));
|
||||
size = readUInt(
|
||||
this.dataView,
|
||||
_indirect - sizeByteWidth,
|
||||
fromByteWidth(this.byteWidth),
|
||||
);
|
||||
}
|
||||
this._length = size as number;
|
||||
} else if (this.valueType === ValueType.KEY) {
|
||||
@@ -172,8 +290,23 @@ export class Reference {
|
||||
if (this.isMap()) {
|
||||
const result: Record<string, unknown> = {};
|
||||
for (let i = 0; i < length; i++) {
|
||||
const key = keyForIndex(i, this.dataView, this.offset, this.parentWidth, this.byteWidth);
|
||||
result[key] = valueForIndexWithKey(i, key, this.dataView, this.offset, this.parentWidth, this.byteWidth, length, this.path).toObject();
|
||||
const key = keyForIndex(
|
||||
i,
|
||||
this.dataView,
|
||||
this.offset,
|
||||
this.parentWidth,
|
||||
this.byteWidth,
|
||||
);
|
||||
result[key] = valueForIndexWithKey(
|
||||
i,
|
||||
key,
|
||||
this.dataView,
|
||||
this.offset,
|
||||
this.parentWidth,
|
||||
this.byteWidth,
|
||||
length,
|
||||
this.path,
|
||||
).toObject();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
import { Builder } from './builder.js'
|
||||
import { BitWidth } from './bit-width.js'
|
||||
import { paddingSize, uwidth, fromByteWidth } from './bit-width-util.js'
|
||||
import { ValueType } from './value-type.js'
|
||||
import { isInline, packedType } from './value-type-util.js'
|
||||
import {fromByteWidth, paddingSize, uwidth} from './bit-width-util.js';
|
||||
import {BitWidth} from './bit-width.js';
|
||||
import {Builder} from './builder.js';
|
||||
import {isInline, packedType} from './value-type-util.js';
|
||||
import {ValueType} from './value-type.js';
|
||||
|
||||
export class StackValue {
|
||||
constructor(private builder: Builder, public type: ValueType, public width: number, public value: number | boolean | null = null, public offset: number = 0) {
|
||||
|
||||
}
|
||||
constructor(
|
||||
private builder: Builder,
|
||||
public type: ValueType,
|
||||
public width: number,
|
||||
public value: number | boolean | null = null,
|
||||
public offset: number = 0,
|
||||
) {}
|
||||
|
||||
elementWidth(size: number, index: number): BitWidth {
|
||||
if (isInline(this.type)) return this.width;
|
||||
@@ -27,9 +31,17 @@ export class StackValue {
|
||||
const newOffset = this.builder.computeOffset(byteWidth);
|
||||
if (this.type === ValueType.FLOAT) {
|
||||
if (this.width === BitWidth.WIDTH32) {
|
||||
this.builder.view.setFloat32(this.builder.offset, this.value as number, true);
|
||||
this.builder.view.setFloat32(
|
||||
this.builder.offset,
|
||||
this.value as number,
|
||||
true,
|
||||
);
|
||||
} else {
|
||||
this.builder.view.setFloat64(this.builder.offset, this.value as number, true);
|
||||
this.builder.view.setFloat64(
|
||||
this.builder.offset,
|
||||
this.value as number,
|
||||
true,
|
||||
);
|
||||
}
|
||||
} else if (this.type === ValueType.INT) {
|
||||
const bitWidth = fromByteWidth(byteWidth);
|
||||
@@ -42,7 +54,7 @@ export class StackValue {
|
||||
} else if (this.type === ValueType.BOOL) {
|
||||
this.builder.pushInt(this.value ? 1 : 0, this.width);
|
||||
} else {
|
||||
throw `Unexpected type: ${this.type}. This might be a bug. Please create an issue https://github.com/google/flatbuffers/issues/new`
|
||||
throw `Unexpected type: ${this.type}. This might be a bug. Please create an issue https://github.com/google/flatbuffers/issues/new`;
|
||||
}
|
||||
this.offset = newOffset;
|
||||
}
|
||||
@@ -56,6 +68,6 @@ export class StackValue {
|
||||
}
|
||||
|
||||
isOffset(): boolean {
|
||||
return !isInline(this.type)
|
||||
return !isInline(this.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,41 +1,42 @@
|
||||
import { ValueType } from './value-type.js'
|
||||
import {ValueType} from './value-type.js';
|
||||
|
||||
export function isInline(value: ValueType): boolean {
|
||||
return value === ValueType.BOOL
|
||||
|| value <= ValueType.FLOAT;
|
||||
return value === ValueType.BOOL || value <= ValueType.FLOAT;
|
||||
}
|
||||
|
||||
export function isNumber(value: ValueType): boolean {
|
||||
return value >= ValueType.INT
|
||||
&& value <= ValueType.FLOAT;
|
||||
return value >= ValueType.INT && value <= ValueType.FLOAT;
|
||||
}
|
||||
|
||||
export function isIndirectNumber(value: ValueType): boolean {
|
||||
return value >= ValueType.INDIRECT_INT
|
||||
&& value <= ValueType.INDIRECT_FLOAT;
|
||||
return value >= ValueType.INDIRECT_INT && value <= ValueType.INDIRECT_FLOAT;
|
||||
}
|
||||
|
||||
export function isTypedVectorElement(value: ValueType): boolean {
|
||||
return value === ValueType.BOOL
|
||||
|| (value >= ValueType.INT
|
||||
&& value <= ValueType.STRING);
|
||||
return (
|
||||
value === ValueType.BOOL ||
|
||||
(value >= ValueType.INT && value <= ValueType.STRING)
|
||||
);
|
||||
}
|
||||
|
||||
export function isTypedVector(value: ValueType): boolean {
|
||||
return value === ValueType.VECTOR_BOOL
|
||||
|| (value >= ValueType.VECTOR_INT
|
||||
&& value <= ValueType.VECTOR_STRING_DEPRECATED);
|
||||
return (
|
||||
value === ValueType.VECTOR_BOOL ||
|
||||
(value >= ValueType.VECTOR_INT &&
|
||||
value <= ValueType.VECTOR_STRING_DEPRECATED)
|
||||
);
|
||||
}
|
||||
|
||||
export function isFixedTypedVector(value: ValueType): boolean {
|
||||
return value >= ValueType.VECTOR_INT2
|
||||
&& value <= ValueType.VECTOR_FLOAT4;
|
||||
return value >= ValueType.VECTOR_INT2 && value <= ValueType.VECTOR_FLOAT4;
|
||||
}
|
||||
|
||||
export function isAVector(value: ValueType): boolean {
|
||||
return isTypedVector(value)
|
||||
|| isFixedTypedVector(value)
|
||||
|| value === ValueType.VECTOR;
|
||||
return (
|
||||
isTypedVector(value) ||
|
||||
isFixedTypedVector(value) ||
|
||||
value === ValueType.VECTOR
|
||||
);
|
||||
}
|
||||
|
||||
export function toTypedVector(valueType: ValueType, length: number): ValueType {
|
||||
@@ -43,7 +44,7 @@ export function toTypedVector(valueType: ValueType, length: number): ValueType {
|
||||
if (length === 2) return valueType - ValueType.INT + ValueType.VECTOR_INT2;
|
||||
if (length === 3) return valueType - ValueType.INT + ValueType.VECTOR_INT3;
|
||||
if (length === 4) return valueType - ValueType.INT + ValueType.VECTOR_INT4;
|
||||
throw "Unexpected length " + length;
|
||||
throw 'Unexpected length ' + length;
|
||||
}
|
||||
|
||||
export function typedVectorElementType(valueType: ValueType): ValueType {
|
||||
@@ -61,4 +62,4 @@ export function fixedTypedVectorElementSize(valueType: ValueType): ValueType {
|
||||
|
||||
export function packedType(valueType: ValueType, bitWidth: number): ValueType {
|
||||
return bitWidth | (valueType << 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,4 +27,4 @@ export enum ValueType {
|
||||
BLOB = 25,
|
||||
BOOL = 26,
|
||||
VECTOR_BOOL = 36,
|
||||
}
|
||||
}
|
||||
|
||||
14
ts/types.ts
14
ts/types.ts
@@ -1,17 +1,17 @@
|
||||
import { ByteBuffer } from './byte-buffer.js'
|
||||
import { Builder } from './builder.js'
|
||||
import {Builder} from './builder.js';
|
||||
import {ByteBuffer} from './byte-buffer.js';
|
||||
|
||||
export type Offset = number;
|
||||
|
||||
export type Table = {
|
||||
bb: ByteBuffer
|
||||
bb_pos: number
|
||||
bb: ByteBuffer;
|
||||
bb_pos: number;
|
||||
};
|
||||
|
||||
export interface IGeneratedObject {
|
||||
pack(builder:Builder): Offset
|
||||
pack(builder: Builder): Offset;
|
||||
}
|
||||
|
||||
export interface IUnpackableObject<T> {
|
||||
unpack(): T
|
||||
}
|
||||
unpack(): T;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export const int32 = new Int32Array(2);
|
||||
export const float32 = new Float32Array(int32.buffer);
|
||||
export const float64 = new Float64Array(int32.buffer);
|
||||
export const isLittleEndian = new Uint16Array(new Uint8Array([1, 0]).buffer)[0] === 1;
|
||||
export const isLittleEndian =
|
||||
new Uint16Array(new Uint8Array([1, 0]).buffer)[0] === 1;
|
||||
|
||||
Reference in New Issue
Block a user