typia 5.0.0-dev.20230823-2 → 5.0.0-dev.2023084

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 (148) hide show
  1. package/lib/factories/MetadataTagFactory.js +4 -2
  2. package/lib/factories/MetadataTagFactory.js.map +1 -1
  3. package/lib/factories/ProtobufFactory.js +2 -1
  4. package/lib/factories/ProtobufFactory.js.map +1 -1
  5. package/lib/factories/internal/metadata/emend_metadata_atomics.js +6 -6
  6. package/lib/factories/internal/metadata/emend_metadata_atomics.js.map +1 -1
  7. package/lib/factories/internal/metadata/iterate_metadata_atomic.js +1 -1
  8. package/lib/factories/internal/metadata/iterate_metadata_atomic.js.map +1 -1
  9. package/lib/programmers/CheckerProgrammer.js +6 -6
  10. package/lib/programmers/CheckerProgrammer.js.map +1 -1
  11. package/lib/programmers/RandomProgrammer.js +5 -5
  12. package/lib/programmers/RandomProgrammer.js.map +1 -1
  13. package/lib/programmers/helpers/AtomicPredicator.js +2 -2
  14. package/lib/programmers/helpers/AtomicPredicator.js.map +1 -1
  15. package/lib/programmers/helpers/ProtobufUtil.js +2 -2
  16. package/lib/programmers/helpers/ProtobufUtil.js.map +1 -1
  17. package/lib/programmers/internal/application_default_string.js +2 -2
  18. package/lib/programmers/internal/application_default_string.js.map +1 -1
  19. package/lib/programmers/internal/application_schema.js +5 -5
  20. package/lib/programmers/internal/application_schema.js.map +1 -1
  21. package/lib/programmers/internal/metadata_to_pattern.js +4 -4
  22. package/lib/programmers/internal/metadata_to_pattern.js.map +1 -1
  23. package/lib/programmers/internal/stringify_dynamic_properties.js +2 -1
  24. package/lib/programmers/internal/stringify_dynamic_properties.js.map +1 -1
  25. package/lib/programmers/json/JsonStringifyProgrammer.js +16 -10
  26. package/lib/programmers/json/JsonStringifyProgrammer.js.map +1 -1
  27. package/lib/programmers/misc/MiscLiteralsProgrammer.js +2 -2
  28. package/lib/programmers/misc/MiscLiteralsProgrammer.js.map +1 -1
  29. package/lib/programmers/protobuf/ProtobufDecodeProgrammer.js +1 -1
  30. package/lib/programmers/protobuf/ProtobufDecodeProgrammer.js.map +1 -1
  31. package/lib/schemas/metadata/IMetadata.d.ts +2 -2
  32. package/lib/schemas/metadata/IMetadataAtomic.d.ts +12 -0
  33. package/lib/schemas/metadata/IMetadataAtomic.js +3 -0
  34. package/lib/schemas/metadata/IMetadataAtomic.js.map +1 -0
  35. package/lib/schemas/metadata/Metadata.d.ts +2 -2
  36. package/lib/schemas/metadata/Metadata.js +49 -44
  37. package/lib/schemas/metadata/Metadata.js.map +1 -1
  38. package/lib/tags/ExclusiveMaximum.d.ts +8 -0
  39. package/lib/tags/ExclusiveMaximum.js +3 -0
  40. package/lib/tags/ExclusiveMaximum.js.map +1 -0
  41. package/lib/tags/ExclusiveMinimum.d.ts +8 -0
  42. package/lib/tags/ExclusiveMinimum.js +3 -0
  43. package/lib/tags/ExclusiveMinimum.js.map +1 -0
  44. package/lib/tags/Format.d.ts +8 -0
  45. package/lib/tags/Format.js +3 -0
  46. package/lib/tags/Format.js.map +1 -0
  47. package/lib/tags/MaxItems.d.ts +8 -0
  48. package/lib/tags/MaxItems.js +3 -0
  49. package/lib/tags/MaxItems.js.map +1 -0
  50. package/lib/tags/MaxLength.d.ts +8 -0
  51. package/lib/tags/MaxLength.js +3 -0
  52. package/lib/tags/MaxLength.js.map +1 -0
  53. package/lib/tags/Maximum.d.ts +8 -0
  54. package/lib/tags/Maximum.js +3 -0
  55. package/lib/tags/Maximum.js.map +1 -0
  56. package/lib/tags/MinItems.d.ts +8 -0
  57. package/lib/tags/MinItems.js +3 -0
  58. package/lib/tags/MinItems.js.map +1 -0
  59. package/lib/tags/MinLength.d.ts +8 -0
  60. package/lib/tags/MinLength.js +3 -0
  61. package/lib/tags/MinLength.js.map +1 -0
  62. package/lib/tags/Minimum.d.ts +8 -0
  63. package/lib/tags/Minimum.js +3 -0
  64. package/lib/tags/Minimum.js.map +1 -0
  65. package/lib/tags/MultipleOf.d.ts +8 -0
  66. package/lib/tags/MultipleOf.js +3 -0
  67. package/lib/tags/MultipleOf.js.map +1 -0
  68. package/lib/tags/Pattern.d.ts +8 -0
  69. package/lib/tags/Pattern.js +3 -0
  70. package/lib/tags/Pattern.js.map +1 -0
  71. package/lib/tags/TagBase.d.ts +10 -0
  72. package/lib/tags/TagBase.js +3 -0
  73. package/lib/tags/TagBase.js.map +1 -0
  74. package/lib/tags/Type.d.ts +13 -0
  75. package/lib/tags/Type.js +3 -0
  76. package/lib/tags/Type.js.map +1 -0
  77. package/lib/tags/index.d.ts +12 -0
  78. package/lib/tags/index.js +29 -0
  79. package/lib/tags/index.js.map +1 -0
  80. package/lib/transformers/features/json/JsonApplicationTransformer.js +1 -1
  81. package/lib/transformers/features/json/JsonApplicationTransformer.js.map +1 -1
  82. package/package.json +1 -1
  83. package/src/Primitive.ts +135 -135
  84. package/src/Resolved.ts +116 -116
  85. package/src/factories/MetadataFactory.ts +46 -46
  86. package/src/factories/MetadataTagFactory.ts +366 -364
  87. package/src/factories/ProtobufFactory.ts +268 -266
  88. package/src/factories/internal/metadata/emend_metadata_atomics.ts +35 -33
  89. package/src/factories/internal/metadata/explore_metadata.ts +38 -38
  90. package/src/factories/internal/metadata/iterate_metadata_atomic.ts +63 -59
  91. package/src/factories/internal/metadata/iterate_metadata_collection.ts +133 -133
  92. package/src/factories/internal/metadata/iterate_metadata_native.ts +210 -210
  93. package/src/factories/internal/metadata/iterate_metadata_resolve.ts +49 -49
  94. package/src/factories/internal/metadata/iterate_metadata_sort.ts +69 -69
  95. package/src/functional/$ProtobufWriter.ts +151 -151
  96. package/src/json.ts +648 -648
  97. package/src/misc.ts +651 -651
  98. package/src/module.ts +709 -709
  99. package/src/programmers/AssertProgrammer.ts +281 -281
  100. package/src/programmers/CheckerProgrammer.ts +1174 -1173
  101. package/src/programmers/IsProgrammer.ts +241 -241
  102. package/src/programmers/RandomProgrammer.ts +874 -874
  103. package/src/programmers/ValidateProgrammer.ts +307 -307
  104. package/src/programmers/helpers/AtomicPredicator.ts +31 -31
  105. package/src/programmers/helpers/FunctionImporeter.ts +91 -91
  106. package/src/programmers/helpers/ProtobufUtil.ts +29 -29
  107. package/src/programmers/helpers/StringifyPredicator.ts +12 -12
  108. package/src/programmers/helpers/disable_function_importer_declare.ts +32 -32
  109. package/src/programmers/internal/application_default_string.ts +37 -33
  110. package/src/programmers/internal/application_resolved.ts +55 -55
  111. package/src/programmers/internal/application_schema.ts +157 -157
  112. package/src/programmers/internal/metadata_to_pattern.ts +34 -34
  113. package/src/programmers/internal/stringify_dynamic_properties.ts +171 -171
  114. package/src/programmers/json/JsonStringifyProgrammer.ts +995 -989
  115. package/src/programmers/misc/MiscAssertCloneProgrammer.ts +71 -71
  116. package/src/programmers/misc/MiscCloneProgrammer.ts +775 -775
  117. package/src/programmers/misc/MiscIsCloneProgrammer.ts +78 -78
  118. package/src/programmers/misc/MiscLiteralsProgrammer.ts +64 -64
  119. package/src/programmers/misc/MiscPruneProgrammer.ts +544 -544
  120. package/src/programmers/misc/MiscValidateCloneProgrammer.ts +85 -85
  121. package/src/programmers/protobuf/ProtobufAssertDecodeProgrammer.ts +75 -75
  122. package/src/programmers/protobuf/ProtobufDecodeProgrammer.ts +673 -673
  123. package/src/programmers/protobuf/ProtobufEncodeProgrammer.ts +814 -814
  124. package/src/programmers/protobuf/ProtobufIsDecodeProgrammer.ts +85 -85
  125. package/src/programmers/protobuf/ProtobufValidateDecodeProgrammer.ts +75 -75
  126. package/src/protobuf.ts +881 -881
  127. package/src/schemas/metadata/IMetadata.ts +27 -28
  128. package/src/schemas/metadata/IMetadataAtomic.ts +13 -0
  129. package/src/schemas/metadata/IMetadataEscaped.ts +6 -6
  130. package/src/schemas/metadata/Metadata.ts +643 -634
  131. package/src/schemas/metadata/MetadataEscaped.ts +51 -51
  132. package/src/tags/ExclusiveMaximum.ts +8 -0
  133. package/src/tags/ExclusiveMinimum.ts +8 -0
  134. package/src/tags/Format.ts +29 -0
  135. package/src/tags/MaxItems.ts +8 -0
  136. package/src/tags/MaxLength.ts +8 -0
  137. package/src/tags/Maximum.ts +8 -0
  138. package/src/tags/MinItems.ts +8 -0
  139. package/src/tags/MinLength.ts +8 -0
  140. package/src/tags/Minimum.ts +8 -0
  141. package/src/tags/MultipleOf.ts +10 -0
  142. package/src/tags/Pattern.ts +8 -0
  143. package/src/tags/TagBase.ts +17 -0
  144. package/src/tags/Type.ts +30 -0
  145. package/src/tags/index.ts +12 -0
  146. package/src/transformers/features/json/JsonApplicationTransformer.ts +111 -111
  147. package/src/transformers/features/misc/MetadataTransformer.ts +53 -53
  148. package/src/utils/RandomGenerator.ts +83 -83
@@ -1,673 +1,673 @@
1
- import ts from "typescript";
2
-
3
- import { ExpressionFactory } from "../../factories/ExpressionFactory";
4
- import { IdentifierFactory } from "../../factories/IdentifierFactory";
5
- import { MetadataCollection } from "../../factories/MetadataCollection";
6
- import { MetadataFactory } from "../../factories/MetadataFactory";
7
- import { ProtobufFactory } from "../../factories/ProtobufFactory";
8
- import { StatementFactory } from "../../factories/StatementFactory";
9
- import { TypeFactory } from "../../factories/TypeFactory";
10
-
11
- import { IMetadataTag } from "../../schemas/metadata/IMetadataTag";
12
- import { Metadata } from "../../schemas/metadata/Metadata";
13
- import { MetadataArray } from "../../schemas/metadata/MetadataArray";
14
- import { MetadataObject } from "../../schemas/metadata/MetadataObject";
15
- import { MetadataProperty } from "../../schemas/metadata/MetadataProperty";
16
-
17
- import { IProject } from "../../transformers/IProject";
18
-
19
- import { Atomic } from "../../typings/Atomic";
20
-
21
- import { FunctionImporter } from "../helpers/FunctionImporeter";
22
- import { ProtobufUtil } from "../helpers/ProtobufUtil";
23
-
24
- export namespace ProtobufDecodeProgrammer {
25
- export const write =
26
- (project: IProject) =>
27
- (modulo: ts.LeftHandSideExpression) =>
28
- (type: ts.Type, name?: string): ts.ArrowFunction => {
29
- const importer: FunctionImporter = new FunctionImporter(
30
- modulo.getText(),
31
- );
32
- const collection: MetadataCollection = new MetadataCollection();
33
- const meta: Metadata = ProtobufFactory.metadata(modulo.getText())(
34
- project.checker,
35
- )(collection)(type);
36
-
37
- const functors = collection
38
- .objects()
39
- .filter((obj) => ProtobufUtil.isStaticObject(obj))
40
- .map((obj) =>
41
- StatementFactory.constant(
42
- `${PREFIX}o${obj.index}`,
43
- write_object_function(project)(importer)(obj),
44
- ),
45
- );
46
- const reader = StatementFactory.constant(
47
- "reader",
48
- ts.factory.createNewExpression(
49
- importer.use("Reader"),
50
- undefined,
51
- [ts.factory.createIdentifier("input")],
52
- ),
53
- );
54
-
55
- return ts.factory.createArrowFunction(
56
- undefined,
57
- undefined,
58
- [
59
- IdentifierFactory.parameter(
60
- "input",
61
- ts.factory.createTypeReferenceNode("Uint8Array"),
62
- ),
63
- ],
64
- ts.factory.createTypeReferenceNode(
65
- `typia.Resolved<${
66
- name ?? TypeFactory.getFullName(project.checker)(type)
67
- }>`,
68
- ),
69
- undefined,
70
- ts.factory.createBlock(
71
- [
72
- ...importer.declare(modulo),
73
- ...functors,
74
- reader,
75
- ts.factory.createReturnStatement(
76
- decode_regular_object(true)(meta.objects[0]!),
77
- ),
78
- ],
79
- true,
80
- ),
81
- );
82
- };
83
-
84
- const write_object_function =
85
- (project: IProject) =>
86
- (importer: FunctionImporter) =>
87
- (obj: MetadataObject): ts.ArrowFunction =>
88
- ts.factory.createArrowFunction(
89
- undefined,
90
- undefined,
91
- [
92
- IdentifierFactory.parameter("reader"),
93
- IdentifierFactory.parameter(
94
- "length",
95
- TypeFactory.keyword("number"),
96
- ts.factory.createNumericLiteral(-1),
97
- ),
98
- ],
99
- TypeFactory.keyword("any"),
100
- undefined,
101
- ts.factory.createBlock(
102
- [
103
- ts.factory.createExpressionStatement(
104
- ts.factory.createBinaryExpression(
105
- ts.factory.createIdentifier("length"),
106
- ts.factory.createToken(
107
- ts.SyntaxKind.EqualsToken,
108
- ),
109
- ts.factory.createConditionalExpression(
110
- ts.factory.createLessThan(
111
- ts.factory.createIdentifier("length"),
112
- ts.factory.createNumericLiteral(0),
113
- ),
114
- undefined,
115
- ts.factory.createCallExpression(
116
- IdentifierFactory.access(READER())(
117
- "size",
118
- ),
119
- undefined,
120
- undefined,
121
- ),
122
- undefined,
123
- ts.factory.createAdd(
124
- ts.factory.createCallExpression(
125
- IdentifierFactory.access(READER())(
126
- "index",
127
- ),
128
- undefined,
129
- undefined,
130
- ),
131
- ts.factory.createIdentifier("length"),
132
- ),
133
- ),
134
- ),
135
- ),
136
- ...write_object_function_body(project)(importer)({
137
- condition: ts.factory.createLessThan(
138
- ts.factory.createCallExpression(
139
- IdentifierFactory.access(READER())("index"),
140
- undefined,
141
- undefined,
142
- ),
143
- ts.factory.createIdentifier("length"),
144
- ),
145
- tag: "tag",
146
- output: "output",
147
- })(obj.properties),
148
- ts.factory.createReturnStatement(
149
- ts.factory.createIdentifier("output"),
150
- ),
151
- ],
152
- true,
153
- ),
154
- );
155
-
156
- const write_object_function_body =
157
- (project: IProject) =>
158
- (importer: FunctionImporter) =>
159
- (props: { condition: ts.Expression; tag: string; output: string }) =>
160
- (properties: MetadataProperty[]): ts.Statement[] => {
161
- let i: number = 1;
162
- const clauses: ts.CaseClause[] = properties
163
- .map((p) => {
164
- const clause = decode_property(project)(importer)(i)(
165
- IdentifierFactory.access(
166
- ts.factory.createIdentifier(props.output),
167
- )(p.key.getSoleLiteral()!),
168
- p.value,
169
- p.tags,
170
- );
171
- i += p.value.binarySize();
172
- return clause;
173
- })
174
- .flat();
175
- return [
176
- StatementFactory.constant(
177
- props.output,
178
- ts.factory.createObjectLiteralExpression(
179
- properties.map((p) =>
180
- ts.factory.createPropertyAssignment(
181
- IdentifierFactory.identifier(
182
- p.key.getSoleLiteral()!,
183
- ),
184
- write_property_default_value(p.value),
185
- ),
186
- ),
187
- true,
188
- ),
189
- ),
190
- ts.factory.createWhileStatement(
191
- props.condition,
192
- ts.factory.createBlock([
193
- StatementFactory.constant(
194
- props.tag,
195
- ts.factory.createCallExpression(
196
- IdentifierFactory.access(READER())("uint32"),
197
- undefined,
198
- undefined,
199
- ),
200
- ),
201
- ts.factory.createSwitchStatement(
202
- ts.factory.createUnsignedRightShift(
203
- ts.factory.createIdentifier(props.tag),
204
- ts.factory.createNumericLiteral(3),
205
- ),
206
- ts.factory.createCaseBlock([
207
- ...clauses,
208
- ts.factory.createDefaultClause([
209
- ts.factory.createExpressionStatement(
210
- ts.factory.createCallExpression(
211
- IdentifierFactory.access(READER())(
212
- "skipType",
213
- ),
214
- undefined,
215
- [
216
- ts.factory.createBitwiseAnd(
217
- ts.factory.createIdentifier(
218
- props.tag,
219
- ),
220
- ts.factory.createNumericLiteral(
221
- 7,
222
- ),
223
- ),
224
- ],
225
- ),
226
- ),
227
- ts.factory.createBreakStatement(),
228
- ]),
229
- ]),
230
- ),
231
- ]),
232
- ),
233
- ];
234
- };
235
-
236
- const write_property_default_value = (value: Metadata) =>
237
- ts.factory.createAsExpression(
238
- value.nullable
239
- ? ts.factory.createNull()
240
- : value.isRequired() === false
241
- ? ts.factory.createIdentifier("undefined")
242
- : value.arrays.length
243
- ? ts.factory.createArrayLiteralExpression()
244
- : value.maps.length
245
- ? ts.factory.createNewExpression(
246
- ts.factory.createIdentifier("Map"),
247
- undefined,
248
- [],
249
- )
250
- : value.natives.length
251
- ? ts.factory.createNewExpression(
252
- ts.factory.createIdentifier("Uint8Array"),
253
- undefined,
254
- [],
255
- )
256
- : value.atomics.some((str) => str === "string") ||
257
- value.constants.some(
258
- (c) =>
259
- c.type === "string" && c.values.some((v) => v === ""),
260
- ) ||
261
- value.templates.some(
262
- (tpl) =>
263
- tpl.length === 1 && tpl[0]!.getName() === "string",
264
- )
265
- ? ts.factory.createStringLiteral("")
266
- : value.objects.length &&
267
- value.objects.some((obj) => !ProtobufUtil.isStaticObject(obj))
268
- ? ts.factory.createObjectLiteralExpression()
269
- : ts.factory.createIdentifier("undefined"),
270
- TypeFactory.keyword("any"),
271
- );
272
-
273
- /* -----------------------------------------------------------
274
- DECODERS
275
- ----------------------------------------------------------- */
276
- const decode_property =
277
- (project: IProject) =>
278
- (importer: FunctionImporter) =>
279
- (index: number) =>
280
- (
281
- accessor: ts.ElementAccessExpression | ts.PropertyAccessExpression,
282
- meta: Metadata,
283
- tags: IMetadataTag[],
284
- ): ts.CaseClause[] => {
285
- const clauses: ts.CaseClause[] = [];
286
- const emplace =
287
- (name: string) => (v: ts.Expression | ts.Statement[]) =>
288
- clauses.push(
289
- ts.factory.createCaseClause(
290
- ts.factory.createNumericLiteral(index++),
291
- Array.isArray(v)
292
- ? [
293
- ts.factory.createExpressionStatement(
294
- ts.factory.createIdentifier(
295
- `// type: ${name}`,
296
- ),
297
- ),
298
- ...v,
299
- ts.factory.createBreakStatement(),
300
- ]
301
- : [
302
- ts.factory.createExpressionStatement(
303
- ts.factory.createIdentifier(
304
- `// ${name}`,
305
- ),
306
- ),
307
- ts.factory.createExpressionStatement(
308
- ts.factory.createBinaryExpression(
309
- accessor,
310
- ts.factory.createToken(
311
- ts.SyntaxKind.EqualsToken,
312
- ),
313
- v,
314
- ),
315
- ),
316
- ts.factory.createBreakStatement(),
317
- ],
318
- ),
319
- );
320
-
321
- const required: boolean = meta.isRequired() && !meta.nullable;
322
- for (const atomic of ProtobufUtil.getAtomics(meta))
323
- emplace(atomic)(decode_atomic(atomic, tags));
324
- if (meta.natives.length) emplace("bytes")(decode_bytes("bytes"));
325
- for (const array of meta.arrays)
326
- emplace(`Array<${array.value.getName()}>`)(
327
- decode_array(accessor, array, required, tags),
328
- );
329
- for (const map of meta.maps)
330
- emplace(`Map<string, ${map.value.getName()}>`)(
331
- decode_map(project)(importer)(
332
- accessor,
333
- map,
334
- required,
335
- tags,
336
- ),
337
- );
338
- for (const obj of meta.objects)
339
- emplace(obj.name)(
340
- ProtobufUtil.isStaticObject(obj)
341
- ? decode_regular_object(false)(obj)
342
- : decode_dynamic_object(project)(importer)(
343
- accessor,
344
- obj,
345
- required,
346
- ),
347
- );
348
- return clauses;
349
- };
350
-
351
- const decode_atomic = (
352
- atomic: Atomic.Literal,
353
- tags: IMetadataTag[],
354
- ): ts.Expression => {
355
- if (atomic === "string") return decode_bytes("string");
356
- const method =
357
- atomic === "bigint"
358
- ? tags.find((t) => t.kind === "type" && t.value === "uint64")
359
- ? "uint64"
360
- : "int64"
361
- : atomic === "number"
362
- ? (() => {
363
- const type = tags.find((t) => t.kind === "type");
364
- if (type === undefined) return "double";
365
- return type.value === "int" || type.value === "int32"
366
- ? "int32"
367
- : type.value === "uint" || type.value === "uint32"
368
- ? "uint32"
369
- : type.value === "int64"
370
- ? "int64"
371
- : type.value === "uint64"
372
- ? "uint64"
373
- : type.value === "float"
374
- ? "float"
375
- : "double";
376
- })()
377
- : "bool";
378
- const call = ts.factory.createCallExpression(
379
- IdentifierFactory.access(ts.factory.createIdentifier("reader"))(
380
- method,
381
- ),
382
- undefined,
383
- undefined,
384
- );
385
- return atomic === "number" &&
386
- (method === "int64" || method === "uint64")
387
- ? ts.factory.createCallExpression(
388
- ts.factory.createIdentifier("Number"),
389
- undefined,
390
- [call],
391
- )
392
- : call;
393
- };
394
-
395
- const decode_bytes = (method: "bytes" | "string"): ts.Expression =>
396
- ts.factory.createCallExpression(
397
- IdentifierFactory.access(ts.factory.createIdentifier("reader"))(
398
- method,
399
- ),
400
- undefined,
401
- undefined,
402
- );
403
-
404
- const decode_array = (
405
- accessor: ts.ElementAccessExpression | ts.PropertyAccessExpression,
406
- array: MetadataArray,
407
- required: boolean,
408
- tags: IMetadataTag[],
409
- ): ts.Statement[] => {
410
- const statements: Array<ts.Expression | ts.Statement> = [];
411
- if (required === false)
412
- statements.push(
413
- ts.factory.createBinaryExpression(
414
- accessor,
415
- ts.factory.createToken(
416
- ts.SyntaxKind.QuestionQuestionEqualsToken,
417
- ),
418
- ts.factory.createAsExpression(
419
- ts.factory.createArrayLiteralExpression(),
420
- ts.factory.createTypeReferenceNode("any[]"),
421
- ),
422
- ),
423
- );
424
- const atomics = ProtobufUtil.getAtomics(array.value);
425
- const decoder = atomics.length
426
- ? () => decode_atomic(atomics[0]!, tags)
427
- : array.value.natives.length
428
- ? () => decode_bytes("bytes")
429
- : array.value.objects.length
430
- ? () => decode_regular_object(false)(array.value.objects[0]!)
431
- : null;
432
- if (decoder === null) throw new Error("Never reach here.");
433
- else if (atomics.length && atomics[0] !== "string") {
434
- statements.push(
435
- ts.factory.createIfStatement(
436
- ts.factory.createStrictEquality(
437
- ts.factory.createNumericLiteral(2),
438
- ts.factory.createBitwiseAnd(
439
- ts.factory.createIdentifier("tag"),
440
- ts.factory.createNumericLiteral(7),
441
- ),
442
- ),
443
- ts.factory.createBlock(
444
- [
445
- StatementFactory.constant(
446
- "piece",
447
- ts.factory.createAdd(
448
- ts.factory.createCallExpression(
449
- IdentifierFactory.access(READER())(
450
- "uint32",
451
- ),
452
- undefined,
453
- undefined,
454
- ),
455
- ts.factory.createCallExpression(
456
- IdentifierFactory.access(READER())(
457
- "index",
458
- ),
459
- undefined,
460
- undefined,
461
- ),
462
- ),
463
- ),
464
- ts.factory.createWhileStatement(
465
- ts.factory.createLessThan(
466
- ts.factory.createCallExpression(
467
- IdentifierFactory.access(READER())(
468
- "index",
469
- ),
470
- undefined,
471
- undefined,
472
- ),
473
- ts.factory.createIdentifier("piece"),
474
- ),
475
- ts.factory.createExpressionStatement(
476
- ts.factory.createCallExpression(
477
- IdentifierFactory.access(accessor)(
478
- "push",
479
- ),
480
- undefined,
481
- [decoder()],
482
- ),
483
- ),
484
- ),
485
- ],
486
- true,
487
- ),
488
- ts.factory.createExpressionStatement(
489
- ts.factory.createCallExpression(
490
- IdentifierFactory.access(accessor)("push"),
491
- undefined,
492
- [decoder()],
493
- ),
494
- ),
495
- ),
496
- );
497
- } else
498
- statements.push(
499
- ts.factory.createCallExpression(
500
- IdentifierFactory.access(accessor)("push"),
501
- undefined,
502
- [decoder()],
503
- ),
504
- );
505
- return statements.map((stmt) =>
506
- ts.isExpression(stmt)
507
- ? ts.factory.createExpressionStatement(stmt)
508
- : stmt,
509
- );
510
- };
511
-
512
- const decode_regular_object =
513
- (top: boolean) =>
514
- (obj: MetadataObject): ts.Expression =>
515
- ts.factory.createCallExpression(
516
- ts.factory.createIdentifier(`${PREFIX}o${obj.index}`),
517
- undefined,
518
- [
519
- ts.factory.createIdentifier("reader"),
520
- ...(top
521
- ? []
522
- : [
523
- ts.factory.createCallExpression(
524
- IdentifierFactory.access(READER())("uint32"),
525
- undefined,
526
- undefined,
527
- ),
528
- ]),
529
- ],
530
- );
531
-
532
- const decode_dynamic_object =
533
- (project: IProject) =>
534
- (importer: FunctionImporter) =>
535
- (
536
- accessor: ts.ElementAccessExpression | ts.PropertyAccessExpression,
537
- obj: MetadataObject,
538
- required: boolean,
539
- ): ts.Statement[] => {
540
- const top = obj.properties[0]!;
541
- return decode_entry(project)(importer)({
542
- initializer: () =>
543
- ts.factory.createBinaryExpression(
544
- accessor,
545
- ts.factory.createToken(
546
- ts.SyntaxKind.QuestionQuestionEqualsToken,
547
- ),
548
- ts.factory.createObjectLiteralExpression(),
549
- ),
550
- setter: () =>
551
- ts.factory.createBinaryExpression(
552
- ts.factory.createElementAccessExpression(
553
- accessor,
554
- ts.factory.createIdentifier("entry.key"),
555
- ),
556
- ts.factory.createToken(ts.SyntaxKind.EqualsToken),
557
- ts.factory.createIdentifier("entry.value"),
558
- ),
559
- })(top, required, top.tags);
560
- };
561
-
562
- const decode_map =
563
- (project: IProject) =>
564
- (importer: FunctionImporter) =>
565
- (
566
- accessor: ts.ElementAccessExpression | ts.PropertyAccessExpression,
567
- map: Metadata.Entry,
568
- required: boolean,
569
- tags: IMetadataTag[],
570
- ): ts.Statement[] =>
571
- decode_entry(project)(importer)({
572
- initializer: () =>
573
- ts.factory.createBinaryExpression(
574
- accessor,
575
- ts.factory.createToken(
576
- ts.SyntaxKind.QuestionQuestionEqualsToken,
577
- ),
578
- ts.factory.createNewExpression(
579
- ts.factory.createIdentifier("Map"),
580
- [
581
- TypeFactory.keyword("any"),
582
- TypeFactory.keyword("any"),
583
- ],
584
- [],
585
- ),
586
- ),
587
- setter: () =>
588
- ts.factory.createCallExpression(
589
- IdentifierFactory.access(accessor)("set"),
590
- undefined,
591
- [
592
- ts.factory.createIdentifier("entry.key"),
593
- ts.factory.createIdentifier("entry.value"),
594
- ],
595
- ),
596
- })(map, required, tags);
597
-
598
- const decode_entry =
599
- (project: IProject) =>
600
- (importer: FunctionImporter) =>
601
- (props: {
602
- initializer: () => ts.Expression;
603
- setter: () => ts.Expression;
604
- }) =>
605
- (
606
- map: Metadata.Entry,
607
- required: boolean,
608
- tags: IMetadataTag[],
609
- ): ts.Statement[] => {
610
- const statements: ts.Statement[] = [
611
- ...(required
612
- ? []
613
- : [
614
- ts.factory.createExpressionStatement(
615
- props.initializer(),
616
- ),
617
- ]),
618
- StatementFactory.constant(
619
- "piece",
620
- ts.factory.createAdd(
621
- ts.factory.createCallExpression(
622
- IdentifierFactory.access(READER())("uint32"),
623
- undefined,
624
- undefined,
625
- ),
626
- ts.factory.createCallExpression(
627
- IdentifierFactory.access(READER())("index"),
628
- undefined,
629
- undefined,
630
- ),
631
- ),
632
- ),
633
- ...write_object_function_body(project)(importer)({
634
- condition: ts.factory.createLessThan(
635
- ts.factory.createCallExpression(
636
- IdentifierFactory.access(READER())("index"),
637
- undefined,
638
- undefined,
639
- ),
640
- ts.factory.createIdentifier("piece"),
641
- ),
642
- tag: "kind",
643
- output: "entry",
644
- })([
645
- MetadataProperty.create({
646
- key: MetadataFactory.soleLiteral("key"),
647
- value: map.key,
648
- description: null,
649
- tags: [],
650
- jsDocTags: [],
651
- }),
652
- MetadataProperty.create({
653
- key: MetadataFactory.soleLiteral("value"),
654
- value: map.value,
655
- description: null,
656
- tags,
657
- jsDocTags: [],
658
- }),
659
- ]),
660
- ts.factory.createExpressionStatement(props.setter()),
661
- ];
662
- return [
663
- ts.factory.createExpressionStatement(
664
- ExpressionFactory.selfCall(
665
- ts.factory.createBlock(statements, true),
666
- ),
667
- ),
668
- ];
669
- };
670
- }
671
-
672
- const PREFIX = "$pd";
673
- const READER = () => ts.factory.createIdentifier("reader");
1
+ import ts from "typescript";
2
+
3
+ import { ExpressionFactory } from "../../factories/ExpressionFactory";
4
+ import { IdentifierFactory } from "../../factories/IdentifierFactory";
5
+ import { MetadataCollection } from "../../factories/MetadataCollection";
6
+ import { MetadataFactory } from "../../factories/MetadataFactory";
7
+ import { ProtobufFactory } from "../../factories/ProtobufFactory";
8
+ import { StatementFactory } from "../../factories/StatementFactory";
9
+ import { TypeFactory } from "../../factories/TypeFactory";
10
+
11
+ import { IMetadataTag } from "../../schemas/metadata/IMetadataTag";
12
+ import { Metadata } from "../../schemas/metadata/Metadata";
13
+ import { MetadataArray } from "../../schemas/metadata/MetadataArray";
14
+ import { MetadataObject } from "../../schemas/metadata/MetadataObject";
15
+ import { MetadataProperty } from "../../schemas/metadata/MetadataProperty";
16
+
17
+ import { IProject } from "../../transformers/IProject";
18
+
19
+ import { Atomic } from "../../typings/Atomic";
20
+
21
+ import { FunctionImporter } from "../helpers/FunctionImporeter";
22
+ import { ProtobufUtil } from "../helpers/ProtobufUtil";
23
+
24
+ export namespace ProtobufDecodeProgrammer {
25
+ export const write =
26
+ (project: IProject) =>
27
+ (modulo: ts.LeftHandSideExpression) =>
28
+ (type: ts.Type, name?: string): ts.ArrowFunction => {
29
+ const importer: FunctionImporter = new FunctionImporter(
30
+ modulo.getText(),
31
+ );
32
+ const collection: MetadataCollection = new MetadataCollection();
33
+ const meta: Metadata = ProtobufFactory.metadata(modulo.getText())(
34
+ project.checker,
35
+ )(collection)(type);
36
+
37
+ const functors = collection
38
+ .objects()
39
+ .filter((obj) => ProtobufUtil.isStaticObject(obj))
40
+ .map((obj) =>
41
+ StatementFactory.constant(
42
+ `${PREFIX}o${obj.index}`,
43
+ write_object_function(project)(importer)(obj),
44
+ ),
45
+ );
46
+ const reader = StatementFactory.constant(
47
+ "reader",
48
+ ts.factory.createNewExpression(
49
+ importer.use("Reader"),
50
+ undefined,
51
+ [ts.factory.createIdentifier("input")],
52
+ ),
53
+ );
54
+
55
+ return ts.factory.createArrowFunction(
56
+ undefined,
57
+ undefined,
58
+ [
59
+ IdentifierFactory.parameter(
60
+ "input",
61
+ ts.factory.createTypeReferenceNode("Uint8Array"),
62
+ ),
63
+ ],
64
+ ts.factory.createTypeReferenceNode(
65
+ `typia.Resolved<${
66
+ name ?? TypeFactory.getFullName(project.checker)(type)
67
+ }>`,
68
+ ),
69
+ undefined,
70
+ ts.factory.createBlock(
71
+ [
72
+ ...importer.declare(modulo),
73
+ ...functors,
74
+ reader,
75
+ ts.factory.createReturnStatement(
76
+ decode_regular_object(true)(meta.objects[0]!),
77
+ ),
78
+ ],
79
+ true,
80
+ ),
81
+ );
82
+ };
83
+
84
+ const write_object_function =
85
+ (project: IProject) =>
86
+ (importer: FunctionImporter) =>
87
+ (obj: MetadataObject): ts.ArrowFunction =>
88
+ ts.factory.createArrowFunction(
89
+ undefined,
90
+ undefined,
91
+ [
92
+ IdentifierFactory.parameter("reader"),
93
+ IdentifierFactory.parameter(
94
+ "length",
95
+ TypeFactory.keyword("number"),
96
+ ts.factory.createNumericLiteral(-1),
97
+ ),
98
+ ],
99
+ TypeFactory.keyword("any"),
100
+ undefined,
101
+ ts.factory.createBlock(
102
+ [
103
+ ts.factory.createExpressionStatement(
104
+ ts.factory.createBinaryExpression(
105
+ ts.factory.createIdentifier("length"),
106
+ ts.factory.createToken(
107
+ ts.SyntaxKind.EqualsToken,
108
+ ),
109
+ ts.factory.createConditionalExpression(
110
+ ts.factory.createLessThan(
111
+ ts.factory.createIdentifier("length"),
112
+ ts.factory.createNumericLiteral(0),
113
+ ),
114
+ undefined,
115
+ ts.factory.createCallExpression(
116
+ IdentifierFactory.access(READER())(
117
+ "size",
118
+ ),
119
+ undefined,
120
+ undefined,
121
+ ),
122
+ undefined,
123
+ ts.factory.createAdd(
124
+ ts.factory.createCallExpression(
125
+ IdentifierFactory.access(READER())(
126
+ "index",
127
+ ),
128
+ undefined,
129
+ undefined,
130
+ ),
131
+ ts.factory.createIdentifier("length"),
132
+ ),
133
+ ),
134
+ ),
135
+ ),
136
+ ...write_object_function_body(project)(importer)({
137
+ condition: ts.factory.createLessThan(
138
+ ts.factory.createCallExpression(
139
+ IdentifierFactory.access(READER())("index"),
140
+ undefined,
141
+ undefined,
142
+ ),
143
+ ts.factory.createIdentifier("length"),
144
+ ),
145
+ tag: "tag",
146
+ output: "output",
147
+ })(obj.properties),
148
+ ts.factory.createReturnStatement(
149
+ ts.factory.createIdentifier("output"),
150
+ ),
151
+ ],
152
+ true,
153
+ ),
154
+ );
155
+
156
+ const write_object_function_body =
157
+ (project: IProject) =>
158
+ (importer: FunctionImporter) =>
159
+ (props: { condition: ts.Expression; tag: string; output: string }) =>
160
+ (properties: MetadataProperty[]): ts.Statement[] => {
161
+ let i: number = 1;
162
+ const clauses: ts.CaseClause[] = properties
163
+ .map((p) => {
164
+ const clause = decode_property(project)(importer)(i)(
165
+ IdentifierFactory.access(
166
+ ts.factory.createIdentifier(props.output),
167
+ )(p.key.getSoleLiteral()!),
168
+ p.value,
169
+ p.tags,
170
+ );
171
+ i += p.value.binarySize();
172
+ return clause;
173
+ })
174
+ .flat();
175
+ return [
176
+ StatementFactory.constant(
177
+ props.output,
178
+ ts.factory.createObjectLiteralExpression(
179
+ properties.map((p) =>
180
+ ts.factory.createPropertyAssignment(
181
+ IdentifierFactory.identifier(
182
+ p.key.getSoleLiteral()!,
183
+ ),
184
+ write_property_default_value(p.value),
185
+ ),
186
+ ),
187
+ true,
188
+ ),
189
+ ),
190
+ ts.factory.createWhileStatement(
191
+ props.condition,
192
+ ts.factory.createBlock([
193
+ StatementFactory.constant(
194
+ props.tag,
195
+ ts.factory.createCallExpression(
196
+ IdentifierFactory.access(READER())("uint32"),
197
+ undefined,
198
+ undefined,
199
+ ),
200
+ ),
201
+ ts.factory.createSwitchStatement(
202
+ ts.factory.createUnsignedRightShift(
203
+ ts.factory.createIdentifier(props.tag),
204
+ ts.factory.createNumericLiteral(3),
205
+ ),
206
+ ts.factory.createCaseBlock([
207
+ ...clauses,
208
+ ts.factory.createDefaultClause([
209
+ ts.factory.createExpressionStatement(
210
+ ts.factory.createCallExpression(
211
+ IdentifierFactory.access(READER())(
212
+ "skipType",
213
+ ),
214
+ undefined,
215
+ [
216
+ ts.factory.createBitwiseAnd(
217
+ ts.factory.createIdentifier(
218
+ props.tag,
219
+ ),
220
+ ts.factory.createNumericLiteral(
221
+ 7,
222
+ ),
223
+ ),
224
+ ],
225
+ ),
226
+ ),
227
+ ts.factory.createBreakStatement(),
228
+ ]),
229
+ ]),
230
+ ),
231
+ ]),
232
+ ),
233
+ ];
234
+ };
235
+
236
+ const write_property_default_value = (value: Metadata) =>
237
+ ts.factory.createAsExpression(
238
+ value.nullable
239
+ ? ts.factory.createNull()
240
+ : value.isRequired() === false
241
+ ? ts.factory.createIdentifier("undefined")
242
+ : value.arrays.length
243
+ ? ts.factory.createArrayLiteralExpression()
244
+ : value.maps.length
245
+ ? ts.factory.createNewExpression(
246
+ ts.factory.createIdentifier("Map"),
247
+ undefined,
248
+ [],
249
+ )
250
+ : value.natives.length
251
+ ? ts.factory.createNewExpression(
252
+ ts.factory.createIdentifier("Uint8Array"),
253
+ undefined,
254
+ [],
255
+ )
256
+ : value.atomics.some((a) => a.type === "string") ||
257
+ value.constants.some(
258
+ (c) =>
259
+ c.type === "string" && c.values.some((v) => v === ""),
260
+ ) ||
261
+ value.templates.some(
262
+ (tpl) =>
263
+ tpl.length === 1 && tpl[0]!.getName() === "string",
264
+ )
265
+ ? ts.factory.createStringLiteral("")
266
+ : value.objects.length &&
267
+ value.objects.some((obj) => !ProtobufUtil.isStaticObject(obj))
268
+ ? ts.factory.createObjectLiteralExpression()
269
+ : ts.factory.createIdentifier("undefined"),
270
+ TypeFactory.keyword("any"),
271
+ );
272
+
273
+ /* -----------------------------------------------------------
274
+ DECODERS
275
+ ----------------------------------------------------------- */
276
+ const decode_property =
277
+ (project: IProject) =>
278
+ (importer: FunctionImporter) =>
279
+ (index: number) =>
280
+ (
281
+ accessor: ts.ElementAccessExpression | ts.PropertyAccessExpression,
282
+ meta: Metadata,
283
+ tags: IMetadataTag[],
284
+ ): ts.CaseClause[] => {
285
+ const clauses: ts.CaseClause[] = [];
286
+ const emplace =
287
+ (name: string) => (v: ts.Expression | ts.Statement[]) =>
288
+ clauses.push(
289
+ ts.factory.createCaseClause(
290
+ ts.factory.createNumericLiteral(index++),
291
+ Array.isArray(v)
292
+ ? [
293
+ ts.factory.createExpressionStatement(
294
+ ts.factory.createIdentifier(
295
+ `// type: ${name}`,
296
+ ),
297
+ ),
298
+ ...v,
299
+ ts.factory.createBreakStatement(),
300
+ ]
301
+ : [
302
+ ts.factory.createExpressionStatement(
303
+ ts.factory.createIdentifier(
304
+ `// ${name}`,
305
+ ),
306
+ ),
307
+ ts.factory.createExpressionStatement(
308
+ ts.factory.createBinaryExpression(
309
+ accessor,
310
+ ts.factory.createToken(
311
+ ts.SyntaxKind.EqualsToken,
312
+ ),
313
+ v,
314
+ ),
315
+ ),
316
+ ts.factory.createBreakStatement(),
317
+ ],
318
+ ),
319
+ );
320
+
321
+ const required: boolean = meta.isRequired() && !meta.nullable;
322
+ for (const atomic of ProtobufUtil.getAtomics(meta))
323
+ emplace(atomic)(decode_atomic(atomic, tags));
324
+ if (meta.natives.length) emplace("bytes")(decode_bytes("bytes"));
325
+ for (const array of meta.arrays)
326
+ emplace(`Array<${array.value.getName()}>`)(
327
+ decode_array(accessor, array, required, tags),
328
+ );
329
+ for (const map of meta.maps)
330
+ emplace(`Map<string, ${map.value.getName()}>`)(
331
+ decode_map(project)(importer)(
332
+ accessor,
333
+ map,
334
+ required,
335
+ tags,
336
+ ),
337
+ );
338
+ for (const obj of meta.objects)
339
+ emplace(obj.name)(
340
+ ProtobufUtil.isStaticObject(obj)
341
+ ? decode_regular_object(false)(obj)
342
+ : decode_dynamic_object(project)(importer)(
343
+ accessor,
344
+ obj,
345
+ required,
346
+ ),
347
+ );
348
+ return clauses;
349
+ };
350
+
351
+ const decode_atomic = (
352
+ atomic: Atomic.Literal,
353
+ tags: IMetadataTag[],
354
+ ): ts.Expression => {
355
+ if (atomic === "string") return decode_bytes("string");
356
+ const method =
357
+ atomic === "bigint"
358
+ ? tags.find((t) => t.kind === "type" && t.value === "uint64")
359
+ ? "uint64"
360
+ : "int64"
361
+ : atomic === "number"
362
+ ? (() => {
363
+ const type = tags.find((t) => t.kind === "type");
364
+ if (type === undefined) return "double";
365
+ return type.value === "int" || type.value === "int32"
366
+ ? "int32"
367
+ : type.value === "uint" || type.value === "uint32"
368
+ ? "uint32"
369
+ : type.value === "int64"
370
+ ? "int64"
371
+ : type.value === "uint64"
372
+ ? "uint64"
373
+ : type.value === "float"
374
+ ? "float"
375
+ : "double";
376
+ })()
377
+ : "bool";
378
+ const call = ts.factory.createCallExpression(
379
+ IdentifierFactory.access(ts.factory.createIdentifier("reader"))(
380
+ method,
381
+ ),
382
+ undefined,
383
+ undefined,
384
+ );
385
+ return atomic === "number" &&
386
+ (method === "int64" || method === "uint64")
387
+ ? ts.factory.createCallExpression(
388
+ ts.factory.createIdentifier("Number"),
389
+ undefined,
390
+ [call],
391
+ )
392
+ : call;
393
+ };
394
+
395
+ const decode_bytes = (method: "bytes" | "string"): ts.Expression =>
396
+ ts.factory.createCallExpression(
397
+ IdentifierFactory.access(ts.factory.createIdentifier("reader"))(
398
+ method,
399
+ ),
400
+ undefined,
401
+ undefined,
402
+ );
403
+
404
+ const decode_array = (
405
+ accessor: ts.ElementAccessExpression | ts.PropertyAccessExpression,
406
+ array: MetadataArray,
407
+ required: boolean,
408
+ tags: IMetadataTag[],
409
+ ): ts.Statement[] => {
410
+ const statements: Array<ts.Expression | ts.Statement> = [];
411
+ if (required === false)
412
+ statements.push(
413
+ ts.factory.createBinaryExpression(
414
+ accessor,
415
+ ts.factory.createToken(
416
+ ts.SyntaxKind.QuestionQuestionEqualsToken,
417
+ ),
418
+ ts.factory.createAsExpression(
419
+ ts.factory.createArrayLiteralExpression(),
420
+ ts.factory.createTypeReferenceNode("any[]"),
421
+ ),
422
+ ),
423
+ );
424
+ const atomics = ProtobufUtil.getAtomics(array.value);
425
+ const decoder = atomics.length
426
+ ? () => decode_atomic(atomics[0]!, tags)
427
+ : array.value.natives.length
428
+ ? () => decode_bytes("bytes")
429
+ : array.value.objects.length
430
+ ? () => decode_regular_object(false)(array.value.objects[0]!)
431
+ : null;
432
+ if (decoder === null) throw new Error("Never reach here.");
433
+ else if (atomics.length && atomics[0] !== "string") {
434
+ statements.push(
435
+ ts.factory.createIfStatement(
436
+ ts.factory.createStrictEquality(
437
+ ts.factory.createNumericLiteral(2),
438
+ ts.factory.createBitwiseAnd(
439
+ ts.factory.createIdentifier("tag"),
440
+ ts.factory.createNumericLiteral(7),
441
+ ),
442
+ ),
443
+ ts.factory.createBlock(
444
+ [
445
+ StatementFactory.constant(
446
+ "piece",
447
+ ts.factory.createAdd(
448
+ ts.factory.createCallExpression(
449
+ IdentifierFactory.access(READER())(
450
+ "uint32",
451
+ ),
452
+ undefined,
453
+ undefined,
454
+ ),
455
+ ts.factory.createCallExpression(
456
+ IdentifierFactory.access(READER())(
457
+ "index",
458
+ ),
459
+ undefined,
460
+ undefined,
461
+ ),
462
+ ),
463
+ ),
464
+ ts.factory.createWhileStatement(
465
+ ts.factory.createLessThan(
466
+ ts.factory.createCallExpression(
467
+ IdentifierFactory.access(READER())(
468
+ "index",
469
+ ),
470
+ undefined,
471
+ undefined,
472
+ ),
473
+ ts.factory.createIdentifier("piece"),
474
+ ),
475
+ ts.factory.createExpressionStatement(
476
+ ts.factory.createCallExpression(
477
+ IdentifierFactory.access(accessor)(
478
+ "push",
479
+ ),
480
+ undefined,
481
+ [decoder()],
482
+ ),
483
+ ),
484
+ ),
485
+ ],
486
+ true,
487
+ ),
488
+ ts.factory.createExpressionStatement(
489
+ ts.factory.createCallExpression(
490
+ IdentifierFactory.access(accessor)("push"),
491
+ undefined,
492
+ [decoder()],
493
+ ),
494
+ ),
495
+ ),
496
+ );
497
+ } else
498
+ statements.push(
499
+ ts.factory.createCallExpression(
500
+ IdentifierFactory.access(accessor)("push"),
501
+ undefined,
502
+ [decoder()],
503
+ ),
504
+ );
505
+ return statements.map((stmt) =>
506
+ ts.isExpression(stmt)
507
+ ? ts.factory.createExpressionStatement(stmt)
508
+ : stmt,
509
+ );
510
+ };
511
+
512
+ const decode_regular_object =
513
+ (top: boolean) =>
514
+ (obj: MetadataObject): ts.Expression =>
515
+ ts.factory.createCallExpression(
516
+ ts.factory.createIdentifier(`${PREFIX}o${obj.index}`),
517
+ undefined,
518
+ [
519
+ ts.factory.createIdentifier("reader"),
520
+ ...(top
521
+ ? []
522
+ : [
523
+ ts.factory.createCallExpression(
524
+ IdentifierFactory.access(READER())("uint32"),
525
+ undefined,
526
+ undefined,
527
+ ),
528
+ ]),
529
+ ],
530
+ );
531
+
532
+ const decode_dynamic_object =
533
+ (project: IProject) =>
534
+ (importer: FunctionImporter) =>
535
+ (
536
+ accessor: ts.ElementAccessExpression | ts.PropertyAccessExpression,
537
+ obj: MetadataObject,
538
+ required: boolean,
539
+ ): ts.Statement[] => {
540
+ const top = obj.properties[0]!;
541
+ return decode_entry(project)(importer)({
542
+ initializer: () =>
543
+ ts.factory.createBinaryExpression(
544
+ accessor,
545
+ ts.factory.createToken(
546
+ ts.SyntaxKind.QuestionQuestionEqualsToken,
547
+ ),
548
+ ts.factory.createObjectLiteralExpression(),
549
+ ),
550
+ setter: () =>
551
+ ts.factory.createBinaryExpression(
552
+ ts.factory.createElementAccessExpression(
553
+ accessor,
554
+ ts.factory.createIdentifier("entry.key"),
555
+ ),
556
+ ts.factory.createToken(ts.SyntaxKind.EqualsToken),
557
+ ts.factory.createIdentifier("entry.value"),
558
+ ),
559
+ })(top, required, top.tags);
560
+ };
561
+
562
+ const decode_map =
563
+ (project: IProject) =>
564
+ (importer: FunctionImporter) =>
565
+ (
566
+ accessor: ts.ElementAccessExpression | ts.PropertyAccessExpression,
567
+ map: Metadata.Entry,
568
+ required: boolean,
569
+ tags: IMetadataTag[],
570
+ ): ts.Statement[] =>
571
+ decode_entry(project)(importer)({
572
+ initializer: () =>
573
+ ts.factory.createBinaryExpression(
574
+ accessor,
575
+ ts.factory.createToken(
576
+ ts.SyntaxKind.QuestionQuestionEqualsToken,
577
+ ),
578
+ ts.factory.createNewExpression(
579
+ ts.factory.createIdentifier("Map"),
580
+ [
581
+ TypeFactory.keyword("any"),
582
+ TypeFactory.keyword("any"),
583
+ ],
584
+ [],
585
+ ),
586
+ ),
587
+ setter: () =>
588
+ ts.factory.createCallExpression(
589
+ IdentifierFactory.access(accessor)("set"),
590
+ undefined,
591
+ [
592
+ ts.factory.createIdentifier("entry.key"),
593
+ ts.factory.createIdentifier("entry.value"),
594
+ ],
595
+ ),
596
+ })(map, required, tags);
597
+
598
+ const decode_entry =
599
+ (project: IProject) =>
600
+ (importer: FunctionImporter) =>
601
+ (props: {
602
+ initializer: () => ts.Expression;
603
+ setter: () => ts.Expression;
604
+ }) =>
605
+ (
606
+ map: Metadata.Entry,
607
+ required: boolean,
608
+ tags: IMetadataTag[],
609
+ ): ts.Statement[] => {
610
+ const statements: ts.Statement[] = [
611
+ ...(required
612
+ ? []
613
+ : [
614
+ ts.factory.createExpressionStatement(
615
+ props.initializer(),
616
+ ),
617
+ ]),
618
+ StatementFactory.constant(
619
+ "piece",
620
+ ts.factory.createAdd(
621
+ ts.factory.createCallExpression(
622
+ IdentifierFactory.access(READER())("uint32"),
623
+ undefined,
624
+ undefined,
625
+ ),
626
+ ts.factory.createCallExpression(
627
+ IdentifierFactory.access(READER())("index"),
628
+ undefined,
629
+ undefined,
630
+ ),
631
+ ),
632
+ ),
633
+ ...write_object_function_body(project)(importer)({
634
+ condition: ts.factory.createLessThan(
635
+ ts.factory.createCallExpression(
636
+ IdentifierFactory.access(READER())("index"),
637
+ undefined,
638
+ undefined,
639
+ ),
640
+ ts.factory.createIdentifier("piece"),
641
+ ),
642
+ tag: "kind",
643
+ output: "entry",
644
+ })([
645
+ MetadataProperty.create({
646
+ key: MetadataFactory.soleLiteral("key"),
647
+ value: map.key,
648
+ description: null,
649
+ tags: [],
650
+ jsDocTags: [],
651
+ }),
652
+ MetadataProperty.create({
653
+ key: MetadataFactory.soleLiteral("value"),
654
+ value: map.value,
655
+ description: null,
656
+ tags,
657
+ jsDocTags: [],
658
+ }),
659
+ ]),
660
+ ts.factory.createExpressionStatement(props.setter()),
661
+ ];
662
+ return [
663
+ ts.factory.createExpressionStatement(
664
+ ExpressionFactory.selfCall(
665
+ ts.factory.createBlock(statements, true),
666
+ ),
667
+ ),
668
+ ];
669
+ };
670
+ }
671
+
672
+ const PREFIX = "$pd";
673
+ const READER = () => ts.factory.createIdentifier("reader");