capnstruct 0.0.0-stage → 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/README.md CHANGED
@@ -1,3 +1,137 @@
1
- # Temporary Holding Version
1
+ # <img src="docs/public/icon.svg" width="32" height="32" align="top" alt="capnstruct icon" /> capnstruct
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ **Zero-Copy `#[repr(C)]` Structs for Web Workers, `SharedArrayBuffer` & WebAssembly** — the missing shared-memory struct layer between TypeScript, Web Workers, and Rust/Go WASM.
4
+
5
+ [![Live Playground & Docs](https://img.shields.io/badge/Live_Playground-capnstruct.teamchong.net-3b82f6?style=flat-square)](https://capnstruct.teamchong.net)
6
+ [![Core Bundle](https://img.shields.io/badge/Core_Gzip-6.62_KiB-10b981?style=flat-square)](https://capnstruct.teamchong.net/wasm-and-rust/)
7
+ [![Targets](https://img.shields.io/badge/Targets-TS_%7C_Rust_%23%5Brepr(C)%5D_%7C_Go_%26_TinyGo_WASM-f59e0b?style=flat-square)](https://capnstruct.teamchong.net/wasm-and-rust/)
8
+
9
+ **[Live Interactive Playground &rarr; capnstruct.teamchong.net](https://capnstruct.teamchong.net)** &middot; **[MP4 Video (`docs/public/demo.mp4`)](docs/public/demo.mp4)**
10
+
11
+ [![Live Side-by-Side Comparison: Worker postMessage (structuredClone) vs Rust -O3 WASM (serde-wasm-bindgen FFI) vs capnstruct #[repr(C)] (Shared / WasmArena)](docs/public/demo.gif)](https://capnstruct.teamchong.net)
12
+
13
+
14
+ ```ts
15
+ import { struct, u32, f32, u16, str, slice, ref } from 'capnstruct';
16
+ const Waypoint = struct('Waypoint', { lat: f32, lon: f32 });
17
+ const Flight = struct('Flight', { id: u32, callsign: str, alt: u16, waypoints: slice(Waypoint), nextRelay: ref('Flight') });
18
+ const { view: fleet, ptr, len } = Flight.inWasm(wasmMem, workerRows); // 0ms copy: allocates 100k #[repr(C)] rows in WebAssembly.Memory & passes (ptr, len) to Rust/Go WASM!
19
+ ```
20
+ ---
21
+
22
+ ## Why Data Layout Beats Engine & Language Switches
23
+
24
+ Switching JS engines (**Node.js V8 &rarr; Bun JavaScriptCore**) speeds up `JSON.parse` + `.filter()` by **~2x**, and rewriting in **Rust (`rustc -O3` WASM)** without changing the wire format still spends **3.7 ms** scanning `5.27 MiB` of ASCII JSON text (or **23.0 ms** copying strings across the JS&harr;WASM FFI boundary).
25
+
26
+ Restructuring into a contiguous **`capnstruct #[repr(C)]` binary layout** drops execution to **0.17&ndash;0.31 ms in standard JavaScript** (**45x faster** than Rust JSON parsing!), and when you combine `capnstruct` with **Rust / Go / TinyGo WASM**, execution drops to **0.015&ndash;0.071 ms** (**198x&ndash;651x faster** with **0 MB heap / 0 GC pauses**):
27
+
28
+ | Workload | Node.js V8 (JSON) | Bun JSC (~2x) | Rust `-O3` (JSON / FFI) | `capnstruct #[repr(C)]` (JS / Rust / Go WASM) | Speedup |
29
+ | :-------------------------------------------------------- | :-------------------- | :--------------------- | :------------------------- | :------------------------------------------------------- | :---------------------- |
30
+ | **100k `SpdSample` Scan** (`5.27 MiB` JSON vs `2.29 MiB`) | 14.14 ms (`+10.3 MB`) | 5.65 ms (`+6.9 MB`) | 3.68 ms JSON / 23.7 ms FFI | **0.31 ms JS** / **0.071 ms Rust** / **0.084 ms TinyGo** | **45x JS / 198x WASM** |
31
+ | **25k Telemetry Filter** (4% hit rate) | 13.24 ms (`+8.2 MB`) | 5.21 ms (`+5.2 MB`) | 4.16 ms JSON | **0.39 ms JS** / **0.020 ms Rust** / **0.031 ms Go** | **34x JS / 651x WASM** |
32
+ | **25k `QpPoint` JS &harr; WASM Boundary** | 5.48 ms (`+3.7 MB`) | 2.10 ms (`+1.7 MB`) | 5.48 ms (`serde` FFI) | **0.34 ms JS** / **0.036 ms Rust** (`0 B` copy) | **16x JS / 153x WASM** |
33
+ | **25k Worker `postMessage` Round-Trip** | 45.94 ms (`+14.2 MB`) | 35.50 ms (`+5.7 MB`) | - | **0.046 ms JS** (`SharedArrayBuffer` in-place) | **~1,000x faster** |
34
+ | **100k Sorted `rangeBy('id', min, max)`** | 14.06 ms (`+10.3 MB`) | 5.88 ms (`+6.9 MB`) | - | **0.0058 ms JS** (`O(log N)` binary search, `0 B`) | **~2,400x faster** |
35
+ | **10k Cyclic `RingNode` Graph Clone** | 2.63 ms (`+0.7 MB`) | 3.23 ms (`serde_json`) | Throws on cycle | **0.30 ms JS** / **0.016 ms Rust** / **0.019 ms Go** | **173x Go / 190x Rust** |
36
+
37
+ ### Wire Layout & Safety Guarantees
38
+
39
+ ```text
40
+ +-------------------------------------------------------------------+
41
+ | Fixed #[repr(C)] Struct Table (N * def.size bytes, 8B-aligned) |
42
+ | Row 0: [primitive | fixedStr | CapnStr(off,len) | CapnRef(off)] |
43
+ | Row 1: [primitive | fixedStr | CapnStr(off,len) | CapnRef(off)] |
44
+ +-------------------------------------------------------------------+
45
+ | Optional Tail Arena (UTF-8 strings, slices & ref targets) |
46
+ | target_offset = structBaseOffset + fieldOffset + relOff |
47
+ +-------------------------------------------------------------------+
48
+ ```
49
+
50
+ 1. **Zero-Header Fixed Layouts**: Structs using only primitives, `fixedArray`, `fixedStr(N)`, `fixedBytes(N)`, `sentinel()`, `scaled()`, and `f16` have **zero pointers and zero tail arena** (100% byte-for-byte identical to a C/Rust `#[repr(C)]` struct or array).
51
+ 2. **Wire-Safe Pointer Bounds & Amplification Defense**: Wrapping a `Uint8Array` sub-slice clamps the `DataView` window to `[byteOffset .. byteOffset + byteLength]`, validates every `[relOffset, length]` descriptor against `[structEnd .. bufferEnd]`, and enforces an `8x` traversal budget against pointer-aliasing amplification attacks while preserving valid cycles.
52
+ 3. **Cap'n-Style Wire Stride Evolution**: Pass an older schema to `NewSchema.array(v1Bytes, OldSchema)` to read older binary payloads with zero copying; fields beyond the older wire stride return default values (`0`, `""`, `[]`, `null`) and upgrade in place on mutation.
53
+
54
+ ---
55
+
56
+ ## Quick Start
57
+
58
+ ### 1. Fixed `#[repr(C)]` Structs, Variable-Length Strings/Slices & In-Place Mutation
59
+
60
+ ```ts
61
+ import { defineStruct, u32, i32, i16, fixedStr, sentinel, scaled, str, slice } from 'capnstruct';
62
+
63
+ const Waypoint = defineStruct('Waypoint', {
64
+ lat: scaled(i32, 1e6), // 4B int32 on wire <-> float degrees in JS
65
+ lon: scaled(i32, 1e6),
66
+ alt: sentinel(i16, -32768), // -32768 on wire <-> null in JS (0 extra bytes)
67
+ });
68
+
69
+ const RadarPacket = defineStruct('RadarPacket', {
70
+ magic: fixedStr(4), // inline [u8; 4] ASCII
71
+ seq: u32,
72
+ callsign: str, // [u32 relOffset, u32 byteLen] into tail arena
73
+ route: slice(Waypoint), // [u32 relOffset, u32 count] into tail arena
74
+ });
75
+
76
+ const pkt = RadarPacket.create({
77
+ magic: 'RADR',
78
+ seq: 42,
79
+ callsign: 'SFO_101',
80
+ route: [{ lat: 37.6188, lon: -122.375, alt: null }],
81
+ });
82
+
83
+ pkt.seq += 1; // mutates u32 in-place (0 allocations)
84
+ pkt.route.at(0).alt = 1500; // updates nested struct in-place
85
+ const wireBytes: Uint8Array = pkt.bytes;
86
+ ```
87
+
88
+ ### 2. Queryable Binary Tables (`O(log N)` Range Search) & Cyclic Graphs (`ref`)
89
+
90
+ ```ts
91
+ import { defineStruct, u32, str, ref, slice } from 'capnstruct';
92
+
93
+ // 1. O(log N) binary search time-window slice & zero-heap filterBytes:
94
+ const table = RadarPacket.array(wireBytes);
95
+ const subView = table.rangeBy('seq', 10, 50);
96
+
97
+ // 2. Cyclic object graphs packed into flat Uint8Array in O(1) stack space (100% inferred types):
98
+ const GraphNode = defineStruct('GraphNode', (self) => ({
99
+ id: u32,
100
+ label: str,
101
+ next: ref(self),
102
+ children: slice(self),
103
+ }));
104
+
105
+ const n1 = GraphNode.item({ id: 1, label: 'alpha', next: null, children: [] });
106
+ const n2 = GraphNode.item({ id: 2, label: 'beta', next: n1, children: [n1] });
107
+ n1.next = n2;
108
+
109
+ const bytes = GraphNode.pack([n1, n2]);
110
+ const view = GraphNode.array(bytes);
111
+ console.log(view.at(0).next?.next?.id === view.at(0).id); // true (0 allocations)
112
+ ```
113
+
114
+ ### 3. First-Class `Schema.inWasm()` & Zero-Copy Rust `#[repr(C)]` / Go WASM Codegen
115
+
116
+ ```ts
117
+ import { toRustReprC, toGoStruct } from 'capnstruct/codegen';
118
+
119
+ // 1. Allocate or pack directly inside WebAssembly.Memory (via WasmArena or exported capn_alloc/alloc)
120
+ const { view, ptr, len } = RadarPacket.inWasm(wasmInstance.exports, [pkt]);
121
+ wasmInstance.exports.inspect_radar(ptr, len); // 0 FFI copies, 0 serde-wasm-bindgen overhead
122
+
123
+ // 2. Generate #[repr(C)] Rust structs with safe .as_slice(arena), .as_str(arena), .as_ref(arena) methods
124
+ console.log(toRustReprC([Waypoint, RadarPacket]));
125
+ console.log(toGoStruct([Waypoint, RadarPacket], { pkg: 'radar', wasm: true }));
126
+ ```
127
+
128
+ ```bash
129
+ npx capnstruct ./src/schema.ts -o ./src/schema.rs # Rust #[repr(C)] + safe .as_str/.as_slice/.as_ref
130
+ npx capnstruct ./src/schema.ts -o ./src/schema.go --pkg radar # Native Go / GOOS=wasip1
131
+ npx capnstruct ./src/schema.ts -o ./src/main_schema.go --go-wasm # TinyGo (-target=wasi)
132
+ ```
133
+
134
+ | Entrypoint | Minified | Minified + Gzip |
135
+ | :---------------------------------------------------------------------------------- | :-------- | :------------------------------------ |
136
+ | **`capnstruct`** (Core Runtime + `StructArrayView` + `ref` + `slice` + `WasmArena`) | 18.12 KiB | **7.12 KiB** (`6.62 KiB` schema core) |
137
+ | **`capnstruct/codegen`** (Rust `#[repr(C)]` + Go / TinyGo WASM Codegen) | 7.63 KiB | **2.57 KiB** |
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env node
2
+ import { writeFileSync } from 'node:fs';
3
+ import { resolve } from 'node:path';
4
+ import { pathToFileURL } from 'node:url';
5
+ import { toGoStruct, toRustReprC } from './codegen.js';
6
+ async function main() {
7
+ const args = process.argv.slice(2);
8
+ if (args.length === 0 || args.includes('--help') || args.includes('-h')) {
9
+ process.stdout.write([
10
+ 'Usage: capnstruct <schema-module.js> [-o <output.rs|output.go>] [--rust|--go|--go-wasm] [--pkg <name>] [--wasm] [--no-assertions]',
11
+ '',
12
+ 'Generates #[repr(C)] Rust or zero-copy Go / TinyGo WASM struct definitions and compile-time layout assertions',
13
+ 'from a JS/TS module exporting capnstruct StructDef schemas.',
14
+ '',
15
+ ].join('\n'));
16
+ return;
17
+ }
18
+ let inputPath = '';
19
+ let outputPath = '';
20
+ let target = '';
21
+ let pkg = '';
22
+ let wasm = false;
23
+ let assertions = true;
24
+ for (let i = 0; i < args.length; i++) {
25
+ const a = args[i];
26
+ if (a === '-o' || a === '--out') {
27
+ outputPath = args[++i] ?? '';
28
+ }
29
+ else if (a === '--go') {
30
+ target = 'go';
31
+ }
32
+ else if (a === '--go-wasm') {
33
+ target = 'go';
34
+ wasm = true;
35
+ }
36
+ else if (a === '--wasm') {
37
+ wasm = true;
38
+ }
39
+ else if (a === '--rust') {
40
+ target = 'rust';
41
+ }
42
+ else if (a === '--pkg' || a === '--package') {
43
+ pkg = args[++i] ?? '';
44
+ }
45
+ else if (a === '--no-assertions') {
46
+ assertions = false;
47
+ }
48
+ else if (!a.startsWith('-')) {
49
+ inputPath = a;
50
+ }
51
+ }
52
+ if (!inputPath) {
53
+ throw new Error('Missing <schema-module.js> argument');
54
+ }
55
+ if (!target) {
56
+ target = outputPath.endsWith('.go') ? 'go' : 'rust';
57
+ }
58
+ const modUrl = pathToFileURL(resolve(process.cwd(), inputPath)).href;
59
+ const mod = await import(modUrl);
60
+ const code = target === 'go'
61
+ ? toGoStruct(mod, { pkg: pkg || undefined, assertions, wasm })
62
+ : toRustReprC(mod, { assertions });
63
+ if (outputPath) {
64
+ writeFileSync(resolve(process.cwd(), outputPath), code, 'utf8');
65
+ }
66
+ else {
67
+ process.stdout.write(code);
68
+ }
69
+ }
70
+ main().catch((err) => {
71
+ const msg = err instanceof Error ? err.message : String(err);
72
+ process.stderr.write(`capnstruct error: ${msg}\n`);
73
+ process.exitCode = 1;
74
+ });
75
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { StructDefLike } from './index.js';
2
+ export interface RustCodegenOptions {
3
+ /** Additional `#[derive(...)]` traits (default: `['Copy', 'Clone', 'Debug', 'PartialEq']`). */
4
+ derive?: readonly string[];
5
+ /** Emit compile-time size/align/offset_of assertions (default: `true`). */
6
+ assertions?: boolean;
7
+ /** Visibility modifier for structs and fields (default: `'pub'`). */
8
+ vis?: 'pub' | 'pub(crate)' | '';
9
+ }
10
+ export interface GoCodegenOptions {
11
+ /** Go package name (default: `'capnschema'`, or `'main'` when `wasm: true`). */
12
+ pkg?: string;
13
+ /** Emit compile-time size/align/offsetof assertions (default: `true`). */
14
+ assertions?: boolean;
15
+ /** Emit `//go:wasmexport capn_alloc` & `capn_reset` arena helpers for Go (`GOOS=wasip1 GOARCH=wasm`) and TinyGo (`-target=wasi`) WebAssembly (default: `false`). */
16
+ wasm?: boolean;
17
+ }
18
+ export type SchemaCollection = StructDefLike | readonly StructDefLike[] | Readonly<Record<string, StructDefLike>>;
19
+ export declare function toRustReprC(schemas: SchemaCollection, options?: RustCodegenOptions): string;
20
+ export declare const generateRust: typeof toRustReprC;
21
+ export declare function toGoStruct(schemas: SchemaCollection, options?: GoCodegenOptions): string;
22
+ export declare const generateGo: typeof toGoStruct;
23
+ //# sourceMappingURL=codegen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../src/codegen.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3D,MAAM,WAAW,kBAAkB;IACjC,+FAA+F;IAC/F,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,2EAA2E;IAC3E,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,qEAAqE;IACrE,GAAG,CAAC,EAAE,KAAK,GAAG,YAAY,GAAG,EAAE,CAAC;CACjC;AAED,MAAM,WAAW,gBAAgB;IAC/B,gFAAgF;IAChF,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,oKAAoK;IACpK,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,MAAM,gBAAgB,GACxB,aAAa,GACb,SAAS,aAAa,EAAE,GACxB,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC;AA0E5C,wBAAgB,WAAW,CAAC,OAAO,EAAE,gBAAgB,EAAE,OAAO,GAAE,kBAAuB,GAAG,MAAM,CA0E/F;AAED,eAAO,MAAM,YAAY,oBAAc,CAAC;AAoBxC,wBAAgB,UAAU,CAAC,OAAO,EAAE,gBAAgB,EAAE,OAAO,GAAE,gBAAqB,GAAG,MAAM,CAkE5F;AAED,eAAO,MAAM,UAAU,mBAAa,CAAC"}
@@ -0,0 +1,218 @@
1
+ function isStructDef(v) {
2
+ return typeof v === 'object' && v !== null && 'kind' in v && v.kind === 'struct';
3
+ }
4
+ function collectDefs(input) {
5
+ const roots = isStructDef(input)
6
+ ? [input]
7
+ : Array.isArray(input)
8
+ ? input
9
+ : Object.values(input).filter(isStructDef);
10
+ const visited = new Set();
11
+ const ordered = [];
12
+ function visitDesc(desc) {
13
+ if (desc.kind === 'struct') {
14
+ visitStruct(desc);
15
+ }
16
+ else if (desc.kind === 'array' || desc.kind === 'slice' || desc.kind === 'ref') {
17
+ visitDesc(desc.element);
18
+ }
19
+ }
20
+ function visitStruct(def, fallbackName) {
21
+ const name = def.name || fallbackName || 'AnonStruct';
22
+ if (visited.has(name))
23
+ return;
24
+ visited.add(name);
25
+ for (const f of def.fieldList) {
26
+ visitDesc(f.desc);
27
+ }
28
+ ordered.push({ def, name });
29
+ }
30
+ if (!isStructDef(input) && !Array.isArray(input)) {
31
+ for (const [k, v] of Object.entries(input)) {
32
+ if (isStructDef(v))
33
+ visitStruct(v, k);
34
+ }
35
+ }
36
+ else {
37
+ for (const r of roots)
38
+ visitStruct(r);
39
+ }
40
+ return ordered.map(({ def, name }) => (def.name ? def : { ...def, name, rustType: name }));
41
+ }
42
+ function checkVarTypes(desc, flags, seen = new Set()) {
43
+ if (seen.has(desc))
44
+ return;
45
+ seen.add(desc);
46
+ if (desc.kind === 'str') {
47
+ flags.str = true;
48
+ }
49
+ else if (desc.kind === 'slice') {
50
+ flags.slice = true;
51
+ checkVarTypes(desc.element, flags, seen);
52
+ }
53
+ else if (desc.kind === 'ref') {
54
+ flags.ref = true;
55
+ checkVarTypes(desc.element, flags, seen);
56
+ }
57
+ else if (desc.kind === 'array') {
58
+ checkVarTypes(desc.element, flags, seen);
59
+ }
60
+ else if (desc.kind === 'struct') {
61
+ for (const f of desc.fieldList)
62
+ checkVarTypes(f.desc, flags, seen);
63
+ }
64
+ }
65
+ function descHasFloat(desc, seen = new Set()) {
66
+ if (seen.has(desc))
67
+ return false;
68
+ seen.add(desc);
69
+ if (desc.kind === 'primitive')
70
+ return 'float' in desc && Boolean(desc.float);
71
+ if (desc.kind === 'array' || desc.kind === 'slice' || desc.kind === 'ref')
72
+ return descHasFloat(desc.element, seen);
73
+ if (desc.kind === 'struct')
74
+ return desc.fieldList.some((f) => descHasFloat(f.desc, seen));
75
+ return false;
76
+ }
77
+ export function toRustReprC(schemas, options = {}) {
78
+ const defs = collectDefs(schemas);
79
+ const derives = options.derive ?? ['Copy', 'Clone', 'Debug', 'PartialEq'];
80
+ const eqDerives = options.derive ?? Array.from(new Set([...derives, 'Eq']));
81
+ const emitAsserts = options.assertions ?? true;
82
+ const vis = options.vis === undefined ? 'pub ' : options.vis ? `${options.vis} ` : '';
83
+ const flags = { str: false, slice: false, ref: false };
84
+ for (const d of defs) {
85
+ for (const f of d.fieldList) {
86
+ checkVarTypes(f.desc, flags);
87
+ }
88
+ }
89
+ const deriveAttr = eqDerives.length > 0 ? `#[derive(${eqDerives.join(', ')})]\n` : '';
90
+ const blocks = [
91
+ '// Auto-generated by capnstruct. DO NOT EDIT.',
92
+ '#![allow(dead_code, non_camel_case_types, non_snake_case)]',
93
+ ];
94
+ if (flags.str) {
95
+ blocks.push(`#[repr(C)]\n${deriveAttr}${vis}struct CapnStr {\n ${vis}off: u32,\n ${vis}len: u32,\n}\n\nimpl CapnStr {\n #[inline]\n ${vis}fn as_bytes<'a>(&self, base: &'a [u8]) -> &'a [u8] {\n let start = self.off as usize;\n let end = start.checked_add(self.len as usize).expect("CapnStr out of bounds");\n &base[start..end]\n }\n\n #[inline]\n ${vis}fn as_str<'a>(&self, base: &'a [u8]) -> Result<&'a str, core::str::Utf8Error> {\n core::str::from_utf8(self.as_bytes(base))\n }\n}`);
96
+ }
97
+ if (flags.slice) {
98
+ blocks.push(`#[repr(C)]\n${deriveAttr}${vis}struct CapnSlice<T> {\n ${vis}off: u32,\n ${vis}len: u32,\n ${vis}_marker: core::marker::PhantomData<T>,\n}\n\nimpl<T> CapnSlice<T> {\n #[inline]\n ${vis}fn as_slice<'a>(&self, base: &'a [u8]) -> &'a [T] {\n if self.len == 0 {\n return &[];\n }\n let start = self.off as usize;\n let byte_len = (self.len as usize).checked_mul(core::mem::size_of::<T>()).expect("CapnSlice overflow");\n let end = start.checked_add(byte_len).expect("CapnSlice out of bounds");\n assert!(end <= base.len(), "CapnSlice out of bounds");\n unsafe { core::slice::from_raw_parts(base.as_ptr().add(start) as *const T, self.len as usize) }\n }\n}`);
99
+ }
100
+ if (flags.ref) {
101
+ blocks.push(`#[repr(C)]\n${deriveAttr}${vis}struct CapnRef<T> {\n ${vis}off: u32,\n ${vis}present: u32,\n ${vis}_marker: core::marker::PhantomData<T>,\n}\n\nimpl<T> CapnRef<T> {\n #[inline]\n ${vis}fn as_ref<'a>(&self, base: &'a [u8]) -> Option<&'a T> {\n if self.present == 0 {\n return None;\n }\n let start = self.off as usize;\n let end = start.checked_add(core::mem::size_of::<T>()).expect("CapnRef out of bounds");\n assert!(end <= base.len(), "CapnRef out of bounds");\n unsafe { Some(&*(base.as_ptr().add(start) as *const T)) }\n }\n}`);
102
+ }
103
+ for (const def of defs) {
104
+ const name = def.name || 'AnonStruct';
105
+ const hasFloat = def.fieldList.some((f) => descHasFloat(f.desc));
106
+ const structDerives = hasFloat ? derives : eqDerives;
107
+ const sDerive = structDerives.length > 0 ? `#[derive(${structDerives.join(', ')})]\n` : '';
108
+ const lines = [`#[repr(C)]`, `${sDerive}${vis}struct ${name} {`];
109
+ let cur = 0;
110
+ let padIdx = 0;
111
+ for (const f of def.fieldList) {
112
+ if (f.offset > cur) {
113
+ lines.push(` ${vis}_pad${padIdx++}: [u8; ${f.offset - cur}],`);
114
+ }
115
+ lines.push(` ${vis}${f.name}: ${f.desc.rustType},`);
116
+ cur = f.offset + f.size;
117
+ }
118
+ if (def.size > cur) {
119
+ lines.push(` ${vis}_pad${padIdx++}: [u8; ${def.size - cur}],`);
120
+ }
121
+ lines.push('}');
122
+ lines.push(`impl ${name} {\n #[inline]\n ${vis}fn as_slice(base: &[u8], len: usize) -> &[Self] {\n if len == 0 { return &[]; }\n let end = len.checked_mul(core::mem::size_of::<Self>()).expect("CapnSlice overflow");\n assert!(end <= base.len(), "CapnSlice out of bounds");\n unsafe { core::slice::from_raw_parts(base.as_ptr() as *const Self, len) }\n }\n}`);
123
+ if (emitAsserts) {
124
+ lines.push(`const _: () = {`);
125
+ lines.push(` assert!(core::mem::size_of::<${name}>() == ${def.size});`);
126
+ lines.push(` assert!(core::mem::align_of::<${name}>() == ${def.align});`);
127
+ for (const f of def.fieldList) {
128
+ lines.push(` assert!(core::mem::offset_of!(${name}, ${f.name}) == ${f.offset});`);
129
+ }
130
+ lines.push(`};`);
131
+ }
132
+ blocks.push(lines.join('\n'));
133
+ }
134
+ return blocks.join('\n\n') + '\n';
135
+ }
136
+ export const generateRust = toRustReprC;
137
+ function goType(desc) {
138
+ if (desc.kind === 'primitive') {
139
+ const t = desc.type;
140
+ if (t === 'fixedStr' || t === 'fixedBytes')
141
+ return `[${desc.length}]byte`;
142
+ if (t === 'bool')
143
+ return 'bool';
144
+ if (t === 'f32' || t === 'f64')
145
+ return `float${t.slice(1)}`;
146
+ if (t === 'f16')
147
+ return 'uint16';
148
+ return `${t[0] === 'u' ? 'uint' : 'int'}${t.slice(1)}`;
149
+ }
150
+ if (desc.kind === 'str')
151
+ return 'CapnStr';
152
+ if (desc.kind === 'array')
153
+ return `[${desc.length}]${goType(desc.element)}`;
154
+ if (desc.kind === 'slice')
155
+ return `CapnSlice[${goType(desc.element)}]`;
156
+ if (desc.kind === 'ref')
157
+ return `CapnRef[${goType(desc.element)}]`;
158
+ return desc.name || 'AnonStruct';
159
+ }
160
+ const goField = (s) => s[0].toUpperCase() + s.slice(1);
161
+ export function toGoStruct(schemas, options = {}) {
162
+ const defs = collectDefs(schemas);
163
+ const wasm = options.wasm ?? false;
164
+ const pkg = options.pkg || (wasm ? 'main' : 'capnschema');
165
+ const emitAsserts = options.assertions ?? true;
166
+ const flags = { str: false, slice: false, ref: false };
167
+ for (const d of defs) {
168
+ for (const f of d.fieldList)
169
+ checkVarTypes(f.desc, flags);
170
+ }
171
+ const blocks = [
172
+ `// Auto-generated by capnstruct. DO NOT EDIT.\npackage ${pkg}\n\nimport "unsafe"`,
173
+ ];
174
+ if (wasm) {
175
+ blocks.push(`var _capnPin [][]byte\n\n//go:wasmexport capn_alloc\nfunc CapnAlloc(n uint32) uintptr {\n\tif n == 0 {\n\t\treturn 0\n\t}\n\tb := make([]byte, int(n)+8)\n\t_capnPin = append(_capnPin, b)\n\treturn (uintptr(unsafe.Pointer(&b[0])) + 7) & ^uintptr(7)\n}\n\n//go:wasmexport capn_reset\nfunc CapnReset() {\n\t_capnPin = _capnPin[:0]\n}`);
176
+ }
177
+ blocks.push(`func CapnBytes(ptr uintptr, byteLen uint32) []byte {\n\tif ptr == 0 || byteLen == 0 {\n\t\treturn nil\n\t}\n\treturn unsafe.Slice((*byte)(unsafe.Pointer(ptr)), int(byteLen))\n}\n\nfunc CapnView[T any](b []byte) *T {\n\tvar zero T\n\tif uint64(len(b)) < uint64(unsafe.Sizeof(zero)) {\n\t\tpanic("CapnView out of bounds")\n\t}\n\treturn (*T)(unsafe.Pointer(unsafe.SliceData(b)))\n}\n\nfunc CapnSliceView[T any](b []byte, n uint32) []T {\n\tif n == 0 {\n\t\treturn nil\n\t}\n\tvar zero T\n\tif uint64(n)*uint64(unsafe.Sizeof(zero)) > uint64(len(b)) {\n\t\tpanic("CapnSliceView out of bounds")\n\t}\n\treturn unsafe.Slice((*T)(unsafe.Pointer(unsafe.SliceData(b))), int(n))\n}`);
178
+ if (flags.str) {
179
+ blocks.push(`type CapnStr struct {\n\tOff uint32\n\tLen uint32\n}\n\nfunc (s CapnStr) Bytes(base []byte) []byte {\n\tend := uint64(s.Off) + uint64(s.Len)\n\tif end > uint64(len(base)) {\n\t\tpanic("CapnStr out of bounds")\n\t}\n\treturn base[s.Off:end]\n}\n\nfunc (s CapnStr) String(base []byte) string {\n\tb := s.Bytes(base)\n\tif len(b) == 0 {\n\t\treturn ""\n\t}\n\treturn unsafe.String(unsafe.SliceData(b), len(b))\n}`);
180
+ }
181
+ if (flags.slice) {
182
+ blocks.push(`type CapnSlice[T any] struct {\n\tOff uint32\n\tLen uint32\n}\n\nfunc (s CapnSlice[T]) Slice(base []byte) []T {\n\tif s.Len == 0 {\n\t\treturn nil\n\t}\n\tvar zero T\n\tend := uint64(s.Off) + uint64(s.Len)*uint64(unsafe.Sizeof(zero))\n\tif end > uint64(len(base)) {\n\t\tpanic("CapnSlice out of bounds")\n\t}\n\treturn unsafe.Slice((*T)(unsafe.Pointer(&base[s.Off])), int(s.Len))\n}`);
183
+ }
184
+ if (flags.ref) {
185
+ blocks.push(`type CapnRef[T any] struct {\n\tOff uint32\n\tPresent uint32\n}\n\nfunc (r CapnRef[T]) Ptr(base []byte) *T {\n\tif r.Present == 0 {\n\t\treturn nil\n\t}\n\tvar zero T\n\tend := uint64(r.Off) + uint64(unsafe.Sizeof(zero))\n\tif end > uint64(len(base)) {\n\t\tpanic("CapnRef out of bounds")\n\t}\n\treturn (*T)(unsafe.Pointer(&base[r.Off]))\n}`);
186
+ }
187
+ for (const def of defs) {
188
+ const name = def.name || 'AnonStruct';
189
+ const lines = [`type ${name} struct {`];
190
+ let cur = 0;
191
+ let padIdx = 0;
192
+ for (const f of def.fieldList) {
193
+ if (f.offset > cur) {
194
+ lines.push(`\t_pad${padIdx++} [${f.offset - cur}]byte`);
195
+ }
196
+ lines.push(`\t${goField(f.name)} ${goType(f.desc)}`);
197
+ cur = f.offset + f.size;
198
+ }
199
+ if (def.size > cur) {
200
+ lines.push(`\t_pad${padIdx++} [${def.size - cur}]byte`);
201
+ }
202
+ lines.push('}');
203
+ if (emitAsserts) {
204
+ lines.push('const (');
205
+ lines.push(`\t_ = uint(unsafe.Sizeof(${name}{})-${def.size}) + uint(${def.size}-unsafe.Sizeof(${name}{}))`);
206
+ lines.push(`\t_ = uint(unsafe.Alignof(${name}{})-${def.align}) + uint(${def.align}-unsafe.Alignof(${name}{}))`);
207
+ for (const f of def.fieldList) {
208
+ const fn = goField(f.name);
209
+ lines.push(`\t_ = uint(unsafe.Offsetof(${name}{}.${fn})-${f.offset}) + uint(${f.offset}-unsafe.Offsetof(${name}{}.${fn}))`);
210
+ }
211
+ lines.push(')');
212
+ }
213
+ blocks.push(lines.join('\n'));
214
+ }
215
+ return blocks.join('\n\n') + '\n';
216
+ }
217
+ export const generateGo = toGoStruct;
218
+ //# sourceMappingURL=codegen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codegen.js","sourceRoot":"","sources":["../src/codegen.ts"],"names":[],"mappings":"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"}