netron / flexbuffers.js
shethjenil's picture
Upload 30 files
d0d9416 verified
const flexbuffers = {};
flexbuffers.BinaryReader = class {
static open(buffer) {
const length = buffer.length;
if (length >= 3) {
const byteWidth = buffer[length - 1];
if (byteWidth <= 8) {
const packedType = buffer[length - 2];
return new flexbuffers.BinaryReader(buffer, length - 2 - byteWidth, byteWidth, 1 << (packedType & 3), packedType >> 2);
}
}
return null;
}
constructor(buffer, offset, parentWidth, byteWidth, type) {
this._buffer = buffer;
this._length = buffer.length;
this._view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
this._utf8Decoder = new TextDecoder('utf-8');
this._root = new flexbuffers.Reference(this, offset, parentWidth, byteWidth, type);
}
read() {
return this._root.read();
}
get length() {
return this._length;
}
int(offset, size) {
switch (size) {
case 1: return this._view.getInt8(offset);
case 2: return this._view.getInt16(offset, true);
case 4: return this._view.getInt32(offset, true);
case 8: return this._view.getBigInt64(offset, true);
default: throw new flexbuffers.Error(`Invalid int size '${size}'.`);
}
}
uint(offset, size) {
switch (size) {
case 1: return this._view.getUint8(offset);
case 2: return this._view.getUint16(offset, true);
case 4: return this._view.getUint32(offset, true);
case 8: return this._view.getBigUint64(offset, true);
default: throw new flexbuffers.Error(`Invalid uint size '${size}'.`);
}
}
float(offset, size) {
switch (size) {
case 4: return this._view.getFloat32(offset, true);
case 8: return this._view.getFloat64(offset, true);
default: throw new flexbuffers.Error(`Invalid float size '${size}'.`);
}
}
string(offset, size) {
let end = size === undefined ? this._buffer.indexOf(0, offset) : offset + size;
end = end === -1 ? this._buffer.length : end;
const bytes = this._buffer.subarray(offset, end);
return this._utf8Decoder.decode(bytes);
}
bytes(offset, size) {
return this._buffer.slice(offset, offset + size);
}
};
flexbuffers.Reference = class {
constructor(reader, offset, parentWidth, byteWidth, type) {
this._reader = reader;
this._offset = offset;
this._parentWidth = parentWidth;
this._byteWidth = byteWidth;
this._type = type;
}
read() {
switch (this._type) {
case 0x00: // null
return null;
case 0x01: // int
return this._reader.int(this._offset, this._parentWidth);
case 0x02: // uint
return this._reader.uint(this._offset, this._parentWidth);
case 0x03: // float
return this._reader.float(this._offset, this._parentWidth);
case 0x04: { // key
return this._reader.string(this._indirect());
}
case 0x05: { // string
const offset = this._indirect();
const size = this._reader.uint(offset - this._byteWidth, this._byteWidth);
return this._reader.string(offset, size);
}
case 0x06: // indirect int
return this._reader.int(this._indirect(), this._byteWidth);
case 0x07: // indirect uint
return this._reader.uint(this._indirect(), this._byteWidth);
case 0x08: // indirect float
return this._reader.float(this._indirect(), this._byteWidth);
case 0x09: { // map
const offset = this._indirect();
const keysOffset = offset - (this._byteWidth * 3);
const keysVectorOffset = keysOffset - this._reader.uint(keysOffset, this._byteWidth);
const keysByteWidth = this._reader.uint(keysOffset + this._byteWidth, this._byteWidth);
const keys = this._typedVector(keysVectorOffset, keysByteWidth, 0x04);
const values = this._vector(offset, this._byteWidth);
const map = {};
for (let i = 0; i < keys.length; i++) {
map[keys[i]] = values[i];
}
return map;
}
case 0x0a: { // vector
return this._vector(this._indirect(), this._byteWidth);
}
case 0x0b: // vector int
case 0x0c: // vector uint
case 0x0d: // vector float
case 0x0e: // vector key
case 0x0f: // vector string deprecated
case 0x24: { // vector bool
return this._typedVector(this._indirect(), this._byteWidth, this._type - 0x0b + 0x01);
}
case 0x10: // vector int2
case 0x11: // vector uint2
case 0x12: // vector float2
case 0x13: // vector int3
case 0x14: // vector uint3
case 0x15: // vector float3
case 0x16: // vector int4
case 0x17: // vector uint4
case 0x18: { // vector float4
const offset = this._indirect();
const size = (((this._type - 0x10) / 3) >> 0) + 2;
const type = ((this._type - 0x10) % 3) + 0x01;
return this._typedVector(offset, this._byteWidth, type, size);
}
case 0x19: { // blob
const offset = this._indirect();
const size = this._reader.uint(offset - this._byteWidth, this._byteWidth);
return this._reader.bytes(offset, size);
}
case 0x1a: { // bool
return this._reader.uint(this._offset, this._parentWidth) !== 0;
}
default: {
throw new flexbuffers.Error(`Unsupported reference type '${this._type}`);
}
}
}
_indirect() {
return this._offset - this._reader.uint(this._offset, this._parentWidth);
}
_vector(offset, byteWidth) {
const size = this._reader.uint(offset - byteWidth, byteWidth);
const packedTypeOffset = offset + (size * byteWidth);
const vector = new Array(size);
for (let i = 0; i < size; i++) {
const packedType = this._reader.uint(packedTypeOffset + i, 1);
const reference = new flexbuffers.Reference(this._reader, offset + (i * byteWidth), byteWidth, 1 << (packedType & 3), packedType >> 2);
vector[i] = reference.read();
}
return vector;
}
_typedVector(offset, byteWidth, type, size) {
size = size === undefined ? this._reader.uint(offset - byteWidth, byteWidth) : size;
const vector = new Array(size);
for (let i = 0; i < size; i++) {
const reference = new flexbuffers.Reference(this._reader, offset + (i * byteWidth), byteWidth, 1, type);
vector[i] = reference.read();
}
return vector;
}
};
flexbuffers.Error = class extends Error {
constructor(message) {
super(message);
this.name = 'FlexBuffers Error';
this.message = message;
}
};
export const BinaryReader = flexbuffers.BinaryReader;