ya-struct 0.0.5 → 0.0.6

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.
Files changed (61) hide show
  1. package/.editorconfig +8 -0
  2. package/.github/workflows/ci.yml +23 -0
  3. package/.github/workflows/npm-publish.yml +28 -0
  4. package/README.md +150 -18
  5. package/dist/lib/common.d.ts +14 -0
  6. package/dist/lib/common.js +30 -0
  7. package/dist/lib/index.d.ts +5 -0
  8. package/dist/lib/index.js +21 -0
  9. package/dist/lib/layout.d.ts +48 -0
  10. package/dist/lib/layout.js +262 -0
  11. package/dist/lib/parser.d.ts +51 -0
  12. package/dist/lib/parser.js +87 -0
  13. package/dist/lib/types/array.d.ts +10 -0
  14. package/dist/lib/types/array.js +90 -0
  15. package/dist/lib/types/c-types.d.ts +13 -0
  16. package/dist/lib/types/c-types.js +222 -0
  17. package/dist/lib/types/index.d.ts +93 -0
  18. package/dist/lib/types/index.js +122 -0
  19. package/dist/lib/types/integer.d.ts +9 -0
  20. package/dist/lib/types/integer.js +160 -0
  21. package/dist/lib/types/pointer.d.ts +8 -0
  22. package/dist/lib/types/pointer.js +27 -0
  23. package/dist/lib/types/string.d.ts +6 -0
  24. package/dist/lib/types/string.js +56 -0
  25. package/dist/lib/types/struct.d.ts +11 -0
  26. package/dist/lib/types/struct.js +113 -0
  27. package/dist/lib/types/value.d.ts +12 -0
  28. package/dist/lib/types/value.js +8 -0
  29. package/eslint.config.js +127 -0
  30. package/lib/bit-buffer.ts +70 -0
  31. package/lib/common.ts +30 -0
  32. package/lib/index.ts +21 -0
  33. package/lib/layout.ts +262 -0
  34. package/lib/parser.ts +87 -0
  35. package/lib/types/array.ts +90 -0
  36. package/lib/types/c-types.ts +222 -0
  37. package/lib/types/index.ts +122 -0
  38. package/lib/types/integer.ts +160 -0
  39. package/lib/types/pointer.ts +27 -0
  40. package/lib/types/string.ts +56 -0
  41. package/lib/types/struct.ts +113 -0
  42. package/lib/types/value.ts +8 -0
  43. package/package.json +19 -15
  44. package/package.npm.json +25 -0
  45. package/samples/basic.ts +40 -0
  46. package/test/c-structs.ts +399 -0
  47. package/test/compile-util.ts +92 -0
  48. package/tsconfig.json +10 -0
  49. package/.eslintrc +0 -92
  50. package/.github/workflows/CI.yml +0 -39
  51. package/.prettierrc +0 -5
  52. package/lib/builder.js +0 -62
  53. package/lib/index.js +0 -159
  54. package/lib/marshaller.js +0 -88
  55. package/lib/refbuf.js +0 -11
  56. package/lib/types/basic.js +0 -200
  57. package/lib/types/ctypes.js +0 -160
  58. package/test/abi.js +0 -203
  59. package/test/basic.js +0 -92
  60. package/test/ctypes.js +0 -166
  61. package/test/ref.js +0 -35
package/.editorconfig ADDED
@@ -0,0 +1,8 @@
1
+ root = true
2
+
3
+ [*]
4
+ end_of_line = lf
5
+ insert_final_newline = true
6
+ indent_style = space
7
+ indent_size = 2
8
+ trim_trailing_whitespace = true
@@ -0,0 +1,23 @@
1
+ name: CI
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ ci:
7
+ runs-on: ubuntu-latest
8
+ name: Continous integration tests
9
+ steps:
10
+ - uses: actions/checkout@v4
11
+ - uses: actions/setup-node@v4
12
+ with:
13
+ node-version: '24'
14
+ - name: Install libc6-dev-i386
15
+ run: sudo apt-get update && sudo apt-get install -y libc6-dev-i386
16
+ - name: Install dependencies
17
+ run: npm ci
18
+ - name: Build
19
+ run: npm run build
20
+ - name: Run tests
21
+ run: npm run test
22
+ - name: Verify code with linter
23
+ run: npm run lint
@@ -0,0 +1,28 @@
1
+ name: Publish Package to npmjs
2
+ on:
3
+ push:
4
+ tags:
5
+ - '*'
6
+
7
+ permissions:
8
+ id-token: write # Required for OIDC
9
+ contents: read
10
+
11
+ jobs:
12
+ publish:
13
+ runs-on: ubuntu-latest
14
+ permissions:
15
+ contents: read
16
+ id-token: write
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+ # Setup .npmrc file to publish to npm
20
+ - uses: actions/setup-node@v4
21
+ with:
22
+ node-version: '24'
23
+ registry-url: 'https://registry.npmjs.org'
24
+ - run: npm ci
25
+ - run: npm run build
26
+ - run: node node_modules/.bin/releasetool merge --local-package-json package.json --npm-package-json package.npm.json --output package.json
27
+ - run: node node_modules/.bin/releasetool patch-version --package-json package.json --package-version ${{ github.ref_name }}
28
+ - run: npm publish
package/README.md CHANGED
@@ -1,24 +1,156 @@
1
1
  # node-ya-struct
2
- Yet Another Node.js Structure API
3
2
 
3
+ Yet Another Node.js Structure API - A TypeScript library for defining, parsing, and formatting binary data structures with precise control over memory layout, alignment, and ABI compatibility.
4
4
 
5
- ## About
6
- This module allows you to parse and format fixed C-like data structures. Mainly this can be used for native code interoperability, network communication or file formats. The goal is to support types and alignments similar to C structures with support for endianness.
5
+ ## Overview
7
6
 
8
- ## API
9
- TBD
7
+ `node-ya-struct` provides a type-safe way to work with binary data structures in Node.js. It handles complex memory layout calculations including padding, alignment, and platform-specific differences (data models, endianness, compilers). The library is particularly useful for:
8
+
9
+ - Interfacing with native C libraries and system APIs
10
+ - Parsing binary file formats
11
+ - Working with hardware interfaces and low-level protocols
12
+ - Cross-platform binary data serialization
10
13
 
11
14
  ## Features
12
- - Basic Integer type support
13
- - Buffer referencing - buffers can be used as pointers, including garbage collection protection
14
- - Endianness support
15
-
16
- ## Planned Features
17
- - Nested structures
18
- - Nested arrays
19
- - C strings as arrays
20
- - C strings as pointers
21
- - Basic C types
22
- - Bitfields
23
- - Unions
24
- - Field alignments
15
+
16
+ - **Type-safe definitions** - Full TypeScript support with inferred types for parsed values
17
+ - **Multiple data models** - Support for LP64 (64-bit Unix) and ILP32 (32-bit) data models
18
+ - **Packed structs** - Support for packed structures without padding
19
+ - **Endianness control** - Little and big endian support
20
+ - **Zero dependencies** - Pure TypeScript implementation
21
+
22
+ ## Installation
23
+
24
+ ```bash
25
+ npm install ya-struct
26
+ ```
27
+
28
+ ## Quick Start
29
+
30
+ ```typescript
31
+ import { define, types } from "ya-struct";
32
+
33
+ // Define a struct
34
+ const def = define({
35
+ definition: {
36
+ type: "struct",
37
+ packed: false,
38
+ fixedAbi: {},
39
+ fields: [
40
+ { name: "a", definition: types.Int16 },
41
+ { name: "b", definition: types.UInt16 },
42
+ { name: "c", definition: types.UInt32 },
43
+ ]
44
+ }
45
+ });
46
+
47
+ // Create a parser with specific ABI settings
48
+ const parser = def.parser({
49
+ abi: {
50
+ endianness: "little",
51
+ dataModel: "LP64",
52
+ compiler: "gcc",
53
+ }
54
+ });
55
+
56
+ // Parse binary data
57
+ const value = {
58
+ a: 0n,
59
+ b: 1n,
60
+ c: 2n,
61
+ };
62
+
63
+ // Format to binary
64
+ const buffer = parser.format({ value });
65
+
66
+ // Parse back
67
+ const parsed = parser.parse({ data: buffer });
68
+ ```
69
+
70
+ ## API
71
+
72
+ ### `define({ definition })`
73
+
74
+ Creates a struct definition that can be used to create parsers with specific ABI settings.
75
+
76
+ **Parameters:**
77
+ - `definition` - A struct definition object
78
+
79
+ **Returns:** An object with a `parser()` method
80
+
81
+ ### `parser({ abi })`
82
+
83
+ Creates a parser for the defined structure with specific ABI settings.
84
+
85
+ **Parameters:**
86
+ - `abi.endianness` - `"little"` or `"big"`
87
+ - `abi.dataModel` - `"LP64"` (64-bit Unix/Linux) or `"ILP32"` (32-bit)
88
+ - `abi.compiler` - `"gcc"` (currently supported)
89
+
90
+ **Returns:** Parser object with:
91
+ - `size` - Size of the structure in bytes
92
+ - `parse({ data })` - Parse binary data to JavaScript values
93
+ - `format({ value })` - Format JavaScript values to binary data
94
+ - `layout` - Detailed memory layout information
95
+
96
+ ### Built-in Types
97
+
98
+ Available via `types` export:
99
+
100
+ - **Integers:** `Int16`, `UInt16`, `Int32`, `UInt32`, `Int64`, `UInt64`
101
+ - **Strings:** `ascii({ length })` - Fixed-length null-terminated ASCII strings
102
+ - **Pointers:** `pointer` - Platform-specific pointer size
103
+
104
+ ### Custom Types
105
+
106
+ You can define custom field types:
107
+
108
+ ```typescript
109
+ const definition = {
110
+ type: "struct",
111
+ packed: false,
112
+ fixedAbi: {},
113
+ fields: [
114
+ {
115
+ name: "myField",
116
+ definition: {
117
+ type: "integer",
118
+ sizeInBits: 32,
119
+ signed: true,
120
+ fixedAbi: {}
121
+ }
122
+ }
123
+ ]
124
+ } as const;
125
+ ```
126
+
127
+ Supported type kinds:
128
+ - `integer` - Custom integer with specified bit width
129
+ - `float` - Floating point numbers
130
+ - `pointer` - Pointer types
131
+ - `array` - Fixed-length arrays
132
+ - `struct` - Nested structures
133
+ - `string` - Fixed-length strings
134
+ - `c-type` - Native C types (char, int, long, etc.)
135
+
136
+ ## Data Models
137
+
138
+ The library supports different C data models:
139
+
140
+ - **LP64** - Used on 64-bit Unix/Linux systems (long and pointer are 64-bit)
141
+ - **ILP32** - Used on 32-bit systems (int, long, and pointer are 32-bit)
142
+
143
+ ## Packed Structures
144
+
145
+ Set `packed: true` in your struct definition to disable padding and alignment:
146
+
147
+ ```typescript
148
+ const def = define({
149
+ definition: {
150
+ type: "struct",
151
+ packed: true, // No padding between fields
152
+ fixedAbi: {},
153
+ fields: [...]
154
+ }
155
+ });
156
+ ```
@@ -0,0 +1,14 @@
1
+ type TDataModel = "LP64" | "ILP32";
2
+ type TCompiler = "gcc";
3
+ type TEndianness = "little" | "big";
4
+ type TAbi = {
5
+ endianness: TEndianness;
6
+ compiler: TCompiler;
7
+ dataModel: TDataModel;
8
+ };
9
+ declare const align: ({ offset, alignment }: {
10
+ offset: number;
11
+ alignment: number;
12
+ }) => number;
13
+ export type { TDataModel, TCompiler, TEndianness, TAbi };
14
+ export { align };
@@ -0,0 +1,30 @@
1
+ /*type TDataModel = "LP64" | "ILP32";*/
2
+ /*type TCompiler = "gcc";*/
3
+ /*type TEndianness = "little" | "big";*/
4
+
5
+ /*type TAbi = {
6
+ endianness: TEndianness;
7
+ compiler: TCompiler;
8
+ dataModel: TDataModel;
9
+ };*/
10
+
11
+ const align = ({ offset, alignment }/*: { offset: number; alignment: number }*/)/*: number*/ => {
12
+ const remainder = offset % alignment;
13
+ if (remainder === 0) {
14
+ return offset;
15
+ }
16
+
17
+ return offset + (alignment - remainder);
18
+ };
19
+
20
+ /*export type {
21
+ TDataModel,
22
+ TCompiler,
23
+ TEndianness,
24
+
25
+ TAbi
26
+ };*/
27
+
28
+ export {
29
+ align
30
+ };
@@ -0,0 +1,5 @@
1
+ import { define } from "./parser.js";
2
+ import { types } from "./types/index.js";
3
+ import type { TAbi, TCompiler, TDataModel, TEndianness } from "./common.js";
4
+ export { define, types };
5
+ export type { TAbi, TEndianness, TCompiler, TDataModel };
@@ -0,0 +1,21 @@
1
+ import { define } from "./parser.js";
2
+ import { types } from "./types/index.js";
3
+
4
+ /*import type {
5
+ TAbi,
6
+ TCompiler,
7
+ TDataModel,
8
+ TEndianness,
9
+ } from "./common.ts";*/
10
+
11
+ export {
12
+ define,
13
+ types
14
+ };
15
+
16
+ /*export type {
17
+ TAbi,
18
+ TEndianness,
19
+ TCompiler,
20
+ TDataModel
21
+ };*/
@@ -0,0 +1,48 @@
1
+ import { type TAbi } from "./common.js";
2
+ import type { TFieldType } from "./types/index.js";
3
+ type TLayoutedField = {
4
+ readonly type: "integer";
5
+ readonly offsetInBits: number;
6
+ readonly sizeInBits: number;
7
+ readonly signed: boolean;
8
+ readonly fixedAbi: Partial<TAbi>;
9
+ } | {
10
+ readonly type: "float";
11
+ readonly offsetInBits: number;
12
+ readonly sizeInBits: number;
13
+ readonly fixedAbi: Partial<TAbi>;
14
+ } | {
15
+ readonly type: "pointer";
16
+ readonly offsetInBits: number;
17
+ readonly sizeInBits: number;
18
+ readonly fixedAbi: Partial<TAbi>;
19
+ } | {
20
+ readonly type: "array";
21
+ readonly elementType: TLayoutedField;
22
+ readonly length: number;
23
+ readonly offsetInBits: number;
24
+ readonly sizeInBits: number;
25
+ } | {
26
+ readonly type: "struct";
27
+ readonly offsetInBits: number;
28
+ readonly sizeInBits: number;
29
+ readonly fields: readonly {
30
+ readonly name: string;
31
+ readonly definition: TLayoutedField;
32
+ }[];
33
+ readonly packed: boolean;
34
+ readonly fixedAbi: Partial<TAbi>;
35
+ } | {
36
+ readonly type: "string";
37
+ readonly charSizeInBits: number;
38
+ readonly length: number;
39
+ readonly offsetInBits: number;
40
+ readonly sizeInBits: number;
41
+ };
42
+ declare const layout: ({ definition, abi, currentOffsetInBits }: {
43
+ definition: TFieldType;
44
+ abi: TAbi;
45
+ currentOffsetInBits: number;
46
+ }) => TLayoutedField;
47
+ export { layout };
48
+ export type { TLayoutedField };
@@ -0,0 +1,262 @@
1
+ import { align, /*type TAbi */} from "./common.js";
2
+ import { createCTypeNormalizer } from "./types/c-types.js";
3
+ /*import type { TFieldType } from "./types/index.ts";*/
4
+ import nodeUtil from "node:util";
5
+
6
+ /*type TLayoutedField = {
7
+ readonly type: "integer";
8
+ readonly offsetInBits: number;
9
+ readonly sizeInBits: number;
10
+ readonly signed: boolean;
11
+ readonly fixedAbi: Partial<TAbi>;
12
+ } | {
13
+ readonly type: "float";
14
+ readonly offsetInBits: number;
15
+ readonly sizeInBits: number;
16
+ readonly fixedAbi: Partial<TAbi>;
17
+ } | {
18
+ readonly type: "pointer";
19
+ readonly offsetInBits: number;
20
+ readonly sizeInBits: number;
21
+ readonly fixedAbi: Partial<TAbi>;
22
+ } | {
23
+ readonly type: "array";
24
+ readonly elementType: TLayoutedField;
25
+ readonly length: number;
26
+ readonly offsetInBits: number;
27
+ readonly sizeInBits: number;
28
+ } | {
29
+ readonly type: "struct";
30
+ readonly offsetInBits: number;
31
+ readonly sizeInBits: number;
32
+ readonly fields: readonly { readonly name: string; readonly definition: TLayoutedField }[];
33
+ readonly packed: boolean;
34
+ readonly fixedAbi: Partial<TAbi>;
35
+ } | {
36
+ readonly type: "string";
37
+ readonly charSizeInBits: number;
38
+ readonly length: number;
39
+ readonly offsetInBits: number;
40
+ readonly sizeInBits: number;
41
+ };*/
42
+
43
+ const pointerSizeInBitsByDataModel = ({ dataModel }/*: { dataModel: TAbi["dataModel"] }*/)/*: number*/ => {
44
+ switch (dataModel) {
45
+ case "LP64":
46
+ return 64;
47
+ case "ILP32":
48
+ return 32;
49
+ default:
50
+ throw Error(`unsupported data model "${dataModel}" for pointer size determination`);
51
+ }
52
+ };
53
+
54
+ const layoutStruct = ({
55
+ definition,
56
+ abi,
57
+ currentOffsetInBits: initialOffsetInBits
58
+ }/*: {
59
+ definition: TFieldType & { type: "struct" },
60
+ abi: TAbi,
61
+ currentOffsetInBits: number
62
+ }*/)/*: TLayoutedField*/ => {
63
+
64
+ // TODO: implement alignment handling
65
+ const structAlignmentInBits = 64;
66
+ // const fieldAlignmentInBits = 64;
67
+ const fieldAlignmentInBits = 1;
68
+ const pointerSizeInBits = pointerSizeInBitsByDataModel({ dataModel: abi.dataModel });
69
+
70
+ let currentOffsetInBits = align({ offset: initialOffsetInBits, alignment: structAlignmentInBits });
71
+ let layoutedFields/*: (TLayoutedField & { type: "struct" })["fields"]*/ = [];
72
+
73
+ // eslint-disable-next-line max-statements,complexity
74
+ definition.fields.forEach((field) => {
75
+
76
+ let normalizedField/*: TFieldType*/ = field.definition;
77
+
78
+ if (field.definition.type === "c-type") {
79
+ const cTypeNormalizer = createCTypeNormalizer({ abi });
80
+ normalizedField = cTypeNormalizer.normalize({ cField: field.definition });
81
+ }
82
+
83
+ if (!definition.packed) {
84
+ switch (normalizedField.type) {
85
+ case "integer":
86
+ case "float": {
87
+ const sizeInBits = normalizedField.sizeInBits;
88
+
89
+ if (abi.compiler === "gcc" && abi.dataModel === "ILP32" && sizeInBits === 64) {
90
+ // special handling for gcc 64-bit integers on ILP32 data model (alignment to 32 bits)
91
+ currentOffsetInBits = align({ offset: currentOffsetInBits, alignment: 32 });
92
+ } else {
93
+ currentOffsetInBits = align({ offset: currentOffsetInBits, alignment: sizeInBits });
94
+ }
95
+
96
+ break;
97
+ }
98
+ case "string": {
99
+ // no special alignment needed
100
+ break;
101
+ }
102
+ case "pointer": {
103
+ currentOffsetInBits = align({ offset: currentOffsetInBits, alignment: pointerSizeInBits });
104
+ break;
105
+ }
106
+ default:
107
+ throw Error(`unsupported field type for struct layout: ${nodeUtil.inspect(field.definition)}`);
108
+ }
109
+ }
110
+
111
+ // eslint-disable-next-line no-use-before-define
112
+ const fieldLayout = layout({ definition: normalizedField, abi, currentOffsetInBits });
113
+
114
+ layoutedFields = [
115
+ ...layoutedFields,
116
+ {
117
+ name: field.name,
118
+ definition: fieldLayout
119
+ }
120
+ ];
121
+
122
+ currentOffsetInBits = align({ offset: fieldLayout.offsetInBits + fieldLayout.sizeInBits, alignment: fieldAlignmentInBits });
123
+ });
124
+
125
+ return {
126
+ type: "struct",
127
+ offsetInBits: initialOffsetInBits,
128
+ sizeInBits: currentOffsetInBits - initialOffsetInBits,
129
+ fields: layoutedFields,
130
+ packed: definition.packed,
131
+ fixedAbi: definition.fixedAbi
132
+ };
133
+ };
134
+
135
+ const layoutPrimitive = ({
136
+ definition,
137
+ abi,
138
+ currentOffsetInBits
139
+ }/*: {
140
+ definition: TFieldType & ({ type: "integer" } | { type: "float" } | { type: "pointer" }),
141
+ abi: TAbi,
142
+ currentOffsetInBits: number
143
+ }*/)/*: TLayoutedField*/ => {
144
+
145
+ if (definition.type === "integer") {
146
+ return {
147
+ type: "integer",
148
+ offsetInBits: currentOffsetInBits,
149
+ sizeInBits: definition.sizeInBits,
150
+ signed: definition.signed,
151
+ fixedAbi: definition.fixedAbi
152
+ };
153
+ }
154
+
155
+ if (definition.type === "float") {
156
+ return {
157
+ type: "float",
158
+ offsetInBits: currentOffsetInBits,
159
+ sizeInBits: definition.sizeInBits,
160
+ fixedAbi: definition.fixedAbi
161
+ };
162
+ }
163
+
164
+ const pointerSizeInBits = pointerSizeInBitsByDataModel({ dataModel: abi.dataModel });
165
+
166
+ return {
167
+ type: definition.type,
168
+ offsetInBits: currentOffsetInBits,
169
+ sizeInBits: pointerSizeInBits,
170
+ fixedAbi: definition.fixedAbi
171
+ };
172
+ };
173
+
174
+ const layoutString = ({
175
+ definition,
176
+ currentOffsetInBits
177
+ }/*: {
178
+ definition: TFieldType & { type: "string" },
179
+ abi: TAbi,
180
+ currentOffsetInBits: number
181
+ }*/)/*: TLayoutedField*/ => {
182
+
183
+ const sizeInBits = definition.charSizeInBits * definition.length;
184
+
185
+ return {
186
+ type: "string",
187
+ offsetInBits: currentOffsetInBits,
188
+ sizeInBits,
189
+ charSizeInBits: definition.charSizeInBits,
190
+ length: definition.length
191
+ };
192
+ };
193
+
194
+ const layoutArray = ({
195
+ definition,
196
+ abi,
197
+ currentOffsetInBits
198
+ }/*: {
199
+ definition: TFieldType & { type: "array" },
200
+ abi: TAbi,
201
+ currentOffsetInBits: number
202
+ }*/)/*: TLayoutedField*/ => {
203
+
204
+ // eslint-disable-next-line no-use-before-define
205
+ const elementLayout = layout({ definition: definition.elementType, abi, currentOffsetInBits: 0 });
206
+
207
+ // TODO: handle alignment
208
+ const sizeInBits = elementLayout.sizeInBits * definition.length;
209
+
210
+ return {
211
+ type: "array",
212
+ offsetInBits: currentOffsetInBits,
213
+ sizeInBits,
214
+ elementType: elementLayout,
215
+ length: definition.length
216
+ };
217
+ };
218
+
219
+ const layout = ({
220
+ definition,
221
+ abi,
222
+ currentOffsetInBits
223
+ }/*: {
224
+ definition: TFieldType,
225
+ abi: TAbi,
226
+ currentOffsetInBits: number
227
+ // eslint-disable-next-line complexity
228
+ }*/)/*: TLayoutedField*/ => {
229
+
230
+ if (definition.type === "struct") {
231
+ return layoutStruct({ definition, abi, currentOffsetInBits });
232
+ }
233
+
234
+ if (definition.type === "integer" || definition.type === "float" || definition.type === "pointer") {
235
+ return layoutPrimitive({ definition, abi, currentOffsetInBits });
236
+ }
237
+
238
+ if (definition.type === "string") {
239
+ return layoutString({ definition, abi, currentOffsetInBits });
240
+ }
241
+
242
+ if (definition.type === "array") {
243
+ return layoutArray({ definition, abi, currentOffsetInBits });
244
+ }
245
+
246
+ if (definition.type === "c-type") {
247
+ const cTypeNormalizer = createCTypeNormalizer({ abi });
248
+ const basicField = cTypeNormalizer.normalize({ cField: definition });
249
+
250
+ return layout({ definition: basicField, abi, currentOffsetInBits });
251
+ }
252
+
253
+ throw Error("not implemented yet");
254
+ };
255
+
256
+ export {
257
+ layout
258
+ };
259
+
260
+ /*export type {
261
+ TLayoutedField
262
+ };*/
@@ -0,0 +1,51 @@
1
+ import type { TAbi } from "./common.js";
2
+ import { type TLayoutedField } from "./layout.js";
3
+ import type { TFieldType } from "./types/index.js";
4
+ type FieldValue<T extends TFieldType> = T extends {
5
+ type: "integer";
6
+ } ? bigint : T extends {
7
+ type: "float";
8
+ } ? number : T extends {
9
+ type: "pointer";
10
+ } ? bigint : T extends {
11
+ type: "string";
12
+ } ? string : T extends {
13
+ type: "array";
14
+ elementType: infer E;
15
+ length: number;
16
+ } ? FieldValue<E & TFieldType>[] : T extends {
17
+ type: "struct";
18
+ fields: infer F;
19
+ } ? StructValue<F & readonly {
20
+ name: string;
21
+ definition: TFieldType;
22
+ }[]> : never;
23
+ type StructValue<F extends readonly {
24
+ name: string;
25
+ definition: TFieldType;
26
+ }[]> = {
27
+ [K in F[number] as K["name"]]: FieldValue<K["definition"]>;
28
+ };
29
+ type Simplify<T> = {
30
+ [K in keyof T]: T[K];
31
+ } & {};
32
+ type TParsedValueOfDefinition<T extends TFieldType> = Simplify<FieldValue<T>>;
33
+ type TParser<T extends TFieldType> = {
34
+ size: number;
35
+ parse: ({ data }: {
36
+ data: Uint8Array;
37
+ }) => TParsedValueOfDefinition<T>;
38
+ format: ({ value }: {
39
+ value: TParsedValueOfDefinition<T>;
40
+ }) => Uint8Array;
41
+ layout: TLayoutedField;
42
+ };
43
+ declare const define: <const T extends TFieldType>({ definition }: {
44
+ definition: T;
45
+ }) => {
46
+ definition: T;
47
+ parser: ({ abi }: {
48
+ abi: TAbi;
49
+ }) => TParser<T>;
50
+ };
51
+ export { define };