bufferfy
Version:
Fast and efficient buffer serialization.
1,609 lines (1,575 loc) • 47.7 kB
JavaScript
'use strict';
var uint8arrayTools = require('uint8array-tools');
var util = require('util');
var os = require('os');
var base = require('@scure/base');
// src/utilities/Context.ts
var Context = class {
constructor() {
this.offset = 0;
}
};
// src/utilities/Error.ts
var BufferfyError = class extends Error {
};
var BufferfyByteLengthError = class extends BufferfyError {
constructor() {
super("Buffer is not of sufficient byteLength to decode.");
}
};
// src/Codecs/Abstract/DecodeTransform.ts
var DecodeTransformStream = class extends TransformStream {
constructor(codec) {
super({
transform: async (chunk, controller) => {
this._valueBytes = uint8arrayTools.concat([this._valueBytes, chunk]);
try {
while (this._valueBytes.byteLength) {
const value = codec.decode(this._valueBytes);
controller.enqueue(value);
const byteLength = codec.byteLength(value);
this._valueBytes = this._valueBytes.subarray(byteLength, this._valueBytes.byteLength);
}
} catch (error) {
if (error instanceof BufferfyByteLengthError)
return;
controller.error(error);
}
}
});
this._valueBytes = Uint8Array.from([]);
}
};
// src/Codecs/Abstract/EncodeTransform.ts
var EncodeTransformStream = class extends TransformStream {
constructor(codec) {
super({
async transform(value, controller) {
try {
const chunk = codec.encode(value);
controller.enqueue(chunk);
} catch (error) {
controller.error(error);
}
}
});
}
};
// src/Codecs/Abstract/index.ts
var AbstractCodec = class {
/**
* Encodes a value of this codecs type into a buffer.
*
* @param {Value} value - Value of this codec's type.
* @param {Uint8Array} [target] - A target buffer to write into.
* @param {number} [offset=0] - Offset at which to write into the target.
* @return {Uint8Array} Buffer encoding of value.
*
*/
encode(value, target, offset = 0) {
const c = new Context();
const byteLength = this.byteLength(value);
if (target) {
const buffer2 = offset ? new Uint8Array(target.buffer, target.byteOffset + offset, byteLength) : target;
this._encode(value, buffer2, c);
return buffer2;
}
const buffer = new Uint8Array(new ArrayBuffer(byteLength), 0, byteLength);
this._encode(value, buffer, c);
return buffer;
}
Encoder() {
return new EncodeTransformStream(this);
}
/**
* Decodes a buffer to a value of this codecs type.
*
* @param {Uint8Array} buffer - The buffer to be decoded.
* @param {number} [offset=0] - Offset at which to read at.
* @return {Value} Value decoded from the buffer
*
*/
decode(source, offset = 0) {
const c = new Context();
const buffer = new Uint8Array(source.buffer, source.byteOffset + offset, source.byteLength - offset);
return this._decode(buffer, c);
}
Decoder() {
return new DecodeTransformStream(this);
}
};
// src/Codecs/VarInt/VarInt60.ts
var VarInt60Codec = class extends AbstractCodec {
isValid(value) {
return typeof value === "number" && Number.isInteger(value) && value >= 0 && value < 281474976710656;
}
byteLength(value) {
return value < 32 ? 1 : value < 8192 ? 2 : value < 2097152 ? 3 : value < 536870912 ? 4 : value < 137438953472 ? 5 : value < 35184372088832 ? 6 : 7;
}
_encode(value, buffer, c) {
let byteLength = this.byteLength(value);
switch (byteLength) {
case 1: {
buffer[c.offset++] = value;
return;
}
case 2: {
buffer[c.offset++] = value >>> 8 | 32;
buffer[c.offset++] = value & 255;
return;
}
case 3: {
buffer[c.offset++] = value >>> 16 | 64;
buffer[c.offset++] = value >>> 8 & 255;
buffer[c.offset++] = value & 255;
return;
}
case 4: {
buffer[c.offset++] = value >>> 24 | 96;
buffer[c.offset++] = value >>> 16 & 255;
buffer[c.offset++] = value >>> 8 & 255;
buffer[c.offset++] = value & 255;
return;
}
case 5: {
buffer[c.offset++] = value / 2 ** 32 | 128;
buffer[c.offset++] = value >>> 24 & 255;
buffer[c.offset++] = value >>> 16 & 255;
buffer[c.offset++] = value >>> 8 & 255;
buffer[c.offset++] = value & 255;
return;
}
case 6: {
buffer[c.offset++] = value / 2 ** 40 | 160;
buffer[c.offset++] = value / 2 ** 32 & 255;
buffer[c.offset++] = value >>> 24 & 255;
buffer[c.offset++] = value >>> 16 & 255;
buffer[c.offset++] = value >>> 8 & 255;
buffer[c.offset++] = value & 255;
return;
}
case 7: {
buffer[c.offset++] = value / 2 ** 48 | 192;
buffer[c.offset++] = value / 2 ** 40 & 255;
buffer[c.offset++] = value / 2 ** 32 & 255;
buffer[c.offset++] = value >>> 24 & 255;
buffer[c.offset++] = value >>> 16 & 255;
buffer[c.offset++] = value >>> 8 & 255;
buffer[c.offset++] = value & 255;
return;
}
}
}
_decode(buffer, c) {
if (buffer.byteLength < c.offset + 1)
throw new BufferfyByteLengthError();
const byte0 = buffer[c.offset++];
const lengthBits = 224 & byte0;
const remainingByteLength = lengthBits / 32;
if (buffer.byteLength < c.offset + remainingByteLength)
throw new BufferfyByteLengthError();
switch (remainingByteLength) {
case 0: {
return byte0;
}
case 1: {
return (31 & byte0) * 2 ** 8 + buffer[c.offset++];
}
case 2: {
return (31 & byte0) * 2 ** 16 + buffer[c.offset++] * 2 ** 8 + buffer[c.offset++];
}
case 3: {
return (31 & byte0) * 2 ** 24 + buffer[c.offset++] * 2 ** 16 + buffer[c.offset++] * 2 ** 8 + buffer[c.offset++];
}
case 4: {
return (31 & byte0) * 2 ** 32 + buffer[c.offset++] * 2 ** 24 + buffer[c.offset++] * 2 ** 16 + buffer[c.offset++] * 2 ** 8 + buffer[c.offset++];
}
case 5: {
return (31 & byte0) * 2 ** 40 + buffer[c.offset++] * 2 ** 32 + buffer[c.offset++] * 2 ** 24 + buffer[c.offset++] * 2 ** 16 + buffer[c.offset++] * 2 ** 8 + buffer[c.offset++];
}
case 6: {
return (31 & byte0) * 2 ** 48 + buffer[c.offset++] * 2 ** 40 + buffer[c.offset++] * 2 ** 32 + buffer[c.offset++] * 2 ** 24 + buffer[c.offset++] * 2 ** 16 + buffer[c.offset++] * 2 ** 8 + buffer[c.offset++];
}
}
}
};
// src/Codecs/Bytes/Variable.ts
var BytesVariableCodec = class extends AbstractCodec {
constructor(lengthCodec = new VarInt60Codec()) {
super();
this.lengthCodec = lengthCodec;
}
isValid(value) {
return value instanceof Uint8Array;
}
byteLength(value) {
return this.lengthCodec.byteLength(value.byteLength) + value.byteLength;
}
_encode(value, buffer, c) {
this.lengthCodec._encode(value.byteLength, buffer, c);
for (const byte of value)
buffer[c.offset++] = byte;
}
_decode(buffer, c) {
const byteLength = this.lengthCodec._decode(buffer, c);
if (buffer.byteLength < c.offset + byteLength)
throw new BufferfyByteLengthError();
const value = new Uint8Array(buffer.buffer, buffer.byteOffset + c.offset, byteLength);
c.offset += byteLength;
return value;
}
};
// src/Codecs/Any/index.ts
var createAnyCodec = (options) => new AnyCodec(options);
var AnyCodec = class extends AbstractCodec {
constructor(options) {
super();
this._encodeValue = options?.encode || ((value) => new TextEncoder().encode(JSON.stringify(value)));
this._decodeValue = options?.decode || ((buffer) => JSON.parse(new TextDecoder().decode(buffer)));
this.lengthCodec = options?.lengthCodec || new VarInt60Codec();
this._bytesCodec = new BytesVariableCodec(this.lengthCodec);
}
isValid(_value) {
return true;
}
byteLength(value) {
let byteLength = this._encodeValue(value).byteLength;
return this.lengthCodec.byteLength(byteLength) + byteLength;
}
_encode(value, buffer, c) {
const valueBuffer = this._encodeValue(value);
return this._bytesCodec._encode(valueBuffer, buffer, c);
}
_decode(buffer, c) {
const valueBuffer = this._bytesCodec._decode(buffer, c);
return this._decodeValue(valueBuffer);
}
};
// src/Codecs/Array/Fixed.ts
var ArrayFixedCodec = class extends AbstractCodec {
constructor(length, itemCodec) {
super();
this.length = length;
this.itemCodec = itemCodec;
}
isValid(value) {
if (!Array.isArray(value) || value.length !== this.length)
return false;
for (const item of value)
if (!this.itemCodec.isValid(item))
return false;
return true;
}
byteLength(value) {
let byteLength = 0;
for (const item of value)
byteLength += this.itemCodec.byteLength(item);
return byteLength;
}
_encode(value, buffer, c) {
for (const item of value)
this.itemCodec._encode(item, buffer, c);
}
_decode(buffer, c) {
const value = Array(this.length);
for (let i = 0; i < this.length; i++)
value[i] = this.itemCodec._decode(buffer, c);
return value;
}
};
// src/Codecs/Array/Variable.ts
var ArrayVariableCodec = class extends AbstractCodec {
constructor(itemCodec, lengthCodec = new VarInt60Codec()) {
super();
this.itemCodec = itemCodec;
this.lengthCodec = lengthCodec;
}
isValid(value) {
if (!Array.isArray(value))
return false;
for (const item of value)
if (!this.itemCodec.isValid(item))
return false;
return true;
}
byteLength(value) {
let byteLength = this.lengthCodec.byteLength(value.length);
for (const item of value)
byteLength += this.itemCodec.byteLength(item);
return byteLength;
}
_encode(value, buffer, c) {
this.lengthCodec._encode(value.length, buffer, c);
for (const item of value)
this.itemCodec._encode(item, buffer, c);
}
_decode(buffer, c) {
const length = this.lengthCodec._decode(buffer, c);
const value = Array(length);
for (let i = 0; i < length; i++)
value[i] = this.itemCodec._decode(buffer, c);
return value;
}
};
// src/Codecs/BitField/index.ts
var BIT_MAP = {
0: 128,
1: 64,
2: 32,
3: 16,
4: 8,
5: 4,
6: 2,
7: 1
};
var createBitFieldCodec = (keys) => new BitFieldCodec(keys);
var BitFieldCodec = class extends AbstractCodec {
constructor(keys) {
super();
this.keys = keys;
}
isValid(value) {
if (!value || typeof value !== "object")
return false;
for (const key of this.keys)
if (typeof value[key] !== "boolean")
return false;
return true;
}
byteLength(_value) {
return Math.ceil(this.keys.length / 8);
}
_encode(value, buffer, c) {
for (let i = 0; i < this.keys.length; i++) {
if (i % 8 === 0)
buffer[c.offset] = 0;
if (value[this.keys[i]] === true)
buffer[c.offset] |= BIT_MAP[i % 8];
if (i % 8 === 7)
c.offset++;
}
if (this.keys.length % 8 !== 0)
c.offset++;
}
_decode(buffer, c) {
if (buffer.byteLength < c.offset + Math.ceil(this.keys.length / 8))
throw new BufferfyByteLengthError();
const value = {};
for (let i = 0; i < this.keys.length; i++) {
value[this.keys[i]] = (buffer[c.offset] & BIT_MAP[i % 8]) > 0;
if (i % 8 === 7)
c.offset++;
}
if (this.keys.length % 8 !== 0)
c.offset++;
return value;
}
};
// src/Codecs/Boolean/index.ts
var createBooleanCodec = () => new BooleanCodec();
var BooleanCodec = class extends AbstractCodec {
isValid(value) {
return typeof value === "boolean";
}
byteLength(_value) {
return 1;
}
_encode(value, buffer, c) {
buffer[c.offset++] = value ? 1 : 0;
}
_decode(buffer, c) {
if (buffer.byteLength < c.offset + 1)
throw new BufferfyByteLengthError();
return buffer[c.offset++] === 1;
}
};
// src/Codecs/Bytes/Fixed.ts
var BytesFixedCodec = class extends AbstractCodec {
constructor(byteLength) {
super();
this._byteLength = byteLength;
}
isValid(value) {
return value instanceof Uint8Array;
}
byteLength(_) {
return this._byteLength;
}
_encode(value, buffer, c) {
for (const byte of value)
buffer[c.offset++] = byte;
}
_decode(buffer, c) {
if (buffer.byteLength < c.offset + this._byteLength)
throw new BufferfyByteLengthError();
const value = new Uint8Array(buffer.buffer, buffer.byteOffset + c.offset, this._byteLength);
c.offset += this._byteLength;
return value;
}
};
var createConstantCodec = (value) => {
if (typeof value === "object" && value !== null)
return new DeepConstantCodec(value);
return new ConstantCodec(value);
};
var ConstantCodec = class extends AbstractCodec {
constructor(value) {
super();
this.value = value;
}
isValid(value) {
return value === this.value;
}
byteLength(_value) {
return 0;
}
_encode(_value, _buffer, _c) {
return;
}
_decode(_buffer, _c) {
return this.value;
}
};
var DeepConstantCodec = class extends ConstantCodec {
constructor(value) {
super(value);
this.value = value;
}
isValid(value) {
return util.isDeepStrictEqual(value, this.value);
}
};
var createFloatCodec = (bits = 64, endianness = os.endianness()) => {
switch (endianness) {
case "BE": {
switch (bits) {
case 32: {
return new Float32BECodec();
}
case 64: {
return new Float64BECodec();
}
}
}
case "LE": {
switch (bits) {
case 32: {
return new Float32LECodec();
}
case 64: {
return new Float64LECodec();
}
}
}
}
};
var Float32BECodec = class extends AbstractCodec {
isValid(value) {
return typeof value === "number";
}
byteLength(_) {
return 4;
}
_encode(value, buffer, c) {
const dataView = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
dataView.setFloat32(c.offset, value, false);
c.offset += 4;
}
_decode(buffer, c) {
if (buffer.byteLength < c.offset + 4)
throw new BufferfyByteLengthError();
const dataView = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
const value = dataView.getFloat32(c.offset, false);
c.offset += 4;
return value;
}
};
var Float32LECodec = class extends Float32BECodec {
_encode(value, buffer, c) {
const dataView = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
dataView.setFloat32(c.offset, value, true);
c.offset += 4;
}
_decode(buffer, c) {
if (buffer.byteLength < c.offset + 4)
throw new BufferfyByteLengthError();
const dataView = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
const value = dataView.getFloat32(c.offset, true);
c.offset += 4;
return value;
}
};
var Float64BECodec = class extends AbstractCodec {
isValid(value) {
return typeof value === "number";
}
byteLength(_) {
return 8;
}
_encode(value, buffer, c) {
const dataView = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
dataView.setFloat64(c.offset, value, false);
c.offset += 8;
}
_decode(buffer, c) {
if (buffer.byteLength < c.offset + 8)
throw new BufferfyByteLengthError();
const dataView = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
const value = dataView.getFloat64(c.offset, false);
c.offset += 8;
return value;
}
};
var Float64LECodec = class extends Float64BECodec {
_encode(value, buffer, c) {
const dataView = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
dataView.setFloat64(c.offset, value, true);
c.offset += 8;
}
_decode(buffer, c) {
if (buffer.byteLength < c.offset + 8)
throw new BufferfyByteLengthError();
const dataView = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
const value = dataView.getFloat64(c.offset, true);
c.offset += 8;
return value;
}
};
var createUIntCodec = (bits = 48, endianness = os.endianness()) => {
if (bits === 8)
return new UInt8Codec();
switch (endianness) {
case "BE": {
switch (bits) {
case 16: {
return new UInt16BECodec();
}
case 24: {
return new UInt24BECodec();
}
case 32: {
return new UInt32BECodec();
}
case 40: {
return new UInt40BECodec();
}
case 48: {
return new UInt48BECodec();
}
}
}
case "LE": {
switch (bits) {
case 16: {
return new UInt16LECodec();
}
case 24: {
return new UInt24LECodec();
}
case 32: {
return new UInt32LECodec();
}
case 40: {
return new UInt40LECodec();
}
case 48: {
return new UInt48LECodec();
}
}
}
}
};
var UInt8Codec = class extends AbstractCodec {
constructor() {
super();
this._bufferMap = {};
for (let i = 0; i < 256; i++)
this._bufferMap[i] = Buffer.from([i]);
}
isValid(value) {
return typeof value === "number" && Number.isInteger(value) && value >= 0 && value < 256;
}
byteLength(_) {
return 1;
}
_encode(value, buffer, c) {
buffer[c.offset++] = value;
}
_decode(buffer, c) {
if (buffer.byteLength < c.offset + 1)
throw new BufferfyByteLengthError();
return buffer[c.offset++];
}
};
var UInt16BECodec = class extends AbstractCodec {
isValid(value) {
return typeof value === "number" && Number.isInteger(value) && value >= 0 && value < 65536;
}
byteLength(_) {
return 2;
}
_encode(value, buffer, c) {
buffer[c.offset++] = value >>> 8;
buffer[c.offset++] = value & 255;
}
_decode(buffer, c) {
if (buffer.byteLength < c.offset + 2)
throw new BufferfyByteLengthError();
return buffer[c.offset++] * 2 ** 8 + buffer[c.offset++];
}
};
var UInt16LECodec = class extends UInt16BECodec {
_encode(value, buffer, c) {
buffer[c.offset++] = value & 255;
buffer[c.offset++] = value >>> 8;
}
_decode(buffer, c) {
if (buffer.byteLength < c.offset + 2)
throw new BufferfyByteLengthError();
return buffer[c.offset++] + buffer[c.offset++] * 2 ** 8;
}
};
var UInt24BECodec = class extends AbstractCodec {
isValid(value) {
return typeof value === "number" && Number.isInteger(value) && value >= 0 && value < 16777216;
}
byteLength(_) {
return 3;
}
_encode(value, buffer, c) {
buffer[c.offset++] = value >>> 16;
buffer[c.offset++] = value >>> 8 & 255;
buffer[c.offset++] = value & 255;
}
_decode(buffer, c) {
if (buffer.byteLength < c.offset + 3)
throw new BufferfyByteLengthError();
return buffer[c.offset++] * 2 ** 16 + buffer[c.offset++] * 2 ** 8 + buffer[c.offset++];
}
};
var UInt24LECodec = class extends UInt24BECodec {
_encode(value, buffer, c) {
buffer[c.offset++] = value & 255;
buffer[c.offset++] = value >>> 8 & 255;
buffer[c.offset++] = value >>> 16;
}
_decode(buffer, c) {
if (buffer.byteLength < c.offset + 3)
throw new BufferfyByteLengthError();
return buffer[c.offset++] + buffer[c.offset++] * 2 ** 8 + buffer[c.offset++] * 2 ** 16;
}
};
var UInt32BECodec = class extends AbstractCodec {
isValid(value) {
return typeof value === "number" && Number.isInteger(value) && value >= 0 && value < 4294967296;
}
byteLength(_) {
return 4;
}
_encode(value, buffer, c) {
buffer[c.offset++] = value >>> 24;
buffer[c.offset++] = value >>> 16 & 255;
buffer[c.offset++] = value >>> 8 & 255;
buffer[c.offset++] = value & 255;
}
_decode(buffer, c) {
if (buffer.byteLength < c.offset + 4)
throw new BufferfyByteLengthError();
return buffer[c.offset++] * 2 ** 24 + buffer[c.offset++] * 2 ** 16 + buffer[c.offset++] * 2 ** 8 + buffer[c.offset++];
}
};
var UInt32LECodec = class extends UInt32BECodec {
_encode(value, buffer, c) {
buffer[c.offset++] = value >>> 24;
buffer[c.offset++] = value >>> 16 & 255;
buffer[c.offset++] = value >>> 8 & 255;
buffer[c.offset++] = value & 255;
}
_decode(buffer, c) {
if (buffer.byteLength < c.offset + 4)
throw new BufferfyByteLengthError();
return buffer[c.offset++] * 2 ** 24 + buffer[c.offset++] * 2 ** 16 + buffer[c.offset++] * 2 ** 8 + buffer[c.offset++];
}
};
var UInt40BECodec = class extends AbstractCodec {
isValid(value) {
return typeof value === "number" && Number.isInteger(value) && value >= 0 && value < 1099511627776;
}
byteLength(_) {
return 5;
}
_encode(value, buffer, c) {
buffer[c.offset++] = value / 2 ** 32;
buffer[c.offset++] = value >>> 24 & 255;
buffer[c.offset++] = value >>> 16 & 255;
buffer[c.offset++] = value >>> 8 & 255;
buffer[c.offset++] = value & 255;
}
_decode(buffer, c) {
if (buffer.byteLength < c.offset + 5)
throw new BufferfyByteLengthError();
return buffer[c.offset++] * 2 ** 32 + buffer[c.offset++] * 2 ** 24 + buffer[c.offset++] * 2 ** 16 + buffer[c.offset++] * 2 ** 8 + buffer[c.offset++];
}
};
var UInt40LECodec = class extends UInt40BECodec {
_encode(value, buffer, c) {
buffer[c.offset++] = value & 255;
buffer[c.offset++] = value >>> 8 & 255;
buffer[c.offset++] = value >>> 16 & 255;
buffer[c.offset++] = value >>> 24 & 255;
buffer[c.offset++] = value / 2 ** 32;
}
_decode(buffer, c) {
if (buffer.byteLength < c.offset + 5)
throw new BufferfyByteLengthError();
return buffer[c.offset++] + buffer[c.offset++] * 2 ** 8 + buffer[c.offset++] * 2 ** 16 + buffer[c.offset++] * 2 ** 24 + buffer[c.offset++] * 2 ** 32;
}
};
var UInt48BECodec = class extends AbstractCodec {
isValid(value) {
return typeof value === "number" && Number.isInteger(value) && value >= 0 && value < 281474976710656;
}
byteLength(_) {
return 6;
}
_encode(value, buffer, c) {
buffer[c.offset++] = value / 2 ** 40;
buffer[c.offset++] = value / 2 ** 32 & 255;
buffer[c.offset++] = value >>> 24 & 255;
buffer[c.offset++] = value >>> 16 & 255;
buffer[c.offset++] = value >>> 8 & 255;
buffer[c.offset++] = value & 255;
}
_decode(buffer, c) {
if (buffer.byteLength < c.offset + 6)
throw new BufferfyByteLengthError();
return buffer[c.offset++] * 2 ** 40 + buffer[c.offset++] * 2 ** 32 + buffer[c.offset++] * 2 ** 24 + buffer[c.offset++] * 2 ** 16 + buffer[c.offset++] * 2 ** 8 + buffer[c.offset++];
}
};
var UInt48LECodec = class extends UInt48BECodec {
_encode(value, buffer, c) {
buffer[c.offset++] = value & 255;
buffer[c.offset++] = value >>> 8 & 255;
buffer[c.offset++] = value >>> 16 & 255;
buffer[c.offset++] = value >>> 24 & 255;
buffer[c.offset++] = value / 2 ** 32 & 255;
buffer[c.offset++] = value / 2 ** 40;
}
_decode(buffer, c) {
if (buffer.byteLength < c.offset + 6)
throw new BufferfyByteLengthError();
return buffer[c.offset++] + buffer[c.offset++] * 2 ** 8 + buffer[c.offset++] * 2 ** 16 + buffer[c.offset++] * 2 ** 24 + buffer[c.offset++] * 2 ** 32 + buffer[c.offset++] * 2 ** 40;
}
};
// src/Codecs/Int/index.ts
var createIntCodec = (bits = 48, endianness = os.endianness()) => {
if (bits === 8)
return new Int8Codec();
switch (endianness) {
case "BE": {
switch (bits) {
case 16: {
return new Int16BECodec();
}
case 24: {
return new Int24BECodec();
}
case 32: {
return new Int32BECodec();
}
case 40: {
return new Int40BECodec();
}
case 48: {
return new Int48BECodec();
}
}
}
case "LE": {
switch (bits) {
case 16: {
return new Int16LECodec();
}
case 24: {
return new Int24LECodec();
}
case 32: {
return new Int32LECodec();
}
case 40: {
return new Int40LECodec();
}
case 48: {
return new Int48LECodec();
}
}
}
}
};
var Int8Codec = class extends UInt8Codec {
isValid(value) {
return typeof value === "number" && Number.isInteger(value) && value >= -127 && value <= 127;
}
_encode(value, buffer, c) {
super._encode(value + 127, buffer, c);
}
_decode(buffer, c) {
return super._decode(buffer, c) - 127;
}
};
var Int16BECodec = class extends UInt16BECodec {
isValid(value) {
return typeof value === "number" && Number.isInteger(value) && value >= -32767 && value <= 32767;
}
_encode(value, buffer, c) {
super._encode(value + 32767, buffer, c);
}
_decode(buffer, c) {
return super._decode(buffer, c) - 32767;
}
};
var Int16LECodec = class extends UInt16LECodec {
isValid(value) {
return typeof value === "number" && Number.isInteger(value) && value >= -32767 && value <= 32767;
}
_encode(value, buffer, c) {
super._encode(value + 32767, buffer, c);
}
_decode(buffer, c) {
return super._decode(buffer, c) - 32767;
}
};
var Int24BECodec = class extends UInt24BECodec {
isValid(value) {
return typeof value === "number" && Number.isInteger(value) && value >= -8388607 && value <= 8388607;
}
_encode(value, buffer, c) {
super._encode(value + 8388607, buffer, c);
}
_decode(buffer, c) {
return super._decode(buffer, c) - 8388607;
}
};
var Int24LECodec = class extends UInt24LECodec {
isValid(value) {
return typeof value === "number" && Number.isInteger(value) && value >= -8388607 && value <= 8388607;
}
_encode(value, buffer, c) {
super._encode(value + 8388607, buffer, c);
}
_decode(buffer, c) {
return super._decode(buffer, c) - 8388607;
}
};
var Int32BECodec = class extends UInt32BECodec {
isValid(value) {
return typeof value === "number" && Number.isInteger(value) && value >= -2147483647 && value <= 2147483647;
}
_encode(value, buffer, c) {
super._encode(value + 2147483647, buffer, c);
}
_decode(buffer, c) {
return super._decode(buffer, c) - 2147483647;
}
};
var Int32LECodec = class extends UInt32LECodec {
isValid(value) {
return typeof value === "number" && Number.isInteger(value) && value >= -2147483647 && value <= 2147483647;
}
_encode(value, buffer, c) {
super._encode(value + 2147483647, buffer, c);
}
_decode(buffer, c) {
return super._decode(buffer, c) - 2147483647;
}
};
var Int40BECodec = class extends UInt40BECodec {
isValid(value) {
return typeof value === "number" && Number.isInteger(value) && value >= -549755813887 && value <= 549755813887;
}
_encode(value, buffer, c) {
super._encode(value + 549755813887, buffer, c);
}
_decode(buffer, c) {
return super._decode(buffer, c) - 549755813887;
}
};
var Int40LECodec = class extends UInt40LECodec {
isValid(value) {
return typeof value === "number" && Number.isInteger(value) && value >= -549755813887 && value <= 549755813887;
}
_encode(value, buffer, c) {
super._encode(value + 549755813887, buffer, c);
}
_decode(buffer, c) {
return super._decode(buffer, c) - 549755813887;
}
};
var Int48BECodec = class extends UInt48BECodec {
isValid(value) {
return typeof value === "number" && Number.isInteger(value) && value >= -140737488355327 && value <= 140737488355327;
}
_encode(value, buffer, c) {
super._encode(value + 140737488355327, buffer, c);
}
_decode(buffer, c) {
return super._decode(buffer, c) - 140737488355327;
}
};
var Int48LECodec = class extends UInt48LECodec {
isValid(value) {
return typeof value === "number" && Number.isInteger(value) && value >= -140737488355327 && value <= 140737488355327;
}
_encode(value, buffer, c) {
super._encode(value + 140737488355327, buffer, c);
}
_decode(buffer, c) {
return super._decode(buffer, c) - 140737488355327;
}
};
// src/Codecs/Object/index.ts
function createObjectCodec(properties) {
return new ObjectCodec(properties);
}
var ObjectCodec = class extends AbstractCodec {
constructor(properties) {
super();
this.properties = properties;
this.entries = Object.entries(properties);
}
isValid(value) {
if (typeof value !== "object" || value === null)
return false;
for (const [key, codec] of this.entries)
if (!codec.isValid(value[key]))
return false;
return true;
}
byteLength(value) {
let byteLength = 0;
for (const [key, codec] of this.entries)
byteLength += codec.byteLength(value[key]);
return byteLength;
}
_encode(value, buffer, c) {
for (const [key, codec] of this.entries)
codec._encode(value[key], buffer, c);
}
_decode(buffer, c) {
const value = {};
for (const [key, codec] of this.entries)
value[key] = codec._decode(buffer, c);
return value;
}
};
// src/Codecs/Record/Fixed.ts
var RecordFixedCodec = class extends AbstractCodec {
constructor(length, keyCodec, valueCodec) {
super();
this.length = length;
this.keyCodec = keyCodec;
this.valueCodec = valueCodec;
}
isValid(value) {
if (value === null || typeof value !== "object")
return false;
const entries = Object.entries(value);
if (entries.length !== this.length)
return false;
for (const [key, property] of entries)
if (!this.keyCodec.isValid(key) || !this.valueCodec.isValid(property))
return false;
return true;
}
byteLength(value) {
let byteLength = 0;
for (const [key, property] of Object.entries(value))
byteLength += this.keyCodec.byteLength(key) + this.valueCodec.byteLength(property);
return byteLength;
}
_encode(value, buffer, c) {
for (const [key, property] of Object.entries(value)) {
this.keyCodec._encode(key, buffer, c);
this.valueCodec._encode(property, buffer, c);
}
}
_decode(buffer, c) {
const value = {};
let index = this.length;
while (index--)
value[this.keyCodec._decode(buffer, c)] = this.valueCodec._decode(buffer, c);
return value;
}
};
// src/Codecs/Record/Variable.ts
var RecordVariableCodec = class extends AbstractCodec {
constructor(keyCodec, valueCodec, lengthCodec = new VarInt60Codec()) {
super();
this.keyCodec = keyCodec;
this.valueCodec = valueCodec;
this.lengthCodec = lengthCodec;
}
isValid(value) {
if (value === null || typeof value !== "object")
return false;
for (const [key, property] of Object.entries(value))
if (!this.keyCodec.isValid(key) || !this.valueCodec.isValid(property))
return false;
return true;
}
byteLength(value) {
const entries = Object.entries(value);
let byteLength = this.lengthCodec.byteLength(entries.length);
for (const [key, property] of entries)
byteLength += this.keyCodec.byteLength(key) + this.valueCodec.byteLength(property);
return byteLength;
}
_encode(value, buffer, c) {
const entries = Object.entries(value);
this.lengthCodec._encode(entries.length, buffer, c);
for (const [key, property] of entries) {
this.keyCodec._encode(key, buffer, c);
this.valueCodec._encode(property, buffer, c);
}
}
_decode(buffer, c) {
const value = {};
let index = this.lengthCodec._decode(buffer, c);
while (index--) {
const key = this.keyCodec._decode(buffer, c);
value[key] = this.valueCodec._decode(buffer, c);
}
return value;
}
};
var StringFixedCodec = class extends AbstractCodec {
constructor(byteLength, encoding = "utf8") {
super();
this.encoding = encoding;
this._byteLength = byteLength;
this._bufferCodec = new BytesFixedCodec(byteLength);
}
isValid(value) {
return typeof value === "string";
}
byteLength(_value) {
return this._byteLength;
}
_encode(value, buffer, c) {
if (this.encoding === "utf8") {
const result = new TextEncoder().encodeInto(value, new Uint8Array(buffer.buffer, buffer.byteOffset + c.offset, this._byteLength));
c.offset += result.written;
return;
}
let valueBuffer;
switch (this.encoding) {
case "hex": {
valueBuffer = base.hex.decode(value);
break;
}
case "base32": {
valueBuffer = base.base32.decode(value);
break;
}
case "base58": {
valueBuffer = base.base58.decode(value);
break;
}
case "base64": {
valueBuffer = base.base64.decode(value);
break;
}
case "base64url": {
valueBuffer = base.base64url.decode(value);
break;
}
}
if (!valueBuffer)
throw new BufferfyError("Invalid encoding");
this._bufferCodec._encode(valueBuffer, buffer, c);
}
_decode(buffer, c) {
const valueBuffer = this._bufferCodec._decode(buffer, c);
let value;
switch (this.encoding) {
case "hex": {
value = base.hex.encode(valueBuffer);
break;
}
case "base32": {
value = base.base32.encode(valueBuffer);
break;
}
case "base58": {
value = base.base58.encode(valueBuffer);
break;
}
case "base64": {
value = base.base64.encode(valueBuffer);
break;
}
case "base64url": {
value = base.base64url.encode(valueBuffer);
break;
}
case "utf8": {
value = new TextDecoder().decode(valueBuffer);
break;
}
}
return value;
}
};
var StringVariableCodec = class extends AbstractCodec {
constructor(encoding = "utf8", lengthCodec = new VarInt60Codec()) {
super();
this.encoding = encoding;
this.lengthCodec = lengthCodec;
this._bufferCodec = new BytesVariableCodec(this.lengthCodec);
}
isValid(value) {
return typeof value === "string";
}
byteLength(value) {
let valueBuffer;
switch (this.encoding) {
case "hex": {
const byteLength = value.length / 2;
return this.lengthCodec.byteLength(byteLength) + byteLength;
}
case "base32": {
valueBuffer = base.base32.decode(value);
break;
}
case "base58": {
valueBuffer = base.base58.decode(value);
break;
}
case "base64": {
valueBuffer = base.base64.decode(value);
break;
}
case "base64url": {
valueBuffer = base.base64url.decode(value);
break;
}
case "utf8": {
valueBuffer = new TextEncoder().encode(value);
break;
}
}
if (!valueBuffer)
throw new BufferfyError("Invalid encoding");
return this._bufferCodec.byteLength(valueBuffer);
}
_encode(value, buffer, c) {
let valueBuffer;
switch (this.encoding) {
case "hex": {
valueBuffer = base.hex.decode(value);
break;
}
case "base32": {
valueBuffer = base.base32.decode(value);
break;
}
case "base58": {
valueBuffer = base.base58.decode(value);
break;
}
case "base64": {
valueBuffer = base.base64.decode(value);
break;
}
case "base64url": {
valueBuffer = base.base64url.decode(value);
break;
}
case "utf8": {
valueBuffer = new TextEncoder().encode(value);
break;
}
}
if (!valueBuffer)
throw new BufferfyError("Invalid encoding");
this._bufferCodec._encode(valueBuffer, buffer, c);
}
_decode(buffer, c) {
const valueBuffer = this._bufferCodec._decode(buffer, c);
let value;
switch (this.encoding) {
case "hex": {
value = base.hex.encode(valueBuffer);
break;
}
case "base32": {
value = base.base32.encode(valueBuffer);
break;
}
case "base58": {
value = base.base58.encode(valueBuffer);
break;
}
case "base64": {
value = base.base64.encode(valueBuffer);
break;
}
case "base64url": {
value = base.base64url.encode(valueBuffer);
break;
}
case "utf8": {
value = new TextDecoder().decode(valueBuffer);
break;
}
}
return value;
}
};
// src/Codecs/Transform/index.ts
var createTransformCodec = (targetCodec, options) => new TransformCodec(targetCodec, options);
var TransformCodec = class extends AbstractCodec {
constructor(targetCodec, options) {
super();
this.targetCodec = targetCodec;
this._isSourceValid = options.isValid || ((value) => targetCodec.isValid(options.encode(value)));
this._encodeSource = options.encode;
this._decodeTarget = options.decode;
}
isValid(value) {
try {
const isValid = this._isSourceValid(value);
return isValid;
} catch (error) {
return false;
}
}
byteLength(value) {
return this.targetCodec.byteLength(this._encodeSource(value));
}
_encode(value, buffer, c) {
return this.targetCodec._encode(this._encodeSource(value), buffer, c);
}
_decode(buffer, c) {
const preOffset = c.offset;
const targetValue = this.targetCodec._decode(buffer, c);
const postOffset = c.offset;
const targetBuffer = new Uint8Array(buffer.buffer, buffer.byteOffset + preOffset, postOffset - preOffset);
return this._decodeTarget(targetValue, targetBuffer);
}
};
// src/Codecs/Tuple/index.ts
var createTupleCodec = (codecs) => new TupleCodec(codecs);
var TupleCodec = class extends AbstractCodec {
constructor(codecs) {
super();
this.codecs = codecs;
}
isValid(value) {
if (!Array.isArray(value) || value.length !== this.codecs.length)
return false;
for (let i = 0; i < this.codecs.length; i++)
if (!this.codecs[i].isValid(value[i]))
return false;
return true;
}
byteLength(value) {
let byteLength = 0;
for (let i = 0; i < this.codecs.length; i++)
byteLength += this.codecs[i].byteLength(value[i]);
return byteLength;
}
_encode(value, buffer, c) {
for (let i = 0; i < this.codecs.length; i++)
this.codecs[i]._encode(value[i], buffer, c);
}
_decode(buffer, c) {
const value = new Array(this.codecs.length);
for (let i = 0; i < this.codecs.length; i++)
value[i] = this.codecs[i]._decode(buffer, c);
return value;
}
};
// src/Codecs/Union/index.ts
var createUnionCodec = (codecs, indexCodec = new VarInt60Codec()) => new UnionCodec(codecs, indexCodec);
var UnionCodec = class _UnionCodec extends AbstractCodec {
constructor(codecs, indexCodec = new VarInt60Codec()) {
super();
this.indexCodec = indexCodec;
this.codecs = codecs.flatMap((codec) => {
if (codec instanceof _UnionCodec)
return codec.codecs;
return codec;
});
}
isValid(value) {
for (const codec of this.codecs)
if (codec.isValid(value))
return true;
return false;
}
byteLength(value) {
for (let i = 0; i < this.codecs.length; i++) {
if (this.codecs[i].isValid(value))
return this.indexCodec.byteLength(i) + this.codecs[i].byteLength(value);
}
throw new BufferfyError("Value does not match any codec");
}
_encode(value, buffer, c) {
for (let i = 0; i < this.codecs.length; i++) {
if (this.codecs[i].isValid(value)) {
this.indexCodec._encode(i, buffer, c);
this.codecs[i]._encode(value, buffer, c);
return;
}
}
throw new BufferfyError("Value does not match any codec");
}
_decode(buffer, c) {
const index = this.indexCodec._decode(buffer, c);
return this.codecs[index]._decode(buffer, c);
}
};
// src/Codecs/VarInt/VarInt15.ts
var VarInt15Codec = class extends AbstractCodec {
isValid(value) {
return typeof value === "number" && Number.isInteger(value) && value >= 0 && value < 32768;
}
byteLength(value) {
return value < 128 ? 1 : 2;
}
_encode(value, buffer, c) {
const byteLength = this.byteLength(value);
switch (byteLength) {
case 1: {
buffer[c.offset++] = value;
return;
}
case 2: {
buffer[c.offset++] = value >>> 8 | 128;
buffer[c.offset++] = value & 255;
return;
}
}
}
_decode(buffer, c) {
if (buffer.byteLength < c.offset + 1)
throw new BufferfyByteLengthError();
const byte0 = buffer[c.offset++];
const lengthBits = 128 & byte0;
const remainingByteLength = lengthBits / 128;
if (buffer.byteLength < c.offset + remainingByteLength)
throw new BufferfyByteLengthError();
switch (remainingByteLength) {
case 0: {
return byte0;
}
case 1: {
return (127 & byte0) * 2 ** 8 + buffer[c.offset++];
}
}
}
};
// src/Codecs/VarInt/VarInt30.ts
var VarInt30Codec = class extends AbstractCodec {
isValid(value) {
return typeof value === "number" && Number.isInteger(value) && value >= 0 && value < 1073741824;
}
byteLength(value) {
return value < 64 ? 1 : value < 16384 ? 2 : value < 4194304 ? 3 : 4;
}
_encode(value, buffer, c) {
const byteLength = this.byteLength(value);
switch (byteLength) {
case 1: {
buffer[c.offset++] = value;
return;
}
case 2: {
buffer[c.offset++] = value >>> 8 | 64;
buffer[c.offset++] = value & 255;
return;
}
case 3: {
buffer[c.offset++] = value >>> 16 | 128;
buffer[c.offset++] = value >>> 8 & 255;
buffer[c.offset++] = value & 255;
return;
}
case 4: {
buffer[c.offset++] = value >>> 24 | 192;
buffer[c.offset++] = value >>> 16 & 255;
buffer[c.offset++] = value >>> 8 & 255;
buffer[c.offset++] = value & 255;
return;
}
}
}
_decode(buffer, c) {
if (buffer.byteLength < c.offset + 1)
throw new BufferfyByteLengthError();
const byte0 = buffer[c.offset++];
const lengthBits = 192 & byte0;
const remainingByteLength = lengthBits / 64;
if (buffer.byteLength < c.offset + remainingByteLength)
throw new BufferfyByteLengthError();
switch (remainingByteLength) {
case 0: {
return byte0;
}
case 1: {
return (63 & byte0) * 2 ** 8 + buffer[c.offset++];
}
case 2: {
return (63 & byte0) * 2 ** 16 + buffer[c.offset++] * 2 ** 8 + buffer[c.offset++];
}
case 3: {
return (63 & byte0) * 2 ** 24 + buffer[c.offset++] * 2 ** 16 + buffer[c.offset++] * 2 ** 8 + buffer[c.offset++];
}
}
}
};
// src/Codecs/Array/index.ts
function createArrayCodec(itemCodec, lengthOrCodec = new VarInt60Codec()) {
if (typeof lengthOrCodec === "number")
return new ArrayFixedCodec(lengthOrCodec, itemCodec);
return new ArrayVariableCodec(itemCodec, lengthOrCodec);
}
// src/Codecs/Bytes/index.ts
function createBytesCodec(lengthOrCodec = new VarInt60Codec()) {
if (typeof lengthOrCodec === "number")
return new BytesFixedCodec(lengthOrCodec);
return new BytesVariableCodec(lengthOrCodec);
}
// src/Codecs/Object/Merge/index.ts
var mergeObjectCodecs = (objectCodecs) => {
const properties = {};
for (const objectCodec of objectCodecs)
for (const [key, codec] of objectCodec.entries)
properties[key] = codec;
return new ObjectCodec(properties);
};
// src/Codecs/Object/Omit/index.ts
var omitObjectCodec = (objectCodec, keys) => {
const keySet = new Set(keys);
const pickedProperties = {};
for (const [key, codec] of objectCodec.entries)
if (!keySet.has(key))
pickedProperties[key] = codec;
return new ObjectCodec(pickedProperties);
};
// src/Codecs/Object/Pick/index.ts
var pickObjectCodec = (objectCodec, keys) => {
const keySet = new Set(keys);
const pickedProperties = {};
for (const [key, codec] of objectCodec.entries)
if (keySet.has(key))
pickedProperties[key] = codec;
return new ObjectCodec(pickedProperties);
};
// src/Codecs/Record/index.ts
function createRecordCodec(keyCodec, valueCodec, lengthOrCodec = new VarInt60Codec()) {
if (typeof lengthOrCodec === "number")
return new RecordFixedCodec(lengthOrCodec, keyCodec, valueCodec);
return new RecordVariableCodec(keyCodec, valueCodec, lengthOrCodec);
}
// src/Codecs/String/index.ts
function createStringCodec(encoding = "utf8", byteLengthOrCodec = new VarInt60Codec()) {
if (typeof byteLengthOrCodec === "number") {
return new StringFixedCodec(byteLengthOrCodec, encoding);
}
return new StringVariableCodec(encoding, byteLengthOrCodec);
}
// src/Codecs/VarInt/index.ts
var createVarIntCodec = (bits = 60) => {
switch (bits) {
case 15: {
return new VarInt15Codec();
}
case 30: {
return new VarInt30Codec();
}
case 60: {
return new VarInt60Codec();
}
}
};
// src/Codec.ts
var Codec = {
Any: createAnyCodec,
Array: createArrayCodec,
BitField: createBitFieldCodec,
Boolean: createBooleanCodec(),
Bytes: createBytesCodec,
Constant: createConstantCodec,
Enum: (enumValues, indexCodec) => createUnionCodec(
enumValues.map((value) => createConstantCodec(value)),
indexCodec
),
False: createConstantCodec(false),
Float: createFloatCodec,
Int: createIntCodec,
Merge: mergeObjectCodecs,
Null: createConstantCodec(null),
Nullable: (codec) => createUnionCodec([codec, createConstantCodec(null)]),
Object: createObjectCodec,
Omit: omitObjectCodec,
Optional: (codec) => createUnionCodec([codec, createConstantCodec(void 0)]),
Pick: pickObjectCodec,
Record: createRecordCodec,
String: createStringCodec,
Transform: createTransformCodec,
True: createConstantCodec(true),
Tuple: createTupleCodec,
UInt: createUIntCodec,
Undefined: createConstantCodec(void 0),
Union: createUnionCodec,
VarInt: createVarIntCodec
};
exports.AbstractCodec = AbstractCodec;
exports.AnyCodec = AnyCodec;
exports.ArrayFixedCodec = ArrayFixedCodec;
exports.ArrayVariableCodec = ArrayVariableCodec;
exports.BitFieldCodec = BitFieldCodec;
exports.BooleanCodec = BooleanCodec;
exports.BytesFixedCodec = BytesFixedCodec;
exports.BytesVariableCodec = BytesVariableCodec;
exports.Codec = Codec;
exports.ConstantCodec = ConstantCodec;
exports.Float32BECodec = Float32BECodec;
exports.Float32LECodec = Float32LECodec;
exports.Float64BECodec = Float64BECodec;
exports.Float64LECodec = Float64LECodec;
exports.Int16BECodec = Int16BECodec;
exports.Int16LECodec = Int16LECodec;
exports.Int24BECodec = Int24BECodec;
exports.Int24LECodec = Int24LECodec;
exports.Int32BECodec = Int32BECodec;
exports.Int32LECodec = Int32LECodec;
exports.Int40BECodec = Int40BECodec;
exports.Int40LECodec = Int40LECodec;
exports.Int48BECodec = Int48BECodec;
exports.Int48LECodec = Int48LECodec;
exports.Int8Codec = Int8Codec;
exports.ObjectCodec = ObjectCodec;
exports.RecordFixedCodec = RecordFixedCodec;
exports.RecordVariableCodec = RecordVariableCodec;
exports.StringFixedCodec = StringFixedCodec;
exports.StringVariableCodec = StringVariableCodec;
exports.TransformCodec = TransformCodec;
exports.TupleCodec = TupleCodec;
exports.UInt16BECodec = UInt16BECodec;
exports.UInt16LECodec = UInt16LECodec;
exports.UInt24BECodec = UInt24BECodec;
exports.UInt24LECodec = UInt24LECodec;
exports.UInt32BECodec = UInt32BECodec;
exports.UInt32LECodec = UInt32LECodec;
exports.UInt40BECodec = UInt40BECodec;
exports.UInt40LECodec = UInt40LECodec;
exports.UInt48BECodec = UInt48BECodec;
exports.UInt48LECodec = UInt48LECodec;
exports.UInt8Codec = UInt8Codec;
exports.UnionCodec = UnionCodec;
exports.VarInt15Codec = VarInt15Codec;
exports.VarInt30Codec = VarInt30Codec;
exports.VarInt60Codec = VarInt60Codec;