data-struct 0.0.11-n → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +52 -0
- package/README.md +164 -83
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +86 -0
- package/dist/index.d.ts +86 -0
- package/dist/index.mjs +2 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +57 -17
- package/.npmignore +0 -3
- package/benchmark/benchmark.js +0 -52
- package/gruntfile.js +0 -36
- package/src/dataReader.js +0 -128
- package/src/dataTypes.js +0 -15
- package/src/dataWriter.js +0 -141
- package/src/index.js +0 -3
- package/test/tests.js +0 -219
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.1.0] - 2026-05-17
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- Full TypeScript rewrite.
|
|
12
|
+
- New codec-token API: `t.bool`, `t.i8/u8/i16/u16/i32/u32`, `t.f32/f64`, `t.i64/u64`, `t.string`, `t.shortBytes`, `t.bytes`.
|
|
13
|
+
- Little-endian variants under `t.le.*`.
|
|
14
|
+
- `struct(schema)` factory that compiles a schema once and reuses it across `encode`/`decode`/`sizeOf` calls.
|
|
15
|
+
- Functional `encode(value, schema)` and `decode(buf, schema)`.
|
|
16
|
+
- `Infer<S>` type helper that derives the TypeScript shape of decoded values from a schema.
|
|
17
|
+
- `DataStructError` with codes (`VALUE_OUT_OF_RANGE`, `STRING_TOO_LONG`, `BYTES_TOO_LONG`, `ARRAY_TOO_LONG`, `BUFFER_UNDERFLOW`, `SCHEMA_MISMATCH`, `INVALID_SCHEMA`), `path` (e.g. `$.skills[1].description`), and `offset` (for decode errors).
|
|
18
|
+
- Dual ESM + CommonJS build with separate `.d.mts` / `.d.cts` type declarations.
|
|
19
|
+
- Vitest test suite (wire-format goldens, roundtrip, error paths) with v8 coverage.
|
|
20
|
+
- `tinybench`-based benchmark suite.
|
|
21
|
+
- GitHub Actions: CI matrix (Node 20/22/24 on Linux + Node 22 on macOS/Windows), on-demand benchmark workflow, tag-triggered release with npm provenance.
|
|
22
|
+
- Dependabot, PR template, CODEOWNERS.
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
- Module format: package is now `"type": "module"`; entry points are `dist/index.mjs` (ESM) and `dist/index.cjs` (CJS).
|
|
26
|
+
- Minimum Node.js version: `>=20.9`.
|
|
27
|
+
- Encoder now allocates the output `Buffer` exactly once via a two-pass measure/write strategy (no `Buffer.concat`).
|
|
28
|
+
- Decoded `shortBytes` / `bytes` are returned as independent copies of the source memory rather than aliased views.
|
|
29
|
+
- Replaced deprecated `new Buffer(...)` calls with `Buffer.allocUnsafe` (for output) and `TextEncoder`/`TextDecoder` for string codecs.
|
|
30
|
+
- Build: `tsup` now emits minified output. `dist/index.mjs` shrinks from ~15 KB to ~7.5 KB (~-50%); behaviour is unchanged.
|
|
31
|
+
|
|
32
|
+
### Removed
|
|
33
|
+
- Legacy exports `DataTypes`, `DataReader`, `DataWriter` (clean break — see README migration table).
|
|
34
|
+
- `grunt`, `grunt-simple-mocha`, `jit-grunt`, `grunt-contrib-jshint`, `chai`, `benchmark`.
|
|
35
|
+
|
|
36
|
+
### Wire format
|
|
37
|
+
- **Byte-identical** with `0.0.x` for the corresponding new codecs. The previous test suite's golden buffers are preserved as goldens in `test/wire-format.test.ts`.
|
|
38
|
+
|
|
39
|
+
### Performance
|
|
40
|
+
|
|
41
|
+
- Field-iteration path strings (`${path}.${key}`, `${path}[${i}]`) are no longer allocated on the happy path. `struct` / `array` codecs now wrap each child call in `try { ... } catch (e) { rethrowWithPrefix(e, segment) }` and build the error path only when something throws. Measured on Node 22:
|
|
42
|
+
- `nested` encode (compiled): -33%
|
|
43
|
+
- `list of list` encode (compiled): -59%
|
|
44
|
+
- `list of list` decode (compiled): -45%
|
|
45
|
+
- `hero` encode / decode (compiled): -17% each
|
|
46
|
+
|
|
47
|
+
### Security
|
|
48
|
+
|
|
49
|
+
- Decoded structs are now created with a `null` prototype, neutralising prototype-pollution risk if a schema is built from untrusted input that contains a `__proto__` key.
|
|
50
|
+
- String decoder now uses `TextDecoder` in `fatal: true` mode and throws `SCHEMA_MISMATCH` on malformed UTF-8 (previously such bytes were silently replaced with `U+FFFD`).
|
|
51
|
+
- `struct.encode` now asserts that `write()` emits exactly as many bytes as `measure()` reported. Defends against codec bugs leaking uninitialised memory from `Buffer.allocUnsafe`.
|
|
52
|
+
- CI now runs `npm audit --audit-level=high --omit=dev` and fails on high/critical advisories in production dependencies.
|
package/README.md
CHANGED
|
@@ -1,98 +1,179 @@
|
|
|
1
|
-
#
|
|
1
|
+
# data-struct
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://github.com/rzcoder/data-struct/actions/workflows/ci.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/data-struct)
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
Schema-driven binary serialization between JavaScript values and Node `Buffer`s.
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
- **Tiny.** No runtime dependencies.
|
|
9
|
+
- **Typed.** A schema infers the exact TypeScript shape of the decoded value via `Infer<S>`.
|
|
10
|
+
- **Fast.** Two-pass encoder allocates the output buffer exactly once.
|
|
11
|
+
- **Dual-format.** Ships ESM + CommonJS + `.d.ts` for both.
|
|
12
|
+
- **Wire-stable.** Big-endian by default, byte-identical with prior `0.0.x` releases.
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
npm install data-struct
|
|
9
18
|
```
|
|
10
19
|
|
|
20
|
+
Requires Node `>=20.9`.
|
|
11
21
|
|
|
12
22
|
## Usage
|
|
13
23
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
24
|
+
```ts
|
|
25
|
+
import { struct, t, type Infer } from 'data-struct';
|
|
26
|
+
|
|
27
|
+
const Hero = struct({
|
|
28
|
+
id: t.u32,
|
|
29
|
+
name: t.string,
|
|
30
|
+
hp: t.i16,
|
|
31
|
+
skills: [{ id: t.u16, description: t.string }],
|
|
32
|
+
playable: t.bool,
|
|
33
|
+
experience: t.u32,
|
|
34
|
+
position: { x: t.u16, y: t.u16 },
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
type Hero = Infer<typeof Hero.schema>;
|
|
38
|
+
|
|
39
|
+
const buf = Hero.encode({
|
|
40
|
+
id: 9,
|
|
41
|
+
name: 'CirnoBaka',
|
|
42
|
+
hp: 146,
|
|
43
|
+
skills: [
|
|
44
|
+
{ id: 34, description: 'freezing frogs' },
|
|
45
|
+
{ id: 16, description: 'perfect math' },
|
|
46
|
+
],
|
|
47
|
+
playable: false,
|
|
48
|
+
experience: 99_999_999,
|
|
49
|
+
position: { x: 2, y: 3 },
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const hero = Hero.decode(buf); // typed as Hero
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Functional form, when you don't want to keep a compiled `struct` around:
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import { encode, decode, t } from 'data-struct';
|
|
59
|
+
|
|
60
|
+
const Map2D = [[t.u8]];
|
|
61
|
+
const buf = encode([[0, 1, 0], [1, 0, 1]], Map2D);
|
|
62
|
+
const map = decode(buf, Map2D); // number[][]
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## API
|
|
66
|
+
|
|
67
|
+
### Codec tokens — `t`
|
|
68
|
+
|
|
69
|
+
| Token | Bytes | TS type | Notes |
|
|
70
|
+
| ---------------- | ---------- | ------------ | ------------------------------------------- |
|
|
71
|
+
| `t.bool` | 1 | `boolean` | |
|
|
72
|
+
| `t.i8` / `t.u8` | 1 | `number` | |
|
|
73
|
+
| `t.i16` / `t.u16`| 2 | `number` | big-endian |
|
|
74
|
+
| `t.i32` / `t.u32`| 4 | `number` | big-endian |
|
|
75
|
+
| `t.f32` / `t.f64`| 4 / 8 | `number` | big-endian |
|
|
76
|
+
| `t.i64` / `t.u64`| 8 | `bigint` | big-endian |
|
|
77
|
+
| `t.string` | 2 + utf-8 | `string` | uint16 length prefix, max 65535 utf-8 bytes |
|
|
78
|
+
| `t.shortBytes` | 2 + n | `Uint8Array` | uint16 length prefix, max 65535 bytes |
|
|
79
|
+
| `t.bytes` | 4 + n | `Uint8Array` | uint32 length prefix, max 4294967295 bytes |
|
|
80
|
+
|
|
81
|
+
Little-endian variants live under `t.le.*` (e.g. `t.le.u32`, `t.le.f64`, `t.le.string`).
|
|
82
|
+
|
|
83
|
+
### Schema shape
|
|
84
|
+
|
|
85
|
+
A schema is one of:
|
|
62
86
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
87
|
+
- A codec token (`t.u32`).
|
|
88
|
+
- A single-element array `[Schema]` — encodes as a uint16 length prefix followed by N child encodings.
|
|
89
|
+
- A plain object — fields encoded in declared key order.
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
type Schema = Codec<unknown> | Schema[] | { [k: string]: Schema };
|
|
93
|
+
type Infer<S> = /* recursively maps each leaf to its TS type */;
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Functions
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
struct<S extends Schema>(schema: S): {
|
|
100
|
+
schema: S;
|
|
101
|
+
encode(value: Infer<S>): Buffer;
|
|
102
|
+
decode(input: Uint8Array): Infer<S>;
|
|
103
|
+
sizeOf(value: Infer<S>): number;
|
|
77
104
|
};
|
|
78
105
|
|
|
79
|
-
|
|
80
|
-
|
|
106
|
+
encode<S extends Schema>(value: Infer<S>, schema: S): Buffer;
|
|
107
|
+
decode<S extends Schema>(input: Uint8Array, schema: S): Infer<S>;
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
`struct(schema)` compiles the schema tree once and reuses the compiled codec across calls — prefer it in hot paths.
|
|
111
|
+
|
|
112
|
+
### Errors
|
|
81
113
|
|
|
114
|
+
Validation throws `DataStructError` with a `code`:
|
|
82
115
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
116
|
+
| Code | When |
|
|
117
|
+
| --------------------- | ------------------------------------------------- |
|
|
118
|
+
| `VALUE_OUT_OF_RANGE` | Numeric value outside the leaf's range or non-int |
|
|
119
|
+
| `STRING_TOO_LONG` | UTF-8 byte length exceeds 65535 |
|
|
120
|
+
| `BYTES_TOO_LONG` | Bytes value exceeds the leaf's length cap |
|
|
121
|
+
| `ARRAY_TOO_LONG` | Array length exceeds 65535 |
|
|
122
|
+
| `BUFFER_UNDERFLOW` | Decode would read past the end of the input |
|
|
123
|
+
| `SCHEMA_MISMATCH` | Value shape does not match the schema |
|
|
124
|
+
| `INVALID_SCHEMA` | Schema itself is malformed |
|
|
125
|
+
|
|
126
|
+
Every error carries `path` (e.g. `$.skills[1].description`) and, for decode errors, `offset`.
|
|
127
|
+
|
|
128
|
+
## Wire format
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
bool : 1 byte 0x00 = false, anything else = true
|
|
132
|
+
i8/u8 : 1 byte
|
|
133
|
+
i16/u16 : 2 bytes BE
|
|
134
|
+
i32/u32 : 4 bytes BE
|
|
135
|
+
f32/f64 : 4 / 8 bytes BE
|
|
136
|
+
i64/u64 : 8 bytes BE
|
|
137
|
+
string : uint16 BE length || utf-8 bytes
|
|
138
|
+
shortBytes : uint16 BE length || raw bytes
|
|
139
|
+
bytes : uint32 BE length || raw bytes
|
|
140
|
+
array [E] : uint16 BE length || N encoded elements
|
|
141
|
+
object {…} : fields encoded in declared key order, no header
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
LE variants (`t.le.*`) swap the byte order of length prefixes and the numeric payload.
|
|
145
|
+
|
|
146
|
+
## Migration from `0.0.x`
|
|
147
|
+
|
|
148
|
+
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.
|
|
149
|
+
|
|
150
|
+
| Old | New |
|
|
151
|
+
| ------------------------- | ------------------------- |
|
|
152
|
+
| `DataTypes.boolean` | `t.bool` |
|
|
153
|
+
| `DataTypes.int8` / `uint8`| `t.i8` / `t.u8` |
|
|
154
|
+
| `DataTypes.int16`/`uint16`| `t.i16` / `t.u16` |
|
|
155
|
+
| `DataTypes.int32`/`uint32`| `t.i32` / `t.u32` |
|
|
156
|
+
| `DataTypes.float` | `t.f32` |
|
|
157
|
+
| `DataTypes.double` | `t.f64` |
|
|
158
|
+
| `DataTypes.string` | `t.string` |
|
|
159
|
+
| `DataTypes.shortBuffer` | `t.shortBytes` |
|
|
160
|
+
| `DataTypes.buffer` | `t.bytes` |
|
|
161
|
+
| `DataWriter(obj, scheme)` | `encode(obj, schema)` |
|
|
162
|
+
| `DataReader(buf, scheme)` | `decode(buf, schema)` |
|
|
163
|
+
|
|
164
|
+
The legacy `DataTypes` / `DataReader` / `DataWriter` exports are removed.
|
|
165
|
+
|
|
166
|
+
## Development
|
|
167
|
+
|
|
168
|
+
```sh
|
|
169
|
+
npm install
|
|
170
|
+
npm run typecheck
|
|
171
|
+
npm run lint
|
|
172
|
+
npm test
|
|
173
|
+
npm run bench
|
|
174
|
+
npm run build
|
|
175
|
+
```
|
|
93
176
|
|
|
94
|
-
|
|
177
|
+
## License
|
|
95
178
|
|
|
96
|
-
|
|
97
|
-
var mapClone = DataReader(mapBuf, mapScheme);
|
|
98
|
-
```
|
|
179
|
+
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
'use strict';var buffer=require('buffer');var d=class extends Error{code;path;offset;constructor(s,i,n={}){super(n.path?`${i} at ${n.path}`:i,{cause:n.cause}),this.name="DataStructError",this.code=s,this.path=n.path??"$",this.offset=n.offset;}};var F=new TextEncoder,V=new TextDecoder("utf-8",{fatal:true}),G=255,C=65535,U=4294967295,j=-128,X=127,O=-32768,E=32767,T=-2147483648,D=2147483647,q=-(1n<<63n),P=(1n<<63n)-1n,Y=(1n<<64n)-1n;function l(e,s,i){if(s+i>e.byteLength)throw new d("BUFFER_UNDERFLOW",`need ${i} byte(s) at offset ${s}, but buffer has ${e.byteLength}`,{offset:s})}function W(e,s,i,n){if(typeof e!="number"||!Number.isInteger(e)||e<s||e>i)throw new d("VALUE_OUT_OF_RANGE",`${n} requires integer in [${s}, ${i}], got ${e}`)}function L(e,s){if(typeof e!="number")throw new d("VALUE_OUT_OF_RANGE",`${s} requires number, got ${typeof e}`)}function z(e,s,i,n){if(typeof e!="bigint"||e<s||e>i)throw new d("VALUE_OUT_OF_RANGE",`${n} requires bigint in [${s}, ${i}], got ${e}`)}function N(e,s){if(!(e instanceof Uint8Array))throw new d("SCHEMA_MISMATCH",`${s} requires Uint8Array, got ${typeof e}`)}function x(e,s,i,n,r){return {tag:e,impl:{measure:()=>s,write(o,c,u,m){return r(m),i(o,u,m),u+s},read(o,c,u){return l(o,u,s),{value:n(o,u),offset:u+s}}}}}var J={measure:()=>1,write(e,s,i,n){if(typeof n!="boolean")throw new d("SCHEMA_MISMATCH",`bool requires boolean, got ${typeof n}`);return e.setUint8(i,n?1:0),i+1},read(e,s,i){return l(e,i,1),{value:e.getInt8(i)!==0,offset:i+1}}};function R(e,s){return {tag:s,impl:{measure(n,r){if(typeof n!="string")throw new d("SCHEMA_MISMATCH",`string requires string, got ${typeof n}`);let t=F.encode(n);if(t.byteLength>C)throw new d("STRING_TOO_LONG",`string UTF-8 byte length ${t.byteLength} exceeds 65535`);return r.strings.push(t),2+t.byteLength},write(n,r,t,o,c){let u=c.strings[c.cursor++];return n.setUint16(t,u.byteLength,e),t+=2,r.set(u,t),t+u.byteLength},read(n,r,t){l(n,t,2);let o=n.getUint16(t,e);t+=2,l(n,t,o);let c;try{c=V.decode(r.subarray(t,t+o));}catch(u){throw new d("SCHEMA_MISMATCH","invalid UTF-8 in string field",{offset:t,cause:u})}return {value:c,offset:t+o}}}}}function H(e,s){return {tag:s,impl:{measure(n){if(N(n,"shortBytes"),n.byteLength>C)throw new d("BYTES_TOO_LONG",`shortBytes length ${n.byteLength} exceeds 65535`);return 2+n.byteLength},write(n,r,t,o){return n.setUint16(t,o.byteLength,e),t+=2,r.set(o,t),t+o.byteLength},read(n,r,t){l(n,t,2);let o=n.getUint16(t,e);t+=2,l(n,t,o);let c=new Uint8Array(o);return c.set(r.subarray(t,t+o)),{value:c,offset:t+o}}}}}function B(e,s){return {tag:s,impl:{measure(n){if(N(n,"bytes"),n.byteLength>U)throw new d("BYTES_TOO_LONG",`bytes length ${n.byteLength} exceeds 4294967295`);return 4+n.byteLength},write(n,r,t,o){return n.setUint32(t,o.byteLength,e),t+=4,r.set(o,t),t+o.byteLength},read(n,r,t){l(n,t,4);let o=n.getUint32(t,e);t+=4,l(n,t,o);let c=new Uint8Array(o);return c.set(r.subarray(t,t+o)),{value:c,offset:t+o}}}}}function h(e,s,i,n,r,t,o){let c={"i:1":(a,y,g)=>a.setInt8(y,g),"u:1":(a,y,g)=>a.setUint8(y,g),"i:2":(a,y,g,w)=>a.setInt16(y,g,w),"u:2":(a,y,g,w)=>a.setUint16(y,g,w),"i:4":(a,y,g,w)=>a.setInt32(y,g,w),"u:4":(a,y,g,w)=>a.setUint32(y,g,w)},u={"i:1":(a,y)=>a.getInt8(y),"u:1":(a,y)=>a.getUint8(y),"i:2":(a,y,g)=>a.getInt16(y,g),"u:2":(a,y,g)=>a.getUint16(y,g),"i:4":(a,y,g)=>a.getInt32(y,g),"u:4":(a,y,g)=>a.getUint32(y,g)},m=`${i?"i":"u"}:${s}`,p=c[m],_=u[m];return x(e,s,(a,y,g)=>p(a,y,g,o),(a,y)=>_(a,y,o),a=>W(a,n,r,t))}function S(e,s,i,n){return s===4?x(e,4,(r,t,o)=>r.setFloat32(t,o,n),(r,t)=>r.getFloat32(t,n),r=>L(r,i)):x(e,8,(r,t,o)=>r.setFloat64(t,o,n),(r,t)=>r.getFloat64(t,n),r=>L(r,i))}function I(e,s,i,n){let r=s?q:0n,t=s?P:Y;return x(e,8,(o,c,u)=>{s?o.setBigInt64(c,u,n):o.setBigUint64(c,u,n);},(o,c)=>s?o.getBigInt64(c,n):o.getBigUint64(c,n),o=>z(o,r,t,i))}var b=false,f=true,K={bool:{tag:0,impl:J},i8:h(16,1,true,j,X,"i8",b),u8:h(17,1,false,0,G,"u8",b),i16:h(32,2,true,O,E,"i16",b),u16:h(33,2,false,0,C,"u16",b),i32:h(48,4,true,T,D,"i32",b),u32:h(49,4,false,0,U,"u32",b),f32:S(64,4,"f32",b),f64:S(65,8,"f64",b),i64:I(80,true,"i64",b),u64:I(81,false,"u64",b),string:R(b,512),shortBytes:H(b,528),bytes:B(b,529)},Q={i16:h(4128,2,true,O,E,"le.i16",f),u16:h(4129,2,false,0,C,"le.u16",f),i32:h(4144,4,true,T,D,"le.i32",f),u32:h(4145,4,false,0,U,"le.u32",f),f32:S(4160,4,"le.f32",f),f64:S(4161,8,"le.f64",f),i64:I(4176,true,"le.i64",f),u64:I(4177,false,"le.u64",f),string:R(f,4608),shortBytes:H(f,4624),bytes:B(f,4625)},Z={...K,le:Q};var k=65535,ee=" at ";function te(e){return typeof e=="object"&&e!==null&&"impl"in e&&"tag"in e&&typeof e.tag=="number"}function A(e,s){if(!(e instanceof d))throw e;let i=e.path==="$"?"":e.path.slice(1),n=`$${s}${i}`,r=e.path==="$"?"":`${ee}${e.path}`,t=r&&e.message.endsWith(r)?e.message.slice(0,-r.length):e.message,o={path:n};throw e.offset!==void 0&&(o.offset=e.offset),o.cause=e.cause??e,new d(e.code,t,o)}function $(e){if(te(e))return e;if(Array.isArray(e)){if(e.length!==1)throw new d("INVALID_SCHEMA",`array schema must have exactly one element descriptor, got ${e.length}`);let s=e[0];if(s===void 0)throw new d("INVALID_SCHEMA","array schema element is undefined");return ne($(s))}if(typeof e=="object"&&e!==null)return re(e);throw new d("INVALID_SCHEMA",`unsupported schema node: ${String(e)}`)}function ne(e){return {tag:256,impl:{measure(i,n){if(!Array.isArray(i))throw new d("SCHEMA_MISMATCH",`expected array, got ${typeof i}`);if(i.length>k)throw new d("ARRAY_TOO_LONG",`array length ${i.length} exceeds ${k}`);let r=2;for(let t=0;t<i.length;t++)try{r+=e.impl.measure(i[t],n);}catch(o){A(o,`[${t}]`);}return r},write(i,n,r,t,o){i.setUint16(r,t.length,false),r+=2;for(let c=0;c<t.length;c++)try{r=e.impl.write(i,n,r,t[c],o);}catch(u){A(u,`[${c}]`);}return r},read(i,n,r){if(r+2>i.byteLength)throw new d("BUFFER_UNDERFLOW",`need 2 byte(s) for array length at offset ${r}`,{offset:r});let t=i.getUint16(r,false);r+=2;let o=new Array(t);for(let c=0;c<t;c++)try{let u=e.impl.read(i,n,r);o[c]=u.value,r=u.offset;}catch(u){A(u,`[${c}]`);}return {value:o,offset:r}}}}}function re(e){let i=Object.keys(e).map(r=>{let t=e[r];if(t===void 0)throw new d("INVALID_SCHEMA",`field "${r}" is undefined`);return [r,$(t)]});return {tag:768,impl:{measure(r,t){if(typeof r!="object"||r===null||Array.isArray(r))throw new d("SCHEMA_MISMATCH",`expected object, got ${typeof r}`);let o=r,c=0;for(let[u,m]of i)try{c+=m.impl.measure(o[u],t);}catch(p){A(p,`.${u}`);}return c},write(r,t,o,c,u){for(let[m,p]of i)try{o=p.impl.write(r,t,o,c[m],u);}catch(_){A(_,`.${m}`);}return o},read(r,t,o){let c=Object.create(null);for(let[u,m]of i)try{let p=m.impl.read(r,t,o);c[u]=p.value,o=p.offset;}catch(p){A(p,`.${u}`);}return {value:c,offset:o}}}}}function M(e){let s=$(e);return {schema:e,encode(i){let n={strings:[],cursor:0},r=s.impl.measure(i,n),t=buffer.Buffer.allocUnsafe(r),o=new DataView(t.buffer,t.byteOffset,t.byteLength);n.cursor=0;let c=s.impl.write(o,t,0,i,n);if(c!==r)throw new d("INVALID_SCHEMA",`internal size mismatch: measured ${r}, wrote ${c}`);return t},decode(i){if(!(i instanceof Uint8Array))throw new d("SCHEMA_MISMATCH",`decode expects Uint8Array, got ${typeof i}`);let n=new DataView(i.buffer,i.byteOffset,i.byteLength),{value:r}=s.impl.read(n,i,0);return r},sizeOf(i){return s.impl.measure(i,{strings:[],cursor:0})}}}function oe(e,s){return M(s).encode(e)}function ie(e,s){return M(s).decode(e)}exports.DataStructError=d;exports.decode=ie;exports.encode=oe;exports.struct=M;exports.t=Z;//# sourceMappingURL=index.cjs.map
|
|
2
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/codecs.ts","../src/struct.ts"],"names":["DataStructError","code","message","opts","textEncoder","textDecoder","U8_MAX","U16_MAX","U32_MAX","I8_MIN","I8_MAX","I16_MIN","I16_MAX","I32_MIN","I32_MAX","I64_MIN","I64_MAX","U64_MAX","ensureCapacity","view","offset","need","ensureInt","value","min","max","type","ensureFiniteNumber","ensureBigInt","ensureUint8Array","fixed","tag","size","write","read","validate","_bytes","boolImpl","makeString","littleEndian","plan","encoded","bytes","_value","length","cause","makeShortBytes","makeBytes","intCodec","signed","name","setters","v","o","x","le","getters","key","setter","getter","floatCodec","bigIntCodec","BE","LE","beCodecs","leCodecs","t","ARRAY_LENGTH_MAX","PATH_AT","isCodec","rethrowWithPrefix","err","segment","oldPath","newPath","oldSuffix","baseMessage","compile","schema","element","arrayCodec","structCodec","i","e","out","r","fields","child","obj","codec","struct","Buffer","written","input","encode","decode"],"mappings":"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","file":"index.cjs","sourcesContent":["export type DataStructErrorCode =\n | 'VALUE_OUT_OF_RANGE'\n | 'STRING_TOO_LONG'\n | 'BYTES_TOO_LONG'\n | 'ARRAY_TOO_LONG'\n | 'BUFFER_UNDERFLOW'\n | 'SCHEMA_MISMATCH'\n | 'INVALID_SCHEMA';\n\nexport interface DataStructErrorOptions {\n path?: string;\n offset?: number;\n cause?: unknown;\n}\n\nexport class DataStructError extends Error {\n readonly code: DataStructErrorCode;\n readonly path: string;\n readonly offset: number | undefined;\n\n constructor(code: DataStructErrorCode, message: string, opts: DataStructErrorOptions = {}) {\n super(opts.path ? `${message} at ${opts.path}` : message, { cause: opts.cause });\n this.name = 'DataStructError';\n this.code = code;\n this.path = opts.path ?? '$';\n this.offset = opts.offset;\n }\n}\n","import { DataStructError } from './errors.js';\nimport type { Codec, CodecImpl } from './types.js';\n\nconst textEncoder = new TextEncoder();\nconst textDecoder = new TextDecoder('utf-8', { fatal: true });\n\nconst U8_MAX = 0xff;\nconst U16_MAX = 0xffff;\nconst U32_MAX = 0xffffffff;\nconst I8_MIN = -0x80;\nconst I8_MAX = 0x7f;\nconst I16_MIN = -0x8000;\nconst I16_MAX = 0x7fff;\nconst I32_MIN = -0x80000000;\nconst I32_MAX = 0x7fffffff;\nconst I64_MIN = -(1n << 63n);\nconst I64_MAX = (1n << 63n) - 1n;\nconst U64_MAX = (1n << 64n) - 1n;\n\n// Leaves throw without path context; parent codecs (struct/array) prefix\n// the segment via prefixPath() in struct.ts. This keeps the happy path\n// allocation-free for the field-iteration string concatenations.\n\nfunction ensureCapacity(view: DataView, offset: number, need: number): void {\n if (offset + need > view.byteLength) {\n throw new DataStructError(\n 'BUFFER_UNDERFLOW',\n `need ${need} byte(s) at offset ${offset}, but buffer has ${view.byteLength}`,\n { offset },\n );\n }\n}\n\nfunction ensureInt(value: number, min: number, max: number, type: string): void {\n if (typeof value !== 'number' || !Number.isInteger(value) || value < min || value > max) {\n throw new DataStructError(\n 'VALUE_OUT_OF_RANGE',\n `${type} requires integer in [${min}, ${max}], got ${value}`,\n );\n }\n}\n\nfunction ensureFiniteNumber(value: number, type: string): void {\n if (typeof value !== 'number') {\n throw new DataStructError('VALUE_OUT_OF_RANGE', `${type} requires number, got ${typeof value}`);\n }\n}\n\nfunction ensureBigInt(value: bigint, min: bigint, max: bigint, type: string): void {\n if (typeof value !== 'bigint' || value < min || value > max) {\n throw new DataStructError(\n 'VALUE_OUT_OF_RANGE',\n `${type} requires bigint in [${min}, ${max}], got ${value}`,\n );\n }\n}\n\nfunction ensureUint8Array(value: unknown, type: string): asserts value is Uint8Array {\n if (!(value instanceof Uint8Array)) {\n throw new DataStructError(\n 'SCHEMA_MISMATCH',\n `${type} requires Uint8Array, got ${typeof value}`,\n );\n }\n}\n\nfunction fixed<T>(\n tag: number,\n size: number,\n write: (view: DataView, offset: number, value: T) => void,\n read: (view: DataView, offset: number) => T,\n validate: (value: T) => void,\n): Codec<T> {\n const impl: CodecImpl<T> = {\n measure: () => size,\n write(view, _bytes, offset, value) {\n validate(value);\n write(view, offset, value);\n return offset + size;\n },\n read(view, _bytes, offset) {\n ensureCapacity(view, offset, size);\n return { value: read(view, offset), offset: offset + size };\n },\n };\n return { tag, impl };\n}\n\nconst boolImpl: CodecImpl<boolean> = {\n measure: () => 1,\n write(view, _bytes, offset, value) {\n if (typeof value !== 'boolean') {\n throw new DataStructError('SCHEMA_MISMATCH', `bool requires boolean, got ${typeof value}`);\n }\n view.setUint8(offset, value ? 1 : 0);\n return offset + 1;\n },\n read(view, _bytes, offset) {\n ensureCapacity(view, offset, 1);\n return { value: view.getInt8(offset) !== 0, offset: offset + 1 };\n },\n};\n\nfunction makeString(littleEndian: boolean, tag: number): Codec<string> {\n const impl: CodecImpl<string> = {\n measure(value, plan) {\n if (typeof value !== 'string') {\n throw new DataStructError('SCHEMA_MISMATCH', `string requires string, got ${typeof value}`);\n }\n const encoded = textEncoder.encode(value);\n if (encoded.byteLength > U16_MAX) {\n throw new DataStructError(\n 'STRING_TOO_LONG',\n `string UTF-8 byte length ${encoded.byteLength} exceeds 65535`,\n );\n }\n plan.strings.push(encoded);\n return 2 + encoded.byteLength;\n },\n write(view, bytes, offset, _value, plan) {\n const encoded = plan.strings[plan.cursor++] as Uint8Array;\n view.setUint16(offset, encoded.byteLength, littleEndian);\n offset += 2;\n bytes.set(encoded, offset);\n return offset + encoded.byteLength;\n },\n read(view, bytes, offset) {\n ensureCapacity(view, offset, 2);\n const length = view.getUint16(offset, littleEndian);\n offset += 2;\n ensureCapacity(view, offset, length);\n let value: string;\n try {\n value = textDecoder.decode(bytes.subarray(offset, offset + length));\n } catch (cause) {\n throw new DataStructError('SCHEMA_MISMATCH', 'invalid UTF-8 in string field', {\n offset,\n cause,\n });\n }\n return { value, offset: offset + length };\n },\n };\n return { tag, impl };\n}\n\nfunction makeShortBytes(littleEndian: boolean, tag: number): Codec<Uint8Array> {\n const impl: CodecImpl<Uint8Array> = {\n measure(value) {\n ensureUint8Array(value, 'shortBytes');\n if (value.byteLength > U16_MAX) {\n throw new DataStructError(\n 'BYTES_TOO_LONG',\n `shortBytes length ${value.byteLength} exceeds 65535`,\n );\n }\n return 2 + value.byteLength;\n },\n write(view, bytes, offset, value) {\n view.setUint16(offset, value.byteLength, littleEndian);\n offset += 2;\n bytes.set(value, offset);\n return offset + value.byteLength;\n },\n read(view, bytes, offset) {\n ensureCapacity(view, offset, 2);\n const length = view.getUint16(offset, littleEndian);\n offset += 2;\n ensureCapacity(view, offset, length);\n const value = new Uint8Array(length);\n value.set(bytes.subarray(offset, offset + length));\n return { value, offset: offset + length };\n },\n };\n return { tag, impl };\n}\n\nfunction makeBytes(littleEndian: boolean, tag: number): Codec<Uint8Array> {\n const impl: CodecImpl<Uint8Array> = {\n measure(value) {\n ensureUint8Array(value, 'bytes');\n if (value.byteLength > U32_MAX) {\n throw new DataStructError(\n 'BYTES_TOO_LONG',\n `bytes length ${value.byteLength} exceeds 4294967295`,\n );\n }\n return 4 + value.byteLength;\n },\n write(view, bytes, offset, value) {\n view.setUint32(offset, value.byteLength, littleEndian);\n offset += 4;\n bytes.set(value, offset);\n return offset + value.byteLength;\n },\n read(view, bytes, offset) {\n ensureCapacity(view, offset, 4);\n const length = view.getUint32(offset, littleEndian);\n offset += 4;\n ensureCapacity(view, offset, length);\n const value = new Uint8Array(length);\n value.set(bytes.subarray(offset, offset + length));\n return { value, offset: offset + length };\n },\n };\n return { tag, impl };\n}\n\nfunction intCodec(\n tag: number,\n size: number,\n signed: boolean,\n min: number,\n max: number,\n name: string,\n littleEndian: boolean,\n): Codec<number> {\n const setters: Record<string, (view: DataView, o: number, v: number, le: boolean) => void> = {\n 'i:1': (v, o, x) => v.setInt8(o, x),\n 'u:1': (v, o, x) => v.setUint8(o, x),\n 'i:2': (v, o, x, le) => v.setInt16(o, x, le),\n 'u:2': (v, o, x, le) => v.setUint16(o, x, le),\n 'i:4': (v, o, x, le) => v.setInt32(o, x, le),\n 'u:4': (v, o, x, le) => v.setUint32(o, x, le),\n };\n const getters: Record<string, (view: DataView, o: number, le: boolean) => number> = {\n 'i:1': (v, o) => v.getInt8(o),\n 'u:1': (v, o) => v.getUint8(o),\n 'i:2': (v, o, le) => v.getInt16(o, le),\n 'u:2': (v, o, le) => v.getUint16(o, le),\n 'i:4': (v, o, le) => v.getInt32(o, le),\n 'u:4': (v, o, le) => v.getUint32(o, le),\n };\n const key = `${signed ? 'i' : 'u'}:${size}`;\n const setter = setters[key] as (view: DataView, o: number, v: number, le: boolean) => void;\n const getter = getters[key] as (view: DataView, o: number, le: boolean) => number;\n return fixed<number>(\n tag,\n size,\n (view, offset, value) => setter(view, offset, value, littleEndian),\n (view, offset) => getter(view, offset, littleEndian),\n (value) => ensureInt(value, min, max, name),\n );\n}\n\nfunction floatCodec(tag: number, size: 4 | 8, name: string, littleEndian: boolean): Codec<number> {\n if (size === 4) {\n return fixed<number>(\n tag,\n 4,\n (view, offset, value) => view.setFloat32(offset, value, littleEndian),\n (view, offset) => view.getFloat32(offset, littleEndian),\n (value) => ensureFiniteNumber(value, name),\n );\n }\n return fixed<number>(\n tag,\n 8,\n (view, offset, value) => view.setFloat64(offset, value, littleEndian),\n (view, offset) => view.getFloat64(offset, littleEndian),\n (value) => ensureFiniteNumber(value, name),\n );\n}\n\nfunction bigIntCodec(\n tag: number,\n signed: boolean,\n name: string,\n littleEndian: boolean,\n): Codec<bigint> {\n const min = signed ? I64_MIN : 0n;\n const max = signed ? I64_MAX : U64_MAX;\n return fixed<bigint>(\n tag,\n 8,\n (view, offset, value) => {\n if (signed) view.setBigInt64(offset, value, littleEndian);\n else view.setBigUint64(offset, value, littleEndian);\n },\n (view, offset) =>\n signed ? view.getBigInt64(offset, littleEndian) : view.getBigUint64(offset, littleEndian),\n (value) => ensureBigInt(value, min, max, name),\n );\n}\n\nconst BE = false;\nconst LE = true;\n\nconst beCodecs = {\n bool: { tag: 0x000, impl: boolImpl } as Codec<boolean>,\n i8: intCodec(0x010, 1, true, I8_MIN, I8_MAX, 'i8', BE),\n u8: intCodec(0x011, 1, false, 0, U8_MAX, 'u8', BE),\n i16: intCodec(0x020, 2, true, I16_MIN, I16_MAX, 'i16', BE),\n u16: intCodec(0x021, 2, false, 0, U16_MAX, 'u16', BE),\n i32: intCodec(0x030, 4, true, I32_MIN, I32_MAX, 'i32', BE),\n u32: intCodec(0x031, 4, false, 0, U32_MAX, 'u32', BE),\n f32: floatCodec(0x040, 4, 'f32', BE),\n f64: floatCodec(0x041, 8, 'f64', BE),\n i64: bigIntCodec(0x050, true, 'i64', BE),\n u64: bigIntCodec(0x051, false, 'u64', BE),\n string: makeString(BE, 0x200),\n shortBytes: makeShortBytes(BE, 0x210),\n bytes: makeBytes(BE, 0x211),\n};\n\nconst leCodecs = {\n i16: intCodec(0x1020, 2, true, I16_MIN, I16_MAX, 'le.i16', LE),\n u16: intCodec(0x1021, 2, false, 0, U16_MAX, 'le.u16', LE),\n i32: intCodec(0x1030, 4, true, I32_MIN, I32_MAX, 'le.i32', LE),\n u32: intCodec(0x1031, 4, false, 0, U32_MAX, 'le.u32', LE),\n f32: floatCodec(0x1040, 4, 'le.f32', LE),\n f64: floatCodec(0x1041, 8, 'le.f64', LE),\n i64: bigIntCodec(0x1050, true, 'le.i64', LE),\n u64: bigIntCodec(0x1051, false, 'le.u64', LE),\n string: makeString(LE, 0x1200),\n shortBytes: makeShortBytes(LE, 0x1210),\n bytes: makeBytes(LE, 0x1211),\n};\n\nexport const t = {\n ...beCodecs,\n le: leCodecs,\n} as const;\n\nexport type TypeRegistry = typeof t;\n","import { Buffer } from 'node:buffer';\nimport { DataStructError } from './errors.js';\nimport type { AnyCodec, Codec, CodecImpl, EncodePlan, Infer, Schema } from './types.js';\n\nconst ARRAY_LENGTH_MAX = 0xffff;\nconst PATH_AT = ' at ';\n\nfunction isCodec(v: unknown): v is AnyCodec {\n return (\n typeof v === 'object' &&\n v !== null &&\n 'impl' in v &&\n 'tag' in v &&\n typeof (v as { tag: unknown }).tag === 'number'\n );\n}\n\n// Re-throw a DataStructError after prefixing its path with a new segment.\n// `segment` is either `.field` or `[index]`. Only allocated on the error path.\nfunction rethrowWithPrefix(err: unknown, segment: string): never {\n if (!(err instanceof DataStructError)) throw err;\n const oldPath = err.path === '$' ? '' : err.path.slice(1);\n const newPath = `$${segment}${oldPath}`;\n // DataStructError's constructor appends \" at <path>\" to the message when\n // a path is provided; strip the previous suffix so we don't accumulate.\n const oldSuffix = err.path === '$' ? '' : `${PATH_AT}${err.path}`;\n const baseMessage =\n oldSuffix && err.message.endsWith(oldSuffix)\n ? err.message.slice(0, -oldSuffix.length)\n : err.message;\n const opts: { path: string; offset?: number; cause?: unknown } = { path: newPath };\n if (err.offset !== undefined) opts.offset = err.offset;\n opts.cause = err.cause ?? err;\n throw new DataStructError(err.code, baseMessage, opts);\n}\n\nfunction compile(schema: Schema): AnyCodec {\n if (isCodec(schema)) return schema;\n if (Array.isArray(schema)) {\n if (schema.length !== 1) {\n throw new DataStructError(\n 'INVALID_SCHEMA',\n `array schema must have exactly one element descriptor, got ${schema.length}`,\n );\n }\n const element = schema[0];\n if (element === undefined) {\n throw new DataStructError('INVALID_SCHEMA', 'array schema element is undefined');\n }\n return arrayCodec(compile(element));\n }\n if (typeof schema === 'object' && schema !== null) {\n return structCodec(schema as Record<string, Schema>);\n }\n throw new DataStructError('INVALID_SCHEMA', `unsupported schema node: ${String(schema)}`);\n}\n\nfunction arrayCodec(element: AnyCodec): Codec<unknown[]> {\n const impl: CodecImpl<unknown[]> = {\n measure(value, plan) {\n if (!Array.isArray(value)) {\n throw new DataStructError('SCHEMA_MISMATCH', `expected array, got ${typeof value}`);\n }\n if (value.length > ARRAY_LENGTH_MAX) {\n throw new DataStructError(\n 'ARRAY_TOO_LONG',\n `array length ${value.length} exceeds ${ARRAY_LENGTH_MAX}`,\n );\n }\n let size = 2;\n for (let i = 0; i < value.length; i++) {\n try {\n size += element.impl.measure(value[i], plan);\n } catch (e) {\n rethrowWithPrefix(e, `[${i}]`);\n }\n }\n return size;\n },\n write(view, bytes, offset, value, plan) {\n view.setUint16(offset, value.length, false);\n offset += 2;\n for (let i = 0; i < value.length; i++) {\n try {\n offset = element.impl.write(view, bytes, offset, value[i], plan);\n } catch (e) {\n rethrowWithPrefix(e, `[${i}]`);\n }\n }\n return offset;\n },\n read(view, bytes, offset) {\n if (offset + 2 > view.byteLength) {\n throw new DataStructError(\n 'BUFFER_UNDERFLOW',\n `need 2 byte(s) for array length at offset ${offset}`,\n { offset },\n );\n }\n const length = view.getUint16(offset, false);\n offset += 2;\n const out = new Array<unknown>(length);\n for (let i = 0; i < length; i++) {\n try {\n const r = element.impl.read(view, bytes, offset);\n out[i] = r.value;\n offset = r.offset;\n } catch (e) {\n rethrowWithPrefix(e, `[${i}]`);\n }\n }\n return { value: out, offset };\n },\n };\n return { tag: 0x100, impl };\n}\n\nfunction structCodec(schema: Record<string, Schema>): Codec<Record<string, unknown>> {\n const keys = Object.keys(schema);\n const fields: [string, AnyCodec][] = keys.map((key) => {\n const child = schema[key];\n if (child === undefined) {\n throw new DataStructError('INVALID_SCHEMA', `field \"${key}\" is undefined`);\n }\n return [key, compile(child)];\n });\n\n const impl: CodecImpl<Record<string, unknown>> = {\n measure(value, plan) {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n throw new DataStructError('SCHEMA_MISMATCH', `expected object, got ${typeof value}`);\n }\n const obj = value as Record<string, unknown>;\n let size = 0;\n for (const [key, codec] of fields) {\n try {\n size += codec.impl.measure(obj[key], plan);\n } catch (e) {\n rethrowWithPrefix(e, `.${key}`);\n }\n }\n return size;\n },\n write(view, bytes, offset, value, plan) {\n for (const [key, codec] of fields) {\n try {\n offset = codec.impl.write(view, bytes, offset, value[key], plan);\n } catch (e) {\n rethrowWithPrefix(e, `.${key}`);\n }\n }\n return offset;\n },\n read(view, bytes, offset) {\n const out = Object.create(null) as Record<string, unknown>;\n for (const [key, codec] of fields) {\n try {\n const r = codec.impl.read(view, bytes, offset);\n out[key] = r.value;\n offset = r.offset;\n } catch (e) {\n rethrowWithPrefix(e, `.${key}`);\n }\n }\n return { value: out, offset };\n },\n };\n return { tag: 0x300, impl };\n}\n\nexport interface Struct<S extends Schema> {\n readonly schema: S;\n encode(value: Infer<S>): Buffer;\n decode(input: Uint8Array): Infer<S>;\n sizeOf(value: Infer<S>): number;\n}\n\nexport function struct<S extends Schema>(schema: S): Struct<S> {\n const codec = compile(schema);\n\n return {\n schema,\n encode(value): Buffer {\n const plan: EncodePlan = { strings: [], cursor: 0 };\n const size = codec.impl.measure(value, plan);\n const out = Buffer.allocUnsafe(size);\n const view = new DataView(out.buffer, out.byteOffset, out.byteLength);\n plan.cursor = 0;\n const written = codec.impl.write(view, out, 0, value, plan);\n if (written !== size) {\n throw new DataStructError(\n 'INVALID_SCHEMA',\n `internal size mismatch: measured ${size}, wrote ${written}`,\n );\n }\n return out;\n },\n decode(input): Infer<S> {\n if (!(input instanceof Uint8Array)) {\n throw new DataStructError(\n 'SCHEMA_MISMATCH',\n `decode expects Uint8Array, got ${typeof input}`,\n );\n }\n const view = new DataView(input.buffer, input.byteOffset, input.byteLength);\n const { value } = codec.impl.read(view, input, 0);\n return value as Infer<S>;\n },\n sizeOf(value): number {\n return codec.impl.measure(value, { strings: [], cursor: 0 });\n },\n };\n}\n\nexport function encode<S extends Schema>(value: Infer<S>, schema: S): Buffer {\n return struct(schema).encode(value);\n}\n\nexport function decode<S extends Schema>(input: Uint8Array, schema: S): Infer<S> {\n return struct(schema).decode(input);\n}\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { Buffer } from 'node:buffer';
|
|
2
|
+
|
|
3
|
+
declare const phantom: unique symbol;
|
|
4
|
+
interface EncodePlan {
|
|
5
|
+
strings: Uint8Array[];
|
|
6
|
+
cursor: number;
|
|
7
|
+
}
|
|
8
|
+
interface ReadResult<T> {
|
|
9
|
+
value: T;
|
|
10
|
+
offset: number;
|
|
11
|
+
}
|
|
12
|
+
interface CodecImpl<T> {
|
|
13
|
+
measure(value: T, plan: EncodePlan): number;
|
|
14
|
+
write(view: DataView, bytes: Uint8Array, offset: number, value: T, plan: EncodePlan): number;
|
|
15
|
+
read(view: DataView, bytes: Uint8Array, offset: number): ReadResult<T>;
|
|
16
|
+
}
|
|
17
|
+
interface Codec<T> {
|
|
18
|
+
readonly tag: number;
|
|
19
|
+
readonly impl: CodecImpl<T>;
|
|
20
|
+
readonly [phantom]?: T;
|
|
21
|
+
}
|
|
22
|
+
type AnyCodec = Codec<any>;
|
|
23
|
+
type Schema = AnyCodec | readonly Schema[] | {
|
|
24
|
+
readonly [key: string]: Schema;
|
|
25
|
+
};
|
|
26
|
+
type Infer<S> = S extends Codec<infer T> ? T : S extends readonly (infer E)[] ? E extends Schema ? Infer<E>[] : never : S extends {
|
|
27
|
+
readonly [key: string]: Schema;
|
|
28
|
+
} ? {
|
|
29
|
+
-readonly [K in keyof S]: Infer<S[K]>;
|
|
30
|
+
} : never;
|
|
31
|
+
|
|
32
|
+
declare const t: {
|
|
33
|
+
readonly le: {
|
|
34
|
+
i16: Codec<number>;
|
|
35
|
+
u16: Codec<number>;
|
|
36
|
+
i32: Codec<number>;
|
|
37
|
+
u32: Codec<number>;
|
|
38
|
+
f32: Codec<number>;
|
|
39
|
+
f64: Codec<number>;
|
|
40
|
+
i64: Codec<bigint>;
|
|
41
|
+
u64: Codec<bigint>;
|
|
42
|
+
string: Codec<string>;
|
|
43
|
+
shortBytes: Codec<Uint8Array<ArrayBufferLike>>;
|
|
44
|
+
bytes: Codec<Uint8Array<ArrayBufferLike>>;
|
|
45
|
+
};
|
|
46
|
+
readonly bool: Codec<boolean>;
|
|
47
|
+
readonly i8: Codec<number>;
|
|
48
|
+
readonly u8: Codec<number>;
|
|
49
|
+
readonly i16: Codec<number>;
|
|
50
|
+
readonly u16: Codec<number>;
|
|
51
|
+
readonly i32: Codec<number>;
|
|
52
|
+
readonly u32: Codec<number>;
|
|
53
|
+
readonly f32: Codec<number>;
|
|
54
|
+
readonly f64: Codec<number>;
|
|
55
|
+
readonly i64: Codec<bigint>;
|
|
56
|
+
readonly u64: Codec<bigint>;
|
|
57
|
+
readonly string: Codec<string>;
|
|
58
|
+
readonly shortBytes: Codec<Uint8Array<ArrayBufferLike>>;
|
|
59
|
+
readonly bytes: Codec<Uint8Array<ArrayBufferLike>>;
|
|
60
|
+
};
|
|
61
|
+
type TypeRegistry = typeof t;
|
|
62
|
+
|
|
63
|
+
type DataStructErrorCode = 'VALUE_OUT_OF_RANGE' | 'STRING_TOO_LONG' | 'BYTES_TOO_LONG' | 'ARRAY_TOO_LONG' | 'BUFFER_UNDERFLOW' | 'SCHEMA_MISMATCH' | 'INVALID_SCHEMA';
|
|
64
|
+
interface DataStructErrorOptions {
|
|
65
|
+
path?: string;
|
|
66
|
+
offset?: number;
|
|
67
|
+
cause?: unknown;
|
|
68
|
+
}
|
|
69
|
+
declare class DataStructError extends Error {
|
|
70
|
+
readonly code: DataStructErrorCode;
|
|
71
|
+
readonly path: string;
|
|
72
|
+
readonly offset: number | undefined;
|
|
73
|
+
constructor(code: DataStructErrorCode, message: string, opts?: DataStructErrorOptions);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
interface Struct<S extends Schema> {
|
|
77
|
+
readonly schema: S;
|
|
78
|
+
encode(value: Infer<S>): Buffer;
|
|
79
|
+
decode(input: Uint8Array): Infer<S>;
|
|
80
|
+
sizeOf(value: Infer<S>): number;
|
|
81
|
+
}
|
|
82
|
+
declare function struct<S extends Schema>(schema: S): Struct<S>;
|
|
83
|
+
declare function encode<S extends Schema>(value: Infer<S>, schema: S): Buffer;
|
|
84
|
+
declare function decode<S extends Schema>(input: Uint8Array, schema: S): Infer<S>;
|
|
85
|
+
|
|
86
|
+
export { type Codec, type CodecImpl, DataStructError, type DataStructErrorCode, type DataStructErrorOptions, type Infer, type Schema, type Struct, type TypeRegistry, decode, encode, struct, t };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { Buffer } from 'node:buffer';
|
|
2
|
+
|
|
3
|
+
declare const phantom: unique symbol;
|
|
4
|
+
interface EncodePlan {
|
|
5
|
+
strings: Uint8Array[];
|
|
6
|
+
cursor: number;
|
|
7
|
+
}
|
|
8
|
+
interface ReadResult<T> {
|
|
9
|
+
value: T;
|
|
10
|
+
offset: number;
|
|
11
|
+
}
|
|
12
|
+
interface CodecImpl<T> {
|
|
13
|
+
measure(value: T, plan: EncodePlan): number;
|
|
14
|
+
write(view: DataView, bytes: Uint8Array, offset: number, value: T, plan: EncodePlan): number;
|
|
15
|
+
read(view: DataView, bytes: Uint8Array, offset: number): ReadResult<T>;
|
|
16
|
+
}
|
|
17
|
+
interface Codec<T> {
|
|
18
|
+
readonly tag: number;
|
|
19
|
+
readonly impl: CodecImpl<T>;
|
|
20
|
+
readonly [phantom]?: T;
|
|
21
|
+
}
|
|
22
|
+
type AnyCodec = Codec<any>;
|
|
23
|
+
type Schema = AnyCodec | readonly Schema[] | {
|
|
24
|
+
readonly [key: string]: Schema;
|
|
25
|
+
};
|
|
26
|
+
type Infer<S> = S extends Codec<infer T> ? T : S extends readonly (infer E)[] ? E extends Schema ? Infer<E>[] : never : S extends {
|
|
27
|
+
readonly [key: string]: Schema;
|
|
28
|
+
} ? {
|
|
29
|
+
-readonly [K in keyof S]: Infer<S[K]>;
|
|
30
|
+
} : never;
|
|
31
|
+
|
|
32
|
+
declare const t: {
|
|
33
|
+
readonly le: {
|
|
34
|
+
i16: Codec<number>;
|
|
35
|
+
u16: Codec<number>;
|
|
36
|
+
i32: Codec<number>;
|
|
37
|
+
u32: Codec<number>;
|
|
38
|
+
f32: Codec<number>;
|
|
39
|
+
f64: Codec<number>;
|
|
40
|
+
i64: Codec<bigint>;
|
|
41
|
+
u64: Codec<bigint>;
|
|
42
|
+
string: Codec<string>;
|
|
43
|
+
shortBytes: Codec<Uint8Array<ArrayBufferLike>>;
|
|
44
|
+
bytes: Codec<Uint8Array<ArrayBufferLike>>;
|
|
45
|
+
};
|
|
46
|
+
readonly bool: Codec<boolean>;
|
|
47
|
+
readonly i8: Codec<number>;
|
|
48
|
+
readonly u8: Codec<number>;
|
|
49
|
+
readonly i16: Codec<number>;
|
|
50
|
+
readonly u16: Codec<number>;
|
|
51
|
+
readonly i32: Codec<number>;
|
|
52
|
+
readonly u32: Codec<number>;
|
|
53
|
+
readonly f32: Codec<number>;
|
|
54
|
+
readonly f64: Codec<number>;
|
|
55
|
+
readonly i64: Codec<bigint>;
|
|
56
|
+
readonly u64: Codec<bigint>;
|
|
57
|
+
readonly string: Codec<string>;
|
|
58
|
+
readonly shortBytes: Codec<Uint8Array<ArrayBufferLike>>;
|
|
59
|
+
readonly bytes: Codec<Uint8Array<ArrayBufferLike>>;
|
|
60
|
+
};
|
|
61
|
+
type TypeRegistry = typeof t;
|
|
62
|
+
|
|
63
|
+
type DataStructErrorCode = 'VALUE_OUT_OF_RANGE' | 'STRING_TOO_LONG' | 'BYTES_TOO_LONG' | 'ARRAY_TOO_LONG' | 'BUFFER_UNDERFLOW' | 'SCHEMA_MISMATCH' | 'INVALID_SCHEMA';
|
|
64
|
+
interface DataStructErrorOptions {
|
|
65
|
+
path?: string;
|
|
66
|
+
offset?: number;
|
|
67
|
+
cause?: unknown;
|
|
68
|
+
}
|
|
69
|
+
declare class DataStructError extends Error {
|
|
70
|
+
readonly code: DataStructErrorCode;
|
|
71
|
+
readonly path: string;
|
|
72
|
+
readonly offset: number | undefined;
|
|
73
|
+
constructor(code: DataStructErrorCode, message: string, opts?: DataStructErrorOptions);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
interface Struct<S extends Schema> {
|
|
77
|
+
readonly schema: S;
|
|
78
|
+
encode(value: Infer<S>): Buffer;
|
|
79
|
+
decode(input: Uint8Array): Infer<S>;
|
|
80
|
+
sizeOf(value: Infer<S>): number;
|
|
81
|
+
}
|
|
82
|
+
declare function struct<S extends Schema>(schema: S): Struct<S>;
|
|
83
|
+
declare function encode<S extends Schema>(value: Infer<S>, schema: S): Buffer;
|
|
84
|
+
declare function decode<S extends Schema>(input: Uint8Array, schema: S): Infer<S>;
|
|
85
|
+
|
|
86
|
+
export { type Codec, type CodecImpl, DataStructError, type DataStructErrorCode, type DataStructErrorOptions, type Infer, type Schema, type Struct, type TypeRegistry, decode, encode, struct, t };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import {Buffer}from'buffer';var d=class extends Error{code;path;offset;constructor(s,i,n={}){super(n.path?`${i} at ${n.path}`:i,{cause:n.cause}),this.name="DataStructError",this.code=s,this.path=n.path??"$",this.offset=n.offset;}};var F=new TextEncoder,V=new TextDecoder("utf-8",{fatal:true}),G=255,C=65535,U=4294967295,j=-128,X=127,O=-32768,E=32767,T=-2147483648,D=2147483647,q=-(1n<<63n),P=(1n<<63n)-1n,Y=(1n<<64n)-1n;function l(e,s,i){if(s+i>e.byteLength)throw new d("BUFFER_UNDERFLOW",`need ${i} byte(s) at offset ${s}, but buffer has ${e.byteLength}`,{offset:s})}function W(e,s,i,n){if(typeof e!="number"||!Number.isInteger(e)||e<s||e>i)throw new d("VALUE_OUT_OF_RANGE",`${n} requires integer in [${s}, ${i}], got ${e}`)}function L(e,s){if(typeof e!="number")throw new d("VALUE_OUT_OF_RANGE",`${s} requires number, got ${typeof e}`)}function z(e,s,i,n){if(typeof e!="bigint"||e<s||e>i)throw new d("VALUE_OUT_OF_RANGE",`${n} requires bigint in [${s}, ${i}], got ${e}`)}function N(e,s){if(!(e instanceof Uint8Array))throw new d("SCHEMA_MISMATCH",`${s} requires Uint8Array, got ${typeof e}`)}function x(e,s,i,n,r){return {tag:e,impl:{measure:()=>s,write(o,c,u,m){return r(m),i(o,u,m),u+s},read(o,c,u){return l(o,u,s),{value:n(o,u),offset:u+s}}}}}var J={measure:()=>1,write(e,s,i,n){if(typeof n!="boolean")throw new d("SCHEMA_MISMATCH",`bool requires boolean, got ${typeof n}`);return e.setUint8(i,n?1:0),i+1},read(e,s,i){return l(e,i,1),{value:e.getInt8(i)!==0,offset:i+1}}};function R(e,s){return {tag:s,impl:{measure(n,r){if(typeof n!="string")throw new d("SCHEMA_MISMATCH",`string requires string, got ${typeof n}`);let t=F.encode(n);if(t.byteLength>C)throw new d("STRING_TOO_LONG",`string UTF-8 byte length ${t.byteLength} exceeds 65535`);return r.strings.push(t),2+t.byteLength},write(n,r,t,o,c){let u=c.strings[c.cursor++];return n.setUint16(t,u.byteLength,e),t+=2,r.set(u,t),t+u.byteLength},read(n,r,t){l(n,t,2);let o=n.getUint16(t,e);t+=2,l(n,t,o);let c;try{c=V.decode(r.subarray(t,t+o));}catch(u){throw new d("SCHEMA_MISMATCH","invalid UTF-8 in string field",{offset:t,cause:u})}return {value:c,offset:t+o}}}}}function H(e,s){return {tag:s,impl:{measure(n){if(N(n,"shortBytes"),n.byteLength>C)throw new d("BYTES_TOO_LONG",`shortBytes length ${n.byteLength} exceeds 65535`);return 2+n.byteLength},write(n,r,t,o){return n.setUint16(t,o.byteLength,e),t+=2,r.set(o,t),t+o.byteLength},read(n,r,t){l(n,t,2);let o=n.getUint16(t,e);t+=2,l(n,t,o);let c=new Uint8Array(o);return c.set(r.subarray(t,t+o)),{value:c,offset:t+o}}}}}function B(e,s){return {tag:s,impl:{measure(n){if(N(n,"bytes"),n.byteLength>U)throw new d("BYTES_TOO_LONG",`bytes length ${n.byteLength} exceeds 4294967295`);return 4+n.byteLength},write(n,r,t,o){return n.setUint32(t,o.byteLength,e),t+=4,r.set(o,t),t+o.byteLength},read(n,r,t){l(n,t,4);let o=n.getUint32(t,e);t+=4,l(n,t,o);let c=new Uint8Array(o);return c.set(r.subarray(t,t+o)),{value:c,offset:t+o}}}}}function h(e,s,i,n,r,t,o){let c={"i:1":(a,y,g)=>a.setInt8(y,g),"u:1":(a,y,g)=>a.setUint8(y,g),"i:2":(a,y,g,w)=>a.setInt16(y,g,w),"u:2":(a,y,g,w)=>a.setUint16(y,g,w),"i:4":(a,y,g,w)=>a.setInt32(y,g,w),"u:4":(a,y,g,w)=>a.setUint32(y,g,w)},u={"i:1":(a,y)=>a.getInt8(y),"u:1":(a,y)=>a.getUint8(y),"i:2":(a,y,g)=>a.getInt16(y,g),"u:2":(a,y,g)=>a.getUint16(y,g),"i:4":(a,y,g)=>a.getInt32(y,g),"u:4":(a,y,g)=>a.getUint32(y,g)},m=`${i?"i":"u"}:${s}`,p=c[m],_=u[m];return x(e,s,(a,y,g)=>p(a,y,g,o),(a,y)=>_(a,y,o),a=>W(a,n,r,t))}function S(e,s,i,n){return s===4?x(e,4,(r,t,o)=>r.setFloat32(t,o,n),(r,t)=>r.getFloat32(t,n),r=>L(r,i)):x(e,8,(r,t,o)=>r.setFloat64(t,o,n),(r,t)=>r.getFloat64(t,n),r=>L(r,i))}function I(e,s,i,n){let r=s?q:0n,t=s?P:Y;return x(e,8,(o,c,u)=>{s?o.setBigInt64(c,u,n):o.setBigUint64(c,u,n);},(o,c)=>s?o.getBigInt64(c,n):o.getBigUint64(c,n),o=>z(o,r,t,i))}var b=false,f=true,K={bool:{tag:0,impl:J},i8:h(16,1,true,j,X,"i8",b),u8:h(17,1,false,0,G,"u8",b),i16:h(32,2,true,O,E,"i16",b),u16:h(33,2,false,0,C,"u16",b),i32:h(48,4,true,T,D,"i32",b),u32:h(49,4,false,0,U,"u32",b),f32:S(64,4,"f32",b),f64:S(65,8,"f64",b),i64:I(80,true,"i64",b),u64:I(81,false,"u64",b),string:R(b,512),shortBytes:H(b,528),bytes:B(b,529)},Q={i16:h(4128,2,true,O,E,"le.i16",f),u16:h(4129,2,false,0,C,"le.u16",f),i32:h(4144,4,true,T,D,"le.i32",f),u32:h(4145,4,false,0,U,"le.u32",f),f32:S(4160,4,"le.f32",f),f64:S(4161,8,"le.f64",f),i64:I(4176,true,"le.i64",f),u64:I(4177,false,"le.u64",f),string:R(f,4608),shortBytes:H(f,4624),bytes:B(f,4625)},Z={...K,le:Q};var k=65535,ee=" at ";function te(e){return typeof e=="object"&&e!==null&&"impl"in e&&"tag"in e&&typeof e.tag=="number"}function A(e,s){if(!(e instanceof d))throw e;let i=e.path==="$"?"":e.path.slice(1),n=`$${s}${i}`,r=e.path==="$"?"":`${ee}${e.path}`,t=r&&e.message.endsWith(r)?e.message.slice(0,-r.length):e.message,o={path:n};throw e.offset!==void 0&&(o.offset=e.offset),o.cause=e.cause??e,new d(e.code,t,o)}function $(e){if(te(e))return e;if(Array.isArray(e)){if(e.length!==1)throw new d("INVALID_SCHEMA",`array schema must have exactly one element descriptor, got ${e.length}`);let s=e[0];if(s===void 0)throw new d("INVALID_SCHEMA","array schema element is undefined");return ne($(s))}if(typeof e=="object"&&e!==null)return re(e);throw new d("INVALID_SCHEMA",`unsupported schema node: ${String(e)}`)}function ne(e){return {tag:256,impl:{measure(i,n){if(!Array.isArray(i))throw new d("SCHEMA_MISMATCH",`expected array, got ${typeof i}`);if(i.length>k)throw new d("ARRAY_TOO_LONG",`array length ${i.length} exceeds ${k}`);let r=2;for(let t=0;t<i.length;t++)try{r+=e.impl.measure(i[t],n);}catch(o){A(o,`[${t}]`);}return r},write(i,n,r,t,o){i.setUint16(r,t.length,false),r+=2;for(let c=0;c<t.length;c++)try{r=e.impl.write(i,n,r,t[c],o);}catch(u){A(u,`[${c}]`);}return r},read(i,n,r){if(r+2>i.byteLength)throw new d("BUFFER_UNDERFLOW",`need 2 byte(s) for array length at offset ${r}`,{offset:r});let t=i.getUint16(r,false);r+=2;let o=new Array(t);for(let c=0;c<t;c++)try{let u=e.impl.read(i,n,r);o[c]=u.value,r=u.offset;}catch(u){A(u,`[${c}]`);}return {value:o,offset:r}}}}}function re(e){let i=Object.keys(e).map(r=>{let t=e[r];if(t===void 0)throw new d("INVALID_SCHEMA",`field "${r}" is undefined`);return [r,$(t)]});return {tag:768,impl:{measure(r,t){if(typeof r!="object"||r===null||Array.isArray(r))throw new d("SCHEMA_MISMATCH",`expected object, got ${typeof r}`);let o=r,c=0;for(let[u,m]of i)try{c+=m.impl.measure(o[u],t);}catch(p){A(p,`.${u}`);}return c},write(r,t,o,c,u){for(let[m,p]of i)try{o=p.impl.write(r,t,o,c[m],u);}catch(_){A(_,`.${m}`);}return o},read(r,t,o){let c=Object.create(null);for(let[u,m]of i)try{let p=m.impl.read(r,t,o);c[u]=p.value,o=p.offset;}catch(p){A(p,`.${u}`);}return {value:c,offset:o}}}}}function M(e){let s=$(e);return {schema:e,encode(i){let n={strings:[],cursor:0},r=s.impl.measure(i,n),t=Buffer.allocUnsafe(r),o=new DataView(t.buffer,t.byteOffset,t.byteLength);n.cursor=0;let c=s.impl.write(o,t,0,i,n);if(c!==r)throw new d("INVALID_SCHEMA",`internal size mismatch: measured ${r}, wrote ${c}`);return t},decode(i){if(!(i instanceof Uint8Array))throw new d("SCHEMA_MISMATCH",`decode expects Uint8Array, got ${typeof i}`);let n=new DataView(i.buffer,i.byteOffset,i.byteLength),{value:r}=s.impl.read(n,i,0);return r},sizeOf(i){return s.impl.measure(i,{strings:[],cursor:0})}}}function oe(e,s){return M(s).encode(e)}function ie(e,s){return M(s).decode(e)}export{d as DataStructError,ie as decode,oe as encode,M as struct,Z as t};//# sourceMappingURL=index.mjs.map
|
|
2
|
+
//# sourceMappingURL=index.mjs.map
|