binencode
TypeScript library for encoding and decoding structured binary data. Supports scalars, strings, arrays, objects, and arbitrary nesting — all serialized to a compact big-endian binary wire format.
Installation
npm install binencode
pnpm add binencode
Quick Start
import { bin, serial } from "binencode";
const value = bin.auto({ name: "Alice", score: 42, tags: ["admin", "user"] });
const buffer = serial.encode(value);
const decoded = serial.decode(buffer);
const js = serial.toJS(decoded);
Core Concepts
All values in binencode are represented as Binary objects — typed wrappers around raw byte buffers. The bin namespace provides constructors, serial handles encode/decode, and BinaryBuffer is the underlying growable byte buffer.
Creating Binary Values
bin.auto(value) — automatic conversion
Converts any plain JS value to the appropriate Binary type:
bin.auto(null)
bin.auto(true)
bin.auto(42)
bin.auto(3.14)
bin.auto(42n)
bin.auto("hello")
bin.auto([1, 2, 3])
bin.auto({ x: 1 })
null/undefined | BinaryNull |
boolean | BinaryBool |
| integer | BinaryInt32 |
| float | BinaryFloat32 |
bigint | BinaryInt64 |
string | BinaryString |
Array | BinaryArray |
| plain object | BinaryObject |
Explicit constructors
Use these when you need precise control over the numeric type:
bin.nil()
bin.bool(true)
bin.byte(0xff)
bin.int32(-100)
bin.uint32(4294967295)
bin.int64(-9007199254740993n)
bin.uint64(18446744073709551615n)
bin.float32(3.14)
bin.float64(3.141592653589793)
bin.string("hello 🌍")
bin.char("A")
Collections
bin.array(
bin.int32(1),
bin.string("two"),
bin.nil(),
)
bin.object({ x: bin.int32(10), y: bin.float32(3.14) })
bin.object(new Map([
["key", bin.string("value")],
]))
Serialization
serial.encode(binary, out?)
Serializes a Binary value into a BinaryBuffer. Optionally appends into an existing buffer.
import { bin, serial } from "binencode";
const encoded = serial.encode(bin.auto({ id: 1, name: "Alice" }));
serial.decode(buffer)
Deserializes a BinaryBuffer back into a Binary value.
const decoded = serial.decode(encoded);
serial.toJS(binary)
Converts a Binary back to a plain JavaScript value.
serial.toJS(bin.int32(42))
serial.toJS(bin.string("hi"))
serial.toJS(bin.array(bin.int32(1), bin.int32(2)))
serial.toJS(bin.object({ a: bin.bool(true) }))
Examples
Round-trip a primitive
import { bin, serial } from "binencode";
const original = bin.float64(Math.PI);
const buffer = serial.encode(original);
const result = serial.toJS(serial.decode(buffer));
Round-trip a nested structure
const data = bin.auto({
config: {
host: "localhost",
port: 8080,
tags: ["primary", "read-only"],
},
count: 2,
});
const encoded = serial.encode(data);
const decoded = serial.toJS(serial.decode(encoded));
Append to an existing buffer
import { BinaryBuffer, bin, serial } from "binencode";
const out = new BinaryBuffer();
serial.encode(bin.int32(1), out);
serial.encode(bin.string("hello"), out);
Check if a value is Binary
import { bin, isBin } from "binencode";
isBin(bin.int32(5))
isBin(42)
isBin({})
Wire Format
Each value is encoded as:
[type: i32][componentType: i32][count: i32][data...]
All integers are big-endian. Arrays and objects encode their children recursively. Object keys are encoded as strings before each value.
API Reference
bin namespace
bin.auto(x) | Converts any JS value to Binary |
bin.nil() | Null value |
bin.bool(v) | Boolean |
bin.byte(v) | Unsigned 8-bit integer |
bin.int32(v) | Signed 32-bit integer |
bin.uint32(v) | Unsigned 32-bit integer |
bin.int64(v) | Signed 64-bit integer (bigint) |
bin.uint64(v) | Unsigned 64-bit integer (bigint) |
bin.float32(v) | 32-bit float |
bin.float64(v) | 64-bit float |
bin.char(v) | Single character scalar |
bin.string(v) | UTF-8 string |
bin.array(...items) | Heterogeneous array of Binary |
bin.object(record | map) | Key-value object |
serial namespace
serial.encode(binary, out?) | Encode a Binary to a BinaryBuffer |
serial.decode(buffer) | Decode a BinaryBuffer to a Binary |
serial.toJS(binary) | Convert a Binary to a plain JS value |
isBin(x)
Type guard — returns true if x is a branded Binary value.
BinaryBuffer
Low-level growable byte buffer used internally. Useful if you need direct byte access or want to manage a shared output buffer.
import { BinaryBuffer } from "binencode";
const buf = new BinaryBuffer();
buf.writeInt32(42);
buf.setCursor(0);
buf.readInt32();