@naeemo/capnp 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 capnp-ts contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,103 @@
1
+ # Cap'n Proto TypeScript
2
+
3
+ A pure TypeScript implementation of Cap'n Proto, featuring zero-copy deserialization and full interoperability with the official C++ implementation.
4
+
5
+ [中文文档](./README.zh.md)
6
+
7
+ ## Features
8
+
9
+ - 🚀 **Zero-Copy Deserialization** - Read data directly from buffers without parsing
10
+ - 🔧 **Pure TypeScript** - No WASM or native dependencies, works in any JS environment
11
+ - ✅ **Official Compatible** - Tested against official C++ implementation
12
+ - 📦 **Schema Code Generation** - Generate TypeScript types from `.capnp` schemas
13
+ - ⚡ **High Performance** - 1.4μs serialization, 0.6μs deserialization for simple structs
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ npm install @naeemo/capnp
19
+ ```
20
+
21
+ ## Quick Start
22
+
23
+ ### Basic Usage
24
+
25
+ ```typescript
26
+ import { MessageBuilder, MessageReader } from '@naeemo/capnp';
27
+
28
+ // Build a message
29
+ const builder = new MessageBuilder();
30
+ const root = builder.initRoot(2, 1); // 2 data words, 1 pointer
31
+ root.setInt32(0, 42);
32
+ root.setText(0, 'Hello, Cap\'n Proto!');
33
+ const buffer = builder.toArrayBuffer();
34
+
35
+ // Read a message
36
+ const reader = new MessageReader(buffer);
37
+ const data = reader.getRoot(2, 1);
38
+ console.log(data.getInt32(0)); // 42
39
+ console.log(data.getText(0)); // "Hello, Cap'n Proto!"
40
+ ```
41
+
42
+ ### Code Generation
43
+
44
+ Generate TypeScript types from your Cap'n Proto schema:
45
+
46
+ ```bash
47
+ npx tsx src/cli/codegen.ts schema.capnp -o types.ts
48
+ ```
49
+
50
+ Generated code includes:
51
+ - TypeScript interfaces
52
+ - Reader classes (getters)
53
+ - Builder classes (setters + factory method)
54
+
55
+ Example:
56
+ ```typescript
57
+ // Generated from schema
58
+ export interface Person {
59
+ id: bigint;
60
+ name: string;
61
+ }
62
+
63
+ export class PersonReader {
64
+ get id(): bigint { ... }
65
+ get name(): string { ... }
66
+ }
67
+
68
+ export class PersonBuilder {
69
+ static create(message: MessageBuilder): PersonBuilder { ... }
70
+ setId(value: bigint): void { ... }
71
+ setName(value: string): void { ... }
72
+ }
73
+ ```
74
+
75
+ ## Performance
76
+
77
+ | Operation | Latency | Throughput |
78
+ |-----------|---------|------------|
79
+ | Simple struct serialize | 1.4 μs | 684K ops/sec |
80
+ | Simple struct deserialize | 0.6 μs | 1.66M ops/sec |
81
+ | Nested struct serialize | 4.1 μs | 243K ops/sec |
82
+ | List (100 items) serialize | 6.8 μs | 147K ops/sec |
83
+
84
+ See [PERFORMANCE.md](./PERFORMANCE.md) for detailed benchmarks.
85
+
86
+ ## Documentation
87
+
88
+ - [API Documentation](./docs/API.md)
89
+ - [Performance Report](./PERFORMANCE.md)
90
+ - [Test Coverage](./TEST_COVERAGE.md)
91
+ - [Changelog](./CHANGELOG.md)
92
+
93
+ ## Contributing
94
+
95
+ We welcome contributions! Please see [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines.
96
+
97
+ ## Credits
98
+
99
+ Developed by **Naeemo** and [Moonshot AI](https://github.com/MoonshotAI).
100
+
101
+ ## License
102
+
103
+ MIT License - see [LICENSE](./LICENSE) for details.
package/README.zh.md ADDED
@@ -0,0 +1,83 @@
1
+ # Cap'n Proto TypeScript
2
+
3
+ 纯 TypeScript 实现的 Cap'n Proto,支持零拷贝反序列化,与官方 C++ 实现完全兼容。
4
+
5
+ [English Documentation](./README.md)
6
+
7
+ ## 特性
8
+
9
+ - 🚀 **零拷贝反序列化** - 直接从缓冲区读取数据,无需解析
10
+ - 🔧 **纯 TypeScript** - 无 WASM 或原生依赖,可在任何 JS 环境运行
11
+ - ✅ **官方兼容** - 已通过官方 C++ 实现测试验证
12
+ - 📦 **Schema 代码生成** - 从 `.capnp` 模式生成 TypeScript 类型
13
+ - ⚡ **高性能** - 简单结构序列化 1.4μs,反序列化 0.6μs
14
+
15
+ ## 安装
16
+
17
+ ```bash
18
+ npm install @naeemo/capnp
19
+ ```
20
+
21
+ ## 快速开始
22
+
23
+ ### 基础用法
24
+
25
+ ```typescript
26
+ import { MessageBuilder, MessageReader } from '@naeemo/capnp';
27
+
28
+ // 构建消息
29
+ const builder = new MessageBuilder();
30
+ const root = builder.initRoot(2, 1); // 2 个数据字,1 个指针
31
+ root.setInt32(0, 42);
32
+ root.setText(0, '你好,Cap\'n Proto!');
33
+ const buffer = builder.toArrayBuffer();
34
+
35
+ // 读取消息
36
+ const reader = new MessageReader(buffer);
37
+ const data = reader.getRoot(2, 1);
38
+ console.log(data.getInt32(0)); // 42
39
+ console.log(data.getText(0)); // "你好,Cap'n Proto!"
40
+ ```
41
+
42
+ ### 代码生成
43
+
44
+ 从 Cap'n Proto 模式生成 TypeScript 类型:
45
+
46
+ ```bash
47
+ npx tsx src/cli/codegen.ts schema.capnp -o types.ts
48
+ ```
49
+
50
+ 生成的代码包括:
51
+ - TypeScript 接口
52
+ - Reader 类(getter)
53
+ - Builder 类(setter + 工厂方法)
54
+
55
+ ## 性能
56
+
57
+ | 操作 | 延迟 | 吞吐量 |
58
+ |-----------|---------|------------|
59
+ | 简单结构序列化 | 1.4 μs | 68万 ops/sec |
60
+ | 简单结构反序列化 | 0.6 μs | 166万 ops/sec |
61
+ | 嵌套结构序列化 | 4.1 μs | 24万 ops/sec |
62
+ | 列表(100项)序列化 | 6.8 μs | 14万 ops/sec |
63
+
64
+ 详见 [PERFORMANCE.md](./PERFORMANCE.md)
65
+
66
+ ## 文档
67
+
68
+ - [API 文档](./docs/API.md)
69
+ - [性能报告](./PERFORMANCE.md)
70
+ - [测试覆盖](./TEST_COVERAGE.md)
71
+ - [更新日志](./CHANGELOG.md)
72
+
73
+ ## 贡献
74
+
75
+ 欢迎贡献!请查看 [CONTRIBUTING.md](./CONTRIBUTING.md) 了解指南。
76
+
77
+ ## 致谢
78
+
79
+ 由 **Naeemo** 和 [Moonshot AI](https://github.com/MoonshotAI) 共同开发。
80
+
81
+ ## 许可证
82
+
83
+ MIT 许可证 - 详见 [LICENSE](./LICENSE)
package/dist/cli.js ADDED
@@ -0,0 +1,394 @@
1
+ #!/usr/bin/env node
2
+ #!/usr/bin/env node
3
+ import { readFileSync, writeFileSync } from "node:fs";
4
+ import { parseArgs } from "node:util";
5
+
6
+ //#region src/codegen/enum-gen.ts
7
+ /**
8
+ * Enum generator
9
+ */
10
+ function generateEnum(enum_, lines) {
11
+ lines.push(`export enum ${enum_.name} {`);
12
+ for (const value of enum_.values) lines.push(` ${value.name} = ${value.index},`);
13
+ lines.push("}");
14
+ lines.push("");
15
+ }
16
+
17
+ //#endregion
18
+ //#region src/codegen/type-utils.ts
19
+ function isPointerType(type) {
20
+ if (typeof type === "string") return type === "Text" || type === "Data";
21
+ return type.kind === "list" || type.kind === "struct";
22
+ }
23
+ function getTypeSize(type) {
24
+ if (typeof type !== "string") return 8;
25
+ switch (type) {
26
+ case "Void": return 0;
27
+ case "Bool": return 1;
28
+ case "Int8":
29
+ case "UInt8": return 1;
30
+ case "Int16":
31
+ case "UInt16": return 2;
32
+ case "Int32":
33
+ case "UInt32":
34
+ case "Float32": return 4;
35
+ case "Int64":
36
+ case "UInt64":
37
+ case "Float64": return 8;
38
+ default: return 8;
39
+ }
40
+ }
41
+ function mapTypeToTs(type) {
42
+ if (typeof type !== "string") {
43
+ if (type.kind === "list") return `${mapTypeToTs(type.elementType)}[]`;
44
+ return type.name;
45
+ }
46
+ switch (type) {
47
+ case "Void": return "void";
48
+ case "Bool": return "boolean";
49
+ case "Int8":
50
+ case "Int16":
51
+ case "Int32":
52
+ case "UInt8":
53
+ case "UInt16":
54
+ case "UInt32":
55
+ case "Float32":
56
+ case "Float64": return "number";
57
+ case "Int64":
58
+ case "UInt64": return "bigint";
59
+ case "Text": return "string";
60
+ case "Data": return "Uint8Array";
61
+ default: return "unknown";
62
+ }
63
+ }
64
+ function getGetterMethod(type) {
65
+ if (typeof type !== "string") {
66
+ if (type.kind === "list") return "getList";
67
+ return "getStruct";
68
+ }
69
+ switch (type) {
70
+ case "Void": return "getVoid";
71
+ case "Bool": return "getBool";
72
+ case "Int8": return "getInt8";
73
+ case "Int16": return "getInt16";
74
+ case "Int32": return "getInt32";
75
+ case "Int64": return "getInt64";
76
+ case "UInt8": return "getUint8";
77
+ case "UInt16": return "getUint16";
78
+ case "UInt32": return "getUint32";
79
+ case "UInt64": return "getUint64";
80
+ case "Float32": return "getFloat32";
81
+ case "Float64": return "getFloat64";
82
+ case "Text": return "getText";
83
+ case "Data": return "getData";
84
+ default: return "getUnknown";
85
+ }
86
+ }
87
+ function getSetterMethod(type) {
88
+ if (typeof type !== "string") {
89
+ if (type.kind === "list") return "initList";
90
+ return "initStruct";
91
+ }
92
+ switch (type) {
93
+ case "Void": return "setVoid";
94
+ case "Bool": return "setBool";
95
+ case "Int8": return "setInt8";
96
+ case "Int16": return "setInt16";
97
+ case "Int32": return "setInt32";
98
+ case "Int64": return "setInt64";
99
+ case "UInt8": return "setUint8";
100
+ case "UInt16": return "setUint16";
101
+ case "UInt32": return "setUint32";
102
+ case "UInt64": return "setUint64";
103
+ case "Float32": return "setFloat32";
104
+ case "Float64": return "setFloat64";
105
+ case "Text": return "setText";
106
+ case "Data": return "setData";
107
+ default: return "setUnknown";
108
+ }
109
+ }
110
+ function capitalize(str) {
111
+ return str.charAt(0).toUpperCase() + str.slice(1);
112
+ }
113
+
114
+ //#endregion
115
+ //#region src/codegen/struct-gen.ts
116
+ function generateStruct(struct, lines) {
117
+ let dataWords = 0;
118
+ let pointerCount = 0;
119
+ let dataOffset = 0;
120
+ for (const field of struct.fields) if (isPointerType(field.type)) pointerCount++;
121
+ else dataOffset += getTypeSize(field.type);
122
+ dataWords = Math.ceil(dataOffset / 8);
123
+ lines.push(`export interface ${struct.name} {`);
124
+ for (const field of struct.fields) lines.push(` ${field.name}: ${mapTypeToTs(field.type)};`);
125
+ lines.push("}");
126
+ lines.push("");
127
+ generateReader(struct, dataWords, pointerCount, lines);
128
+ generateBuilder(struct, dataWords, pointerCount, lines);
129
+ }
130
+ function generateReader(struct, _dataWords, _pointerCount, lines) {
131
+ lines.push(`export class ${struct.name}Reader {`);
132
+ lines.push(" private reader: StructReader;");
133
+ lines.push("");
134
+ lines.push(" constructor(reader: StructReader) {");
135
+ lines.push(" this.reader = reader;");
136
+ lines.push(" }");
137
+ lines.push("");
138
+ let dataOffset = 0;
139
+ let pointerIndex = 0;
140
+ for (const field of struct.fields) {
141
+ const tsType = mapTypeToTs(field.type);
142
+ if (isPointerType(field.type)) {
143
+ lines.push(` get ${field.name}(): ${tsType} {`);
144
+ lines.push(` return this.reader.${getGetterMethod(field.type)}(${pointerIndex});`);
145
+ lines.push(" }");
146
+ pointerIndex++;
147
+ } else {
148
+ lines.push(` get ${field.name}(): ${tsType} {`);
149
+ lines.push(` return this.reader.${getGetterMethod(field.type)}(${dataOffset});`);
150
+ lines.push(" }");
151
+ dataOffset += getTypeSize(field.type);
152
+ }
153
+ lines.push("");
154
+ }
155
+ lines.push("}");
156
+ lines.push("");
157
+ }
158
+ function generateBuilder(struct, dataWords, pointerCount, lines) {
159
+ lines.push(`export class ${struct.name}Builder {`);
160
+ lines.push(" private builder: StructBuilder;");
161
+ lines.push("");
162
+ lines.push(" constructor(builder: StructBuilder) {");
163
+ lines.push(" this.builder = builder;");
164
+ lines.push(" }");
165
+ lines.push("");
166
+ lines.push(` static create(message: MessageBuilder): ${struct.name}Builder {`);
167
+ lines.push(` const root = message.initRoot(${dataWords}, ${pointerCount});`);
168
+ lines.push(` return new ${struct.name}Builder(root);`);
169
+ lines.push(" }");
170
+ lines.push("");
171
+ let dataOffset = 0;
172
+ let pointerIndex = 0;
173
+ for (const field of struct.fields) {
174
+ const tsType = mapTypeToTs(field.type);
175
+ const method = getSetterMethod(field.type);
176
+ if (isPointerType(field.type)) {
177
+ lines.push(` set${capitalize(field.name)}(value: ${tsType}): void {`);
178
+ lines.push(` this.builder.${method}(${pointerIndex}, value);`);
179
+ lines.push(" }");
180
+ pointerIndex++;
181
+ } else {
182
+ lines.push(` set${capitalize(field.name)}(value: ${tsType}): void {`);
183
+ lines.push(` this.builder.${method}(${dataOffset}, value);`);
184
+ lines.push(" }");
185
+ dataOffset += getTypeSize(field.type);
186
+ }
187
+ lines.push("");
188
+ }
189
+ lines.push("}");
190
+ lines.push("");
191
+ }
192
+
193
+ //#endregion
194
+ //#region src/codegen/generator-v2.ts
195
+ /**
196
+ * Main code generator v2
197
+ */
198
+ const DEFAULT_OPTIONS = { runtimeImportPath: "@naeemo/capnp" };
199
+ function generateCode(schema, options) {
200
+ const opts = {
201
+ ...DEFAULT_OPTIONS,
202
+ ...options
203
+ };
204
+ const lines = [];
205
+ lines.push("// Generated by capnp-ts-codegen");
206
+ lines.push("// DO NOT EDIT MANUALLY");
207
+ lines.push("");
208
+ lines.push(`import { MessageReader, MessageBuilder, StructReader, StructBuilder } from "${opts.runtimeImportPath}";`);
209
+ lines.push("");
210
+ for (const enum_ of schema.enums) generateEnum(enum_, lines);
211
+ for (const struct of schema.structs) generateStruct(struct, lines);
212
+ return lines.join("\n");
213
+ }
214
+
215
+ //#endregion
216
+ //#region src/codegen/parser-v2.ts
217
+ const PRIMITIVE_TYPES = new Set([
218
+ "Void",
219
+ "Bool",
220
+ "Int8",
221
+ "Int16",
222
+ "Int32",
223
+ "Int64",
224
+ "UInt8",
225
+ "UInt16",
226
+ "UInt32",
227
+ "UInt64",
228
+ "Float32",
229
+ "Float64",
230
+ "Text",
231
+ "Data"
232
+ ]);
233
+ function isPrimitive(type) {
234
+ return PRIMITIVE_TYPES.has(type);
235
+ }
236
+ /**
237
+ * 解析 Cap'n Proto schema
238
+ *
239
+ * 支持的语法:
240
+ * - Struct 定义
241
+ * - Enum 定义
242
+ * - 基础类型字段
243
+ * - List 类型
244
+ * - 嵌套 struct 引用
245
+ *
246
+ * 不支持的语法(会忽略或报错):
247
+ * - Union
248
+ * - Group
249
+ * - Interface
250
+ * - Const
251
+ * - Annotation
252
+ * - 默认值
253
+ */
254
+ function parseSchemaV2(source) {
255
+ const structs = [];
256
+ const enums = [];
257
+ const cleanSource = source.replace(/#.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "");
258
+ const structRegex = /struct\s+(\w+)\s*\{([^}]*)\}/g;
259
+ let match;
260
+ while ((match = structRegex.exec(cleanSource)) !== null) {
261
+ const name = match[1];
262
+ const body = match[2];
263
+ const fields = parseFields(body);
264
+ structs.push({
265
+ name,
266
+ fields
267
+ });
268
+ }
269
+ const enumRegex = /enum\s+(\w+)\s*\{([^}]*)\}/g;
270
+ while ((match = enumRegex.exec(cleanSource)) !== null) {
271
+ const name = match[1];
272
+ const body = match[2];
273
+ const values = parseEnumValues(body);
274
+ enums.push({
275
+ name,
276
+ values
277
+ });
278
+ }
279
+ return {
280
+ structs,
281
+ enums
282
+ };
283
+ }
284
+ function parseFields(body) {
285
+ const fields = [];
286
+ const fieldRegex = /(\w+)\s*@(\d+)\s*:\s*([^;]+);/g;
287
+ let match;
288
+ while ((match = fieldRegex.exec(body)) !== null) {
289
+ const name = match[1];
290
+ const index = Number.parseInt(match[2]);
291
+ const type = parseType(match[3].trim());
292
+ fields.push({
293
+ name,
294
+ index,
295
+ type
296
+ });
297
+ }
298
+ return fields.sort((a, b) => a.index - b.index);
299
+ }
300
+ function parseType(typeStr) {
301
+ const listMatch = typeStr.match(/^List\((.+)\)$/);
302
+ if (listMatch) return {
303
+ kind: "list",
304
+ elementType: parseType(listMatch[1].trim())
305
+ };
306
+ if (isPrimitive(typeStr)) return typeStr;
307
+ return {
308
+ kind: "struct",
309
+ name: typeStr
310
+ };
311
+ }
312
+ function parseEnumValues(body) {
313
+ const values = [];
314
+ const valueRegex = /(\w+)\s*@(\d+)\s*;/g;
315
+ let match;
316
+ while ((match = valueRegex.exec(body)) !== null) {
317
+ const name = match[1];
318
+ const index = Number.parseInt(match[2]);
319
+ values.push({
320
+ name,
321
+ index
322
+ });
323
+ }
324
+ return values.sort((a, b) => a.index - b.index);
325
+ }
326
+
327
+ //#endregion
328
+ //#region src/cli.ts
329
+ /**
330
+ * Cap'n Proto CLI
331
+ *
332
+ * Usage:
333
+ * capnp gen schema.capnp -o types.ts
334
+ */
335
+ const { values, positionals } = parseArgs({
336
+ args: process.argv.slice(2),
337
+ options: {
338
+ output: {
339
+ type: "string",
340
+ short: "o"
341
+ },
342
+ help: {
343
+ type: "boolean",
344
+ short: "h"
345
+ }
346
+ },
347
+ allowPositionals: true
348
+ });
349
+ if (values.help || positionals.length === 0) {
350
+ console.log(`
351
+ Cap'n Proto TypeScript CLI
352
+
353
+ Usage:
354
+ capnp gen <schema.capnp> [options] Generate TypeScript from schema
355
+ capnp --help Show this help
356
+
357
+ Options:
358
+ -o, --output Output file (default: stdout)
359
+ -h, --help Show this help
360
+
361
+ Examples:
362
+ npx @naeemo/capnp gen schema.capnp -o types.ts
363
+ capnp gen schema.capnp > types.ts
364
+ `);
365
+ process.exit(0);
366
+ }
367
+ const command = positionals[0];
368
+ if (command !== "gen") {
369
+ console.error(`Unknown command: ${command}`);
370
+ console.error("Run \"capnp --help\" for usage");
371
+ process.exit(1);
372
+ }
373
+ const inputFile = positionals[1];
374
+ if (!inputFile) {
375
+ console.error("Error: Missing input file");
376
+ console.error("Usage: capnp gen <schema.capnp>");
377
+ process.exit(1);
378
+ }
379
+ const outputFile = values.output;
380
+ async function main() {
381
+ const code = generateCode(parseSchemaV2(readFileSync(inputFile, "utf-8")));
382
+ if (outputFile) {
383
+ writeFileSync(outputFile, code);
384
+ console.error(`Generated: ${outputFile}`);
385
+ } else console.log(code);
386
+ }
387
+ main().catch((err) => {
388
+ console.error("Error:", err.message);
389
+ process.exit(1);
390
+ });
391
+
392
+ //#endregion
393
+ export { };
394
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","names":[],"sources":["../src/codegen/enum-gen.ts","../src/codegen/type-utils.ts","../src/codegen/struct-gen.ts","../src/codegen/generator-v2.ts","../src/codegen/parser-v2.ts","../src/cli.ts"],"sourcesContent":["/**\n * Enum generator\n */\n\nexport function generateEnum(\n enum_: { name: string; values: { name: string; index: number }[] },\n lines: string[]\n): void {\n lines.push(`export enum ${enum_.name} {`);\n for (const value of enum_.values) {\n lines.push(` ${value.name} = ${value.index},`);\n }\n lines.push('}');\n lines.push('');\n}\n","/**\n * Type mapping utilities\n */\n\nimport type { Type } from './parser-v2.js';\n\nexport function isPointerType(type: Type): boolean {\n if (typeof type === 'string') {\n return type === 'Text' || type === 'Data';\n }\n return type.kind === 'list' || type.kind === 'struct';\n}\n\nexport function getTypeSize(type: Type): number {\n if (typeof type !== 'string') return 8;\n switch (type) {\n case 'Void':\n return 0;\n case 'Bool':\n return 1;\n case 'Int8':\n case 'UInt8':\n return 1;\n case 'Int16':\n case 'UInt16':\n return 2;\n case 'Int32':\n case 'UInt32':\n case 'Float32':\n return 4;\n case 'Int64':\n case 'UInt64':\n case 'Float64':\n return 8;\n default:\n return 8;\n }\n}\n\nexport function mapTypeToTs(type: Type): string {\n if (typeof type !== 'string') {\n if (type.kind === 'list') return `${mapTypeToTs(type.elementType)}[]`;\n return type.name;\n }\n switch (type) {\n case 'Void':\n return 'void';\n case 'Bool':\n return 'boolean';\n case 'Int8':\n case 'Int16':\n case 'Int32':\n case 'UInt8':\n case 'UInt16':\n case 'UInt32':\n case 'Float32':\n case 'Float64':\n return 'number';\n case 'Int64':\n case 'UInt64':\n return 'bigint';\n case 'Text':\n return 'string';\n case 'Data':\n return 'Uint8Array';\n default:\n return 'unknown';\n }\n}\n\nexport function getGetterMethod(type: Type): string {\n if (typeof type !== 'string') {\n if (type.kind === 'list') return 'getList';\n return 'getStruct';\n }\n switch (type) {\n case 'Void':\n return 'getVoid';\n case 'Bool':\n return 'getBool';\n case 'Int8':\n return 'getInt8';\n case 'Int16':\n return 'getInt16';\n case 'Int32':\n return 'getInt32';\n case 'Int64':\n return 'getInt64';\n case 'UInt8':\n return 'getUint8';\n case 'UInt16':\n return 'getUint16';\n case 'UInt32':\n return 'getUint32';\n case 'UInt64':\n return 'getUint64';\n case 'Float32':\n return 'getFloat32';\n case 'Float64':\n return 'getFloat64';\n case 'Text':\n return 'getText';\n case 'Data':\n return 'getData';\n default:\n return 'getUnknown';\n }\n}\n\nexport function getSetterMethod(type: Type): string {\n if (typeof type !== 'string') {\n if (type.kind === 'list') return 'initList';\n return 'initStruct';\n }\n switch (type) {\n case 'Void':\n return 'setVoid';\n case 'Bool':\n return 'setBool';\n case 'Int8':\n return 'setInt8';\n case 'Int16':\n return 'setInt16';\n case 'Int32':\n return 'setInt32';\n case 'Int64':\n return 'setInt64';\n case 'UInt8':\n return 'setUint8';\n case 'UInt16':\n return 'setUint16';\n case 'UInt32':\n return 'setUint32';\n case 'UInt64':\n return 'setUint64';\n case 'Float32':\n return 'setFloat32';\n case 'Float64':\n return 'setFloat64';\n case 'Text':\n return 'setText';\n case 'Data':\n return 'setData';\n default:\n return 'setUnknown';\n }\n}\n\nexport function capitalize(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n","/**\n * Struct generator\n */\n\nimport type { Struct } from './parser-v2.js';\nimport {\n capitalize,\n getGetterMethod,\n getSetterMethod,\n getTypeSize,\n isPointerType,\n mapTypeToTs,\n} from './type-utils.js';\n\nexport function generateStruct(struct: Struct, lines: string[]): void {\n let dataWords = 0;\n let pointerCount = 0;\n let dataOffset = 0;\n\n for (const field of struct.fields) {\n if (isPointerType(field.type)) {\n pointerCount++;\n } else {\n dataOffset += getTypeSize(field.type);\n }\n }\n dataWords = Math.ceil(dataOffset / 8);\n\n // Interface\n lines.push(`export interface ${struct.name} {`);\n for (const field of struct.fields) {\n lines.push(` ${field.name}: ${mapTypeToTs(field.type)};`);\n }\n lines.push('}');\n lines.push('');\n\n // Reader\n generateReader(struct, dataWords, pointerCount, lines);\n\n // Builder\n generateBuilder(struct, dataWords, pointerCount, lines);\n}\n\nfunction generateReader(\n struct: Struct,\n _dataWords: number,\n _pointerCount: number,\n lines: string[]\n): void {\n lines.push(`export class ${struct.name}Reader {`);\n lines.push(' private reader: StructReader;');\n lines.push('');\n lines.push(' constructor(reader: StructReader) {');\n lines.push(' this.reader = reader;');\n lines.push(' }');\n lines.push('');\n\n let dataOffset = 0;\n let pointerIndex = 0;\n for (const field of struct.fields) {\n const tsType = mapTypeToTs(field.type);\n if (isPointerType(field.type)) {\n lines.push(` get ${field.name}(): ${tsType} {`);\n lines.push(` return this.reader.${getGetterMethod(field.type)}(${pointerIndex});`);\n lines.push(' }');\n pointerIndex++;\n } else {\n lines.push(` get ${field.name}(): ${tsType} {`);\n lines.push(` return this.reader.${getGetterMethod(field.type)}(${dataOffset});`);\n lines.push(' }');\n dataOffset += getTypeSize(field.type);\n }\n lines.push('');\n }\n lines.push('}');\n lines.push('');\n}\n\nfunction generateBuilder(\n struct: Struct,\n dataWords: number,\n pointerCount: number,\n lines: string[]\n): void {\n lines.push(`export class ${struct.name}Builder {`);\n lines.push(' private builder: StructBuilder;');\n lines.push('');\n lines.push(' constructor(builder: StructBuilder) {');\n lines.push(' this.builder = builder;');\n lines.push(' }');\n lines.push('');\n lines.push(` static create(message: MessageBuilder): ${struct.name}Builder {`);\n lines.push(` const root = message.initRoot(${dataWords}, ${pointerCount});`);\n lines.push(` return new ${struct.name}Builder(root);`);\n lines.push(' }');\n lines.push('');\n\n let dataOffset = 0;\n let pointerIndex = 0;\n for (const field of struct.fields) {\n const tsType = mapTypeToTs(field.type);\n const method = getSetterMethod(field.type);\n if (isPointerType(field.type)) {\n lines.push(` set${capitalize(field.name)}(value: ${tsType}): void {`);\n lines.push(` this.builder.${method}(${pointerIndex}, value);`);\n lines.push(' }');\n pointerIndex++;\n } else {\n lines.push(` set${capitalize(field.name)}(value: ${tsType}): void {`);\n lines.push(` this.builder.${method}(${dataOffset}, value);`);\n lines.push(' }');\n dataOffset += getTypeSize(field.type);\n }\n lines.push('');\n }\n lines.push('}');\n lines.push('');\n}\n","/**\n * Main code generator v2\n */\n\nimport { generateEnum } from './enum-gen.js';\nimport type { Schema } from './parser-v2.js';\nimport { generateStruct } from './struct-gen.js';\n\nexport interface GeneratorOptions {\n runtimeImportPath?: string;\n}\n\nconst DEFAULT_OPTIONS: GeneratorOptions = {\n runtimeImportPath: '@naeemo/capnp',\n};\n\nexport function generateCode(schema: Schema, options?: GeneratorOptions): string {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n const lines: string[] = [];\n\n lines.push('// Generated by capnp-ts-codegen');\n lines.push('// DO NOT EDIT MANUALLY');\n lines.push('');\n lines.push(\n `import { MessageReader, MessageBuilder, StructReader, StructBuilder } from \"${opts.runtimeImportPath}\";`\n );\n lines.push('');\n\n for (const enum_ of schema.enums) {\n generateEnum(enum_, lines);\n }\n\n for (const struct of schema.structs) {\n generateStruct(struct, lines);\n }\n\n return lines.join('\\n');\n}\n","/**\n * Cap'n Proto Schema 解析器 v2 - 简化版\n * 基于正则的解析器,支持常用 Cap'n Proto 语法\n */\n\n// 基础类型\nexport type PrimitiveType =\n | 'Void'\n | 'Bool'\n | 'Int8'\n | 'Int16'\n | 'Int32'\n | 'Int64'\n | 'UInt8'\n | 'UInt16'\n | 'UInt32'\n | 'UInt64'\n | 'Float32'\n | 'Float64'\n | 'Text'\n | 'Data';\n\nexport interface ListType {\n kind: 'list';\n elementType: Type;\n}\n\nexport interface StructType {\n kind: 'struct';\n name: string;\n}\n\nexport type Type = PrimitiveType | ListType | StructType;\n\nexport interface Field {\n name: string;\n index: number;\n type: Type;\n}\n\nexport interface Struct {\n name: string;\n fields: Field[];\n}\n\nexport interface EnumValue {\n name: string;\n index: number;\n}\n\nexport interface Enum {\n name: string;\n values: EnumValue[];\n}\n\nexport interface Schema {\n structs: Struct[];\n enums: Enum[];\n}\n\nconst PRIMITIVE_TYPES: Set<string> = new Set([\n 'Void',\n 'Bool',\n 'Int8',\n 'Int16',\n 'Int32',\n 'Int64',\n 'UInt8',\n 'UInt16',\n 'UInt32',\n 'UInt64',\n 'Float32',\n 'Float64',\n 'Text',\n 'Data',\n]);\n\nfunction isPrimitive(type: string): type is PrimitiveType {\n return PRIMITIVE_TYPES.has(type);\n}\n\n/**\n * 解析 Cap'n Proto schema\n *\n * 支持的语法:\n * - Struct 定义\n * - Enum 定义\n * - 基础类型字段\n * - List 类型\n * - 嵌套 struct 引用\n *\n * 不支持的语法(会忽略或报错):\n * - Union\n * - Group\n * - Interface\n * - Const\n * - Annotation\n * - 默认值\n */\nexport function parseSchemaV2(source: string): Schema {\n const structs: Struct[] = [];\n const enums: Enum[] = [];\n\n // 移除注释\n const cleanSource = source\n .replace(/#.*$/gm, '') // 行注释\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, ''); // 块注释\n\n // 解析 struct\n const structRegex = /struct\\s+(\\w+)\\s*\\{([^}]*)\\}/g;\n let match;\n while ((match = structRegex.exec(cleanSource)) !== null) {\n const name = match[1];\n const body = match[2];\n const fields = parseFields(body);\n structs.push({ name, fields });\n }\n\n // 解析 enum\n const enumRegex = /enum\\s+(\\w+)\\s*\\{([^}]*)\\}/g;\n while ((match = enumRegex.exec(cleanSource)) !== null) {\n const name = match[1];\n const body = match[2];\n const values = parseEnumValues(body);\n enums.push({ name, values });\n }\n\n return { structs, enums };\n}\n\nfunction parseFields(body: string): Field[] {\n const fields: Field[] = [];\n\n // 字段格式: name @index :Type;\n const fieldRegex = /(\\w+)\\s*@(\\d+)\\s*:\\s*([^;]+);/g;\n let match;\n\n while ((match = fieldRegex.exec(body)) !== null) {\n const name = match[1];\n const index = Number.parseInt(match[2]);\n const typeStr = match[3].trim();\n const type = parseType(typeStr);\n\n fields.push({ name, index, type });\n }\n\n return fields.sort((a, b) => a.index - b.index);\n}\n\nfunction parseType(typeStr: string): Type {\n // 检查 List 类型\n const listMatch = typeStr.match(/^List\\((.+)\\)$/);\n if (listMatch) {\n const elementType = parseType(listMatch[1].trim());\n return { kind: 'list', elementType };\n }\n\n // 检查基础类型\n if (isPrimitive(typeStr)) {\n return typeStr;\n }\n\n // 假设是 struct 类型\n return { kind: 'struct', name: typeStr };\n}\n\nfunction parseEnumValues(body: string): EnumValue[] {\n const values: EnumValue[] = [];\n\n // 格式: name @index;\n const valueRegex = /(\\w+)\\s*@(\\d+)\\s*;/g;\n let match;\n\n while ((match = valueRegex.exec(body)) !== null) {\n const name = match[1];\n const index = Number.parseInt(match[2]);\n values.push({ name, index });\n }\n\n return values.sort((a, b) => a.index - b.index);\n}\n","#!/usr/bin/env node\n\n/**\n * Cap'n Proto CLI\n *\n * Usage:\n * capnp gen schema.capnp -o types.ts\n */\n\nimport { readFileSync, writeFileSync } from 'node:fs';\nimport { parseArgs } from 'node:util';\nimport { generateCode } from './codegen/generator-v2.js';\nimport { parseSchemaV2 } from './codegen/parser-v2.js';\n\nconst { values, positionals } = parseArgs({\n args: process.argv.slice(2),\n options: {\n output: { type: 'string', short: 'o' },\n help: { type: 'boolean', short: 'h' },\n },\n allowPositionals: true,\n});\n\nif (values.help || positionals.length === 0) {\n console.log(`\nCap'n Proto TypeScript CLI\n\nUsage:\n capnp gen <schema.capnp> [options] Generate TypeScript from schema\n capnp --help Show this help\n\nOptions:\n -o, --output Output file (default: stdout)\n -h, --help Show this help\n\nExamples:\n npx @naeemo/capnp gen schema.capnp -o types.ts\n capnp gen schema.capnp > types.ts\n`);\n process.exit(0);\n}\n\nconst command = positionals[0];\n\nif (command !== 'gen') {\n console.error(`Unknown command: ${command}`);\n console.error('Run \"capnp --help\" for usage');\n process.exit(1);\n}\n\nconst inputFile = positionals[1];\nif (!inputFile) {\n console.error('Error: Missing input file');\n console.error('Usage: capnp gen <schema.capnp>');\n process.exit(1);\n}\n\nconst outputFile = values.output;\n\nasync function main() {\n const source = readFileSync(inputFile, 'utf-8');\n const schema = parseSchemaV2(source);\n const code = generateCode(schema);\n\n if (outputFile) {\n writeFileSync(outputFile, code);\n console.error(`Generated: ${outputFile}`);\n } else {\n console.log(code);\n }\n}\n\nmain().catch((err) => {\n console.error('Error:', err.message);\n process.exit(1);\n});\n"],"mappings":";;;;;;;;AAIA,SAAgB,aACd,OACA,OACM;AACN,OAAM,KAAK,eAAe,MAAM,KAAK,IAAI;AACzC,MAAK,MAAM,SAAS,MAAM,OACxB,OAAM,KAAK,KAAK,MAAM,KAAK,KAAK,MAAM,MAAM,GAAG;AAEjD,OAAM,KAAK,IAAI;AACf,OAAM,KAAK,GAAG;;;;;ACPhB,SAAgB,cAAc,MAAqB;AACjD,KAAI,OAAO,SAAS,SAClB,QAAO,SAAS,UAAU,SAAS;AAErC,QAAO,KAAK,SAAS,UAAU,KAAK,SAAS;;AAG/C,SAAgB,YAAY,MAAoB;AAC9C,KAAI,OAAO,SAAS,SAAU,QAAO;AACrC,SAAQ,MAAR;EACE,KAAK,OACH,QAAO;EACT,KAAK,OACH,QAAO;EACT,KAAK;EACL,KAAK,QACH,QAAO;EACT,KAAK;EACL,KAAK,SACH,QAAO;EACT,KAAK;EACL,KAAK;EACL,KAAK,UACH,QAAO;EACT,KAAK;EACL,KAAK;EACL,KAAK,UACH,QAAO;EACT,QACE,QAAO;;;AAIb,SAAgB,YAAY,MAAoB;AAC9C,KAAI,OAAO,SAAS,UAAU;AAC5B,MAAI,KAAK,SAAS,OAAQ,QAAO,GAAG,YAAY,KAAK,YAAY,CAAC;AAClE,SAAO,KAAK;;AAEd,SAAQ,MAAR;EACE,KAAK,OACH,QAAO;EACT,KAAK,OACH,QAAO;EACT,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK,UACH,QAAO;EACT,KAAK;EACL,KAAK,SACH,QAAO;EACT,KAAK,OACH,QAAO;EACT,KAAK,OACH,QAAO;EACT,QACE,QAAO;;;AAIb,SAAgB,gBAAgB,MAAoB;AAClD,KAAI,OAAO,SAAS,UAAU;AAC5B,MAAI,KAAK,SAAS,OAAQ,QAAO;AACjC,SAAO;;AAET,SAAQ,MAAR;EACE,KAAK,OACH,QAAO;EACT,KAAK,OACH,QAAO;EACT,KAAK,OACH,QAAO;EACT,KAAK,QACH,QAAO;EACT,KAAK,QACH,QAAO;EACT,KAAK,QACH,QAAO;EACT,KAAK,QACH,QAAO;EACT,KAAK,SACH,QAAO;EACT,KAAK,SACH,QAAO;EACT,KAAK,SACH,QAAO;EACT,KAAK,UACH,QAAO;EACT,KAAK,UACH,QAAO;EACT,KAAK,OACH,QAAO;EACT,KAAK,OACH,QAAO;EACT,QACE,QAAO;;;AAIb,SAAgB,gBAAgB,MAAoB;AAClD,KAAI,OAAO,SAAS,UAAU;AAC5B,MAAI,KAAK,SAAS,OAAQ,QAAO;AACjC,SAAO;;AAET,SAAQ,MAAR;EACE,KAAK,OACH,QAAO;EACT,KAAK,OACH,QAAO;EACT,KAAK,OACH,QAAO;EACT,KAAK,QACH,QAAO;EACT,KAAK,QACH,QAAO;EACT,KAAK,QACH,QAAO;EACT,KAAK,QACH,QAAO;EACT,KAAK,SACH,QAAO;EACT,KAAK,SACH,QAAO;EACT,KAAK,SACH,QAAO;EACT,KAAK,UACH,QAAO;EACT,KAAK,UACH,QAAO;EACT,KAAK,OACH,QAAO;EACT,KAAK,OACH,QAAO;EACT,QACE,QAAO;;;AAIb,SAAgB,WAAW,KAAqB;AAC9C,QAAO,IAAI,OAAO,EAAE,CAAC,aAAa,GAAG,IAAI,MAAM,EAAE;;;;;ACvInD,SAAgB,eAAe,QAAgB,OAAuB;CACpE,IAAI,YAAY;CAChB,IAAI,eAAe;CACnB,IAAI,aAAa;AAEjB,MAAK,MAAM,SAAS,OAAO,OACzB,KAAI,cAAc,MAAM,KAAK,CAC3B;KAEA,eAAc,YAAY,MAAM,KAAK;AAGzC,aAAY,KAAK,KAAK,aAAa,EAAE;AAGrC,OAAM,KAAK,oBAAoB,OAAO,KAAK,IAAI;AAC/C,MAAK,MAAM,SAAS,OAAO,OACzB,OAAM,KAAK,KAAK,MAAM,KAAK,IAAI,YAAY,MAAM,KAAK,CAAC,GAAG;AAE5D,OAAM,KAAK,IAAI;AACf,OAAM,KAAK,GAAG;AAGd,gBAAe,QAAQ,WAAW,cAAc,MAAM;AAGtD,iBAAgB,QAAQ,WAAW,cAAc,MAAM;;AAGzD,SAAS,eACP,QACA,YACA,eACA,OACM;AACN,OAAM,KAAK,gBAAgB,OAAO,KAAK,UAAU;AACjD,OAAM,KAAK,kCAAkC;AAC7C,OAAM,KAAK,GAAG;AACd,OAAM,KAAK,wCAAwC;AACnD,OAAM,KAAK,4BAA4B;AACvC,OAAM,KAAK,MAAM;AACjB,OAAM,KAAK,GAAG;CAEd,IAAI,aAAa;CACjB,IAAI,eAAe;AACnB,MAAK,MAAM,SAAS,OAAO,QAAQ;EACjC,MAAM,SAAS,YAAY,MAAM,KAAK;AACtC,MAAI,cAAc,MAAM,KAAK,EAAE;AAC7B,SAAM,KAAK,SAAS,MAAM,KAAK,MAAM,OAAO,IAAI;AAChD,SAAM,KAAK,0BAA0B,gBAAgB,MAAM,KAAK,CAAC,GAAG,aAAa,IAAI;AACrF,SAAM,KAAK,MAAM;AACjB;SACK;AACL,SAAM,KAAK,SAAS,MAAM,KAAK,MAAM,OAAO,IAAI;AAChD,SAAM,KAAK,0BAA0B,gBAAgB,MAAM,KAAK,CAAC,GAAG,WAAW,IAAI;AACnF,SAAM,KAAK,MAAM;AACjB,iBAAc,YAAY,MAAM,KAAK;;AAEvC,QAAM,KAAK,GAAG;;AAEhB,OAAM,KAAK,IAAI;AACf,OAAM,KAAK,GAAG;;AAGhB,SAAS,gBACP,QACA,WACA,cACA,OACM;AACN,OAAM,KAAK,gBAAgB,OAAO,KAAK,WAAW;AAClD,OAAM,KAAK,oCAAoC;AAC/C,OAAM,KAAK,GAAG;AACd,OAAM,KAAK,0CAA0C;AACrD,OAAM,KAAK,8BAA8B;AACzC,OAAM,KAAK,MAAM;AACjB,OAAM,KAAK,GAAG;AACd,OAAM,KAAK,6CAA6C,OAAO,KAAK,WAAW;AAC/E,OAAM,KAAK,qCAAqC,UAAU,IAAI,aAAa,IAAI;AAC/E,OAAM,KAAK,kBAAkB,OAAO,KAAK,gBAAgB;AACzD,OAAM,KAAK,MAAM;AACjB,OAAM,KAAK,GAAG;CAEd,IAAI,aAAa;CACjB,IAAI,eAAe;AACnB,MAAK,MAAM,SAAS,OAAO,QAAQ;EACjC,MAAM,SAAS,YAAY,MAAM,KAAK;EACtC,MAAM,SAAS,gBAAgB,MAAM,KAAK;AAC1C,MAAI,cAAc,MAAM,KAAK,EAAE;AAC7B,SAAM,KAAK,QAAQ,WAAW,MAAM,KAAK,CAAC,UAAU,OAAO,WAAW;AACtE,SAAM,KAAK,oBAAoB,OAAO,GAAG,aAAa,WAAW;AACjE,SAAM,KAAK,MAAM;AACjB;SACK;AACL,SAAM,KAAK,QAAQ,WAAW,MAAM,KAAK,CAAC,UAAU,OAAO,WAAW;AACtE,SAAM,KAAK,oBAAoB,OAAO,GAAG,WAAW,WAAW;AAC/D,SAAM,KAAK,MAAM;AACjB,iBAAc,YAAY,MAAM,KAAK;;AAEvC,QAAM,KAAK,GAAG;;AAEhB,OAAM,KAAK,IAAI;AACf,OAAM,KAAK,GAAG;;;;;;;;ACxGhB,MAAM,kBAAoC,EACxC,mBAAmB,iBACpB;AAED,SAAgB,aAAa,QAAgB,SAAoC;CAC/E,MAAM,OAAO;EAAE,GAAG;EAAiB,GAAG;EAAS;CAC/C,MAAM,QAAkB,EAAE;AAE1B,OAAM,KAAK,mCAAmC;AAC9C,OAAM,KAAK,0BAA0B;AACrC,OAAM,KAAK,GAAG;AACd,OAAM,KACJ,+EAA+E,KAAK,kBAAkB,IACvG;AACD,OAAM,KAAK,GAAG;AAEd,MAAK,MAAM,SAAS,OAAO,MACzB,cAAa,OAAO,MAAM;AAG5B,MAAK,MAAM,UAAU,OAAO,QAC1B,gBAAe,QAAQ,MAAM;AAG/B,QAAO,MAAM,KAAK,KAAK;;;;;ACwBzB,MAAM,kBAA+B,IAAI,IAAI;CAC3C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,SAAS,YAAY,MAAqC;AACxD,QAAO,gBAAgB,IAAI,KAAK;;;;;;;;;;;;;;;;;;;;AAqBlC,SAAgB,cAAc,QAAwB;CACpD,MAAM,UAAoB,EAAE;CAC5B,MAAM,QAAgB,EAAE;CAGxB,MAAM,cAAc,OACjB,QAAQ,UAAU,GAAG,CACrB,QAAQ,qBAAqB,GAAG;CAGnC,MAAM,cAAc;CACpB,IAAI;AACJ,SAAQ,QAAQ,YAAY,KAAK,YAAY,MAAM,MAAM;EACvD,MAAM,OAAO,MAAM;EACnB,MAAM,OAAO,MAAM;EACnB,MAAM,SAAS,YAAY,KAAK;AAChC,UAAQ,KAAK;GAAE;GAAM;GAAQ,CAAC;;CAIhC,MAAM,YAAY;AAClB,SAAQ,QAAQ,UAAU,KAAK,YAAY,MAAM,MAAM;EACrD,MAAM,OAAO,MAAM;EACnB,MAAM,OAAO,MAAM;EACnB,MAAM,SAAS,gBAAgB,KAAK;AACpC,QAAM,KAAK;GAAE;GAAM;GAAQ,CAAC;;AAG9B,QAAO;EAAE;EAAS;EAAO;;AAG3B,SAAS,YAAY,MAAuB;CAC1C,MAAM,SAAkB,EAAE;CAG1B,MAAM,aAAa;CACnB,IAAI;AAEJ,SAAQ,QAAQ,WAAW,KAAK,KAAK,MAAM,MAAM;EAC/C,MAAM,OAAO,MAAM;EACnB,MAAM,QAAQ,OAAO,SAAS,MAAM,GAAG;EAEvC,MAAM,OAAO,UADG,MAAM,GAAG,MAAM,CACA;AAE/B,SAAO,KAAK;GAAE;GAAM;GAAO;GAAM,CAAC;;AAGpC,QAAO,OAAO,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM;;AAGjD,SAAS,UAAU,SAAuB;CAExC,MAAM,YAAY,QAAQ,MAAM,iBAAiB;AACjD,KAAI,UAEF,QAAO;EAAE,MAAM;EAAQ,aADH,UAAU,UAAU,GAAG,MAAM,CAAC;EACd;AAItC,KAAI,YAAY,QAAQ,CACtB,QAAO;AAIT,QAAO;EAAE,MAAM;EAAU,MAAM;EAAS;;AAG1C,SAAS,gBAAgB,MAA2B;CAClD,MAAM,SAAsB,EAAE;CAG9B,MAAM,aAAa;CACnB,IAAI;AAEJ,SAAQ,QAAQ,WAAW,KAAK,KAAK,MAAM,MAAM;EAC/C,MAAM,OAAO,MAAM;EACnB,MAAM,QAAQ,OAAO,SAAS,MAAM,GAAG;AACvC,SAAO,KAAK;GAAE;GAAM;GAAO,CAAC;;AAG9B,QAAO,OAAO,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM;;;;;;;;;;;ACrKjD,MAAM,EAAE,QAAQ,gBAAgB,UAAU;CACxC,MAAM,QAAQ,KAAK,MAAM,EAAE;CAC3B,SAAS;EACP,QAAQ;GAAE,MAAM;GAAU,OAAO;GAAK;EACtC,MAAM;GAAE,MAAM;GAAW,OAAO;GAAK;EACtC;CACD,kBAAkB;CACnB,CAAC;AAEF,IAAI,OAAO,QAAQ,YAAY,WAAW,GAAG;AAC3C,SAAQ,IAAI;;;;;;;;;;;;;;EAcZ;AACA,SAAQ,KAAK,EAAE;;AAGjB,MAAM,UAAU,YAAY;AAE5B,IAAI,YAAY,OAAO;AACrB,SAAQ,MAAM,oBAAoB,UAAU;AAC5C,SAAQ,MAAM,iCAA+B;AAC7C,SAAQ,KAAK,EAAE;;AAGjB,MAAM,YAAY,YAAY;AAC9B,IAAI,CAAC,WAAW;AACd,SAAQ,MAAM,4BAA4B;AAC1C,SAAQ,MAAM,kCAAkC;AAChD,SAAQ,KAAK,EAAE;;AAGjB,MAAM,aAAa,OAAO;AAE1B,eAAe,OAAO;CAGpB,MAAM,OAAO,aADE,cADA,aAAa,WAAW,QAAQ,CACX,CACH;AAEjC,KAAI,YAAY;AACd,gBAAc,YAAY,KAAK;AAC/B,UAAQ,MAAM,cAAc,aAAa;OAEzC,SAAQ,IAAI,KAAK;;AAIrB,MAAM,CAAC,OAAO,QAAQ;AACpB,SAAQ,MAAM,UAAU,IAAI,QAAQ;AACpC,SAAQ,KAAK,EAAE;EACf"}