UNPKG

bufferfy

Version:
1,609 lines (1,575 loc) 47.7 kB
'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;