Encoding & Decoding
Encoding (compile)
The compile function encodes a source object into Vein binary format using a schema.
import { compile } from "@stacknet/lode";
const vein: Uint8Array = compile(sourceObject, schema);Algorithm
The encoder operates in two passes:
- Validation pass — iterate schema fields, check that required fields are present, resolve type tags, encode each value into a byte buffer
- Write pass — allocate a single
ArrayBufferof the exact total size, write the header and all field entries sequentially
Required Field Enforcement
If a required field is missing from the source object, compile throws:
Error: Required field "name" is missingOptional fields (required: false) are silently omitted from the output if undefined or null.
Type Encoding
| Type | Encoding |
|---|---|
string | Raw UTF-8 bytes |
bool | 0x01 (true) or 0x00 (false) |
string[] | count(2) + per item: len(2) + UTF-8 bytes |
map<string,string> | count(2) + per entry: klen(2) + key + vlen(2) + value |
All multi-byte lengths are big-endian unsigned 16-bit integers.
Map keys are sorted lexicographically before encoding. This is not optional — it is how LODE guarantees determinism.
Decoding (decode)
The decode function reads Vein binary back into a plain JavaScript object.
import { decode } from "@stacknet/lode";
const obj: Record<string, any> = decode(vein, schema);Validation
The decoder validates:
- Minimum length — at least 4 bytes (header size)
- Magic bytes — first two bytes must be
0x4C, 0x44("LD") - Version — must match the schema version exactly
- Field bounds — each field’s declared length must not exceed remaining bytes
- Required fields — all required schema fields must be present in the decoded result
Forward Compatibility
If the decoder encounters a field ID that does not exist in the schema, it skips the field (advances the offset by the declared length) without error. This allows a v1 decoder to read payloads produced by a v2 encoder.
Error Cases
// Too short
decode(new Uint8Array([0x4C]), schema);
// → Error: Vein too short: expected at least 4 bytes
// Wrong magic
decode(new Uint8Array([0xFF, 0xFF, 1, 0]), schema);
// → Error: Invalid magic: expected 0x4C44 ("LD"), got 0xffff
// Version mismatch
decode(v2Vein, v1Schema);
// → Error: Version mismatch: vein is v2, schema is v1
// Truncated
decode(truncatedVein, schema);
// → Error: Field 3 declares length 100 but only 12 bytes remainRound-Trip Example
import { compile, decode, loadLode } from "@stacknet/lode";
const schema = loadLode("model-layer-v1.lode");
const original = {
name: "fast",
isDefault: false,
models: ["qwen3:8b"],
defaultModel: "qwen3:8b",
};
const vein = compile(original, schema);
const decoded = decode(vein, schema);
console.log(decoded);
// { name: "fast", isDefault: false, models: ["qwen3:8b"], defaultModel: "qwen3:8b" }