@dusted/anqst 1.5.0 → 1.5.1

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 (80) hide show
  1. package/dist/src/app.js +31 -9
  2. package/dist/src/base93.js +0 -72
  3. package/dist/src/boundary-codec-analysis.js +468 -0
  4. package/dist/src/boundary-codec-leaves.js +602 -0
  5. package/dist/src/boundary-codec-model.js +77 -0
  6. package/dist/src/boundary-codec-plan.js +522 -0
  7. package/dist/src/boundary-codec-render.js +1738 -0
  8. package/dist/src/boundary-codecs.js +174 -0
  9. package/dist/src/emit.js +580 -90
  10. package/dist/src/program.js +1 -1
  11. package/package.json +2 -2
  12. package/dist/src/codecgenerators/basecodecemitters/bigint-qint64/decoder.js +0 -35
  13. package/dist/src/codecgenerators/basecodecemitters/bigint-qint64/encoder.js +0 -36
  14. package/dist/src/codecgenerators/basecodecemitters/bigint-quint64/decoder.js +0 -26
  15. package/dist/src/codecgenerators/basecodecemitters/bigint-quint64/encoder.js +0 -38
  16. package/dist/src/codecgenerators/basecodecemitters/binary-blob/decoder.js +0 -28
  17. package/dist/src/codecgenerators/basecodecemitters/binary-blob/encoder.js +0 -34
  18. package/dist/src/codecgenerators/basecodecemitters/binary-buffer/decoder.js +0 -29
  19. package/dist/src/codecgenerators/basecodecemitters/binary-buffer/encoder.js +0 -36
  20. package/dist/src/codecgenerators/basecodecemitters/binary-float32Array/decoder.js +0 -46
  21. package/dist/src/codecgenerators/basecodecemitters/binary-float32Array/encoder.js +0 -49
  22. package/dist/src/codecgenerators/basecodecemitters/binary-float64Array/decoder.js +0 -46
  23. package/dist/src/codecgenerators/basecodecemitters/binary-float64Array/encoder.js +0 -47
  24. package/dist/src/codecgenerators/basecodecemitters/binary-int16Array/decoder.js +0 -46
  25. package/dist/src/codecgenerators/basecodecemitters/binary-int16Array/encoder.js +0 -49
  26. package/dist/src/codecgenerators/basecodecemitters/binary-int32Array/decoder.js +0 -50
  27. package/dist/src/codecgenerators/basecodecemitters/binary-int32Array/encoder.js +0 -52
  28. package/dist/src/codecgenerators/basecodecemitters/binary-int8Array/decoder.js +0 -38
  29. package/dist/src/codecgenerators/basecodecemitters/binary-int8Array/encoder.js +0 -44
  30. package/dist/src/codecgenerators/basecodecemitters/binary-typedArray/decoder.js +0 -33
  31. package/dist/src/codecgenerators/basecodecemitters/binary-typedArray/encoder.js +0 -34
  32. package/dist/src/codecgenerators/basecodecemitters/binary-uint16Array/decoder.js +0 -46
  33. package/dist/src/codecgenerators/basecodecemitters/binary-uint16Array/encoder.js +0 -49
  34. package/dist/src/codecgenerators/basecodecemitters/binary-uint32Array/decoder.js +0 -46
  35. package/dist/src/codecgenerators/basecodecemitters/binary-uint32Array/encoder.js +0 -49
  36. package/dist/src/codecgenerators/basecodecemitters/binary-uint8Array/decoder.js +0 -28
  37. package/dist/src/codecgenerators/basecodecemitters/binary-uint8Array/encoder.js +0 -34
  38. package/dist/src/codecgenerators/basecodecemitters/boolean/decoder.js +0 -34
  39. package/dist/src/codecgenerators/basecodecemitters/boolean/encoder.js +0 -40
  40. package/dist/src/codecgenerators/basecodecemitters/dynamic-json/decoder.js +0 -43
  41. package/dist/src/codecgenerators/basecodecemitters/dynamic-json/encoder.js +0 -45
  42. package/dist/src/codecgenerators/basecodecemitters/dynamic-object/decoder.js +0 -44
  43. package/dist/src/codecgenerators/basecodecemitters/dynamic-object/encoder.js +0 -46
  44. package/dist/src/codecgenerators/basecodecemitters/integer-int16/decoder.js +0 -32
  45. package/dist/src/codecgenerators/basecodecemitters/integer-int16/encoder.js +0 -43
  46. package/dist/src/codecgenerators/basecodecemitters/integer-int32/decoder.js +0 -26
  47. package/dist/src/codecgenerators/basecodecemitters/integer-int32/encoder.js +0 -37
  48. package/dist/src/codecgenerators/basecodecemitters/integer-int8/decoder.js +0 -26
  49. package/dist/src/codecgenerators/basecodecemitters/integer-int8/encoder.js +0 -37
  50. package/dist/src/codecgenerators/basecodecemitters/integer-qint16/decoder.js +0 -36
  51. package/dist/src/codecgenerators/basecodecemitters/integer-qint16/encoder.js +0 -36
  52. package/dist/src/codecgenerators/basecodecemitters/integer-qint32/decoder.js +0 -25
  53. package/dist/src/codecgenerators/basecodecemitters/integer-qint32/encoder.js +0 -36
  54. package/dist/src/codecgenerators/basecodecemitters/integer-qint8/decoder.js +0 -36
  55. package/dist/src/codecgenerators/basecodecemitters/integer-qint8/encoder.js +0 -36
  56. package/dist/src/codecgenerators/basecodecemitters/integer-quint16/decoder.js +0 -26
  57. package/dist/src/codecgenerators/basecodecemitters/integer-quint16/encoder.js +0 -38
  58. package/dist/src/codecgenerators/basecodecemitters/integer-quint32/decoder.js +0 -27
  59. package/dist/src/codecgenerators/basecodecemitters/integer-quint32/encoder.js +0 -39
  60. package/dist/src/codecgenerators/basecodecemitters/integer-quint8/decoder.js +0 -26
  61. package/dist/src/codecgenerators/basecodecemitters/integer-quint8/encoder.js +0 -38
  62. package/dist/src/codecgenerators/basecodecemitters/integer-uint16/decoder.js +0 -30
  63. package/dist/src/codecgenerators/basecodecemitters/integer-uint16/encoder.js +0 -42
  64. package/dist/src/codecgenerators/basecodecemitters/integer-uint32/decoder.js +0 -31
  65. package/dist/src/codecgenerators/basecodecemitters/integer-uint32/encoder.js +0 -43
  66. package/dist/src/codecgenerators/basecodecemitters/integer-uint8/decoder.js +0 -30
  67. package/dist/src/codecgenerators/basecodecemitters/integer-uint8/encoder.js +0 -40
  68. package/dist/src/codecgenerators/basecodecemitters/number/decoder.js +0 -26
  69. package/dist/src/codecgenerators/basecodecemitters/number/encoder.js +0 -38
  70. package/dist/src/codecgenerators/basecodecemitters/shared/comments.js +0 -13
  71. package/dist/src/codecgenerators/basecodecemitters/shared/contracts.js +0 -2
  72. package/dist/src/codecgenerators/basecodecemitters/shared/fixedwidth.js +0 -53
  73. package/dist/src/codecgenerators/basecodecemitters/shared/index.js +0 -21
  74. package/dist/src/codecgenerators/basecodecemitters/shared/positionalBase93.js +0 -48
  75. package/dist/src/codecgenerators/basecodecemitters/shared/rawbytes.js +0 -30
  76. package/dist/src/codecgenerators/basecodecemitters/string/decoder.js +0 -43
  77. package/dist/src/codecgenerators/basecodecemitters/string/encoder.js +0 -43
  78. package/dist/src/codecgenerators/basecodecemitters/stringArray/decoder.js +0 -80
  79. package/dist/src/codecgenerators/basecodecemitters/stringArray/encoder.js +0 -57
  80. package/dist/src/structured-top-level-codecs.js +0 -1305
@@ -1,1305 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.buildStructuredCodecCatalog = buildStructuredCodecCatalog;
7
- exports.getStructuredPayloadSite = getStructuredPayloadSite;
8
- exports.getStructuredParameterSite = getStructuredParameterSite;
9
- exports.renderTsStructuredCodecHelpers = renderTsStructuredCodecHelpers;
10
- exports.renderCppStructuredCodecHelpers = renderCppStructuredCodecHelpers;
11
- const typescript_1 = __importDefault(require("typescript"));
12
- const base93_1 = require("./base93");
13
- function stripAnQstType(typeText) {
14
- return typeText
15
- .replace(/\bAnQst\.Type\.stringArray\b/g, "string[]")
16
- .replace(/\bAnQst\.Type\.string\b/g, "string")
17
- .replace(/\bAnQst\.Type\.number\b/g, "number")
18
- .replace(/\bAnQst\.Type\.qint64\b/g, "bigint")
19
- .replace(/\bAnQst\.Type\.quint64\b/g, "bigint")
20
- .replace(/\bAnQst\.Type\.qint32\b/g, "number")
21
- .replace(/\bAnQst\.Type\.quint32\b/g, "number")
22
- .replace(/\bAnQst\.Type\.qint16\b/g, "number")
23
- .replace(/\bAnQst\.Type\.quint16\b/g, "number")
24
- .replace(/\bAnQst\.Type\.qint8\b/g, "number")
25
- .replace(/\bAnQst\.Type\.quint8\b/g, "number")
26
- .replace(/\bAnQst\.Type\.int32\b/g, "number")
27
- .replace(/\bAnQst\.Type\.uint32\b/g, "number")
28
- .replace(/\bAnQst\.Type\.int16\b/g, "number")
29
- .replace(/\bAnQst\.Type\.uint16\b/g, "number")
30
- .replace(/\bAnQst\.Type\.int8\b/g, "number")
31
- .replace(/\bAnQst\.Type\.uint8\b/g, "number")
32
- .replace(/\bAnQst\.Type\.buffer\b/g, "ArrayBuffer")
33
- .replace(/\bAnQst\.Type\.blob\b/g, "ArrayBuffer")
34
- .replace(/\bAnQst\.Type\.typedArray\b/g, "Uint8Array")
35
- .replace(/\bAnQst\.Type\.uint8Array\b/g, "Uint8Array")
36
- .replace(/\bAnQst\.Type\.int8Array\b/g, "Int8Array")
37
- .replace(/\bAnQst\.Type\.uint16Array\b/g, "Uint16Array")
38
- .replace(/\bAnQst\.Type\.int16Array\b/g, "Int16Array")
39
- .replace(/\bAnQst\.Type\.uint32Array\b/g, "Uint32Array")
40
- .replace(/\bAnQst\.Type\.int32Array\b/g, "Int32Array")
41
- .replace(/\bAnQst\.Type\.float32Array\b/g, "Float32Array")
42
- .replace(/\bAnQst\.Type\.float64Array\b/g, "Float64Array")
43
- .replace(/\bAnQst\.Type\.object\b/g, "object")
44
- .replace(/\bAnQst\.Type\.json\b/g, "object");
45
- }
46
- function mapTsTypeToCpp(typeText) {
47
- const raw = typeText.trim();
48
- if (/\bAnQst\.Type\.qint64\b/.test(raw))
49
- return "qint64";
50
- if (/\bAnQst\.Type\.quint64\b/.test(raw))
51
- return "quint64";
52
- if (/\bAnQst\.Type\.qint32\b/.test(raw))
53
- return "qint32";
54
- if (/\bAnQst\.Type\.quint32\b/.test(raw))
55
- return "quint32";
56
- if (/\bAnQst\.Type\.qint16\b/.test(raw))
57
- return "qint16";
58
- if (/\bAnQst\.Type\.quint16\b/.test(raw))
59
- return "quint16";
60
- if (/\bAnQst\.Type\.qint8\b/.test(raw))
61
- return "qint8";
62
- if (/\bAnQst\.Type\.quint8\b/.test(raw))
63
- return "quint8";
64
- if (/\bAnQst\.Type\.stringArray\b/.test(raw))
65
- return "QStringList";
66
- if (/\bAnQst\.Type\.string\b/.test(raw))
67
- return "QString";
68
- if (/\bAnQst\.Type\.json\b/.test(raw) || /\bAnQst\.Type\.object\b/.test(raw))
69
- return "QVariantMap";
70
- if (/\bAnQst\.Type\.(?:buffer|blob|typedArray|uint8Array|int8Array|uint16Array|int16Array|uint32Array|int32Array|float32Array|float64Array)\b/.test(raw)) {
71
- return "QByteArray";
72
- }
73
- if (/\bAnQst\.Type\.(u?int(8|16|32))\b/.test(raw)) {
74
- const narrowed = raw.match(/\bAnQst\.Type\.(u?int(?:8|16|32))\b/)?.[1];
75
- if (narrowed === "int8")
76
- return "int8_t";
77
- if (narrowed === "uint8")
78
- return "uint8_t";
79
- if (narrowed === "int16")
80
- return "int16_t";
81
- if (narrowed === "uint16")
82
- return "uint16_t";
83
- if (narrowed === "int32")
84
- return "int32_t";
85
- if (narrowed === "uint32")
86
- return "uint32_t";
87
- }
88
- const t = stripAnQstType(raw);
89
- if (t === "string")
90
- return "QString";
91
- if (t === "number")
92
- return "double";
93
- if (t === "boolean")
94
- return "bool";
95
- if (t === "bigint")
96
- return "qint64";
97
- if (t === "void")
98
- return "void";
99
- if (t === "object")
100
- return "QVariantMap";
101
- if (t === "ArrayBuffer")
102
- return "QByteArray";
103
- if ([
104
- "Uint8Array",
105
- "Int8Array",
106
- "Uint16Array",
107
- "Int16Array",
108
- "Uint32Array",
109
- "Int32Array",
110
- "Float32Array",
111
- "Float64Array"
112
- ].includes(t)) {
113
- return "QByteArray";
114
- }
115
- if (t.endsWith("[]")) {
116
- return `QList<${mapTsTypeToCpp(t.slice(0, -2))}>`;
117
- }
118
- if (t.includes("|"))
119
- return "QString";
120
- return t;
121
- }
122
- function parseTypeNodeFromText(typeText) {
123
- const source = typescript_1.default.createSourceFile("__inline__.ts", `type __X = ${typeText};`, typescript_1.default.ScriptTarget.Latest, true, typescript_1.default.ScriptKind.TS);
124
- const stmt = source.statements.find(typescript_1.default.isTypeAliasDeclaration);
125
- if (!stmt)
126
- throw new Error(`Unable to parse type text: ${typeText}`);
127
- return stmt.type;
128
- }
129
- function parseTypeDeclNode(nodeText) {
130
- const sf = typescript_1.default.createSourceFile("__decl.ts", nodeText, typescript_1.default.ScriptTarget.Latest, true, typescript_1.default.ScriptKind.TS);
131
- for (const stmt of sf.statements) {
132
- if (typescript_1.default.isInterfaceDeclaration(stmt) || typescript_1.default.isTypeAliasDeclaration(stmt))
133
- return stmt;
134
- }
135
- return null;
136
- }
137
- function qNameText(name) {
138
- if (typescript_1.default.isIdentifier(name))
139
- return name.text;
140
- return `${qNameText(name.left)}.${name.right.text}`;
141
- }
142
- function sanitizeIdentifier(value) {
143
- const trimmed = value.replace(/[^A-Za-z0-9_]+/g, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "");
144
- const withFallback = trimmed.length > 0 ? trimmed : "Codec";
145
- return /^[0-9]/.test(withFallback) ? `T_${withFallback}` : withFallback;
146
- }
147
- function scalarShape(typeText, pathHintParts, leaf) {
148
- return { kind: "scalar", typeText, pathHintParts, leaf };
149
- }
150
- function binaryShape(typeText, pathHintParts, binary) {
151
- return { kind: "binary", typeText, pathHintParts, binary };
152
- }
153
- function isStringLikeUnion(node) {
154
- return node.types.every((part) => {
155
- if (typescript_1.default.isLiteralTypeNode(part) && typescript_1.default.isStringLiteral(part.literal))
156
- return true;
157
- if (part.kind === typescript_1.default.SyntaxKind.StringKeyword)
158
- return true;
159
- return false;
160
- });
161
- }
162
- function isBooleanLikeUnion(node) {
163
- return node.types.every((part) => {
164
- if (typescript_1.default.isLiteralTypeNode(part) && (part.literal.kind === typescript_1.default.SyntaxKind.TrueKeyword || part.literal.kind === typescript_1.default.SyntaxKind.FalseKeyword))
165
- return true;
166
- if (part.kind === typescript_1.default.SyntaxKind.BooleanKeyword)
167
- return true;
168
- return false;
169
- });
170
- }
171
- function isNumberLikeUnion(node) {
172
- return node.types.every((part) => {
173
- if (typescript_1.default.isLiteralTypeNode(part) && typescript_1.default.isNumericLiteral(part.literal))
174
- return true;
175
- if (part.kind === typescript_1.default.SyntaxKind.NumberKeyword || part.kind === typescript_1.default.SyntaxKind.BigIntKeyword)
176
- return true;
177
- return false;
178
- });
179
- }
180
- function filterNullishUnionParts(types) {
181
- return types.filter((part) => part.kind !== typescript_1.default.SyntaxKind.NullKeyword && part.kind !== typescript_1.default.SyntaxKind.UndefinedKeyword);
182
- }
183
- class ShapeResolver {
184
- constructor(spec) {
185
- this.spec = spec;
186
- this.declNodes = new Map();
187
- this.namedShapes = new Map();
188
- for (const decl of this.collectDecls()) {
189
- const node = parseTypeDeclNode(decl.nodeText);
190
- if (node)
191
- this.declNodes.set(decl.name, node);
192
- }
193
- }
194
- resolveTypeText(typeText, pathHintParts) {
195
- return this.resolveTypeNode(parseTypeNodeFromText(typeText), typeText, pathHintParts, []);
196
- }
197
- collectDecls() {
198
- const out = new Map();
199
- for (const decl of this.spec.namespaceTypeDecls)
200
- out.set(decl.name, decl);
201
- for (const decl of this.spec.importedTypeDecls.values())
202
- out.set(decl.name, decl);
203
- return [...out.values()];
204
- }
205
- createStructShape(typeText, pathHintParts, members, stack) {
206
- return {
207
- kind: "struct",
208
- typeText,
209
- pathHintParts,
210
- fields: members
211
- .filter((member) => {
212
- return typescript_1.default.isPropertySignature(member) && !!member.type && typescript_1.default.isIdentifier(member.name);
213
- })
214
- .map((member) => ({
215
- name: member.name.text,
216
- optional: !!member.questionToken,
217
- typeText: member.type.getText(),
218
- pathHintParts: [...pathHintParts, member.name.text],
219
- shape: this.resolveTypeNode(member.type, member.type.getText(), [...pathHintParts, member.name.text], stack)
220
- }))
221
- };
222
- }
223
- resolveNamedReference(name, decl) {
224
- const existing = this.namedShapes.get(name);
225
- if (existing)
226
- return existing;
227
- const placeholder = {
228
- kind: "named",
229
- name,
230
- typeText: name,
231
- pathHintParts: [name],
232
- target: scalarShape(name, [name], "string")
233
- };
234
- this.namedShapes.set(name, placeholder);
235
- placeholder.target = typescript_1.default.isInterfaceDeclaration(decl)
236
- ? this.createStructShape(name, [name], decl.members, [name])
237
- : this.resolveTypeNode(decl.type, name, [name], [name]);
238
- return placeholder;
239
- }
240
- resolveTypeNode(node, typeText, pathHintParts, stack) {
241
- if (typescript_1.default.isParenthesizedTypeNode(node)) {
242
- return this.resolveTypeNode(node.type, node.type.getText(), pathHintParts, stack);
243
- }
244
- if (typescript_1.default.isTypeLiteralNode(node)) {
245
- return this.createStructShape(typeText, pathHintParts, node.members, stack);
246
- }
247
- if (typescript_1.default.isArrayTypeNode(node)) {
248
- return {
249
- kind: "array",
250
- typeText,
251
- pathHintParts,
252
- elementTypeText: node.elementType.getText(),
253
- element: this.resolveTypeNode(node.elementType, node.elementType.getText(), [...pathHintParts, "Item"], stack)
254
- };
255
- }
256
- if (typescript_1.default.isLiteralTypeNode(node)) {
257
- if (typescript_1.default.isStringLiteral(node.literal))
258
- return scalarShape(typeText, pathHintParts, "string");
259
- if (typescript_1.default.isNumericLiteral(node.literal))
260
- return scalarShape(typeText, pathHintParts, "number");
261
- if (node.literal.kind === typescript_1.default.SyntaxKind.TrueKeyword || node.literal.kind === typescript_1.default.SyntaxKind.FalseKeyword) {
262
- return scalarShape(typeText, pathHintParts, "boolean");
263
- }
264
- }
265
- if (typescript_1.default.isUnionTypeNode(node)) {
266
- const filtered = filterNullishUnionParts(node.types);
267
- if (filtered.length === 1) {
268
- return this.resolveTypeNode(filtered[0], filtered[0].getText(), pathHintParts, stack);
269
- }
270
- if (isStringLikeUnion(node))
271
- return scalarShape(typeText, pathHintParts, "string");
272
- if (isBooleanLikeUnion(node))
273
- return scalarShape(typeText, pathHintParts, "boolean");
274
- if (isNumberLikeUnion(node))
275
- return scalarShape(typeText, pathHintParts, "number");
276
- return scalarShape(typeText, pathHintParts, "string");
277
- }
278
- if (typescript_1.default.isTypeReferenceNode(node)) {
279
- const name = qNameText(node.typeName);
280
- const rawText = node.getText();
281
- if (name === "Array" || name === "ReadonlyArray") {
282
- const arg = node.typeArguments?.[0];
283
- if (!arg)
284
- throw new Error(`Missing array type argument for ${rawText}`);
285
- return {
286
- kind: "array",
287
- typeText,
288
- pathHintParts,
289
- elementTypeText: arg.getText(),
290
- element: this.resolveTypeNode(arg, arg.getText(), [...pathHintParts, "Item"], stack)
291
- };
292
- }
293
- if (name === "Record") {
294
- return { kind: "dynamic", typeText, pathHintParts };
295
- }
296
- if (name === "Partial" && node.typeArguments?.[0]) {
297
- return this.resolveTypeNode(node.typeArguments[0], node.typeArguments[0].getText(), pathHintParts, stack);
298
- }
299
- if (name === "Promise" && node.typeArguments?.[0]) {
300
- return this.resolveTypeNode(node.typeArguments[0], node.typeArguments[0].getText(), pathHintParts, stack);
301
- }
302
- const leaf = this.resolveLeafReference(rawText, name, pathHintParts);
303
- if (leaf)
304
- return leaf;
305
- const decl = this.declNodes.get(name);
306
- if (decl) {
307
- return this.resolveNamedReference(name, decl);
308
- }
309
- }
310
- switch (node.kind) {
311
- case typescript_1.default.SyntaxKind.StringKeyword:
312
- return scalarShape(typeText, pathHintParts, "string");
313
- case typescript_1.default.SyntaxKind.BooleanKeyword:
314
- return scalarShape(typeText, pathHintParts, "boolean");
315
- case typescript_1.default.SyntaxKind.NumberKeyword:
316
- return scalarShape(typeText, pathHintParts, "number");
317
- case typescript_1.default.SyntaxKind.BigIntKeyword:
318
- return scalarShape(typeText, pathHintParts, "qint64");
319
- case typescript_1.default.SyntaxKind.ObjectKeyword:
320
- return { kind: "dynamic", typeText, pathHintParts };
321
- default: {
322
- const text = node.getText();
323
- const leaf = this.resolveLeafReference(text, text, pathHintParts);
324
- if (leaf)
325
- return leaf;
326
- return scalarShape(typeText, pathHintParts, "string");
327
- }
328
- }
329
- }
330
- resolveLeafReference(rawText, name, pathHintParts) {
331
- const normalized = rawText.trim();
332
- if (normalized === "string" || normalized === "AnQst.Type.string")
333
- return scalarShape(rawText, pathHintParts, "string");
334
- if (normalized === "boolean")
335
- return scalarShape(rawText, pathHintParts, "boolean");
336
- if (normalized === "number" || normalized === "AnQst.Type.number")
337
- return scalarShape(rawText, pathHintParts, "number");
338
- if (normalized === "bigint" || normalized === "AnQst.Type.qint64")
339
- return scalarShape(rawText, pathHintParts, "qint64");
340
- if (normalized === "AnQst.Type.quint64")
341
- return scalarShape(rawText, pathHintParts, "quint64");
342
- if (normalized === "AnQst.Type.qint32")
343
- return scalarShape(rawText, pathHintParts, "qint32");
344
- if (normalized === "AnQst.Type.quint32")
345
- return scalarShape(rawText, pathHintParts, "quint32");
346
- if (normalized === "AnQst.Type.qint16")
347
- return scalarShape(rawText, pathHintParts, "qint16");
348
- if (normalized === "AnQst.Type.quint16")
349
- return scalarShape(rawText, pathHintParts, "quint16");
350
- if (normalized === "AnQst.Type.qint8")
351
- return scalarShape(rawText, pathHintParts, "qint8");
352
- if (normalized === "AnQst.Type.quint8")
353
- return scalarShape(rawText, pathHintParts, "quint8");
354
- if (normalized === "AnQst.Type.int32")
355
- return scalarShape(rawText, pathHintParts, "int32");
356
- if (normalized === "AnQst.Type.uint32")
357
- return scalarShape(rawText, pathHintParts, "uint32");
358
- if (normalized === "AnQst.Type.int16")
359
- return scalarShape(rawText, pathHintParts, "int16");
360
- if (normalized === "AnQst.Type.uint16")
361
- return scalarShape(rawText, pathHintParts, "uint16");
362
- if (normalized === "AnQst.Type.int8")
363
- return scalarShape(rawText, pathHintParts, "int8");
364
- if (normalized === "AnQst.Type.uint8")
365
- return scalarShape(rawText, pathHintParts, "uint8");
366
- if (normalized === "AnQst.Type.object" || normalized === "AnQst.Type.json" || normalized === "object") {
367
- return { kind: "dynamic", typeText: rawText, pathHintParts };
368
- }
369
- if (normalized === "AnQst.Type.buffer" || normalized === "AnQst.Type.blob" || normalized === "ArrayBuffer") {
370
- return binaryShape(rawText, pathHintParts, "ArrayBuffer");
371
- }
372
- if (normalized === "AnQst.Type.typedArray" || normalized === "Uint8Array") {
373
- return binaryShape(rawText, pathHintParts, "Uint8Array");
374
- }
375
- if (normalized === "AnQst.Type.uint8Array")
376
- return binaryShape(rawText, pathHintParts, "Uint8Array");
377
- if (normalized === "AnQst.Type.int8Array")
378
- return binaryShape(rawText, pathHintParts, "Int8Array");
379
- if (normalized === "AnQst.Type.uint16Array")
380
- return binaryShape(rawText, pathHintParts, "Uint16Array");
381
- if (normalized === "AnQst.Type.int16Array")
382
- return binaryShape(rawText, pathHintParts, "Int16Array");
383
- if (normalized === "AnQst.Type.uint32Array")
384
- return binaryShape(rawText, pathHintParts, "Uint32Array");
385
- if (normalized === "AnQst.Type.int32Array")
386
- return binaryShape(rawText, pathHintParts, "Int32Array");
387
- if (normalized === "AnQst.Type.float32Array" || normalized === "Float32Array") {
388
- return binaryShape(rawText, pathHintParts, "Float32Array");
389
- }
390
- if (normalized === "AnQst.Type.float64Array" || normalized === "Float64Array") {
391
- return binaryShape(rawText, pathHintParts, "Float64Array");
392
- }
393
- if (normalized === "AnQst.Type.stringArray") {
394
- return {
395
- kind: "array",
396
- typeText: rawText,
397
- pathHintParts,
398
- elementTypeText: "string",
399
- element: scalarShape("string", [...pathHintParts, "Item"], "string")
400
- };
401
- }
402
- if (name === "Int8Array")
403
- return binaryShape(rawText, pathHintParts, "Int8Array");
404
- if (name === "Uint16Array")
405
- return binaryShape(rawText, pathHintParts, "Uint16Array");
406
- if (name === "Int16Array")
407
- return binaryShape(rawText, pathHintParts, "Int16Array");
408
- if (name === "Uint32Array")
409
- return binaryShape(rawText, pathHintParts, "Uint32Array");
410
- if (name === "Int32Array")
411
- return binaryShape(rawText, pathHintParts, "Int32Array");
412
- return null;
413
- }
414
- }
415
- function analyzeShape(shape, namedCache = new Map(), visiting = new Set()) {
416
- switch (shape.kind) {
417
- case "scalar":
418
- return {
419
- hasBlob: shape.leaf !== "string" && shape.leaf !== "boolean",
420
- hasStrings: shape.leaf === "string" || shape.leaf === "boolean",
421
- hasBinaries: false,
422
- hasDynamics: false
423
- };
424
- case "named": {
425
- const cached = namedCache.get(shape.name);
426
- if (cached)
427
- return cached;
428
- if (visiting.has(shape.name)) {
429
- return { hasBlob: false, hasStrings: false, hasBinaries: false, hasDynamics: false };
430
- }
431
- visiting.add(shape.name);
432
- const analysis = analyzeShape(shape.target, namedCache, visiting);
433
- visiting.delete(shape.name);
434
- namedCache.set(shape.name, analysis);
435
- return analysis;
436
- }
437
- case "dynamic":
438
- return { hasBlob: false, hasStrings: false, hasBinaries: false, hasDynamics: true };
439
- case "binary":
440
- return { hasBlob: false, hasStrings: false, hasBinaries: true, hasDynamics: false };
441
- case "array": {
442
- const inner = analyzeShape(shape.element, namedCache, visiting);
443
- return {
444
- hasBlob: true || inner.hasBlob,
445
- hasStrings: inner.hasStrings,
446
- hasBinaries: inner.hasBinaries,
447
- hasDynamics: inner.hasDynamics
448
- };
449
- }
450
- case "struct": {
451
- return shape.fields.reduce((acc, field) => {
452
- const next = analyzeShape(field.shape, namedCache, visiting);
453
- return {
454
- hasBlob: acc.hasBlob || next.hasBlob || field.optional,
455
- hasStrings: acc.hasStrings || next.hasStrings,
456
- hasBinaries: acc.hasBinaries || next.hasBinaries,
457
- hasDynamics: acc.hasDynamics || next.hasDynamics
458
- };
459
- }, { hasBlob: false, hasStrings: false, hasBinaries: false, hasDynamics: false });
460
- }
461
- }
462
- }
463
- function codecSiteKey(kind, serviceName, memberName, parameterName) {
464
- return kind === "payload"
465
- ? `${serviceName}::${memberName}::payload`
466
- : `${serviceName}::${memberName}::param::${parameterName ?? ""}`;
467
- }
468
- function buildStructuredCodecCatalog(spec) {
469
- const resolver = new ShapeResolver(spec);
470
- const codecs = [];
471
- const codecIdByTypeText = new Map();
472
- const payloadSites = new Map();
473
- const parameterSites = new Map();
474
- const usedCodecIds = new Set();
475
- const ensureCodec = (typeText, pathHintParts) => {
476
- const existing = codecIdByTypeText.get(typeText);
477
- if (existing)
478
- return existing;
479
- const proposed = `AnQstStructured_${sanitizeIdentifier(stripAnQstType(typeText).replace(/\s+/g, "_"))}`;
480
- let codecId = proposed;
481
- let suffix = 2;
482
- while (usedCodecIds.has(codecId)) {
483
- codecId = `${proposed}_${suffix++}`;
484
- }
485
- usedCodecIds.add(codecId);
486
- codecIdByTypeText.set(typeText, codecId);
487
- const shape = resolver.resolveTypeText(typeText, pathHintParts);
488
- codecs.push({
489
- codecId,
490
- typeText,
491
- tsTypeText: stripAnQstType(typeText),
492
- shape,
493
- analysis: analyzeShape(shape)
494
- });
495
- return codecId;
496
- };
497
- for (const service of spec.services) {
498
- for (const member of service.members) {
499
- if (member.payloadTypeText && member.payloadTypeText.trim() !== "void") {
500
- const site = {
501
- siteKey: codecSiteKey("payload", service.name, member.name, null),
502
- kind: "payload",
503
- serviceName: service.name,
504
- memberName: member.name,
505
- parameterName: null,
506
- typeText: member.payloadTypeText,
507
- codecId: ensureCodec(member.payloadTypeText, [service.name, member.name, "Payload"])
508
- };
509
- payloadSites.set(site.siteKey, site);
510
- }
511
- for (const param of member.parameters) {
512
- const site = {
513
- siteKey: codecSiteKey("parameter", service.name, member.name, param.name),
514
- kind: "parameter",
515
- serviceName: service.name,
516
- memberName: member.name,
517
- parameterName: param.name,
518
- typeText: param.typeText,
519
- codecId: ensureCodec(param.typeText, [service.name, member.name, param.name])
520
- };
521
- parameterSites.set(site.siteKey, site);
522
- }
523
- }
524
- }
525
- return { codecs, payloadSites, parameterSites };
526
- }
527
- function getStructuredPayloadSite(catalog, serviceName, memberName) {
528
- return catalog.payloadSites.get(codecSiteKey("payload", serviceName, memberName, null));
529
- }
530
- function getStructuredParameterSite(catalog, serviceName, memberName, parameterName) {
531
- return catalog.parameterSites.get(codecSiteKey("parameter", serviceName, memberName, parameterName));
532
- }
533
- function indent(level) {
534
- return " ".repeat(level);
535
- }
536
- class TsEmitterContext {
537
- constructor() {
538
- this.nextId = 0;
539
- }
540
- next(prefix) {
541
- this.nextId += 1;
542
- return `__${prefix}${this.nextId}`;
543
- }
544
- }
545
- function tsNamedHelperStem(shape, scope = "") {
546
- const scopePrefix = scope ? `${sanitizeIdentifier(scope)}_` : "";
547
- return `__anqstNamed_${scopePrefix}${sanitizeIdentifier(shape.name)}`;
548
- }
549
- function tsNamedEncodeHelperName(shape, scope = "") {
550
- return `${tsNamedHelperStem(shape, scope)}_encode`;
551
- }
552
- function tsNamedCountHelperName(shape, scope = "") {
553
- return `${tsNamedHelperStem(shape, scope)}_count`;
554
- }
555
- function tsNamedDecodeHelperName(shape, scope = "") {
556
- return `${tsNamedHelperStem(shape, scope)}_decode`;
557
- }
558
- function collectNamedShapes(shape, out = new Map()) {
559
- switch (shape.kind) {
560
- case "named":
561
- if (out.has(shape.name))
562
- return out;
563
- out.set(shape.name, shape);
564
- collectNamedShapes(shape.target, out);
565
- return out;
566
- case "array":
567
- collectNamedShapes(shape.element, out);
568
- return out;
569
- case "struct":
570
- for (const field of shape.fields)
571
- collectNamedShapes(field.shape, out);
572
- return out;
573
- default:
574
- return out;
575
- }
576
- }
577
- function tsScalarWriteHelper(leaf) {
578
- switch (leaf) {
579
- case "boolean": return "__anqstPushBool";
580
- case "number": return "__anqstPushFloat64";
581
- case "qint64": return "__anqstPushBigInt64";
582
- case "quint64": return "__anqstPushBigUint64";
583
- case "qint32": return "__anqstPushInt32";
584
- case "quint32": return "__anqstPushUint32";
585
- case "qint16": return "__anqstPushInt16";
586
- case "quint16": return "__anqstPushUint16";
587
- case "qint8": return "__anqstPushInt8";
588
- case "quint8": return "__anqstPushUint8";
589
- case "int32": return "__anqstPushInt32";
590
- case "uint32": return "__anqstPushUint32";
591
- case "int16": return "__anqstPushInt16";
592
- case "uint16": return "__anqstPushUint16";
593
- case "int8": return "__anqstPushInt8";
594
- case "uint8": return "__anqstPushUint8";
595
- default: return "";
596
- }
597
- }
598
- function tsScalarReadHelper(leaf) {
599
- switch (leaf) {
600
- case "boolean": return "__anqstReadBool";
601
- case "number": return "__anqstReadFloat64";
602
- case "qint64": return "__anqstReadBigInt64";
603
- case "quint64": return "__anqstReadBigUint64";
604
- case "qint32": return "__anqstReadInt32";
605
- case "quint32": return "__anqstReadUint32";
606
- case "qint16": return "__anqstReadInt16";
607
- case "quint16": return "__anqstReadUint16";
608
- case "qint8": return "__anqstReadInt8";
609
- case "quint8": return "__anqstReadUint8";
610
- case "int32": return "__anqstReadInt32";
611
- case "uint32": return "__anqstReadUint32";
612
- case "int16": return "__anqstReadInt16";
613
- case "uint16": return "__anqstReadUint16";
614
- case "int8": return "__anqstReadInt8";
615
- case "uint8": return "__anqstReadUint8";
616
- default: return "";
617
- }
618
- }
619
- function binaryEncodeHelperName(binary) {
620
- return `__anqstEncodeBinary_${binary}`;
621
- }
622
- function binaryDecodeHelperName(binary) {
623
- return `__anqstDecodeBinary_${binary}`;
624
- }
625
- function emitTsEncodeShape(shape, valueExpr, lines, ctx, level, scope = "") {
626
- const pad = indent(level);
627
- switch (shape.kind) {
628
- case "scalar":
629
- if (shape.leaf === "string") {
630
- lines.push(`${pad}__strings.push(${valueExpr});`);
631
- }
632
- else if (shape.leaf === "boolean") {
633
- lines.push(`${pad}__strings.push(${valueExpr} ? "1" : "0");`);
634
- }
635
- else {
636
- lines.push(`${pad}${tsScalarWriteHelper(shape.leaf)}(__bytes, ${valueExpr});`);
637
- }
638
- return;
639
- case "named":
640
- lines.push(`${pad}${tsNamedEncodeHelperName(shape, scope)}(${valueExpr}, __bytes, __strings, __binaries, __dynamics);`);
641
- return;
642
- case "dynamic":
643
- lines.push(`${pad}__dynamics.push(${valueExpr});`);
644
- return;
645
- case "binary":
646
- lines.push(`${pad}__binaries.push(${binaryEncodeHelperName(shape.binary)}(${valueExpr}));`);
647
- return;
648
- case "array": {
649
- lines.push(`${pad}__anqstPushUint32(__bytes, ${valueExpr}.length >>> 0);`);
650
- const itemName = ctx.next("item");
651
- lines.push(`${pad}for (const ${itemName} of ${valueExpr}) {`);
652
- emitTsEncodeShape(shape.element, itemName, lines, ctx, level + 1, scope);
653
- lines.push(`${pad}}`);
654
- return;
655
- }
656
- case "struct":
657
- for (const field of shape.fields) {
658
- const fieldExpr = `${valueExpr}.${field.name}`;
659
- if (field.optional) {
660
- const present = ctx.next("present");
661
- lines.push(`${pad}const ${present} = ${fieldExpr} !== undefined;`);
662
- lines.push(`${pad}__anqstPushUint8(__bytes, ${present} ? 1 : 0);`);
663
- lines.push(`${pad}if (${present}) {`);
664
- emitTsEncodeShape(field.shape, `${fieldExpr}!`, lines, ctx, level + 1, scope);
665
- lines.push(`${pad}}`);
666
- }
667
- else {
668
- emitTsEncodeShape(field.shape, fieldExpr, lines, ctx, level, scope);
669
- }
670
- }
671
- }
672
- }
673
- function emitTsCountPass(shape, lines, ctx, level, scope = "") {
674
- const pad = indent(level);
675
- switch (shape.kind) {
676
- case "scalar":
677
- if (shape.leaf === "string" || shape.leaf === "boolean") {
678
- lines.push(`${pad}__counts.stringCount += 1;`);
679
- }
680
- else {
681
- const widths = {
682
- boolean: 0,
683
- number: 8,
684
- qint64: 8,
685
- quint64: 8,
686
- qint32: 4,
687
- quint32: 4,
688
- qint16: 2,
689
- quint16: 2,
690
- qint8: 1,
691
- quint8: 1,
692
- int32: 4,
693
- uint32: 4,
694
- int16: 2,
695
- uint16: 2,
696
- int8: 1,
697
- uint8: 1
698
- };
699
- if (widths[shape.leaf] > 0) {
700
- lines.push(`${pad}__countCursor.offset += ${widths[shape.leaf]};`);
701
- }
702
- }
703
- return;
704
- case "named":
705
- lines.push(`${pad}${tsNamedCountHelperName(shape, scope)}(__blob, __countCursor, __counts);`);
706
- return;
707
- case "dynamic":
708
- lines.push(`${pad}__counts.dynamicCount += 1;`);
709
- return;
710
- case "binary":
711
- lines.push(`${pad}__counts.binaryCount += 1;`);
712
- return;
713
- case "array": {
714
- const countVar = ctx.next("count");
715
- const indexVar = ctx.next("index");
716
- lines.push(`${pad}const ${countVar} = __anqstReadUint32(__blob, __countCursor);`);
717
- lines.push(`${pad}for (let ${indexVar} = 0; ${indexVar} < ${countVar}; ${indexVar} += 1) {`);
718
- emitTsCountPass(shape.element, lines, ctx, level + 1, scope);
719
- lines.push(`${pad}}`);
720
- return;
721
- }
722
- case "struct":
723
- for (const field of shape.fields) {
724
- if (field.optional) {
725
- const present = ctx.next("present");
726
- lines.push(`${pad}const ${present} = __anqstReadUint8(__blob, __countCursor) !== 0;`);
727
- lines.push(`${pad}if (${present}) {`);
728
- emitTsCountPass(field.shape, lines, ctx, level + 1, scope);
729
- lines.push(`${pad}}`);
730
- }
731
- else {
732
- emitTsCountPass(field.shape, lines, ctx, level, scope);
733
- }
734
- }
735
- }
736
- }
737
- function emitTsDecodeValue(shape, lines, ctx, level, scope = "") {
738
- const pad = indent(level);
739
- switch (shape.kind) {
740
- case "scalar":
741
- if (shape.leaf === "string")
742
- return `String(__items[__stringCursor.value++] ?? "")`;
743
- if (shape.leaf === "boolean")
744
- return `String(__items[__stringCursor.value++] ?? "") === "1"`;
745
- return `${tsScalarReadHelper(shape.leaf)}(__blob, __dataCursor)`;
746
- case "named":
747
- return `${tsNamedDecodeHelperName(shape, scope)}(__items, __blob, __stringCursor, __binaryCursor, __dynamicCursor, __dataCursor)`;
748
- case "dynamic":
749
- return `__items[__dynamicCursor.value++]`;
750
- case "binary":
751
- return `${binaryDecodeHelperName(shape.binary)}(String(__items[__binaryCursor.value++] ?? ""))`;
752
- case "array": {
753
- const arrayVar = ctx.next("array");
754
- const countVar = ctx.next("count");
755
- const indexVar = ctx.next("index");
756
- lines.push(`${pad}const ${arrayVar}: ${stripAnQstType(shape.typeText)} = [];`);
757
- lines.push(`${pad}const ${countVar} = __anqstReadUint32(__blob, __dataCursor);`);
758
- lines.push(`${pad}for (let ${indexVar} = 0; ${indexVar} < ${countVar}; ${indexVar} += 1) {`);
759
- const elementExpr = emitTsDecodeValue(shape.element, lines, ctx, level + 1, scope);
760
- lines.push(`${indent(level + 1)}${arrayVar}.push(${elementExpr});`);
761
- lines.push(`${pad}}`);
762
- return arrayVar;
763
- }
764
- case "struct": {
765
- const valueVar = ctx.next("value");
766
- lines.push(`${pad}const ${valueVar} = {} as ${stripAnQstType(shape.typeText)};`);
767
- for (const field of shape.fields) {
768
- if (field.optional) {
769
- const present = ctx.next("present");
770
- lines.push(`${pad}const ${present} = (__anqstReadUint8(__blob, __dataCursor)) !== 0;`);
771
- lines.push(`${pad}if (${present}) {`);
772
- const fieldExpr = emitTsDecodeValue(field.shape, lines, ctx, level + 1, scope);
773
- lines.push(`${indent(level + 1)}${valueVar}.${field.name} = ${fieldExpr};`);
774
- lines.push(`${pad}}`);
775
- }
776
- else {
777
- const fieldExpr = emitTsDecodeValue(field.shape, lines, ctx, level, scope);
778
- lines.push(`${pad}${valueVar}.${field.name} = ${fieldExpr};`);
779
- }
780
- }
781
- return valueVar;
782
- }
783
- }
784
- }
785
- function emitTsCodec(def) {
786
- const namedShapes = [...collectNamedShapes(def.shape).values()];
787
- const ctx = new TsEmitterContext();
788
- const encodeLines = [];
789
- emitTsEncodeShape(def.shape, "value", encodeLines, ctx, 1, def.codecId);
790
- const countLines = [];
791
- emitTsCountPass(def.shape, countLines, ctx, 1, def.codecId);
792
- const decodeLines = [];
793
- const decodeExpr = emitTsDecodeValue(def.shape, decodeLines, ctx, 1, def.codecId);
794
- const encoderName = `encode${def.codecId}`;
795
- const decoderName = `decode${def.codecId}`;
796
- const namedHelpers = namedShapes.map((shape) => {
797
- const helperCtx = new TsEmitterContext();
798
- const helperEncodeLines = [];
799
- emitTsEncodeShape(shape.target, "value", helperEncodeLines, helperCtx, 1, def.codecId);
800
- const helperCountLines = [];
801
- emitTsCountPass(shape.target, helperCountLines, helperCtx, 1, def.codecId);
802
- const helperDecodeLines = [];
803
- const helperDecodeExpr = emitTsDecodeValue(shape.target, helperDecodeLines, helperCtx, 1, def.codecId);
804
- const tsType = stripAnQstType(shape.typeText);
805
- return `function ${tsNamedEncodeHelperName(shape, def.codecId)}(value: ${tsType}, __bytes: number[], __strings: string[], __binaries: string[], __dynamics: unknown[]): void {
806
- ${helperEncodeLines.join("\n")}
807
- }
808
-
809
- function ${tsNamedCountHelperName(shape, def.codecId)}(
810
- __blob: Uint8Array,
811
- __countCursor: { offset: number },
812
- __counts: { stringCount: number; binaryCount: number; dynamicCount: number }
813
- ): void {
814
- ${helperCountLines.join("\n")}
815
- }
816
-
817
- function ${tsNamedDecodeHelperName(shape, def.codecId)}(
818
- __items: unknown[],
819
- __blob: Uint8Array,
820
- __stringCursor: { value: number },
821
- __binaryCursor: { value: number },
822
- __dynamicCursor: { value: number },
823
- __dataCursor: { offset: number }
824
- ): ${tsType} {
825
- ${helperDecodeLines.join("\n")}
826
- return (${helperDecodeExpr}) as ${tsType};
827
- }`;
828
- }).join("\n\n");
829
- return `${namedHelpers ? `${namedHelpers}\n\n` : ""}function ${encoderName}(value: ${def.tsTypeText}): unknown {
830
- const __bytes: number[] = [];
831
- const __strings: string[] = [];
832
- const __binaries: string[] = [];
833
- const __dynamics: unknown[] = [];
834
- ${encodeLines.join("\n")}
835
- return __anqstFinalizeWire(__bytes, __strings, __binaries, __dynamics);
836
- }
837
-
838
- function ${decoderName}(wire: unknown): ${def.tsTypeText} {
839
- const __items = Array.isArray(wire) ? wire : [wire];
840
- const __blob = ${def.analysis.hasBlob ? `__anqstBase93Decode(String(__items[0] ?? ""))` : "new Uint8Array()"};
841
- const __counts = { stringCount: 0, binaryCount: 0, dynamicCount: 0 };
842
- const __countCursor = { offset: 0 };
843
- ${countLines.join("\n")}
844
- const __stringCursor = { value: ${def.analysis.hasBlob ? 1 : 0} };
845
- const __binaryCursor = { value: ${def.analysis.hasBlob ? 1 : 0} + __counts.stringCount };
846
- const __dynamicCursor = { value: ${def.analysis.hasBlob ? 1 : 0} + __counts.stringCount + __counts.binaryCount };
847
- const __dataCursor = { offset: 0 };
848
- ${decodeLines.join("\n")}
849
- return (${decodeExpr}) as ${def.tsTypeText};
850
- }`;
851
- }
852
- function renderTsBinaryHelpers() {
853
- const typedArrayCtorByKind = {
854
- Uint8Array: "Uint8Array",
855
- Int8Array: "Int8Array",
856
- Uint16Array: "Uint16Array",
857
- Int16Array: "Int16Array",
858
- Uint32Array: "Uint32Array",
859
- Int32Array: "Int32Array",
860
- Float32Array: "Float32Array",
861
- Float64Array: "Float64Array"
862
- };
863
- const lines = [
864
- `const __anqstBase93Encode: (d: Uint8Array) => string = ${(0, base93_1.emitBase93Encoder)()};`,
865
- `const __anqstBase93Decode: (s: string) => Uint8Array = ${(0, base93_1.emitBase93Decoder)()};`,
866
- "",
867
- "function __anqstFinalizeWire(bytes: number[], strings: string[], binaries: string[], dynamics: unknown[]): unknown {",
868
- " const items: unknown[] = [];",
869
- " if (bytes.length > 0) items.push(__anqstBase93Encode(Uint8Array.from(bytes)));",
870
- " for (const value of strings) items.push(value);",
871
- " for (const value of binaries) items.push(value);",
872
- " for (const value of dynamics) items.push(value);",
873
- " return items.length === 1 ? items[0] : items;",
874
- "}",
875
- "",
876
- "function __anqstPushUint8(out: number[], value: number): void { out.push(value & 0xff); }",
877
- "function __anqstPushInt8(out: number[], value: number): void { const buf = new Int8Array(1); buf[0] = value; out.push(new Uint8Array(buf.buffer)[0]); }",
878
- "function __anqstPushBool(out: number[], value: boolean): void { out.push(value ? 1 : 0); }",
879
- "function __anqstPushInt16(out: number[], value: number): void { const buf = new ArrayBuffer(2); const view = new DataView(buf); view.setInt16(0, value, true); out.push(...new Uint8Array(buf)); }",
880
- "function __anqstPushUint16(out: number[], value: number): void { const buf = new ArrayBuffer(2); const view = new DataView(buf); view.setUint16(0, value, true); out.push(...new Uint8Array(buf)); }",
881
- "function __anqstPushInt32(out: number[], value: number): void { const buf = new ArrayBuffer(4); const view = new DataView(buf); view.setInt32(0, value, true); out.push(...new Uint8Array(buf)); }",
882
- "function __anqstPushUint32(out: number[], value: number): void { const buf = new ArrayBuffer(4); const view = new DataView(buf); view.setUint32(0, value >>> 0, true); out.push(...new Uint8Array(buf)); }",
883
- "function __anqstPushFloat64(out: number[], value: number): void { const buf = new ArrayBuffer(8); const view = new DataView(buf); view.setFloat64(0, value, true); out.push(...new Uint8Array(buf)); }",
884
- "function __anqstPushBigInt64(out: number[], value: bigint): void { const buf = new ArrayBuffer(8); const view = new DataView(buf); view.setBigInt64(0, value, true); out.push(...new Uint8Array(buf)); }",
885
- "function __anqstPushBigUint64(out: number[], value: bigint): void { const buf = new ArrayBuffer(8); const view = new DataView(buf); view.setBigUint64(0, value, true); out.push(...new Uint8Array(buf)); }",
886
- "",
887
- "function __anqstReadUint8(bytes: Uint8Array, cursor: { offset: number }): number { return bytes[cursor.offset++] ?? 0; }",
888
- "function __anqstReadInt8(bytes: Uint8Array, cursor: { offset: number }): number { const buf = new Uint8Array([bytes[cursor.offset++] ?? 0]); return new Int8Array(buf.buffer)[0] ?? 0; }",
889
- "function __anqstReadBool(bytes: Uint8Array, cursor: { offset: number }): boolean { return (__anqstReadUint8(bytes, cursor) & 1) === 1; }",
890
- "function __anqstReadInt16(bytes: Uint8Array, cursor: { offset: number }): number { const view = new DataView(bytes.buffer, bytes.byteOffset + cursor.offset, 2); const value = view.getInt16(0, true); cursor.offset += 2; return value; }",
891
- "function __anqstReadUint16(bytes: Uint8Array, cursor: { offset: number }): number { const view = new DataView(bytes.buffer, bytes.byteOffset + cursor.offset, 2); const value = view.getUint16(0, true); cursor.offset += 2; return value; }",
892
- "function __anqstReadInt32(bytes: Uint8Array, cursor: { offset: number }): number { const view = new DataView(bytes.buffer, bytes.byteOffset + cursor.offset, 4); const value = view.getInt32(0, true); cursor.offset += 4; return value; }",
893
- "function __anqstReadUint32(bytes: Uint8Array, cursor: { offset: number }): number { const view = new DataView(bytes.buffer, bytes.byteOffset + cursor.offset, 4); const value = view.getUint32(0, true); cursor.offset += 4; return value; }",
894
- "function __anqstReadFloat64(bytes: Uint8Array, cursor: { offset: number }): number { const view = new DataView(bytes.buffer, bytes.byteOffset + cursor.offset, 8); const value = view.getFloat64(0, true); cursor.offset += 8; return value; }",
895
- "function __anqstReadBigInt64(bytes: Uint8Array, cursor: { offset: number }): bigint { const view = new DataView(bytes.buffer, bytes.byteOffset + cursor.offset, 8); const value = view.getBigInt64(0, true); cursor.offset += 8; return value; }",
896
- "function __anqstReadBigUint64(bytes: Uint8Array, cursor: { offset: number }): bigint { const view = new DataView(bytes.buffer, bytes.byteOffset + cursor.offset, 8); const value = view.getBigUint64(0, true); cursor.offset += 8; return value; }",
897
- "",
898
- "function __anqstEncodeBinary_ArrayBuffer(value: ArrayBuffer): string { return __anqstBase93Encode(new Uint8Array(value)); }",
899
- "function __anqstDecodeBinary_ArrayBuffer(encoded: string): ArrayBuffer { const bytes = __anqstBase93Decode(encoded); const copy = new Uint8Array(bytes.byteLength); copy.set(bytes); return copy.buffer as ArrayBuffer; }"
900
- ];
901
- for (const [kind, ctor] of Object.entries(typedArrayCtorByKind)) {
902
- lines.push(`function ${binaryEncodeHelperName(kind)}(value: ${ctor}): string { return __anqstBase93Encode(new Uint8Array(value.buffer, value.byteOffset, value.byteLength)); }`);
903
- lines.push(`function ${binaryDecodeHelperName(kind)}(encoded: string): ${ctor} { const bytes = __anqstBase93Decode(encoded); const buffer = bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength); return new ${ctor}(buffer); }`);
904
- }
905
- return lines.join("\n");
906
- }
907
- function renderTsStructuredCodecHelpers(catalog) {
908
- if (catalog.codecs.length === 0)
909
- return "";
910
- const codecFns = catalog.codecs.map((codec) => emitTsCodec(codec)).join("\n\n");
911
- return `${renderTsBinaryHelpers()}\n\n${codecFns}\n`;
912
- }
913
- function cppScalarWriteHelper(leaf) {
914
- switch (leaf) {
915
- case "boolean": return "anqstPushBool";
916
- case "number": return "anqstPushFloat64";
917
- case "qint64": return "anqstPushQint64";
918
- case "quint64": return "anqstPushQuint64";
919
- case "qint32": return "anqstPushQint32";
920
- case "quint32": return "anqstPushQuint32";
921
- case "qint16": return "anqstPushQint16";
922
- case "quint16": return "anqstPushQuint16";
923
- case "qint8": return "anqstPushQint8";
924
- case "quint8": return "anqstPushQuint8";
925
- case "int32": return "anqstPushInt32";
926
- case "uint32": return "anqstPushUint32";
927
- case "int16": return "anqstPushInt16";
928
- case "uint16": return "anqstPushUint16";
929
- case "int8": return "anqstPushInt8";
930
- case "uint8": return "anqstPushUint8";
931
- default: return "";
932
- }
933
- }
934
- function cppScalarReadHelper(leaf) {
935
- switch (leaf) {
936
- case "boolean": return "anqstReadBool";
937
- case "number": return "anqstReadFloat64";
938
- case "qint64": return "anqstReadQint64";
939
- case "quint64": return "anqstReadQuint64";
940
- case "qint32": return "anqstReadQint32";
941
- case "quint32": return "anqstReadQuint32";
942
- case "qint16": return "anqstReadQint16";
943
- case "quint16": return "anqstReadQuint16";
944
- case "qint8": return "anqstReadQint8";
945
- case "quint8": return "anqstReadQuint8";
946
- case "int32": return "anqstReadInt32";
947
- case "uint32": return "anqstReadUint32";
948
- case "int16": return "anqstReadInt16";
949
- case "uint16": return "anqstReadUint16";
950
- case "int8": return "anqstReadInt8";
951
- case "uint8": return "anqstReadUint8";
952
- default: return "";
953
- }
954
- }
955
- class CppEmitterContext {
956
- constructor() {
957
- this.nextId = 0;
958
- }
959
- next(prefix) {
960
- this.nextId += 1;
961
- return `${prefix}${this.nextId}`;
962
- }
963
- }
964
- function cppNamedHelperStem(shape, scope = "") {
965
- const scopePrefix = scope ? `${sanitizeIdentifier(scope)}_` : "";
966
- return `anqstNamed_${scopePrefix}${sanitizeIdentifier(shape.name)}`;
967
- }
968
- function cppNamedEncodeHelperName(shape, scope = "") {
969
- return `${cppNamedHelperStem(shape, scope)}_encode`;
970
- }
971
- function cppNamedCountHelperName(shape, scope = "") {
972
- return `${cppNamedHelperStem(shape, scope)}_count`;
973
- }
974
- function cppNamedDecodeHelperName(shape, scope = "") {
975
- return `${cppNamedHelperStem(shape, scope)}_decode`;
976
- }
977
- function emitCppEncodeShape(shape, valueExpr, lines, ctx, level, scope = "") {
978
- const pad = " ".repeat(level);
979
- switch (shape.kind) {
980
- case "scalar":
981
- if (shape.leaf === "string") {
982
- lines.push(`${pad}strings.push_back(${valueExpr});`);
983
- }
984
- else if (shape.leaf === "boolean") {
985
- lines.push(`${pad}strings.push_back(${valueExpr} ? QStringLiteral("1") : QStringLiteral("0"));`);
986
- }
987
- else {
988
- lines.push(`${pad}${cppScalarWriteHelper(shape.leaf)}(bytes, ${valueExpr});`);
989
- }
990
- return;
991
- case "named":
992
- lines.push(`${pad}${cppNamedEncodeHelperName(shape, scope)}(${valueExpr}, bytes, strings, binaries, dynamics);`);
993
- return;
994
- case "dynamic":
995
- lines.push(`${pad}dynamics.push_back(QVariant::fromValue(${valueExpr}));`);
996
- return;
997
- case "binary":
998
- lines.push(`${pad}binaries.push_back(anqstEncodeBinary(${valueExpr}));`);
999
- return;
1000
- case "array": {
1001
- const itemName = ctx.next("item");
1002
- lines.push(`${pad}anqstPushUint32(bytes, static_cast<std::uint32_t>(${valueExpr}.size()));`);
1003
- lines.push(`${pad}for (const auto& ${itemName} : ${valueExpr}) {`);
1004
- emitCppEncodeShape(shape.element, itemName, lines, ctx, level + 1, scope);
1005
- lines.push(`${pad}}`);
1006
- return;
1007
- }
1008
- case "struct":
1009
- for (const field of shape.fields) {
1010
- const fieldExpr = `${valueExpr}.${field.name}`;
1011
- if (field.optional) {
1012
- const present = ctx.next("present");
1013
- lines.push(`${pad}const bool ${present} = ${fieldExpr}.has_value();`);
1014
- lines.push(`${pad}anqstPushUint8(bytes, ${present} ? 1u : 0u);`);
1015
- lines.push(`${pad}if (${present}) {`);
1016
- emitCppEncodeShape(field.shape, `${fieldExpr}.value()`, lines, ctx, level + 1, scope);
1017
- lines.push(`${pad}}`);
1018
- }
1019
- else {
1020
- emitCppEncodeShape(field.shape, fieldExpr, lines, ctx, level, scope);
1021
- }
1022
- }
1023
- }
1024
- }
1025
- function emitCppCountPass(shape, lines, ctx, level, scope = "") {
1026
- const pad = " ".repeat(level);
1027
- switch (shape.kind) {
1028
- case "scalar": {
1029
- if (shape.leaf === "string" || shape.leaf === "boolean") {
1030
- lines.push(`${pad}stringCount += 1;`);
1031
- }
1032
- else {
1033
- const widths = {
1034
- boolean: 0,
1035
- number: 8,
1036
- qint64: 8,
1037
- quint64: 8,
1038
- qint32: 4,
1039
- quint32: 4,
1040
- qint16: 2,
1041
- quint16: 2,
1042
- qint8: 1,
1043
- quint8: 1,
1044
- int32: 4,
1045
- uint32: 4,
1046
- int16: 2,
1047
- uint16: 2,
1048
- int8: 1,
1049
- uint8: 1
1050
- };
1051
- if (widths[shape.leaf] > 0) {
1052
- lines.push(`${pad}countOffset += ${widths[shape.leaf]};`);
1053
- }
1054
- }
1055
- return;
1056
- }
1057
- case "named":
1058
- lines.push(`${pad}${cppNamedCountHelperName(shape, scope)}(blob, countOffset, stringCount, binaryCount, dynamicCount);`);
1059
- return;
1060
- case "dynamic":
1061
- lines.push(`${pad}dynamicCount += 1;`);
1062
- return;
1063
- case "binary":
1064
- lines.push(`${pad}binaryCount += 1;`);
1065
- return;
1066
- case "array": {
1067
- const countVar = ctx.next("count");
1068
- lines.push(`${pad}const auto ${countVar} = anqstReadUint32(blob, countOffset);`);
1069
- lines.push(`${pad}for (std::uint32_t i = 0; i < ${countVar}; ++i) {`);
1070
- emitCppCountPass(shape.element, lines, ctx, level + 1, scope);
1071
- lines.push(`${pad}}`);
1072
- return;
1073
- }
1074
- case "struct":
1075
- for (const field of shape.fields) {
1076
- if (field.optional) {
1077
- const present = ctx.next("present");
1078
- lines.push(`${pad}const bool ${present} = anqstReadUint8(blob, countOffset) != 0;`);
1079
- lines.push(`${pad}if (${present}) {`);
1080
- emitCppCountPass(field.shape, lines, ctx, level + 1, scope);
1081
- lines.push(`${pad}}`);
1082
- }
1083
- else {
1084
- emitCppCountPass(field.shape, lines, ctx, level, scope);
1085
- }
1086
- }
1087
- }
1088
- }
1089
- function emitCppDecodeValue(shape, lines, ctx, level, mapCppType, scope = "") {
1090
- const pad = " ".repeat(level);
1091
- switch (shape.kind) {
1092
- case "scalar":
1093
- if (shape.leaf === "string")
1094
- return `items.value(static_cast<int>(stringIndex++)).toString()`;
1095
- if (shape.leaf === "boolean")
1096
- return `items.value(static_cast<int>(stringIndex++)).toString() == QStringLiteral("1")`;
1097
- return `${cppScalarReadHelper(shape.leaf)}(blob, dataOffset)`;
1098
- case "named":
1099
- return `${cppNamedDecodeHelperName(shape, scope)}(items, blob, stringIndex, binaryIndex, dynamicIndex, dataOffset)`;
1100
- case "dynamic":
1101
- return `items.value(static_cast<int>(dynamicIndex++)).toMap()`;
1102
- case "binary":
1103
- return `anqstDecodeBinary(items.value(static_cast<int>(binaryIndex++)).toString())`;
1104
- case "array": {
1105
- const arrayType = mapCppType(shape.typeText, shape.pathHintParts);
1106
- const arrayVar = ctx.next("array");
1107
- const countVar = ctx.next("count");
1108
- lines.push(`${pad}${arrayType} ${arrayVar};`);
1109
- lines.push(`${pad}const auto ${countVar} = anqstReadUint32(blob, dataOffset);`);
1110
- lines.push(`${pad}for (std::uint32_t i = 0; i < ${countVar}; ++i) {`);
1111
- const itemExpr = emitCppDecodeValue(shape.element, lines, ctx, level + 1, mapCppType, scope);
1112
- lines.push(`${" ".repeat(level + 1)}${arrayVar}.push_back(${itemExpr});`);
1113
- lines.push(`${pad}}`);
1114
- return arrayVar;
1115
- }
1116
- case "struct": {
1117
- const valueType = mapCppType(shape.typeText, shape.pathHintParts);
1118
- const valueVar = ctx.next("value");
1119
- lines.push(`${pad}${valueType} ${valueVar}{};`);
1120
- for (const field of shape.fields) {
1121
- if (field.optional) {
1122
- const present = ctx.next("present");
1123
- lines.push(`${pad}if (anqstReadUint8(blob, dataOffset) != 0) {`);
1124
- const fieldExpr = emitCppDecodeValue(field.shape, lines, ctx, level + 1, mapCppType, scope);
1125
- lines.push(`${" ".repeat(level + 1)}${valueVar}.${field.name} = ${fieldExpr};`);
1126
- lines.push(`${pad}} else {`);
1127
- lines.push(`${" ".repeat(level + 1)}${valueVar}.${field.name} = std::nullopt;`);
1128
- lines.push(`${pad}}`);
1129
- }
1130
- else {
1131
- const fieldExpr = emitCppDecodeValue(field.shape, lines, ctx, level, mapCppType, scope);
1132
- lines.push(`${pad}${valueVar}.${field.name} = ${fieldExpr};`);
1133
- }
1134
- }
1135
- return valueVar;
1136
- }
1137
- }
1138
- }
1139
- function emitCppCodec(def, mapCppType) {
1140
- const namedShapes = [...collectNamedShapes(def.shape).values()];
1141
- const ctx = new CppEmitterContext();
1142
- const cppType = mapCppType(def.typeText, def.shape.pathHintParts);
1143
- const encoderName = `encode${def.codecId}`;
1144
- const decoderName = `decode${def.codecId}`;
1145
- const encodeLines = [];
1146
- emitCppEncodeShape(def.shape, "value", encodeLines, ctx, 1, def.codecId);
1147
- const countLines = [];
1148
- if (def.analysis.hasBlob) {
1149
- emitCppCountPass(def.shape, countLines, ctx, 1, def.codecId);
1150
- }
1151
- const decodeLines = [];
1152
- const decodeExpr = emitCppDecodeValue(def.shape, decodeLines, ctx, 1, mapCppType, def.codecId);
1153
- const namedDeclarations = namedShapes.map((shape) => {
1154
- const helperType = mapCppType(shape.typeText, shape.pathHintParts);
1155
- return `inline void ${cppNamedEncodeHelperName(shape, def.codecId)}(
1156
- const ${helperType}& value,
1157
- std::vector<std::uint8_t>& bytes,
1158
- QStringList& strings,
1159
- QStringList& binaries,
1160
- QVariantList& dynamics
1161
- );
1162
- inline void ${cppNamedCountHelperName(shape, def.codecId)}(
1163
- const std::vector<std::uint8_t>& blob,
1164
- std::size_t& countOffset,
1165
- std::size_t& stringCount,
1166
- std::size_t& binaryCount,
1167
- std::size_t& dynamicCount
1168
- );
1169
- inline ${helperType} ${cppNamedDecodeHelperName(shape, def.codecId)}(
1170
- const QVariantList& items,
1171
- const std::vector<std::uint8_t>& blob,
1172
- std::size_t& stringIndex,
1173
- std::size_t& binaryIndex,
1174
- std::size_t& dynamicIndex,
1175
- std::size_t& dataOffset
1176
- );`;
1177
- }).join("\n");
1178
- const namedHelpers = namedShapes.map((shape) => {
1179
- const helperCtx = new CppEmitterContext();
1180
- const helperType = mapCppType(shape.typeText, shape.pathHintParts);
1181
- const helperEncodeLines = [];
1182
- emitCppEncodeShape(shape.target, "value", helperEncodeLines, helperCtx, 1, def.codecId);
1183
- const helperCountLines = [];
1184
- emitCppCountPass(shape.target, helperCountLines, helperCtx, 1, def.codecId);
1185
- const helperDecodeLines = [];
1186
- const helperDecodeExpr = emitCppDecodeValue(shape.target, helperDecodeLines, helperCtx, 1, mapCppType, def.codecId);
1187
- return `inline void ${cppNamedEncodeHelperName(shape, def.codecId)}(
1188
- const ${helperType}& value,
1189
- std::vector<std::uint8_t>& bytes,
1190
- QStringList& strings,
1191
- QStringList& binaries,
1192
- QVariantList& dynamics
1193
- ) {
1194
- ${helperEncodeLines.join("\n")}
1195
- }
1196
-
1197
- inline void ${cppNamedCountHelperName(shape, def.codecId)}(
1198
- const std::vector<std::uint8_t>& blob,
1199
- std::size_t& countOffset,
1200
- std::size_t& stringCount,
1201
- std::size_t& binaryCount,
1202
- std::size_t& dynamicCount
1203
- ) {
1204
- ${helperCountLines.join("\n")}
1205
- }
1206
-
1207
- inline ${helperType} ${cppNamedDecodeHelperName(shape, def.codecId)}(
1208
- const QVariantList& items,
1209
- const std::vector<std::uint8_t>& blob,
1210
- std::size_t& stringIndex,
1211
- std::size_t& binaryIndex,
1212
- std::size_t& dynamicIndex,
1213
- std::size_t& dataOffset
1214
- ) {
1215
- ${helperDecodeLines.join("\n")}
1216
- return ${helperDecodeExpr};
1217
- }`;
1218
- }).join("\n\n");
1219
- return `${namedDeclarations ? `${namedDeclarations}\n\n` : ""}${namedHelpers ? `${namedHelpers}\n\n` : ""}inline QVariant ${encoderName}(const ${cppType}& value) {
1220
- std::vector<std::uint8_t> bytes;
1221
- QStringList strings;
1222
- QStringList binaries;
1223
- QVariantList dynamics;
1224
- ${encodeLines.join("\n")}
1225
- return anqstFinalizeWire(bytes, strings, binaries, dynamics);
1226
- }
1227
-
1228
- inline ${cppType} ${decoderName}(const QVariant& wire) {
1229
- const QVariantList items = anqstNormalizeWireItems(wire);
1230
- const std::vector<std::uint8_t> blob = ${def.analysis.hasBlob ? `(items.isEmpty() ? std::vector<std::uint8_t>{} : base93Decode(items.value(0).toString().toStdString()))` : "std::vector<std::uint8_t>{}"};
1231
- std::size_t stringCount = 0;
1232
- std::size_t binaryCount = 0;
1233
- std::size_t dynamicCount = 0;
1234
- std::size_t countOffset = 0;
1235
- ${countLines.join("\n")}
1236
- std::size_t stringIndex = ${def.analysis.hasBlob ? 1 : 0};
1237
- std::size_t binaryIndex = ${def.analysis.hasBlob ? 1 : 0} + stringCount;
1238
- std::size_t dynamicIndex = ${def.analysis.hasBlob ? 1 : 0} + stringCount + binaryCount;
1239
- std::size_t dataOffset = 0;
1240
- ${decodeLines.join("\n")}
1241
- return ${decodeExpr};
1242
- }`;
1243
- }
1244
- function renderCppStructuredCodecHelpers(catalog, mapCppType) {
1245
- if (catalog.codecs.length === 0)
1246
- return "";
1247
- const helpers = [
1248
- (0, base93_1.emitBase93CppFunctions)(),
1249
- "",
1250
- "inline QVariantList anqstNormalizeWireItems(const QVariant& wire) {",
1251
- " return wire.type() == QVariant::List ? wire.toList() : QVariantList{wire};",
1252
- "}",
1253
- "",
1254
- "inline QVariant anqstFinalizeWire(const std::vector<std::uint8_t>& bytes, const QStringList& strings, const QStringList& binaries, const QVariantList& dynamics) {",
1255
- " QVariantList items;",
1256
- " if (!bytes.empty()) items.push_back(QString::fromStdString(base93Encode(bytes)));",
1257
- " for (const auto& value : strings) items.push_back(value);",
1258
- " for (const auto& value : binaries) items.push_back(value);",
1259
- " for (const auto& value : dynamics) items.push_back(value);",
1260
- " if (items.size() == 1) return items.front();",
1261
- " return items;",
1262
- "}",
1263
- "",
1264
- "inline void anqstPushUint8(std::vector<std::uint8_t>& out, std::uint8_t value) { out.push_back(value); }",
1265
- "inline void anqstPushInt8(std::vector<std::uint8_t>& out, std::int8_t value) { out.push_back(static_cast<std::uint8_t>(value)); }",
1266
- "inline void anqstPushBool(std::vector<std::uint8_t>& out, bool value) { out.push_back(value ? 1u : 0u); }",
1267
- "inline void anqstPushUint16(std::vector<std::uint8_t>& out, std::uint16_t value) { out.push_back(static_cast<std::uint8_t>(value & 0xffu)); out.push_back(static_cast<std::uint8_t>((value >> 8) & 0xffu)); }",
1268
- "inline void anqstPushInt16(std::vector<std::uint8_t>& out, std::int16_t value) { anqstPushUint16(out, static_cast<std::uint16_t>(value)); }",
1269
- "inline void anqstPushQuint16(std::vector<std::uint8_t>& out, quint16 value) { anqstPushUint16(out, static_cast<std::uint16_t>(value)); }",
1270
- "inline void anqstPushQint16(std::vector<std::uint8_t>& out, qint16 value) { anqstPushInt16(out, static_cast<std::int16_t>(value)); }",
1271
- "inline void anqstPushUint32(std::vector<std::uint8_t>& out, std::uint32_t value) { out.push_back(static_cast<std::uint8_t>(value & 0xffu)); out.push_back(static_cast<std::uint8_t>((value >> 8) & 0xffu)); out.push_back(static_cast<std::uint8_t>((value >> 16) & 0xffu)); out.push_back(static_cast<std::uint8_t>((value >> 24) & 0xffu)); }",
1272
- "inline void anqstPushInt32(std::vector<std::uint8_t>& out, std::int32_t value) { anqstPushUint32(out, static_cast<std::uint32_t>(value)); }",
1273
- "inline void anqstPushQuint32(std::vector<std::uint8_t>& out, quint32 value) { anqstPushUint32(out, static_cast<std::uint32_t>(value)); }",
1274
- "inline void anqstPushQint32(std::vector<std::uint8_t>& out, qint32 value) { anqstPushInt32(out, static_cast<std::int32_t>(value)); }",
1275
- "inline void anqstPushQuint64(std::vector<std::uint8_t>& out, quint64 value) { for (int shift = 0; shift < 64; shift += 8) out.push_back(static_cast<std::uint8_t>((static_cast<std::uint64_t>(value) >> shift) & 0xffu)); }",
1276
- "inline void anqstPushQint64(std::vector<std::uint8_t>& out, qint64 value) { anqstPushQuint64(out, static_cast<quint64>(value)); }",
1277
- "inline void anqstPushFloat64(std::vector<std::uint8_t>& out, double value) { std::uint64_t bits = 0; std::memcpy(&bits, &value, sizeof(bits)); anqstPushQuint64(out, bits); }",
1278
- "",
1279
- "inline std::uint8_t anqstReadUint8(const std::vector<std::uint8_t>& bytes, std::size_t& offset) { return offset < bytes.size() ? bytes[offset++] : 0u; }",
1280
- "inline std::int8_t anqstReadInt8(const std::vector<std::uint8_t>& bytes, std::size_t& offset) { return static_cast<std::int8_t>(anqstReadUint8(bytes, offset)); }",
1281
- "inline bool anqstReadBool(const std::vector<std::uint8_t>& bytes, std::size_t& offset) { return anqstReadUint8(bytes, offset) != 0u; }",
1282
- "inline std::uint16_t anqstReadUint16(const std::vector<std::uint8_t>& bytes, std::size_t& offset) { const std::uint16_t b0 = anqstReadUint8(bytes, offset); const std::uint16_t b1 = anqstReadUint8(bytes, offset); return static_cast<std::uint16_t>(b0 | (b1 << 8)); }",
1283
- "inline std::int16_t anqstReadInt16(const std::vector<std::uint8_t>& bytes, std::size_t& offset) { return static_cast<std::int16_t>(anqstReadUint16(bytes, offset)); }",
1284
- "inline quint16 anqstReadQuint16(const std::vector<std::uint8_t>& bytes, std::size_t& offset) { return static_cast<quint16>(anqstReadUint16(bytes, offset)); }",
1285
- "inline qint16 anqstReadQint16(const std::vector<std::uint8_t>& bytes, std::size_t& offset) { return static_cast<qint16>(anqstReadInt16(bytes, offset)); }",
1286
- "inline std::uint32_t anqstReadUint32(const std::vector<std::uint8_t>& bytes, std::size_t& offset) { const std::uint32_t b0 = anqstReadUint8(bytes, offset); const std::uint32_t b1 = anqstReadUint8(bytes, offset); const std::uint32_t b2 = anqstReadUint8(bytes, offset); const std::uint32_t b3 = anqstReadUint8(bytes, offset); return b0 | (b1 << 8) | (b2 << 16) | (b3 << 24); }",
1287
- "inline std::int32_t anqstReadInt32(const std::vector<std::uint8_t>& bytes, std::size_t& offset) { return static_cast<std::int32_t>(anqstReadUint32(bytes, offset)); }",
1288
- "inline quint32 anqstReadQuint32(const std::vector<std::uint8_t>& bytes, std::size_t& offset) { return static_cast<quint32>(anqstReadUint32(bytes, offset)); }",
1289
- "inline qint32 anqstReadQint32(const std::vector<std::uint8_t>& bytes, std::size_t& offset) { return static_cast<qint32>(anqstReadInt32(bytes, offset)); }",
1290
- "inline std::uint64_t anqstReadQuint64(const std::vector<std::uint8_t>& bytes, std::size_t& offset) { std::uint64_t value = 0; for (int shift = 0; shift < 64; shift += 8) value |= (static_cast<std::uint64_t>(anqstReadUint8(bytes, offset)) << shift); return value; }",
1291
- "inline std::int64_t anqstReadQint64(const std::vector<std::uint8_t>& bytes, std::size_t& offset) { return static_cast<std::int64_t>(anqstReadQuint64(bytes, offset)); }",
1292
- "inline double anqstReadFloat64(const std::vector<std::uint8_t>& bytes, std::size_t& offset) { const std::uint64_t bits = anqstReadQuint64(bytes, offset); double value = 0; std::memcpy(&value, &bits, sizeof(value)); return value; }",
1293
- "",
1294
- "inline QString anqstEncodeBinary(const QByteArray& value) {",
1295
- " return QString::fromStdString(base93Encode(std::vector<std::uint8_t>(value.begin(), value.end())));",
1296
- "}",
1297
- "",
1298
- "inline QByteArray anqstDecodeBinary(const QString& encoded) {",
1299
- " const auto bytes = base93Decode(encoded.toStdString());",
1300
- " return QByteArray(reinterpret_cast<const char*>(bytes.data()), static_cast<int>(bytes.size()));",
1301
- "}"
1302
- ];
1303
- const codecs = catalog.codecs.map((codec) => emitCppCodec(codec, mapCppType));
1304
- return `${helpers.join("\n")}\n\n${codecs.join("\n\n")}\n`;
1305
- }