C-style structure serializer and deserializer.
npm install @yume-chan/struct!license
!npm type definitions

!npm bundle size
!Codecov
A C-style structure serializer and deserializer. Written in TypeScript and highly takes advantage of its type system.
The new API is inspired by TypeGPU which improves DX and tree-shaking.
WARNING: The public API is UNSTABLE. Open a GitHub discussion if you have any questions.
``sh`
$ npm i @yume-chan/struct
`ts
import { struct, u8, u16, s32, buffer, string } from "@yume-chan/struct";
const Message = struct(
{
a: u8,
b: u16,
c: s32,
d: buffer(4), // Fixed length Uint8Array
e: buffer("b"), // Use value of b as lengthu32
f: buffer(u32), // length prefixUint8Array
g: buffer(4, {
// Custom conversion between and other typesstring
convert(value: Uint8Array) {
return value[0];
},
back(value: number) {
return new Uint8Array([value, 0, 0, 0]);
},
}),
h: string(64), // is an alias to buffer with UTF-8 string conversion
},
{ littleEndian: true },
);
// Custom reader
const reader = {
position: 0,
readExactly(length) {
const slice = new Uint8Array(100).slice(
this.position,
this.position + length,
);
this.position += length;
return slice;
},
};
const message1 = Message.deserialize(reader); // If reader.readExactly is synchronous, deserialize is also synchronousreader.readExactly
const message2 = await Message.deserialize(reader); // If is asynchronous, so do deserialize
const buffer: Uint8Array = Message.serialize(message1);
`
`ts
import { Field, AsyncExactReadable, Struct, u8 } from "@yume-chan/struct";
const MyField: Field
size: 4, // 0 if dynamically sized,context.buffer
dynamicSize(value: number) {
// Optional, return dynamic size for value
return 0;
},
serialize(
value: number,
context: { buffer: Uint8Array; index: number; littleEndian: boolean },
) {
// Serialize value to at context.indexcontext.reader
},
deserialize(context: {
reader: AsyncExactReadable;
littleEndian: boolean;
}) {
// Deserialize value from
return 0;
},
};
const Message2 = struct({
a: u8,
b: MyField,
});
`
bipedal is a custom async helper that allows the same code to behave synchronously or asynchronously depends on the parameters.
It's inspired by gensync.
The word bipedal refers to animals who walk using two legs.
`ts
import { bipedal } from "@yume-chan/struct";
const fn = bipedal(function* (then, name: string | Promise
name = yield* then(name);
return "Hello, " + name;
});
fn("Simon"); // "Hello, Simon"
await fn(Promise.resolve("Simon")); // "Hello, Simon"
``