ya-struct 0.0.4 → 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 -80
  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/lib/layout.ts ADDED
@@ -0,0 +1,262 @@
1
+ import { align, type TAbi } from "./common.ts";
2
+ import { createCTypeNormalizer } from "./types/c-types.ts";
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
+ };
package/lib/parser.ts ADDED
@@ -0,0 +1,87 @@
1
+ import type { TAbi } from "./common.ts";
2
+ import { layout, type TLayoutedField } from "./layout.ts";
3
+ import type { TFieldType } from "./types/index.ts";
4
+ import { createStructParser } from "./types/struct.ts";
5
+ import type { TValueParser } from "./types/value.ts";
6
+
7
+ type FieldValue<T extends TFieldType> =
8
+ T extends { type: "integer" } ? bigint :
9
+ T extends { type: "float" } ? number :
10
+ T extends { type: "pointer" } ? bigint :
11
+ T extends { type: "string" } ? string :
12
+ T extends { type: "array"; elementType: infer E; length: number }
13
+ ? FieldValue<E & TFieldType>[] :
14
+ T extends { type: "struct"; fields: infer F }
15
+ ? StructValue<F & readonly { name: string; definition: TFieldType }[]> :
16
+ never;
17
+
18
+ type StructValue<
19
+ F extends readonly { name: string; definition: TFieldType }[]
20
+ > = {
21
+ [K in F[number]as K["name"]]: FieldValue<K["definition"]>;
22
+ };
23
+
24
+ type Simplify<T> = {
25
+ [K in keyof T]: T[K]
26
+ } & {};
27
+
28
+ type TParsedValueOfDefinition<T extends TFieldType> = Simplify<FieldValue<T>>;
29
+
30
+ type TParser<T extends TFieldType> = {
31
+ size: number;
32
+ parse: ({ data }: { data: Uint8Array }) => TParsedValueOfDefinition<T>;
33
+ format: ({ value }: { value: TParsedValueOfDefinition<T> }) => Uint8Array;
34
+ layout: TLayoutedField;
35
+ };
36
+
37
+ const define = <const T extends TFieldType>({ definition }: { definition: T }) => {
38
+
39
+ const parser = ({ abi }: { abi: TAbi }): TParser<T> => {
40
+
41
+ type P = TParser<T>;
42
+
43
+ const l = layout({ definition, abi, currentOffsetInBits: 0 });
44
+
45
+ const size = Math.ceil(l.sizeInBits / 8);
46
+
47
+ // console.log(l);
48
+
49
+ let valueParser: TValueParser<TParsedValueOfDefinition<T>>;
50
+
51
+ if (l.type === "struct") {
52
+ valueParser = createStructParser({
53
+ layoutedFields: l.fields,
54
+ endianness: abi.endianness
55
+ }) as unknown as TValueParser<TParsedValueOfDefinition<T>>;
56
+ } else {
57
+ throw Error("only struct root definitions are supported currently");
58
+ }
59
+
60
+ const parse: P["parse"] = ({ data }) => {
61
+ return valueParser.parse({ data, offsetInBits: 0 });
62
+ };
63
+
64
+ const format: P["format"] = ({ value }) => {
65
+ const data = new Uint8Array(l.sizeInBits / 8);
66
+ valueParser.format({ value, target: data, offsetInBits: 0 });
67
+
68
+ return data;
69
+ };
70
+
71
+ return {
72
+ size,
73
+ parse,
74
+ format,
75
+ layout: l
76
+ };
77
+ };
78
+
79
+ return {
80
+ definition,
81
+ parser
82
+ };
83
+ };
84
+
85
+ export {
86
+ define
87
+ };
@@ -0,0 +1,90 @@
1
+ import type { TEndianness } from "../common.ts";
2
+ import type { TFieldType } from "./index.ts";
3
+ import { createIntegerParser } from "./integer.ts";
4
+ import type { TValueParser } from "./value.ts";
5
+
6
+ type TArrayParser = TValueParser<unknown[]>;
7
+
8
+ const createArrayParser = ({
9
+ elementType,
10
+ length,
11
+ endianness
12
+ }: {
13
+ elementType: TFieldType,
14
+ length: number,
15
+ endianness: TEndianness
16
+ }): TArrayParser => {
17
+
18
+ let fieldParser: TValueParser<unknown>;
19
+
20
+ if (elementType.type === "integer") {
21
+ fieldParser = createIntegerParser({
22
+ sizeInBits: elementType.sizeInBits,
23
+ signed: elementType.signed,
24
+ endianness
25
+ }) as TValueParser<unknown>;
26
+ } else {
27
+ throw Error("only integer array elements are supported currently");
28
+ }
29
+
30
+ const elementSizeInBytes = elementType.sizeInBits / 8;
31
+ if (!Number.isInteger(elementSizeInBytes)) {
32
+ throw Error("BUG: non byte-aligned array element size");
33
+ }
34
+
35
+ const parse: TArrayParser["parse"] = ({ data, offsetInBits }) => {
36
+ if (offsetInBits !== 0) {
37
+ throw Error("unaligned array parsing not supported yet");
38
+ }
39
+
40
+ // eslint-disable-next-line prefer-const
41
+ let result: unknown[] = [];
42
+
43
+ for (let i = 0; i < length; i += 1) {
44
+ const fieldData = data.subarray(i * elementSizeInBytes, (i + 1) * elementSizeInBytes);
45
+ const fieldValue = fieldParser.parse({ data: fieldData, offsetInBits: 0 });
46
+ result.push(fieldValue);
47
+ }
48
+
49
+ return result;
50
+ };
51
+
52
+ // eslint-disable-next-line complexity
53
+ const format: TArrayParser["format"] = ({ value, target, offsetInBits }) => {
54
+ if (offsetInBits !== 0) {
55
+ throw Error("unaligned array formatting not supported yet");
56
+ }
57
+
58
+ if (value.length !== length) {
59
+ throw Error(`array length mismatch: field length is ${length}, value length is ${value.length}`);
60
+ }
61
+
62
+ if (target.length < length * elementSizeInBytes) {
63
+ throw Error("not enough space in target for array formatting");
64
+ }
65
+
66
+ for (let i = 0; i < length; i += 1) {
67
+ const fieldTarget = target.subarray(i * elementSizeInBytes, (i + 1) * elementSizeInBytes);
68
+
69
+ try {
70
+ fieldParser.format({
71
+ value: value[i],
72
+ target: fieldTarget,
73
+ offsetInBits: 0
74
+ });
75
+ } catch (ex) {
76
+ throw Error(`failed to format array element at index ${i}`, { cause: ex });
77
+ }
78
+
79
+ }
80
+ };
81
+
82
+ return {
83
+ parse,
84
+ format
85
+ };
86
+ };
87
+
88
+ export {
89
+ createArrayParser
90
+ };
@@ -0,0 +1,222 @@
1
+ import { type TCompiler, type TDataModel, type TAbi } from "../common.ts";
2
+ import { type TFieldType, type TCFieldType, type TPrimitiveBasicFieldType } from "./index.ts";
3
+
4
+ type TCField = TFieldType & { type: "c-type" };
5
+
6
+ type TPartialCTypeMappings = {
7
+ [dataModel in TDataModel]?: {
8
+ [compiler in TCompiler]?: {
9
+ [field in TCFieldType]?: TPrimitiveBasicFieldType
10
+ }
11
+ }
12
+ };
13
+
14
+ const cTypeMappings: TPartialCTypeMappings = {
15
+ LP64: {
16
+ gcc: {
17
+ "char": {
18
+ type: "integer",
19
+ sizeInBits: 8,
20
+ fixedAbi: {},
21
+ signed: true
22
+ },
23
+ "unsigned char": {
24
+ type: "integer",
25
+ sizeInBits: 8,
26
+ fixedAbi: {},
27
+ signed: false
28
+ },
29
+ "short": {
30
+ type: "integer",
31
+ sizeInBits: 16,
32
+ fixedAbi: {},
33
+ signed: true
34
+ },
35
+ "unsigned short": {
36
+ type: "integer",
37
+ sizeInBits: 16,
38
+ fixedAbi: {},
39
+ signed: false
40
+ },
41
+ "int": {
42
+ type: "integer",
43
+ sizeInBits: 32,
44
+ fixedAbi: {},
45
+ signed: true
46
+ },
47
+ "unsigned int": {
48
+ type: "integer",
49
+ sizeInBits: 32,
50
+ fixedAbi: {},
51
+ signed: false
52
+ },
53
+ "long": {
54
+ type: "integer",
55
+ sizeInBits: 64,
56
+ fixedAbi: {},
57
+ signed: true
58
+ },
59
+ "unsigned long": {
60
+ type: "integer",
61
+ sizeInBits: 64,
62
+ fixedAbi: {},
63
+ signed: false
64
+ },
65
+ "long long": {
66
+ type: "integer",
67
+ sizeInBits: 64,
68
+ fixedAbi: {},
69
+ signed: true
70
+ },
71
+ "unsigned long long": {
72
+ type: "integer",
73
+ sizeInBits: 64,
74
+ fixedAbi: {},
75
+ signed: false
76
+ },
77
+ "float": {
78
+ type: "float",
79
+ sizeInBits: 32,
80
+ fixedAbi: {}
81
+ },
82
+ "double": {
83
+ type: "float",
84
+ sizeInBits: 64,
85
+ fixedAbi: {}
86
+ },
87
+ "long double": {
88
+ type: "float",
89
+ sizeInBits: 128,
90
+ fixedAbi: {}
91
+ },
92
+ }
93
+ },
94
+
95
+ ILP32: {
96
+ gcc: {
97
+ "char": {
98
+ type: "integer",
99
+ sizeInBits: 8,
100
+ fixedAbi: {},
101
+ signed: true
102
+ },
103
+ "unsigned char": {
104
+ type: "integer",
105
+ sizeInBits: 8,
106
+ fixedAbi: {},
107
+ signed: false
108
+ },
109
+ "short": {
110
+ type: "integer",
111
+ sizeInBits: 16,
112
+ fixedAbi: {},
113
+ signed: true
114
+ },
115
+ "unsigned short": {
116
+ type: "integer",
117
+ sizeInBits: 16,
118
+ fixedAbi: {},
119
+ signed: false
120
+ },
121
+ "int": {
122
+ type: "integer",
123
+ sizeInBits: 32,
124
+ fixedAbi: {},
125
+ signed: true
126
+ },
127
+ "unsigned int": {
128
+ type: "integer",
129
+ sizeInBits: 32,
130
+ fixedAbi: {},
131
+ signed: false
132
+ },
133
+ "long": {
134
+ type: "integer",
135
+ sizeInBits: 32,
136
+ fixedAbi: {},
137
+ signed: true
138
+ },
139
+ "unsigned long": {
140
+ type: "integer",
141
+ sizeInBits: 32,
142
+ fixedAbi: {},
143
+ signed: false
144
+ },
145
+ "long long": {
146
+ type: "integer",
147
+ sizeInBits: 64,
148
+ fixedAbi: {},
149
+ signed: true
150
+ },
151
+ "unsigned long long": {
152
+ type: "integer",
153
+ sizeInBits: 64,
154
+ fixedAbi: {},
155
+ signed: false
156
+ },
157
+ "float": {
158
+ type: "float",
159
+ sizeInBits: 32,
160
+ fixedAbi: {}
161
+ },
162
+ "double": {
163
+ type: "float",
164
+ sizeInBits: 64,
165
+ fixedAbi: {}
166
+ },
167
+ "long double": {
168
+ type: "float",
169
+ sizeInBits: 128,
170
+ fixedAbi: {}
171
+ },
172
+ }
173
+ }
174
+ };
175
+
176
+ const createCTypeNormalizer = ({
177
+ abi
178
+ }: {
179
+ abi: TAbi
180
+ }) => {
181
+
182
+ const fieldMappings = cTypeMappings[abi.dataModel]?.[abi.compiler];
183
+ if (!fieldMappings) {
184
+ throw Error(`no c-type mappings for data model ${abi.dataModel} and compiler ${abi.compiler}`);
185
+ }
186
+
187
+ const normalize = ({ cField }: { cField: TCField }): TPrimitiveBasicFieldType => {
188
+
189
+ const mapping = fieldMappings[cField.cType];
190
+ if (mapping === undefined) {
191
+ throw Error(`no c-type mapping for c-type "${cField.cType}" for data model ${abi.dataModel} and compiler ${abi.compiler}`);
192
+ }
193
+
194
+ const mappingFixedAbi = mapping.fixedAbi;
195
+ const fieldFixedAbi = cField.fixedAbi;
196
+
197
+ const fixedAbi = {
198
+ ...mappingFixedAbi,
199
+ ...fieldFixedAbi
200
+ };
201
+
202
+ Object.keys(fixedAbi).forEach((keyAsString) => {
203
+ const key = keyAsString as keyof TAbi;
204
+ if (mappingFixedAbi[key] !== undefined && fieldFixedAbi[key] !== undefined) {
205
+ throw Error(`conflicting fixed ABI property for key ${key} between c-type mapping and c-field`);
206
+ }
207
+ });
208
+
209
+ return {
210
+ ...mapping,
211
+ fixedAbi
212
+ };
213
+ };
214
+
215
+ return {
216
+ normalize
217
+ };
218
+ };
219
+
220
+ export {
221
+ createCTypeNormalizer
222
+ };