@exornea/zeno-compiler 1.7.0 → 2.3.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/bin/zeno-codegen.mjs +79 -31
- package/bin/zeno-diff-layout.mjs +60 -0
- package/bin/zeno-inspect.mjs +67 -0
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/analyzer.js +48 -26
- package/dist/analyzer.js.map +1 -1
- package/dist/emitter-ast.d.ts +8 -0
- package/dist/emitter-ast.d.ts.map +1 -0
- package/dist/emitter-ast.js +34 -0
- package/dist/emitter-ast.js.map +1 -0
- package/dist/emitter-capabilities.d.ts +8 -0
- package/dist/emitter-capabilities.d.ts.map +1 -0
- package/dist/emitter-capabilities.js +59 -0
- package/dist/emitter-capabilities.js.map +1 -0
- package/dist/emitter-fields.d.ts +3 -0
- package/dist/emitter-fields.d.ts.map +1 -0
- package/dist/emitter-fields.js +180 -0
- package/dist/emitter-fields.js.map +1 -0
- package/dist/emitter-input.d.ts +3 -0
- package/dist/emitter-input.d.ts.map +1 -0
- package/dist/emitter-input.js +45 -0
- package/dist/emitter-input.js.map +1 -0
- package/dist/emitter-names.d.ts +5 -0
- package/dist/emitter-names.d.ts.map +1 -0
- package/dist/emitter-names.js +10 -0
- package/dist/emitter-names.js.map +1 -0
- package/dist/emitter-runtime-imports.d.ts +3 -0
- package/dist/emitter-runtime-imports.d.ts.map +1 -0
- package/dist/emitter-runtime-imports.js +73 -0
- package/dist/emitter-runtime-imports.js.map +1 -0
- package/dist/emitter-scan-kernels.d.ts +10 -0
- package/dist/emitter-scan-kernels.d.ts.map +1 -0
- package/dist/emitter-scan-kernels.js +174 -0
- package/dist/emitter-scan-kernels.js.map +1 -0
- package/dist/emitter-static-accessors.d.ts +4 -0
- package/dist/emitter-static-accessors.d.ts.map +1 -0
- package/dist/emitter-static-accessors.js +114 -0
- package/dist/emitter-static-accessors.js.map +1 -0
- package/dist/emitter-template.d.ts +7 -0
- package/dist/emitter-template.d.ts.map +1 -1
- package/dist/emitter-template.js +8 -3
- package/dist/emitter-template.js.map +1 -1
- package/dist/emitter-writers.d.ts +4 -0
- package/dist/emitter-writers.d.ts.map +1 -0
- package/dist/emitter-writers.js +246 -0
- package/dist/emitter-writers.js.map +1 -0
- package/dist/emitter.d.ts +9 -1
- package/dist/emitter.d.ts.map +1 -1
- package/dist/emitter.js +31 -660
- package/dist/emitter.js.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/layout-manifest.d.ts +37 -0
- package/dist/layout-manifest.d.ts.map +1 -0
- package/dist/layout-manifest.js +251 -0
- package/dist/layout-manifest.js.map +1 -0
- package/dist/lowering.d.ts +5 -2
- package/dist/lowering.d.ts.map +1 -1
- package/dist/lowering.js +86 -27
- package/dist/lowering.js.map +1 -1
- package/dist/source-map.d.ts +10 -0
- package/dist/source-map.d.ts.map +1 -0
- package/dist/source-map.js +371 -0
- package/dist/source-map.js.map +1 -0
- package/dist/validator.d.ts.map +1 -1
- package/dist/validator.js +34 -16
- package/dist/validator.js.map +1 -1
- package/package.json +5 -3
package/dist/emitter.js
CHANGED
|
@@ -1,10 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import {} from "@exornea/zeno-schema";
|
|
2
|
+
import { emitAstCheckedSource } from "./emitter-ast.js";
|
|
3
|
+
import { emitField } from "./emitter-fields.js";
|
|
4
|
+
import { emitInputInterface } from "./emitter-input.js";
|
|
5
|
+
import { toLittleEndianLiteral, toPascalCase } from "./emitter-names.js";
|
|
6
|
+
import { collectRuntimeImports } from "./emitter-runtime-imports.js";
|
|
7
|
+
import { emitScanRangeHelper, hasScanKernels, normalizeScanKernelMode, } from "./emitter-scan-kernels.js";
|
|
8
|
+
import { emitStaticFieldAccessor } from "./emitter-static-accessors.js";
|
|
3
9
|
import { method } from "./emitter-template.js";
|
|
10
|
+
import { emitDynamicWriterMethods, emitObjectWriterMethod } from "./emitter-writers.js";
|
|
11
|
+
import { createProjectionSourceMap } from "./source-map.js";
|
|
4
12
|
export function emitStructView(layout, options = {}) {
|
|
5
13
|
return emitProjectionFile([layout], options);
|
|
6
14
|
}
|
|
7
15
|
export function emitProjectionFile(layouts, options = {}) {
|
|
16
|
+
return emitAstCheckedSource(emitProjectionFileText(layouts, options), "zeno.view.ts").code;
|
|
17
|
+
}
|
|
18
|
+
function emitProjectionFileText(layouts, options = {}) {
|
|
8
19
|
const lines = [];
|
|
9
20
|
const runtimeImports = collectRuntimeImports(layouts);
|
|
10
21
|
const layoutMap = new Map(layouts.map((layout) => [layout.name, layout]));
|
|
@@ -20,109 +31,13 @@ export function emitProjectionFile(layouts, options = {}) {
|
|
|
20
31
|
}
|
|
21
32
|
return lines.join("\n");
|
|
22
33
|
}
|
|
23
|
-
function
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
for (const field of layout.fields) {
|
|
31
|
-
collectFieldRuntimeImports(field, imports);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
return Array.from(imports).sort();
|
|
35
|
-
}
|
|
36
|
-
function collectFieldRuntimeImports(field, imports) {
|
|
37
|
-
switch (field.kind) {
|
|
38
|
-
case "fixed-bytes":
|
|
39
|
-
imports.add("fixedBytesView");
|
|
40
|
-
imports.add("writeFixedBytes");
|
|
41
|
-
return;
|
|
42
|
-
case "fixed-string":
|
|
43
|
-
imports.add("decodeFixedText");
|
|
44
|
-
imports.add("fixedBytesView");
|
|
45
|
-
imports.add("writeFixedText");
|
|
46
|
-
return;
|
|
47
|
-
case "dynamic-string":
|
|
48
|
-
imports.add("Utf8SpanView");
|
|
49
|
-
return;
|
|
50
|
-
case "dynamic-bytes":
|
|
51
|
-
imports.add("BytesSpanView");
|
|
52
|
-
return;
|
|
53
|
-
case "vector":
|
|
54
|
-
switch (field.element.kind) {
|
|
55
|
-
case "scalar":
|
|
56
|
-
imports.add("ScalarVectorView");
|
|
57
|
-
return;
|
|
58
|
-
case "dynamic-string":
|
|
59
|
-
imports.add("Utf8VectorView");
|
|
60
|
-
return;
|
|
61
|
-
case "dynamic-bytes":
|
|
62
|
-
imports.add("BytesVectorView");
|
|
63
|
-
return;
|
|
64
|
-
case "fixed-bytes":
|
|
65
|
-
imports.add("FixedBytesVectorView");
|
|
66
|
-
return;
|
|
67
|
-
case "fixed-string":
|
|
68
|
-
imports.add("FixedStringVectorView");
|
|
69
|
-
return;
|
|
70
|
-
case "struct":
|
|
71
|
-
imports.add("StructVectorView");
|
|
72
|
-
return;
|
|
73
|
-
case "pointer":
|
|
74
|
-
imports.add("PointerVectorView");
|
|
75
|
-
return;
|
|
76
|
-
default:
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
case "fixed-array":
|
|
80
|
-
collectFixedArrayRuntimeImports(field.element, imports);
|
|
81
|
-
return;
|
|
82
|
-
default:
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
function emitInputInterface(layout) {
|
|
87
|
-
const lines = [`export interface ${layout.name}ViewInput {`];
|
|
88
|
-
for (const field of layout.fields) {
|
|
89
|
-
lines.push(` readonly ${field.name}: ${fieldInputType(field)};`);
|
|
90
|
-
}
|
|
91
|
-
lines.push("}");
|
|
92
|
-
return lines;
|
|
93
|
-
}
|
|
94
|
-
function fieldInputType(field) {
|
|
95
|
-
switch (field.kind) {
|
|
96
|
-
case "scalar":
|
|
97
|
-
return scalarTsType(field.scalar);
|
|
98
|
-
case "fixed-bytes":
|
|
99
|
-
case "dynamic-bytes":
|
|
100
|
-
return "ArrayLike<number> | Uint8Array";
|
|
101
|
-
case "fixed-string":
|
|
102
|
-
case "dynamic-string":
|
|
103
|
-
return "string";
|
|
104
|
-
case "struct":
|
|
105
|
-
return `${field.typeName}ViewInput`;
|
|
106
|
-
case "pointer":
|
|
107
|
-
return "number | null";
|
|
108
|
-
case "fixed-array":
|
|
109
|
-
return `readonly ${fixedArrayInputElementType(field.element)}[]`;
|
|
110
|
-
case "vector":
|
|
111
|
-
switch (field.element.kind) {
|
|
112
|
-
case "scalar":
|
|
113
|
-
return `readonly ${scalarTsType(field.element.scalar)}[]`;
|
|
114
|
-
case "fixed-bytes":
|
|
115
|
-
case "dynamic-bytes":
|
|
116
|
-
return "readonly (ArrayLike<number> | Uint8Array)[]";
|
|
117
|
-
case "fixed-string":
|
|
118
|
-
case "dynamic-string":
|
|
119
|
-
return "readonly string[]";
|
|
120
|
-
case "struct":
|
|
121
|
-
return `readonly ${field.element.typeName}ViewInput[]`;
|
|
122
|
-
case "pointer":
|
|
123
|
-
return "readonly (number | null)[]";
|
|
124
|
-
}
|
|
125
|
-
}
|
|
34
|
+
export function emitProjectionFileWithSourceMap(layouts, generatedFile, options = {}) {
|
|
35
|
+
const sourceMapUrl = `${generatedFile.split(/[\\/]/).pop() ?? generatedFile}.map`;
|
|
36
|
+
const code = `${emitAstCheckedSource(emitProjectionFileText(layouts, options), generatedFile).code}\n//# sourceMappingURL=${sourceMapUrl}\n`;
|
|
37
|
+
return {
|
|
38
|
+
code,
|
|
39
|
+
sourceMap: createProjectionSourceMap(code, layouts, generatedFile),
|
|
40
|
+
};
|
|
126
41
|
}
|
|
127
42
|
function emitLayoutConstants(layout) {
|
|
128
43
|
const lines = [];
|
|
@@ -134,8 +49,8 @@ function emitLayoutConstants(layout) {
|
|
|
134
49
|
return lines;
|
|
135
50
|
}
|
|
136
51
|
function emitStructClass(layout, options, layoutMap) {
|
|
137
|
-
const scalarFields = layout.fields.filter((field) => field.kind === "scalar");
|
|
138
52
|
const littleEndianDefault = toLittleEndianLiteral(layout);
|
|
53
|
+
const scanKernelMode = normalizeScanKernelMode(options.scanKernels);
|
|
139
54
|
const lines = [`export class ${layout.name}View extends ProjectionView {`];
|
|
140
55
|
lines.push(...method `
|
|
141
56
|
static readonly byteLength = ${layout.byteLength};
|
|
@@ -162,585 +77,41 @@ private static assertPointerTargetRange(view: DataView, targetOffset: number, by
|
|
|
162
77
|
}
|
|
163
78
|
}`);
|
|
164
79
|
}
|
|
165
|
-
if (
|
|
80
|
+
if (hasScanKernels(layout, scanKernelMode)) {
|
|
166
81
|
lines.push("");
|
|
167
|
-
lines.push(...
|
|
82
|
+
lines.push(...emitScanRangeHelper(layout));
|
|
168
83
|
}
|
|
169
84
|
lines.push("");
|
|
170
|
-
|
|
171
|
-
lines.push(...method `
|
|
172
|
-
constructor(view: DataView, baseOffset = 0, littleEndian = ${littleEndianDefault}) {
|
|
173
|
-
super(view, baseOffset, littleEndian);
|
|
174
|
-
this.$refreshOffsets();
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
private $refreshOffsets(): void {
|
|
178
|
-
${scalarFields.map((field) => ` this.$${field.name}Offset = this.baseOffset + ${field.offset};`)}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
override rebase(baseOffset: number): this {
|
|
182
|
-
super.rebase(baseOffset);
|
|
183
|
-
this.$refreshOffsets();
|
|
184
|
-
return this;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
override rebaseUnchecked(baseOffset: number): this {
|
|
188
|
-
super.rebaseUnchecked(baseOffset);
|
|
189
|
-
this.$refreshOffsets();
|
|
190
|
-
return this;
|
|
191
|
-
}`);
|
|
192
|
-
}
|
|
193
|
-
else {
|
|
194
|
-
lines.push(...method `
|
|
85
|
+
lines.push(...method `
|
|
195
86
|
constructor(view: DataView, baseOffset = 0, littleEndian = ${littleEndianDefault}) {
|
|
196
87
|
super(view, baseOffset, littleEndian);
|
|
197
88
|
}`);
|
|
198
|
-
}
|
|
199
89
|
lines.push("");
|
|
200
90
|
lines.push(...method `
|
|
201
91
|
static at(view: DataView, baseOffset = 0, littleEndian = ${littleEndianDefault}): ${layout.name}View {
|
|
202
92
|
return new ${layout.name}View(view, baseOffset, littleEndian);
|
|
203
93
|
}`);
|
|
204
94
|
lines.push("");
|
|
205
|
-
|
|
206
|
-
lines.push(...method `
|
|
207
|
-
moveTo(index: number): this {
|
|
208
|
-
this.moveToIndex(index, ${layout.name}View.byteLength);
|
|
209
|
-
this.$refreshOffsets();
|
|
210
|
-
return this;
|
|
211
|
-
}`);
|
|
212
|
-
}
|
|
213
|
-
else {
|
|
214
|
-
lines.push(...method `
|
|
95
|
+
lines.push(...method `
|
|
215
96
|
moveTo(index: number): this {
|
|
216
97
|
return this.moveToIndex(index, ${layout.name}View.byteLength);
|
|
217
98
|
}`);
|
|
218
|
-
}
|
|
219
99
|
lines.push("");
|
|
220
100
|
lines.push(...method `
|
|
221
101
|
moveToUnchecked(index: number): this {
|
|
222
102
|
return this.rebaseUnchecked(index * ${layout.byteLength});
|
|
223
103
|
}`);
|
|
224
104
|
lines.push("");
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
lines.push(line);
|
|
228
|
-
}
|
|
229
|
-
if (writerLines.length > 0) {
|
|
230
|
-
lines.push("");
|
|
231
|
-
}
|
|
232
|
-
const objectWriterLines = emitObjectWriterMethod(layout, layoutMap);
|
|
233
|
-
for (const line of objectWriterLines) {
|
|
234
|
-
lines.push(line);
|
|
235
|
-
}
|
|
236
|
-
if (objectWriterLines.length > 0) {
|
|
237
|
-
lines.push("");
|
|
238
|
-
}
|
|
105
|
+
lines.push(...emitLayerBlock(emitDynamicWriterMethods(layout, layoutMap)));
|
|
106
|
+
lines.push(...emitLayerBlock(emitObjectWriterMethod(layout, layoutMap)));
|
|
239
107
|
for (const field of layout.fields) {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
lines.push(line);
|
|
243
|
-
}
|
|
244
|
-
if (staticAccessorLines.length > 0) {
|
|
245
|
-
lines.push("");
|
|
246
|
-
}
|
|
247
|
-
for (const line of emitField(layout, field, options)) {
|
|
248
|
-
lines.push(line);
|
|
249
|
-
}
|
|
250
|
-
lines.push("");
|
|
108
|
+
lines.push(...emitLayerBlock(emitStaticFieldAccessor(layout, field, scanKernelMode)));
|
|
109
|
+
lines.push(...emitLayerBlock(emitField(layout, field)));
|
|
251
110
|
}
|
|
252
111
|
lines.push("}");
|
|
253
112
|
return lines;
|
|
254
113
|
}
|
|
255
|
-
function
|
|
256
|
-
|
|
257
|
-
if (fields.length === 0) {
|
|
258
|
-
return [];
|
|
259
|
-
}
|
|
260
|
-
const lines = [
|
|
261
|
-
...method `
|
|
262
|
-
static createWriter(view: DataView, baseOffset = 0, tailOffset = ${layout.name}View.byteLength, littleEndian = ${toLittleEndianLiteral(layout)}): DynamicLayoutWriter {
|
|
263
|
-
return new DynamicLayoutWriter(view, tailOffset, baseOffset, littleEndian);
|
|
264
|
-
}`,
|
|
265
|
-
"",
|
|
266
|
-
];
|
|
267
|
-
for (const field of fields) {
|
|
268
|
-
const pascalName = toPascalCase(field.name);
|
|
269
|
-
switch (field.kind) {
|
|
270
|
-
case "dynamic-string":
|
|
271
|
-
lines.push(...method `
|
|
272
|
-
static write${pascalName}(writer: DynamicLayoutWriter, value: string) {
|
|
273
|
-
return writer.writeText(${layout.name}View.${field.name}Offset, value, ${encodingLiteral(field.encoding)});
|
|
274
|
-
}`);
|
|
275
|
-
break;
|
|
276
|
-
case "dynamic-bytes":
|
|
277
|
-
lines.push(...method `
|
|
278
|
-
static write${pascalName}(writer: DynamicLayoutWriter, value: ArrayLike<number> | Uint8Array) {
|
|
279
|
-
return writer.writeBytes(${layout.name}View.${field.name}Offset, value);
|
|
280
|
-
}`);
|
|
281
|
-
break;
|
|
282
|
-
case "vector":
|
|
283
|
-
lines.push(...emitVectorWriterMethod(layout, layoutMap, field, pascalName));
|
|
284
|
-
break;
|
|
285
|
-
}
|
|
286
|
-
lines.push("");
|
|
287
|
-
}
|
|
288
|
-
lines.pop();
|
|
289
|
-
return lines;
|
|
290
|
-
}
|
|
291
|
-
const vectorWriterEmitters = {
|
|
292
|
-
"dynamic-string": ({ layout, field, pascalName }) => method `
|
|
293
|
-
static write${pascalName}(writer: DynamicLayoutWriter, values: readonly string[]) {
|
|
294
|
-
return writer.writeTextVector(${layout.name}View.${field.name}Offset, values, ${encodingLiteral(field.element.encoding)});
|
|
295
|
-
}`,
|
|
296
|
-
"dynamic-bytes": ({ layout, field, pascalName }) => method `
|
|
297
|
-
static write${pascalName}(writer: DynamicLayoutWriter, values: readonly (ArrayLike<number> | Uint8Array)[]) {
|
|
298
|
-
return writer.writeBytesVector(${layout.name}View.${field.name}Offset, values);
|
|
299
|
-
}`,
|
|
300
|
-
"fixed-bytes": ({ layout, field, pascalName }) => method `
|
|
301
|
-
static write${pascalName}(writer: DynamicLayoutWriter, values: readonly (ArrayLike<number> | Uint8Array)[]) {
|
|
302
|
-
return writer.writeFixedBytesVector(${layout.name}View.${field.name}Offset, values, ${field.element.byteLength});
|
|
303
|
-
}`,
|
|
304
|
-
"fixed-string": ({ layout, field, pascalName }) => method `
|
|
305
|
-
static write${pascalName}(writer: DynamicLayoutWriter, values: readonly string[]) {
|
|
306
|
-
return writer.writeFixedTextVector(${layout.name}View.${field.name}Offset, values, ${field.element.byteLength}, ${encodingLiteral(field.element.encoding)});
|
|
307
|
-
}`,
|
|
308
|
-
scalar: ({ layout, field, pascalName }) => method `
|
|
309
|
-
static write${pascalName}(writer: DynamicLayoutWriter, values: readonly ${scalarTsType(field.element.scalar)}[]) {
|
|
310
|
-
return writer.writeScalarVector(${layout.name}View.${field.name}Offset, "${field.element.scalar}", values);
|
|
311
|
-
}`,
|
|
312
|
-
struct: ({ layout, layoutMap, field, pascalName }) => {
|
|
313
|
-
const elementLayout = layoutMap.get(field.element.typeName);
|
|
314
|
-
const alignment = elementLayout?.alignment ?? 1;
|
|
315
|
-
return method `
|
|
316
|
-
static write${pascalName}(writer: DynamicLayoutWriter, values: readonly ${field.element.typeName}ViewInput[]) {
|
|
317
|
-
return writer.writeStructVector(${layout.name}View.${field.name}Offset, values, ${field.element.byteLength}, (view, value, baseOffset, littleEndian) => ${field.element.typeName}View.write(view, value, baseOffset, littleEndian), ${alignment});
|
|
318
|
-
}`;
|
|
319
|
-
},
|
|
320
|
-
pointer: ({ layout, field, pascalName }) => method `
|
|
321
|
-
static write${pascalName}(writer: DynamicLayoutWriter, values: readonly (number | null)[]) {
|
|
322
|
-
return writer.writePointerVector(${layout.name}View.${field.name}Offset, values, ${field.element.targetTypeName}View.byteLength);
|
|
323
|
-
}`,
|
|
324
|
-
};
|
|
325
|
-
function emitVectorWriterMethod(layout, layoutMap, field, pascalName) {
|
|
326
|
-
const emitWriter = vectorWriterEmitters[field.element.kind];
|
|
327
|
-
return emitWriter({ layout, layoutMap, field, pascalName });
|
|
328
|
-
}
|
|
329
|
-
function emitObjectWriterMethod(layout, layoutMap) {
|
|
330
|
-
if (!canEmitObjectWriter(layout, layoutMap)) {
|
|
331
|
-
return [];
|
|
332
|
-
}
|
|
333
|
-
const hasTailFields = hasTailWriterFields(layout, layoutMap);
|
|
334
|
-
const returnType = hasTailFields ? "DynamicLayoutWriter" : "void";
|
|
335
|
-
const bodyLines = [];
|
|
336
|
-
if (hasTailFields) {
|
|
337
|
-
bodyLines.push(` const writer = ${layout.name}View.createWriter(view, baseOffset, ${layout.name}View.byteLength, littleEndian);`);
|
|
338
|
-
}
|
|
339
|
-
for (const field of layout.fields) {
|
|
340
|
-
bodyLines.push(...emitObjectFieldWrite(layout, field));
|
|
341
|
-
}
|
|
342
|
-
if (hasTailFields) {
|
|
343
|
-
bodyLines.push(" return writer;");
|
|
344
|
-
}
|
|
345
|
-
return method `
|
|
346
|
-
static write(view: DataView, value: ${layout.name}ViewInput, baseOffset = 0, littleEndian = ${toLittleEndianLiteral(layout)}): ${returnType} {
|
|
347
|
-
${bodyLines}
|
|
348
|
-
}`;
|
|
349
|
-
}
|
|
350
|
-
function emitObjectFieldWrite(layout, field) {
|
|
351
|
-
const pascalName = toPascalCase(field.name);
|
|
352
|
-
switch (field.kind) {
|
|
353
|
-
case "scalar":
|
|
354
|
-
return [
|
|
355
|
-
` ${layout.name}View.set${pascalName}(view, value.${field.name}, baseOffset, littleEndian);`,
|
|
356
|
-
];
|
|
357
|
-
case "fixed-bytes":
|
|
358
|
-
return [
|
|
359
|
-
` writeFixedBytes(view.buffer, view.byteOffset + baseOffset + ${field.offset}, ${field.byteLength}, value.${field.name});`,
|
|
360
|
-
];
|
|
361
|
-
case "fixed-string":
|
|
362
|
-
return [
|
|
363
|
-
` writeFixedText(view.buffer, view.byteOffset + baseOffset + ${field.offset}, ${field.byteLength}, value.${field.name}, ${encodingLiteral(field.encoding)});`,
|
|
364
|
-
];
|
|
365
|
-
case "dynamic-string":
|
|
366
|
-
case "dynamic-bytes":
|
|
367
|
-
return [` ${layout.name}View.write${pascalName}(writer, value.${field.name});`];
|
|
368
|
-
case "struct":
|
|
369
|
-
return [
|
|
370
|
-
` ${field.typeName}View.write(view, value.${field.name}, baseOffset + ${field.offset}, littleEndian);`,
|
|
371
|
-
];
|
|
372
|
-
case "pointer":
|
|
373
|
-
return [
|
|
374
|
-
` ${layout.name}View.set${pascalName}TargetOffset(view, value.${field.name}, baseOffset, littleEndian);`,
|
|
375
|
-
];
|
|
376
|
-
case "fixed-array":
|
|
377
|
-
return emitFixedArrayObjectFieldWrite(field, encodingLiteral);
|
|
378
|
-
case "vector":
|
|
379
|
-
return [` ${layout.name}View.write${pascalName}(writer, value.${field.name});`];
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
function emitStaticFieldAccessor(layout, field) {
|
|
383
|
-
if (field.kind === "pointer") {
|
|
384
|
-
const pascalName = toPascalCase(field.name);
|
|
385
|
-
const littleEndianDefault = toLittleEndianLiteral(layout);
|
|
386
|
-
const indexOffset = `index * ${layout.byteLength} + ${field.offset}`;
|
|
387
|
-
const pointerPosition = `baseOffset + ${field.offset}`;
|
|
388
|
-
return method `
|
|
389
|
-
static getRaw${pascalName}RelativeOffset(view: DataView, baseOffset = 0, littleEndian = ${littleEndianDefault}): number {
|
|
390
|
-
return view.getUint32(baseOffset + ${field.offset}, littleEndian);
|
|
391
|
-
}
|
|
392
|
-
static get${pascalName}RelativeOffset(view: DataView, baseOffset = 0, littleEndian = ${littleEndianDefault}): number | null {
|
|
393
|
-
const rawValue = ${layout.name}View.getRaw${pascalName}RelativeOffset(view, baseOffset, littleEndian);
|
|
394
|
-
if (rawValue === 0xffffffff) {
|
|
395
|
-
return null;
|
|
396
|
-
}
|
|
397
|
-
return view.getInt32(baseOffset + ${field.offset}, littleEndian);
|
|
398
|
-
}
|
|
399
|
-
static set${pascalName}RelativeOffset(view: DataView, value: number | null, baseOffset = 0, littleEndian = ${littleEndianDefault}): void {
|
|
400
|
-
if (value === null) {
|
|
401
|
-
view.setUint32(baseOffset + ${field.offset}, 0xffffffff, littleEndian);
|
|
402
|
-
return;
|
|
403
|
-
}
|
|
404
|
-
${layout.name}View.assertPointer32Payload(value);
|
|
405
|
-
view.setInt32(baseOffset + ${field.offset}, value, littleEndian);
|
|
406
|
-
}
|
|
407
|
-
static getUnchecked${pascalName}TargetOffset(view: DataView, baseOffset = 0, littleEndian = ${littleEndianDefault}): number | null {
|
|
408
|
-
const relativeOffset = ${layout.name}View.get${pascalName}RelativeOffset(view, baseOffset, littleEndian);
|
|
409
|
-
if (relativeOffset === null) {
|
|
410
|
-
return null;
|
|
411
|
-
}
|
|
412
|
-
return ${pointerPosition} + relativeOffset;
|
|
413
|
-
}
|
|
414
|
-
static get${pascalName}TargetOffset(view: DataView, baseOffset = 0, littleEndian = ${littleEndianDefault}): number | null {
|
|
415
|
-
const targetOffset = ${layout.name}View.getUnchecked${pascalName}TargetOffset(view, baseOffset, littleEndian);
|
|
416
|
-
if (targetOffset === null) {
|
|
417
|
-
return null;
|
|
418
|
-
}
|
|
419
|
-
${layout.name}View.assertPointerTargetRange(view, targetOffset, ${field.targetTypeName}View.byteLength);
|
|
420
|
-
return targetOffset;
|
|
421
|
-
}
|
|
422
|
-
static setUnchecked${pascalName}TargetOffset(view: DataView, targetOffset: number | null, baseOffset = 0, littleEndian = ${littleEndianDefault}): void {
|
|
423
|
-
if (targetOffset === null) {
|
|
424
|
-
${layout.name}View.set${pascalName}RelativeOffset(view, null, baseOffset, littleEndian);
|
|
425
|
-
return;
|
|
426
|
-
}
|
|
427
|
-
const relativeOffset = targetOffset - (${pointerPosition});
|
|
428
|
-
${layout.name}View.set${pascalName}RelativeOffset(view, relativeOffset, baseOffset, littleEndian);
|
|
429
|
-
}
|
|
430
|
-
static set${pascalName}TargetOffset(view: DataView, targetOffset: number | null, baseOffset = 0, littleEndian = ${littleEndianDefault}): void {
|
|
431
|
-
if (targetOffset !== null) {
|
|
432
|
-
${layout.name}View.assertPointerTargetRange(view, targetOffset, ${field.targetTypeName}View.byteLength);
|
|
433
|
-
}
|
|
434
|
-
${layout.name}View.setUnchecked${pascalName}TargetOffset(view, targetOffset, baseOffset, littleEndian);
|
|
435
|
-
}
|
|
436
|
-
static get${pascalName}RelativeOffsetAt(view: DataView, index: number, littleEndian = ${littleEndianDefault}): number | null {
|
|
437
|
-
const rawValue = ${layout.name}View.getRaw${pascalName}RelativeOffset(view, index * ${layout.byteLength}, littleEndian);
|
|
438
|
-
if (rawValue === 0xffffffff) {
|
|
439
|
-
return null;
|
|
440
|
-
}
|
|
441
|
-
return view.getInt32(${indexOffset}, littleEndian);
|
|
442
|
-
}
|
|
443
|
-
static set${pascalName}RelativeOffsetAt(view: DataView, value: number | null, index: number, littleEndian = ${littleEndianDefault}): void {
|
|
444
|
-
if (value === null) {
|
|
445
|
-
view.setUint32(${indexOffset}, 0xffffffff, littleEndian);
|
|
446
|
-
return;
|
|
447
|
-
}
|
|
448
|
-
${layout.name}View.assertPointer32Payload(value);
|
|
449
|
-
view.setInt32(${indexOffset}, value, littleEndian);
|
|
450
|
-
}`;
|
|
451
|
-
}
|
|
452
|
-
if (field.kind !== "scalar") {
|
|
453
|
-
return [];
|
|
454
|
-
}
|
|
455
|
-
const getterMethod = scalarGetterMethod(field.scalar);
|
|
456
|
-
const setterMethod = scalarSetterMethod(field.scalar);
|
|
457
|
-
const typeName = scalarTsType(field.scalar);
|
|
458
|
-
const littleEndianDefault = toLittleEndianLiteral(layout);
|
|
459
|
-
const endianArg = field.byteLength === 1 || field.scalar === "bool" ? "" : ", littleEndian";
|
|
460
|
-
const getterBody = field.scalar === "bool"
|
|
461
|
-
? ` return view.${getterMethod}(baseOffset + ${field.offset}) !== 0;`
|
|
462
|
-
: ` return view.${getterMethod}(baseOffset + ${field.offset}${endianArg});`;
|
|
463
|
-
const setterBody = field.scalar === "bool"
|
|
464
|
-
? ` view.${setterMethod}(baseOffset + ${field.offset}, value ? 1 : 0);`
|
|
465
|
-
: ` view.${setterMethod}(baseOffset + ${field.offset}, value${endianArg});`;
|
|
466
|
-
const indexOffset = `index * ${layout.byteLength} + ${field.offset}`;
|
|
467
|
-
const indexGetterBody = field.scalar === "bool"
|
|
468
|
-
? ` return view.${getterMethod}(${indexOffset}) !== 0;`
|
|
469
|
-
: ` return view.${getterMethod}(${indexOffset}${endianArg});`;
|
|
470
|
-
const indexSetterBody = field.scalar === "bool"
|
|
471
|
-
? ` view.${setterMethod}(${indexOffset}, value ? 1 : 0);`
|
|
472
|
-
: ` view.${setterMethod}(${indexOffset}, value${endianArg});`;
|
|
473
|
-
const pascalName = toPascalCase(field.name);
|
|
474
|
-
return [
|
|
475
|
-
` static get${pascalName}(view: DataView, baseOffset = 0, littleEndian = ${littleEndianDefault}): ${typeName} {`,
|
|
476
|
-
getterBody,
|
|
477
|
-
" }",
|
|
478
|
-
` static set${pascalName}(view: DataView, value: ${typeName}, baseOffset = 0, littleEndian = ${littleEndianDefault}): void {`,
|
|
479
|
-
setterBody,
|
|
480
|
-
" }",
|
|
481
|
-
` static get${pascalName}At(view: DataView, index: number, littleEndian = ${littleEndianDefault}): ${typeName} {`,
|
|
482
|
-
indexGetterBody,
|
|
483
|
-
" }",
|
|
484
|
-
` static set${pascalName}At(view: DataView, value: ${typeName}, index: number, littleEndian = ${littleEndianDefault}): void {`,
|
|
485
|
-
indexSetterBody,
|
|
486
|
-
" }",
|
|
487
|
-
...emitScalarSumKernel(layout, field, getterMethod, littleEndianDefault, pascalName),
|
|
488
|
-
];
|
|
489
|
-
}
|
|
490
|
-
function emitScalarSumKernel(layout, field, getterMethod, littleEndianDefault, pascalName) {
|
|
491
|
-
if (!isNumberSumScalar(field.scalar)) {
|
|
492
|
-
return [];
|
|
493
|
-
}
|
|
494
|
-
const endianArg = field.byteLength === 1 ? "" : ", littleEndian";
|
|
495
|
-
return method `
|
|
496
|
-
static sum${pascalName}(view: DataView, count: number, baseOffset = 0, littleEndian = ${littleEndianDefault}): number {
|
|
497
|
-
if (!Number.isInteger(count) || count < 0) {
|
|
498
|
-
throw new RangeError(\`Invalid record count: \${count}\`);
|
|
499
|
-
}
|
|
500
|
-
if (!Number.isFinite(baseOffset) || !Number.isInteger(baseOffset) || baseOffset < 0) {
|
|
501
|
-
throw new RangeError(\`Invalid base offset: \${baseOffset}\`);
|
|
502
|
-
}
|
|
503
|
-
if (count === 0) {
|
|
504
|
-
return 0;
|
|
505
|
-
}
|
|
506
|
-
const start = baseOffset + ${field.offset};
|
|
507
|
-
const limit = start + count * ${layout.byteLength};
|
|
508
|
-
const lastByte = start + (count - 1) * ${layout.byteLength} + ${field.byteLength};
|
|
509
|
-
if (lastByte > view.byteLength) {
|
|
510
|
-
throw new RangeError(\`scan range exceeds DataView length \${view.byteLength}\`);
|
|
511
|
-
}
|
|
512
|
-
let sum = 0;
|
|
513
|
-
for (let offset = start; offset < limit; offset += ${layout.byteLength}) {
|
|
514
|
-
sum += view.${getterMethod}(offset${endianArg});
|
|
515
|
-
}
|
|
516
|
-
return sum;
|
|
517
|
-
}`;
|
|
518
|
-
}
|
|
519
|
-
function isNumberSumScalar(kind) {
|
|
520
|
-
return kind !== "i64" && kind !== "u64" && kind !== "bool";
|
|
521
|
-
}
|
|
522
|
-
function emitField(layout, field, options) {
|
|
523
|
-
switch (field.kind) {
|
|
524
|
-
case "scalar": {
|
|
525
|
-
const getterMethod = scalarGetterMethod(field.scalar);
|
|
526
|
-
const setterMethod = scalarSetterMethod(field.scalar);
|
|
527
|
-
const typeName = scalarTsType(field.scalar);
|
|
528
|
-
const getterArgs = field.byteLength === 1 || field.scalar === "bool" ? "" : ", this.littleEndian";
|
|
529
|
-
const instanceOffset = options.optimizeCursorOffsets
|
|
530
|
-
? `this.$${field.name}Offset`
|
|
531
|
-
: `this.baseOffset + ${field.offset}`;
|
|
532
|
-
const getterBody = field.scalar === "bool"
|
|
533
|
-
? `return this.view.${getterMethod}(${instanceOffset}) !== 0;`
|
|
534
|
-
: `return this.view.${getterMethod}(${instanceOffset}${getterArgs});`;
|
|
535
|
-
const setterBody = field.scalar === "bool"
|
|
536
|
-
? `this.view.${setterMethod}(${instanceOffset}, value ? 1 : 0);`
|
|
537
|
-
: `this.view.${setterMethod}(${instanceOffset}, value${getterArgs});`;
|
|
538
|
-
return method `
|
|
539
|
-
get ${field.name}(): ${typeName} {
|
|
540
|
-
${getterBody}
|
|
541
|
-
}
|
|
542
|
-
set ${field.name}(value: ${typeName}) {
|
|
543
|
-
${setterBody}
|
|
544
|
-
}`;
|
|
545
|
-
}
|
|
546
|
-
case "fixed-bytes":
|
|
547
|
-
return method `
|
|
548
|
-
${field.name}Bytes(): Uint8Array {
|
|
549
|
-
return fixedBytesView(this.backingBuffer(), this.backingOffset(${field.offset}), ${field.byteLength});
|
|
550
|
-
}`;
|
|
551
|
-
case "fixed-string":
|
|
552
|
-
return method `
|
|
553
|
-
${field.name}Text(): string {
|
|
554
|
-
return decodeFixedText(this.backingBuffer(), this.backingOffset(${field.offset}), ${field.byteLength}, ${encodingLiteral(field.encoding)});
|
|
555
|
-
}
|
|
556
|
-
${field.name}Bytes(): Uint8Array {
|
|
557
|
-
return fixedBytesView(this.backingBuffer(), this.backingOffset(${field.offset}), ${field.byteLength});
|
|
558
|
-
}`;
|
|
559
|
-
case "dynamic-string":
|
|
560
|
-
return method `
|
|
561
|
-
${field.name}View(): Utf8SpanView {
|
|
562
|
-
return new Utf8SpanView(this.view, ${field.offset}, this.baseOffset, this.littleEndian, ${encodingLiteral(field.encoding)});
|
|
563
|
-
}`;
|
|
564
|
-
case "dynamic-bytes":
|
|
565
|
-
return method `
|
|
566
|
-
${field.name}View(): BytesSpanView {
|
|
567
|
-
return new BytesSpanView(this.view, ${field.offset}, this.baseOffset, this.littleEndian);
|
|
568
|
-
}
|
|
569
|
-
${field.name}Bytes(): Uint8Array {
|
|
570
|
-
return this.${field.name}View().bytes();
|
|
571
|
-
}`;
|
|
572
|
-
case "struct":
|
|
573
|
-
return method `
|
|
574
|
-
${field.name}View(): ${field.typeName}View {
|
|
575
|
-
return new ${field.typeName}View(this.view, this.absoluteOffset(${field.offset}), this.littleEndian);
|
|
576
|
-
}`;
|
|
577
|
-
case "pointer": {
|
|
578
|
-
const pascalName = toPascalCase(field.name);
|
|
579
|
-
return method `
|
|
580
|
-
get raw${pascalName}RelativeOffset(): number {
|
|
581
|
-
return this.view.getUint32(this.baseOffset + ${field.offset}, this.littleEndian);
|
|
582
|
-
}
|
|
583
|
-
get ${field.name}RelativeOffset(): number | null {
|
|
584
|
-
const rawValue = this.raw${pascalName}RelativeOffset;
|
|
585
|
-
if (rawValue === 0xffffffff) {
|
|
586
|
-
return null;
|
|
587
|
-
}
|
|
588
|
-
return this.view.getInt32(this.baseOffset + ${field.offset}, this.littleEndian);
|
|
589
|
-
}
|
|
590
|
-
set ${field.name}RelativeOffset(value: number | null) {
|
|
591
|
-
if (value === null) {
|
|
592
|
-
this.view.setUint32(this.baseOffset + ${field.offset}, 0xffffffff, this.littleEndian);
|
|
593
|
-
return;
|
|
594
|
-
}
|
|
595
|
-
if (!Number.isInteger(value) || value < -0x80000000 || value > 0x7fffffff || value === -1) {
|
|
596
|
-
throw new RangeError(\`pointer32 target offset must encode to signed i32 except -1: \${value}\`);
|
|
597
|
-
}
|
|
598
|
-
this.view.setInt32(this.baseOffset + ${field.offset}, value, this.littleEndian);
|
|
599
|
-
}
|
|
600
|
-
get unchecked${pascalName}TargetOffset(): number | null {
|
|
601
|
-
const relativeOffset = this.${field.name}RelativeOffset;
|
|
602
|
-
if (relativeOffset === null) {
|
|
603
|
-
return null;
|
|
604
|
-
}
|
|
605
|
-
return this.baseOffset + ${field.offset} + relativeOffset;
|
|
606
|
-
}
|
|
607
|
-
get ${field.name}TargetOffset(): number | null {
|
|
608
|
-
const targetOffset = this.unchecked${pascalName}TargetOffset;
|
|
609
|
-
if (targetOffset === null) {
|
|
610
|
-
return null;
|
|
611
|
-
}
|
|
612
|
-
${layout.name}View.assertPointerTargetRange(this.view, targetOffset, ${field.targetTypeName}View.byteLength);
|
|
613
|
-
return targetOffset;
|
|
614
|
-
}
|
|
615
|
-
set unchecked${pascalName}TargetOffset(targetOffset: number | null) {
|
|
616
|
-
if (targetOffset === null) {
|
|
617
|
-
this.${field.name}RelativeOffset = null;
|
|
618
|
-
return;
|
|
619
|
-
}
|
|
620
|
-
const relativeOffset = targetOffset - (this.baseOffset + ${field.offset});
|
|
621
|
-
this.${field.name}RelativeOffset = relativeOffset;
|
|
622
|
-
}
|
|
623
|
-
set ${field.name}TargetOffset(targetOffset: number | null) {
|
|
624
|
-
if (targetOffset !== null) {
|
|
625
|
-
${layout.name}View.assertPointerTargetRange(this.view, targetOffset, ${field.targetTypeName}View.byteLength);
|
|
626
|
-
}
|
|
627
|
-
this.unchecked${pascalName}TargetOffset = targetOffset;
|
|
628
|
-
}
|
|
629
|
-
${field.name}View(): ${field.targetTypeName}View | null {
|
|
630
|
-
const targetOffset = this.${field.name}TargetOffset;
|
|
631
|
-
if (targetOffset === null) {
|
|
632
|
-
return null;
|
|
633
|
-
}
|
|
634
|
-
const target = new ${field.targetTypeName}View(this.view, 0, this.littleEndian);
|
|
635
|
-
target.moveToOffset(targetOffset, ${field.targetTypeName}View.byteLength);
|
|
636
|
-
return target;
|
|
637
|
-
}
|
|
638
|
-
${field.name}Into(out: ${field.targetTypeName}View): boolean {
|
|
639
|
-
const targetOffset = this.${field.name}TargetOffset;
|
|
640
|
-
if (targetOffset === null) {
|
|
641
|
-
return false;
|
|
642
|
-
}
|
|
643
|
-
out.moveToOffset(targetOffset, ${field.targetTypeName}View.byteLength);
|
|
644
|
-
return true;
|
|
645
|
-
}`;
|
|
646
|
-
}
|
|
647
|
-
case "fixed-array":
|
|
648
|
-
return emitFixedArrayFieldAccessor(field, encodingLiteral);
|
|
649
|
-
case "vector":
|
|
650
|
-
switch (field.element.kind) {
|
|
651
|
-
case "scalar":
|
|
652
|
-
return method `
|
|
653
|
-
${field.name}View(): ScalarVectorView<${scalarTsType(field.element.scalar)}> {
|
|
654
|
-
return new ScalarVectorView(this.view, ${field.offset}, "${field.element.scalar}", this.baseOffset, this.littleEndian);
|
|
655
|
-
}`;
|
|
656
|
-
case "dynamic-string":
|
|
657
|
-
return method `
|
|
658
|
-
${field.name}View(): Utf8VectorView {
|
|
659
|
-
return new Utf8VectorView(this.view, ${field.offset}, this.baseOffset, this.littleEndian, ${encodingLiteral(field.element.encoding)});
|
|
660
|
-
}`;
|
|
661
|
-
case "dynamic-bytes":
|
|
662
|
-
return method `
|
|
663
|
-
${field.name}View(): BytesVectorView {
|
|
664
|
-
return new BytesVectorView(this.view, ${field.offset}, this.baseOffset, this.littleEndian);
|
|
665
|
-
}`;
|
|
666
|
-
case "fixed-bytes":
|
|
667
|
-
return method `
|
|
668
|
-
${field.name}View(): FixedBytesVectorView {
|
|
669
|
-
return new FixedBytesVectorView(this.view, ${field.offset}, ${field.element.byteLength}, this.baseOffset, this.littleEndian);
|
|
670
|
-
}`;
|
|
671
|
-
case "fixed-string":
|
|
672
|
-
return method `
|
|
673
|
-
${field.name}View(): FixedStringVectorView {
|
|
674
|
-
return new FixedStringVectorView(this.view, ${field.offset}, ${field.element.byteLength}, this.baseOffset, this.littleEndian, ${encodingLiteral(field.element.encoding)});
|
|
675
|
-
}`;
|
|
676
|
-
case "struct":
|
|
677
|
-
return method `
|
|
678
|
-
${field.name}View(): StructVectorView<${field.element.typeName}View> {
|
|
679
|
-
return new StructVectorView(this.view, ${field.offset}, ${field.element.byteLength}, (view, baseOffset, littleEndian) => new ${field.element.typeName}View(view, baseOffset, littleEndian), this.baseOffset, this.littleEndian);
|
|
680
|
-
}`;
|
|
681
|
-
case "pointer":
|
|
682
|
-
return method `
|
|
683
|
-
${field.name}View(): PointerVectorView<${field.element.targetTypeName}View> {
|
|
684
|
-
return new PointerVectorView(this.view, ${field.offset}, ${field.element.targetTypeName}View.byteLength, (view, baseOffset, littleEndian) => new ${field.element.targetTypeName}View(view, baseOffset, littleEndian), this.baseOffset, this.littleEndian);
|
|
685
|
-
}`;
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
function toPascalCase(name) {
|
|
690
|
-
return name.slice(0, 1).toUpperCase() + name.slice(1);
|
|
691
|
-
}
|
|
692
|
-
function toLittleEndianLiteral(layout) {
|
|
693
|
-
return layout.endianness === "little" ? "true" : "false";
|
|
694
|
-
}
|
|
695
|
-
function encodingLiteral(encoding) {
|
|
696
|
-
return encoding === "ascii" ? "\"ascii\"" : "\"utf8\"";
|
|
697
|
-
}
|
|
698
|
-
function hasTailWriterFields(layout, layoutMap) {
|
|
699
|
-
return layout.fields.some((field) => isTailWriterField(field, layoutMap));
|
|
700
|
-
}
|
|
701
|
-
function isTailWriterField(field, layoutMap) {
|
|
702
|
-
switch (field.kind) {
|
|
703
|
-
case "dynamic-string":
|
|
704
|
-
case "dynamic-bytes":
|
|
705
|
-
return true;
|
|
706
|
-
case "vector":
|
|
707
|
-
return (field.element.kind === "scalar" ||
|
|
708
|
-
field.element.kind === "fixed-bytes" ||
|
|
709
|
-
field.element.kind === "fixed-string" ||
|
|
710
|
-
field.element.kind === "dynamic-string" ||
|
|
711
|
-
field.element.kind === "dynamic-bytes" ||
|
|
712
|
-
field.element.kind === "pointer" ||
|
|
713
|
-
canWriteStructVectorElement(field.element, layoutMap));
|
|
714
|
-
default:
|
|
715
|
-
return false;
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
function canEmitObjectWriter(layout, layoutMap) {
|
|
719
|
-
return layout.fields.every((field) => canWriteObjectField(field, layoutMap));
|
|
720
|
-
}
|
|
721
|
-
function canWriteObjectField(field, layoutMap) {
|
|
722
|
-
switch (field.kind) {
|
|
723
|
-
case "scalar":
|
|
724
|
-
case "fixed-bytes":
|
|
725
|
-
case "fixed-string":
|
|
726
|
-
case "dynamic-string":
|
|
727
|
-
case "dynamic-bytes":
|
|
728
|
-
case "struct":
|
|
729
|
-
case "pointer":
|
|
730
|
-
return true;
|
|
731
|
-
case "fixed-array":
|
|
732
|
-
return (field.element.kind !== "struct" ||
|
|
733
|
-
canWriteFixedArrayStructElement(field.element, layoutMap, hasTailWriterFields));
|
|
734
|
-
case "vector":
|
|
735
|
-
return (field.element.kind !== "struct" ||
|
|
736
|
-
canWriteStructVectorElement(field.element, layoutMap));
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
function canWriteStructVectorElement(element, layoutMap) {
|
|
740
|
-
if (element.kind !== "struct") {
|
|
741
|
-
return false;
|
|
742
|
-
}
|
|
743
|
-
const elementLayout = layoutMap.get(element.typeName);
|
|
744
|
-
return elementLayout !== undefined && !hasTailWriterFields(elementLayout, layoutMap);
|
|
114
|
+
function emitLayerBlock(lines) {
|
|
115
|
+
return lines.length === 0 ? [] : [...lines, ""];
|
|
745
116
|
}
|
|
746
117
|
//# sourceMappingURL=emitter.js.map
|