zon-format
Version:
ZON: The most token-efficient serialization format for LLMs - beats CSV, TOON, JSON, and all competitors
193 lines (192 loc) • 5.92 kB
JavaScript
"use strict";
/**
* Binary ZON Encoder
*
* Encodes JavaScript values to compact binary format
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.BinaryZonEncoder = void 0;
exports.encodeBinary = encodeBinary;
const constants_1 = require("./constants");
/**
* Binary ZON Encoder
*/
class BinaryZonEncoder {
constructor() {
this.buffer = [];
}
/**
* Encode data to binary ZON format
*/
encode(data) {
this.buffer = [];
this.buffer.push(...constants_1.MAGIC_HEADER);
this.encodeValue(data);
return new Uint8Array(this.buffer);
}
/**
* Encode a single value
*/
encodeValue(value) {
if (value === null || value === undefined) {
this.buffer.push(constants_1.TypeMarker.NIL);
}
else if (typeof value === 'boolean') {
this.buffer.push(value ? constants_1.TypeMarker.TRUE : constants_1.TypeMarker.FALSE);
}
else if (typeof value === 'number') {
this.encodeNumber(value);
}
else if (typeof value === 'string') {
this.encodeString(value);
}
else if (Array.isArray(value)) {
this.encodeArray(value);
}
else if (typeof value === 'object') {
this.encodeObject(value);
}
else {
throw new Error(`Unsupported type: ${typeof value}`);
}
}
/**
* Encode a number (int or float)
*/
encodeNumber(value) {
if (Number.isInteger(value)) {
if (value >= 0 && value <= 127) {
this.buffer.push((0, constants_1.createPositiveFixint)(value));
}
else if (value >= -32 && value < 0) {
this.buffer.push((0, constants_1.createNegativeFixint)(value));
}
else if (value >= 0 && value <= 0xFF) {
this.buffer.push(constants_1.TypeMarker.UINT8);
this.buffer.push(value);
}
else if (value >= 0 && value <= 0xFFFF) {
this.buffer.push(constants_1.TypeMarker.UINT16);
this.writeUint16(value);
}
else if (value >= 0 && value <= 0xFFFFFFFF) {
this.buffer.push(constants_1.TypeMarker.UINT32);
this.writeUint32(value);
}
else if (value >= -128 && value <= 127) {
this.buffer.push(constants_1.TypeMarker.INT8);
this.buffer.push(value & 0xFF);
}
else if (value >= -32768 && value <= 32767) {
this.buffer.push(constants_1.TypeMarker.INT16);
this.writeInt16(value);
}
else {
this.buffer.push(constants_1.TypeMarker.INT32);
this.writeInt32(value);
}
}
else {
this.buffer.push(constants_1.TypeMarker.FLOAT64);
this.writeFloat64(value);
}
}
/**
* Encode a string
*/
encodeString(value) {
const bytes = new TextEncoder().encode(value);
const length = bytes.length;
if (length <= 31) {
this.buffer.push((0, constants_1.createFixstr)(length));
}
else if (length <= 0xFF) {
this.buffer.push(constants_1.TypeMarker.STR8);
this.buffer.push(length);
}
else if (length <= 0xFFFF) {
this.buffer.push(constants_1.TypeMarker.STR16);
this.writeUint16(length);
}
else {
this.buffer.push(constants_1.TypeMarker.STR32);
this.writeUint32(length);
}
this.buffer.push(...bytes);
}
/**
* Encode an array
*/
encodeArray(value) {
const length = value.length;
if (length <= 15) {
this.buffer.push((0, constants_1.createFixarray)(length));
}
else if (length <= 0xFFFF) {
this.buffer.push(constants_1.TypeMarker.ARRAY16);
this.writeUint16(length);
}
else {
this.buffer.push(constants_1.TypeMarker.ARRAY32);
this.writeUint32(length);
}
for (const item of value) {
this.encodeValue(item);
}
}
/**
* Encode an object/map
*/
encodeObject(value) {
const keys = Object.keys(value);
const length = keys.length;
if (length <= 15) {
this.buffer.push((0, constants_1.createFixmap)(length));
}
else if (length <= 0xFFFF) {
this.buffer.push(constants_1.TypeMarker.MAP16);
this.writeUint16(length);
}
else {
this.buffer.push(constants_1.TypeMarker.MAP32);
this.writeUint32(length);
}
for (const key of keys) {
this.encodeString(key);
this.encodeValue(value[key]);
}
}
// Helper methods for writing multi-byte values
writeUint16(value) {
this.buffer.push((value >> 8) & 0xFF);
this.buffer.push(value & 0xFF);
}
writeUint32(value) {
this.buffer.push((value >> 24) & 0xFF);
this.buffer.push((value >> 16) & 0xFF);
this.buffer.push((value >> 8) & 0xFF);
this.buffer.push(value & 0xFF);
}
writeInt16(value) {
this.writeUint16(value & 0xFFFF);
}
writeInt32(value) {
this.writeUint32(value & 0xFFFFFFFF);
}
writeFloat64(value) {
const buffer = new ArrayBuffer(8);
const view = new DataView(buffer);
view.setFloat64(0, value, false);
for (let i = 0; i < 8; i++) {
this.buffer.push(view.getUint8(i));
}
}
}
exports.BinaryZonEncoder = BinaryZonEncoder;
/**
* Encode data to binary ZON format
*/
function encodeBinary(data) {
const encoder = new BinaryZonEncoder();
return encoder.encode(data);
}