Skip to content

Repository files navigation

data-struct

CInpm

Schema-driven binary serialization between JavaScript values and Node Buffers.

  • Tiny. No runtime dependencies.
  • Typed. A schema infers the exact TypeScript shape of the decoded value via Infer<S>.
  • Fast. Two-pass encoder allocates the output buffer exactly once.
  • Dual-format. Ships ESM + CommonJS + .d.ts for both.
  • Wire-stable. Big-endian by default, byte-identical with prior 0.0.x releases.

Install

npm install data-struct

Requires Node >=20.9.

Usage

import{struct,t,typeInfer}from'data-struct';constHero=struct({id: t.u32,name: t.string,hp: t.i16,skills: [{id: t.u16,description: t.string}],playable: t.bool,experience: t.u32,position: {x: t.u16,y: t.u16},});typeHero=Infer<typeofHero.schema>;constbuf=Hero.encode({id: 9,name: 'CirnoBaka',hp: 146,skills: [{id: 34,description: 'freezing frogs'},{id: 16,description: 'perfect math'},],playable: false,experience: 99_999_999,position: {x: 2,y: 3},});consthero=Hero.decode(buf);// typed as Hero

Functional form, when you don't want to keep a compiled struct around:

import{encode,decode,t}from'data-struct';constMap2D=[[t.u8]];constbuf=encode([[0,1,0],[1,0,1]],Map2D);constmap=decode(buf,Map2D);// number[][]

API

Codec tokens — t

TokenBytesTS typeNotes
t.bool1boolean
t.i8 / t.u81number
t.i16 / t.u162numberbig-endian
t.i32 / t.u324numberbig-endian
t.f32 / t.f644 / 8numberbig-endian
t.i64 / t.u648bigintbig-endian
t.string2 + utf-8stringuint16 length prefix, max 65535 utf-8 bytes
t.shortBytes2 + nUint8Arrayuint16 length prefix, max 65535 bytes
t.bytes4 + nUint8Arrayuint32 length prefix, max 4294967295 bytes

Little-endian variants live under t.le.* (e.g. t.le.u32, t.le.f64, t.le.string).

Schema shape

A schema is one of:

  • A codec token (t.u32).
  • A single-element array [Schema] — encodes as a uint16 length prefix followed by N child encodings.
  • A plain object — fields encoded in declared key order.
typeSchema=Codec<unknown>|Schema[]|{[k: string]: Schema};typeInfer<S>=/* recursively maps each leaf to its TS type */;

Functions

struct<SextendsSchema>(schema: S): {schema: S;encode(value: Infer<S>): Buffer;decode(input: Uint8Array): Infer<S>;sizeOf(value: Infer<S>): number;};encode<SextendsSchema>(value: Infer<S>,schema: S): Buffer;decode<SextendsSchema>(input: Uint8Array,schema: S): Infer<S>;

struct(schema) compiles the schema tree once and reuses the compiled codec across calls — prefer it in hot paths.

Errors

Validation throws DataStructError with a code:

CodeWhen
VALUE_OUT_OF_RANGENumeric value outside the leaf's range or non-int
STRING_TOO_LONGUTF-8 byte length exceeds 65535
BYTES_TOO_LONGBytes value exceeds the leaf's length cap
ARRAY_TOO_LONGArray length exceeds 65535
BUFFER_UNDERFLOWDecode would read past the end of the input
SCHEMA_MISMATCHValue shape does not match the schema
INVALID_SCHEMASchema itself is malformed

Every error carries path (e.g. $.skills[1].description) and, for decode errors, offset.

Wire format

bool : 1 byte 0x00 = false, anything else = true
i8/u8 : 1 byte
i16/u16 : 2 bytes BE
i32/u32 : 4 bytes BE
f32/f64 : 4 / 8 bytes BE
i64/u64 : 8 bytes BE
string : uint16 BE length || utf-8 bytes
shortBytes : uint16 BE length || raw bytes
bytes : uint32 BE length || raw bytes
array [E] : uint16 BE length || N encoded elements
object {…} : fields encoded in declared key order, no header

LE variants (t.le.*) swap the byte order of length prefixes and the numeric payload.

Migration from 0.0.x

The 0.1.0 release is a full rewrite with a new API surface. The wire format is preserved, so buffers produced by older versions decode correctly under the new codecs.

OldNew
DataTypes.booleant.bool
DataTypes.int8 / uint8t.i8 / t.u8
DataTypes.int16/uint16t.i16 / t.u16
DataTypes.int32/uint32t.i32 / t.u32
DataTypes.floatt.f32
DataTypes.doublet.f64
DataTypes.stringt.string
DataTypes.shortBuffert.shortBytes
DataTypes.buffert.bytes
DataWriter(obj, scheme)encode(obj, schema)
DataReader(buf, scheme)decode(buf, schema)

The legacy DataTypes / DataReader / DataWriter exports are removed.

Development

npm install
npm run typecheck
npm run lint
npm test
npm run bench
npm run build

License

MIT

About

Convert between JS object and Node.js buffer

Resources

Stars

6 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages