Skip to content

Repository files navigation

structon

Random-access struct encoding/decoding as an extensible class for msgpackr, cbor-x, and compatible binary encoders.

Overview

structon extracts the random-access struct functionality from msgpackr's struct.js into a standalone, class-based package. It exposes a createStructon(BaseClass) factory that returns a class extending any compatible encoder. The resulting class encodes top-level plain objects as compact fixed-width structs with lazy-access property getters, while delegating inner nested-object encoding to the underlying base encoder (msgpackr or cbor-x).

Binary format compatibility: the byte layout produced by structon is identical to msgpackr's struct.js format. Data written by either implementation can be read by the other.

Key features

  • Zero-copy lazy access — property getters read directly from the raw buffer; no full deserialization needed to access a single field.
  • Extensible base class — extend msgpackr's Packr/Encoder or cbor-x's Encoder (or any compatible encoder).
  • Structure caching — structure definitions are incrementally learned and can be persisted via saveStructures/getStructures callbacks.
  • Nested struct support — nested plain objects are encoded by the base encoder; nested structs within a struct field are handled recursively.
  • Binary compatible with msgpackr's struct.js random-access format.

Installation

npm install structon
# peer dependency for msgpackr usage:
npm install msgpackr
# or for cbor-x:
npm install cbor-x

Usage

With msgpackr

import{Packr}from'msgpackr';import{createStructon}from'structon';constStructon=createStructon(Packr);// Persist structures so they survive process restartsletsavedStructures=null;constenc=newStructon({structures: [],saveStructures(s){savedStructures=s;},getStructures(){returnsavedStructures;},});constbuf=enc.encode({name: 'Alice',age: 30,score: 99.5});constobj=enc.decode(buf);console.log(obj.name);// 'Alice' — reads from buffer without full decodeconsole.log(obj.age);// 30console.log(obj.toJSON());// { name: 'Alice', age: 30, score: 99.5 }

With cbor-x

import{Encoder}from'cbor-x';import{createStructon}from'structon';constStructon=createStructon(Encoder);constenc=newStructon({structures: []});constbuf=enc.encode({id: 1,label: 'widget'});constobj=enc.decode(buf);console.log(obj.id);// 1console.log(obj.label);// 'widget'

Non-struct values pass through

Values that are not plain objects (arrays, strings, numbers, Maps, etc.) are encoded and decoded by the base class transparently.

enc.encode([1,2,3]);// regular msgpack/cbor arrayenc.encode('hello');// regular msgpack/cbor stringenc.encode(newMap([['a',1]]));// regular msgpack/cbor map

API

createStructon(BaseClass)

Returns a Structon class that extends BaseClass.

Parameters

  • BaseClassPackr from msgpackr, Encoder from cbor-x, or any compatible encoder class.

Returns a class with the following additions over BaseClass:

MemberDescription
encode(value)Encodes plain objects as structs; other values via base class.
decode(buffer)Decodes struct buffers into lazy objects; other buffers via base class.
typedStructsArray of learned structure definitions (auto-populated).
_decodeSliceDirect(src, start, end)Low-level slice decoder used by struct getters.

Constructor options

All options from the base class are forwarded. Additional behaviour:

OptionDescription
structuresShared structure definitions array (passed to base class).
saveStructures(s)Called when new struct definitions are learned (msgpackr API).
getStructures()Called to load previously saved structures (msgpackr API).
saveShared(s)cbor-x equivalent of saveStructures.
getShared()cbor-x equivalent of getStructures.

Binary format

The format is identical to msgpackr's struct.js:

[header (1-4 bytes)][fixed-width field section][variable ref section]
  • Header: record ID encoded as 0x20 + id (single byte for ids 0-15), or 0x38/0x39/0x3a with 1/2/3 extra bytes for larger IDs.
  • Fixed section: one fixed-width slot per field — numbers as uint8/uint32/float64, strings as 0/1/2-byte ref offsets, objects as 2/4-byte ref offsets, dates as float64.
  • Ref section: UTF-8 string bytes followed by msgpack/cbor-encoded object bytes.

Field access resolves directly from the buffer — only the bytes for the accessed field are read.

Interoperability with msgpackr

structon is bidirectionally byte-compatible with msgpackr's randomAccessStructure: true mode (msgpackr ≤ 1.11.10, before its struct.js was removed). The test suite verifies all four directions:

  • Structon writes → native Packr reads
  • native Packr writes → Structon reads
  • byte-identical output for a given plain object
  • mixed types + nested objects round-trip when structures and typedStructs are shared

These compatibility tests pin msgpackr 1.11.10 as a dev dependency.

License

Apache 2.0 — see LICENSE.

About

Random-access struct encoding/decoding as an extensible class for msgpackr and cbor-x

Resources

Code of conduct

Contributing

Security policy

Stars

13 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages