# @yume-chan/struct

> C-style structure serializer and deserializer.

Latest version **2.3.2** (published 2025-12-17) · MIT license · 0 weekly downloads

## Install

```sh
npm install @yume-chan/struct
pnpm add @yume-chan/struct
yarn add @yume-chan/struct
bun add @yume-chan/struct
```

## Health

**Score 70/100 (B)** — status: stable.

Positive: has types; esm support; no vulnerabilities; has provenance; high maintenance score; high quality score.

Warnings: low downloads.

## Facts

| | |
|---|---|
| Version | 2.3.2 |
| Published | 2025-12-17 |
| First published | 2021-01-05 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 2 |
| Unpacked size | 141.7 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Provenance | attested (GitHub Actions) |
| GitHub stars | 3256 |
| Author | Simon Chan |
| Maintainers | yume-chan |
| Keywords | structure, serialization, deserialization, typescript |

## Links

- npm: https://www.npmjs.com/package/@yume-chan/struct
- Repository: https://github.com/yume-chan/ya-webadb
- Homepage: https://github.com/yume-chan/ya-webadb/tree/main/packages/struct#readme
- Issues: https://github.com/yume-chan/ya-webadb/issues
- npm.io page: https://npm.io/package/@yume-chan/struct

## Dependencies (2)

- [@yume-chan/async](https://npm.io/package/@yume-chan/async.md) ^4.1.3
- [@yume-chan/no-data-view](https://npm.io/package/@yume-chan/no-data-view.md) ^2.0.0

## Recent versions

- 2.3.2 (latest) — 2025-12-17
- 3.0.0-beta.4 (beta) — 2026-10-09
- 3.0.0-beta.3 — 2026-09-17
- 3.0.0-beta.2 — 2026-08-11
- 3.0.0-beta.1 — 2026-08-01
- 3.0.0-beta.0 — 2026-07-28
- 2.0.1 — 2025-04-04
- 2.0.0 — 2025-04-04
- 1.0.0 — 2024-12-02
- 0.0.0-next-20241130050937 — 2024-11-30
- 0.0.0-next-20241129144018 — 2024-11-29
- 0.0.0-next-20240917062356 — 2024-09-17
- 0.0.0-20240714132542 — 2024-07-14
- 0.0.24 — 2024-06-18
- 0.0.23 — 2024-03-21
- … 20 more at https://npm.io/package/@yume-chan/struct/versions

## README

# @yume-chan/struct

<!--
cspell: ignore Codecov
-->

![license](https://img.shields.io/npm/l/@yume-chan/struct)
![npm type definitions](https://img.shields.io/npm/types/@yume-chan/struct)
[![npm version](https://img.shields.io/npm/v/@yume-chan/struct)](https://www.npmjs.com/package/@yume-chan/struct)
![npm bundle size](https://img.shields.io/bundlephobia/min/@yume-chan/struct)
![Codecov](https://img.shields.io/codecov/c/github/yume-chan/ya-webadb?flag=struct&token=2fU3Cx2Edq)

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](https://docs.swmansion.com/TypeGPU/) which improves DX and tree-shaking.

**WARNING:** The public API is UNSTABLE. Open a GitHub discussion if you have any questions.

## Installation

```sh
$ npm i @yume-chan/struct
```

## Quick Start

```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 length
        f: buffer(u32), // `u32` length prefix
        g: buffer(4, {
            // Custom conversion between `Uint8Array` and other types
            convert(value: Uint8Array) {
                return value[0];
            },
            back(value: number) {
                return new Uint8Array([value, 0, 0, 0]);
            },
        }),
        h: string(64), // `string` 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 synchronous
const message2 = await Message.deserialize(reader); // If `reader.readExactly` is asynchronous, so do `deserialize`

const buffer: Uint8Array = Message.serialize(message1);
```

## Custom field types

```ts
import { Field, AsyncExactReadable, Struct, u8 } from "@yume-chan/struct";

const MyField: Field<number, never, never> = {
    size: 4, // `0` if dynamically sized,
    dynamicSize(value: number) {
        // Optional, return dynamic size for value
        return 0;
    },
    serialize(
        value: number,
        context: { buffer: Uint8Array; index: number; littleEndian: boolean },
    ) {
        // Serialize value to `context.buffer` at `context.index`
    },
    deserialize(context: {
        reader: AsyncExactReadable;
        littleEndian: boolean;
    }) {
        // Deserialize value from `context.reader`
        return 0;
    },
};

const Message2 = struct({
    a: u8,
    b: MyField,
});
```

## Bipedal

`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](https://github.com/loganfsmyth/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<string>) {
    name = yield* then(name);
    return "Hello, " + name;
});

fn("Simon"); // "Hello, Simon"
await fn(Promise.resolve("Simon")); // "Hello, Simon"
```

---
_Source: https://npm.io/package/@yume-chan/struct · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
