typia 5.0.0-dev.20230814-2 → 5.0.0-dev.20230819

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 (77) hide show
  1. package/lib/factories/ExpressionFactory.d.ts +2 -0
  2. package/lib/factories/ExpressionFactory.js +38 -0
  3. package/lib/factories/ExpressionFactory.js.map +1 -1
  4. package/lib/factories/StatementFactory.d.ts +2 -0
  5. package/lib/factories/StatementFactory.js +11 -0
  6. package/lib/factories/StatementFactory.js.map +1 -1
  7. package/lib/functional/$ProtobufReader.d.ts +33 -0
  8. package/lib/functional/$ProtobufReader.js +155 -0
  9. package/lib/functional/$ProtobufReader.js.map +1 -0
  10. package/lib/functional/$ProtobufSizer.d.ts +36 -0
  11. package/lib/functional/$ProtobufSizer.js +105 -0
  12. package/lib/functional/$ProtobufSizer.js.map +1 -0
  13. package/lib/functional/$ProtobufWriter.d.ts +45 -0
  14. package/lib/functional/$ProtobufWriter.js +107 -0
  15. package/lib/functional/$ProtobufWriter.js.map +1 -0
  16. package/lib/functional/IProtobufWriter.d.ts +15 -0
  17. package/lib/functional/IProtobufWriter.js +3 -0
  18. package/lib/functional/IProtobufWriter.js.map +1 -0
  19. package/lib/functional/Namespace.js +13 -6
  20. package/lib/functional/Namespace.js.map +1 -1
  21. package/lib/programmers/FeatureProgrammer.js +2 -2
  22. package/lib/programmers/FeatureProgrammer.js.map +1 -1
  23. package/lib/programmers/helpers/CloneJoiner.js +1 -7
  24. package/lib/programmers/helpers/CloneJoiner.js.map +1 -1
  25. package/lib/programmers/helpers/FunctionImporeter.d.ts +2 -1
  26. package/lib/programmers/helpers/FunctionImporeter.js +12 -3
  27. package/lib/programmers/helpers/FunctionImporeter.js.map +1 -1
  28. package/lib/programmers/helpers/ProtobufWire.d.ts +16 -12
  29. package/lib/programmers/helpers/UnionExplorer.js +15 -20
  30. package/lib/programmers/helpers/UnionExplorer.js.map +1 -1
  31. package/lib/programmers/helpers/disable_function_importer_declare.js +1 -0
  32. package/lib/programmers/helpers/disable_function_importer_declare.js.map +1 -1
  33. package/lib/programmers/internal/decode_union_object.js +12 -30
  34. package/lib/programmers/internal/decode_union_object.js.map +1 -1
  35. package/lib/programmers/protobuf/ProtobufEncodeProgrammer.js +313 -130
  36. package/lib/programmers/protobuf/ProtobufEncodeProgrammer.js.map +1 -1
  37. package/lib/programmers/protobuf/ProtobufMessageProgrammer.js +8 -2
  38. package/lib/programmers/protobuf/ProtobufMessageProgrammer.js.map +1 -1
  39. package/lib/protobuf.d.ts +4 -4
  40. package/lib/protobuf.js +23 -9
  41. package/lib/protobuf.js.map +1 -1
  42. package/lib/schemas/metadata/MetadataObject.js +4 -0
  43. package/lib/schemas/metadata/MetadataObject.js.map +1 -1
  44. package/lib/transformers/CallExpressionTransformer.js +0 -4
  45. package/lib/transformers/CallExpressionTransformer.js.map +1 -1
  46. package/package.json +1 -1
  47. package/src/factories/ExpressionFactory.ts +38 -0
  48. package/src/factories/StatementFactory.ts +32 -0
  49. package/src/functional/$ProtobufReader.ts +189 -0
  50. package/src/functional/$ProtobufSizer.ts +144 -0
  51. package/src/functional/$ProtobufWriter.ts +152 -0
  52. package/src/functional/IProtobufWriter.ts +18 -0
  53. package/src/functional/Namespace.ts +14 -7
  54. package/src/programmers/FeatureProgrammer.ts +2 -2
  55. package/src/programmers/helpers/CloneJoiner.ts +1 -25
  56. package/src/programmers/helpers/FunctionImporeter.ts +15 -4
  57. package/src/programmers/helpers/ProtobufWire.ts +18 -12
  58. package/src/programmers/helpers/UnionExplorer.ts +25 -20
  59. package/src/programmers/helpers/disable_function_importer_declare.ts +1 -0
  60. package/src/programmers/internal/decode_union_object.ts +17 -6
  61. package/src/programmers/protobuf/ProtobufEncodeProgrammer.ts +653 -209
  62. package/src/programmers/protobuf/ProtobufMessageProgrammer.ts +4 -1
  63. package/src/protobuf.ts +33 -33
  64. package/src/schemas/metadata/MetadataObject.ts +10 -0
  65. package/src/transformers/CallExpressionTransformer.ts +0 -4
  66. package/lib/programmers/protobuf/ProtobufSizeProgrammer.d.ts +0 -5
  67. package/lib/programmers/protobuf/ProtobufSizeProgrammer.js +0 -409
  68. package/lib/programmers/protobuf/ProtobufSizeProgrammer.js.map +0 -1
  69. package/lib/transformers/features/protobuf/CreateProtobufSizeTransformer.d.ts +0 -3
  70. package/lib/transformers/features/protobuf/CreateProtobufSizeTransformer.js +0 -10
  71. package/lib/transformers/features/protobuf/CreateProtobufSizeTransformer.js.map +0 -1
  72. package/lib/transformers/features/protobuf/ProtobufSizeTransformer.d.ts +0 -3
  73. package/lib/transformers/features/protobuf/ProtobufSizeTransformer.js +0 -10
  74. package/lib/transformers/features/protobuf/ProtobufSizeTransformer.js.map +0 -1
  75. package/src/programmers/protobuf/ProtobufSizeProgrammer.ts +0 -716
  76. package/src/transformers/features/protobuf/CreateProtobufSizeTransformer.ts +0 -9
  77. package/src/transformers/features/protobuf/ProtobufSizeTransformer.ts +0 -9
@@ -1,5 +1,6 @@
1
1
  import ts from "typescript";
2
2
 
3
+ import { ExpressionFactory } from "../../factories/ExpressionFactory";
3
4
  import { IdentifierFactory } from "../../factories/IdentifierFactory";
4
5
  import { MetadataCollection } from "../../factories/MetadataCollection";
5
6
  import { ProtobufFactory } from "../../factories/ProtobufFactory";
@@ -24,6 +25,8 @@ import { FunctionImporter } from "../helpers/FunctionImporeter";
24
25
  import { ProtobufUtil } from "../helpers/ProtobufUtil";
25
26
  import { ProtobufWire } from "../helpers/ProtobufWire";
26
27
  import { UnionExplorer } from "../helpers/UnionExplorer";
28
+ import { UnionPredicator } from "../helpers/UnionPredicator";
29
+ import { decode_union_object } from "../internal/decode_union_object";
27
30
 
28
31
  export namespace ProtobufEncodeProgrammer {
29
32
  export const write =
@@ -36,25 +39,39 @@ export namespace ProtobufEncodeProgrammer {
36
39
  project.checker,
37
40
  )(collection)(type);
38
41
 
39
- // @todo
40
- meta;
41
- write_object_function_body;
42
- write_map_function_body;
43
- explore_objects;
44
- explore_arrays;
42
+ const callEncoder =
43
+ (writer: string) => (factory: ts.NewExpression) =>
44
+ StatementFactory.constant(
45
+ writer,
46
+ ts.factory.createCallExpression(
47
+ ts.factory.createIdentifier("encoder"),
48
+ undefined,
49
+ [factory],
50
+ ),
51
+ );
45
52
 
46
53
  const block: ts.Statement[] = [
47
54
  StatementFactory.constant(
48
- "writer",
55
+ "encoder",
56
+ write_encoder(project)(importer)(collection)(meta),
57
+ ),
58
+ callEncoder("sizer")(
49
59
  ts.factory.createNewExpression(
50
- importer.use("Writer"),
60
+ importer.use("Sizer"),
51
61
  undefined,
62
+ [],
63
+ ),
64
+ ),
65
+ callEncoder("writer")(
66
+ ts.factory.createNewExpression(
67
+ importer.use("Writer"),
52
68
  undefined,
69
+ [ts.factory.createIdentifier("sizer")],
53
70
  ),
54
71
  ),
55
72
  ts.factory.createReturnStatement(
56
73
  ts.factory.createCallExpression(
57
- IdentifierFactory.access(WRITER())("finish"),
74
+ IdentifierFactory.access(WRITER())("buffer"),
58
75
  undefined,
59
76
  undefined,
60
77
  ),
@@ -77,68 +94,108 @@ export namespace ProtobufEncodeProgrammer {
77
94
  ts.factory.createTypeReferenceNode("Uint8Array"),
78
95
  undefined,
79
96
  ts.factory.createBlock(
80
- [...importer.declare(modulo), ...block],
97
+ [...importer.declare(modulo, false), ...block],
81
98
  true,
82
99
  ),
83
100
  );
84
101
  };
85
102
 
86
- const write_object_function_body =
103
+ const write_encoder =
87
104
  (project: IProject) =>
88
- (config: FeatureProgrammer.IConfig) =>
89
105
  (importer: FunctionImporter) =>
90
- (
91
- input: ts.Expression,
92
- obj: MetadataObject,
93
- explore: FeatureProgrammer.IExplore,
94
- tags: IMetadataTag[],
95
- ): ts.Block => {
96
- const top: MetadataProperty = obj.properties[0]!;
97
- if (top.key.isSoleLiteral() === false)
98
- return write_map_function_body(project)(config)(importer)(
99
- input,
100
- top,
101
- explore,
102
- tags,
106
+ (collection: MetadataCollection) =>
107
+ (meta: Metadata): ts.ArrowFunction => {
108
+ const functors = collection
109
+ .objects()
110
+ .filter((obj) => obj._Messagable())
111
+ .map((obj) =>
112
+ StatementFactory.constant(
113
+ `${PREFIX}o${obj.index}`,
114
+ write_object_function(project)(importer)(
115
+ ts.factory.createIdentifier("input"),
116
+ obj,
117
+ {
118
+ source: "function",
119
+ from: "object",
120
+ tracable: false,
121
+ postfix: "",
122
+ },
123
+ ),
124
+ ),
103
125
  );
104
- let index: number = 1;
105
- return ts.factory.createBlock(
106
- obj.properties
107
- .map((property) => {
108
- const statements: ts.NodeArray<ts.Statement> = decode(
109
- project,
110
- )(config)(importer)(index)(
111
- input,
112
- property.value,
113
- explore,
114
- property.tags,
115
- ).statements;
116
- index += property.value.binarySize();
117
- return statements;
118
- })
119
- .flat(),
120
- true,
126
+ const main = decode(project)(importer)(null)(
127
+ ts.factory.createIdentifier("input"),
128
+ meta,
129
+ {
130
+ source: "top",
131
+ from: "top",
132
+ tracable: false,
133
+ postfix: "",
134
+ },
135
+ [],
136
+ );
137
+ return ts.factory.createArrowFunction(
138
+ undefined,
139
+ undefined,
140
+ [IdentifierFactory.parameter("writer")],
141
+ TypeFactory.keyword("any"),
142
+ undefined,
143
+ ts.factory.createBlock(
144
+ [
145
+ ...importer.declareUnions(),
146
+ ...functors,
147
+ ...IsProgrammer.write_function_statements(project)(
148
+ importer,
149
+ )(collection),
150
+ ...main.statements,
151
+ ts.factory.createReturnStatement(
152
+ ts.factory.createIdentifier("writer"),
153
+ ),
154
+ ],
155
+ true,
156
+ ),
121
157
  );
122
158
  };
123
159
 
124
- const write_map_function_body =
160
+ const write_object_function =
125
161
  (project: IProject) =>
126
- (config: FeatureProgrammer.IConfig) =>
127
162
  (importer: FunctionImporter) =>
128
163
  (
129
164
  input: ts.Expression,
130
- entry: Metadata.Entry,
165
+ obj: MetadataObject,
131
166
  explore: FeatureProgrammer.IExplore,
132
- tags: IMetadataTag[],
133
- ): ts.Block => {
134
- project;
135
- config;
136
- importer;
137
- input;
138
- entry;
139
- explore;
140
- tags;
141
- return ts.factory.createBlock([], true);
167
+ ): ts.ArrowFunction => {
168
+ let index: number = 1;
169
+ const body: ts.Statement[] = obj.properties
170
+ .map((p) => {
171
+ const block = decode(project)(importer)(index)(
172
+ IdentifierFactory.access(input)(
173
+ p.key.getSoleLiteral()!,
174
+ ),
175
+ p.value,
176
+ explore,
177
+ p.tags,
178
+ );
179
+ index += p.value.binarySize();
180
+ return [
181
+ ts.factory.createExpressionStatement(
182
+ ts.factory.createIdentifier(
183
+ `// property "${p.key.getSoleLiteral()!}"`,
184
+ ),
185
+ ),
186
+ ...block.statements,
187
+ ];
188
+ })
189
+ .flat();
190
+
191
+ return ts.factory.createArrowFunction(
192
+ undefined,
193
+ undefined,
194
+ [IdentifierFactory.parameter("input")],
195
+ TypeFactory.keyword("any"),
196
+ undefined,
197
+ ts.factory.createBlock(body, true),
198
+ );
142
199
  };
143
200
 
144
201
  /* -----------------------------------------------------------
@@ -146,7 +203,6 @@ export namespace ProtobufEncodeProgrammer {
146
203
  ----------------------------------------------------------- */
147
204
  const decode =
148
205
  (project: IProject) =>
149
- (config: FeatureProgrammer.IConfig) =>
150
206
  (importer: FunctionImporter) =>
151
207
  (index: number | null) =>
152
208
  (
@@ -155,6 +211,61 @@ export namespace ProtobufEncodeProgrammer {
155
211
  explore: FeatureProgrammer.IExplore,
156
212
  tags: IMetadataTag[],
157
213
  ): ts.Block => {
214
+ const wrapper: (block: ts.Block) => ts.Block =
215
+ meta.isRequired() && meta.nullable === false
216
+ ? (block) => block
217
+ : meta.isRequired() === false && meta.nullable === false
218
+ ? (block) =>
219
+ ts.factory.createBlock(
220
+ [
221
+ ts.factory.createIfStatement(
222
+ ts.factory.createLogicalAnd(
223
+ ts.factory.createInequality(
224
+ ts.factory.createIdentifier(
225
+ "undefined",
226
+ ),
227
+ input,
228
+ ),
229
+ ts.factory.createInequality(
230
+ ts.factory.createNull(),
231
+ input,
232
+ ),
233
+ ),
234
+ block,
235
+ ),
236
+ ],
237
+ true,
238
+ )
239
+ : meta.isRequired() === false
240
+ ? (block) =>
241
+ ts.factory.createBlock(
242
+ [
243
+ ts.factory.createIfStatement(
244
+ ts.factory.createInequality(
245
+ ts.factory.createIdentifier(
246
+ "undefined",
247
+ ),
248
+ input,
249
+ ),
250
+ block,
251
+ ),
252
+ ],
253
+ true,
254
+ )
255
+ : (block) =>
256
+ ts.factory.createBlock(
257
+ [
258
+ ts.factory.createIfStatement(
259
+ ts.factory.createInequality(
260
+ ts.factory.createNull(),
261
+ input,
262
+ ),
263
+ block,
264
+ ),
265
+ ],
266
+ true,
267
+ );
268
+
158
269
  // STARTS FROM ATOMIC TYPES
159
270
  const unions: IUnion[] = ProtobufUtil.atomics(meta).map((type) => ({
160
271
  type,
@@ -164,134 +275,350 @@ export namespace ProtobufEncodeProgrammer {
164
275
  ts.factory.createStringLiteral(type),
165
276
  ts.factory.createTypeOfExpression(input),
166
277
  ),
167
- value: () => decode_atomic(input, type, tags),
278
+ value: (index) => decode_atomic(index!)(input, type, tags),
168
279
  }));
169
280
 
170
- project;
171
- config;
172
- importer;
173
- index;
174
- explore;
175
- unions;
281
+ // CONSIDER BYTES
282
+ if (meta.natives.length)
283
+ unions.push({
284
+ type: "bytes",
285
+ is: () =>
286
+ ExpressionFactory.isInstanceOf("Uint8Array")(input),
287
+ value: (index) => decode_bytes("bytes")(index!)(input),
288
+ });
289
+
290
+ // CONSIDER MAPS
291
+ if (meta.maps.length)
292
+ unions.push({
293
+ type: "map",
294
+ is: () => ExpressionFactory.isInstanceOf("Map")(input),
295
+ value: (index) =>
296
+ decode_map(project)(importer)(index!)(
297
+ input,
298
+ meta.maps[0]!,
299
+ {
300
+ ...explore,
301
+ from: "array",
302
+ },
303
+ tags,
304
+ ),
305
+ });
176
306
 
177
307
  // CONSIDER ARRAYS
308
+ if (meta.arrays.length)
309
+ unions.push({
310
+ type: "array",
311
+ is: () => ExpressionFactory.isArray(input),
312
+ value: (index) =>
313
+ explore_arrays(project)(importer)(index!)(
314
+ input,
315
+ meta.arrays,
316
+ {
317
+ ...explore,
318
+ from: "array",
319
+ },
320
+ tags,
321
+ ),
322
+ });
178
323
 
179
324
  // CONSIDER OBJECTS
325
+ if (meta.objects.length)
326
+ unions.push({
327
+ type: "object",
328
+ is: () =>
329
+ ExpressionFactory.isObject({
330
+ checkNull: true,
331
+ checkArray: false,
332
+ })(input),
333
+ value: (index) =>
334
+ explore_objects(project)(importer)(0)(index)(
335
+ input,
336
+ meta.objects,
337
+ {
338
+ ...explore,
339
+ from: "object",
340
+ },
341
+ tags,
342
+ ),
343
+ });
180
344
 
181
- // CONSIDER MAPS
182
-
183
- return ts.factory.createBlock([]);
345
+ // RETURNS
346
+ if (unions.length === 1) return wrapper(unions[0]!.value(index));
347
+ else
348
+ return wrapper(
349
+ iterate(importer)(index)(unions)(meta.getName())(input),
350
+ );
184
351
  };
185
352
 
186
- const decode_object =
353
+ const iterate =
354
+ (importer: FunctionImporter) =>
355
+ (index: number | null) =>
356
+ (unions: IUnion[]) =>
357
+ (expected: string) =>
358
+ (input: ts.Expression) =>
359
+ ts.factory.createBlock(
360
+ [
361
+ unions
362
+ .map((u, i) =>
363
+ ts.factory.createIfStatement(
364
+ u.is(),
365
+ u.value(index ? index + i : null),
366
+ i === unions.length - 1
367
+ ? create_throw_error(importer)(expected)(
368
+ input,
369
+ )
370
+ : undefined,
371
+ ),
372
+ )
373
+ .reverse()
374
+ .reduce((a, b) =>
375
+ ts.factory.createIfStatement(
376
+ b.expression,
377
+ b.thenStatement,
378
+ a,
379
+ ),
380
+ ),
381
+ ],
382
+ true,
383
+ );
384
+
385
+ const decode_map =
187
386
  (project: IProject) =>
188
- (config: FeatureProgrammer.IConfig) =>
189
387
  (importer: FunctionImporter) =>
388
+ (index: number) =>
190
389
  (
191
390
  input: ts.Expression,
192
- object: MetadataObject,
391
+ map: Metadata.Entry,
193
392
  explore: FeatureProgrammer.IExplore,
393
+ tags: IMetadataTag[],
194
394
  ): ts.Block => {
195
- project;
196
- config;
197
- importer;
198
- input;
199
- object;
200
- explore;
201
-
395
+ const each: ts.Statement[] = [
396
+ ts.factory.createExpressionStatement(
397
+ decode_tag(ProtobufWire.LEN)(index),
398
+ ),
399
+ ts.factory.createExpressionStatement(
400
+ ts.factory.createCallExpression(
401
+ IdentifierFactory.access(WRITER())("fork"),
402
+ undefined,
403
+ undefined,
404
+ ),
405
+ ),
406
+ ...decode(project)(importer)(1)(
407
+ ts.factory.createIdentifier("key"),
408
+ map.key,
409
+ explore,
410
+ [],
411
+ ).statements,
412
+ ...decode(project)(importer)(2)(
413
+ ts.factory.createIdentifier("value"),
414
+ map.value,
415
+ explore,
416
+ tags,
417
+ ).statements,
418
+ ts.factory.createExpressionStatement(
419
+ ts.factory.createCallExpression(
420
+ IdentifierFactory.access(WRITER())("ldelim"),
421
+ undefined,
422
+ undefined,
423
+ ),
424
+ ),
425
+ ];
202
426
  return ts.factory.createBlock(
203
- [].map((exp) => ts.factory.createExpressionStatement(exp)),
427
+ [
428
+ ts.factory.createForOfStatement(
429
+ undefined,
430
+ StatementFactory.entry("key")("value"),
431
+ input,
432
+ ts.factory.createBlock(each),
433
+ ),
434
+ ],
204
435
  true,
205
436
  );
206
437
  };
207
438
 
208
- const decode_array =
439
+ const decode_object =
209
440
  (project: IProject) =>
210
- (config: FeatureProgrammer.IConfig) =>
211
441
  (importer: FunctionImporter) =>
212
- (index: number) =>
442
+ (index: number | null) =>
213
443
  (
214
444
  input: ts.Expression,
215
- array: MetadataArray,
445
+ object: MetadataObject,
216
446
  explore: FeatureProgrammer.IExplore,
217
447
  tags: IMetadataTag[],
218
- ): ts.Block =>
219
- ts.factory.createBlock(
448
+ ): ts.Block => {
449
+ const top: MetadataProperty = object.properties[0]!;
450
+ if (top.key.isSoleLiteral() === false)
451
+ return decode_map(project)(importer)(index!)(
452
+ ts.factory.createCallExpression(
453
+ ts.factory.createIdentifier("Object.entries"),
454
+ [],
455
+ [input],
456
+ ),
457
+ top,
458
+ explore,
459
+ tags,
460
+ );
461
+ return ts.factory.createBlock(
220
462
  [
221
463
  ...(index !== null
222
464
  ? [
223
- ts.factory.createExpressionStatement(
224
- decode_tag(ProtobufWire.LEN)(index),
465
+ decode_tag(ProtobufWire.LEN)(index),
466
+ ts.factory.createCallExpression(
467
+ IdentifierFactory.access(WRITER())("fork"),
468
+ undefined,
469
+ undefined,
225
470
  ),
226
471
  ]
227
472
  : []),
228
- ts.factory.createForOfStatement(
229
- undefined,
230
- ts.factory.createVariableDeclarationList(
231
- [ts.factory.createVariableDeclaration("elem")],
232
- undefined,
233
- ),
234
- input,
235
- decode(project)(config)(importer)(index)(
236
- ts.factory.createIdentifier("elem"),
237
- array.value,
238
- explore,
239
- tags,
473
+ ts.factory.createCallExpression(
474
+ ts.factory.createIdentifier(
475
+ `${PREFIX}o${object.index}`,
240
476
  ),
477
+ [],
478
+ [input],
241
479
  ),
242
- ],
480
+ ...(index !== null
481
+ ? [
482
+ ts.factory.createCallExpression(
483
+ IdentifierFactory.access(WRITER())("ldelim"),
484
+ undefined,
485
+ undefined,
486
+ ),
487
+ ]
488
+ : []),
489
+ ].map((expr) => ts.factory.createExpressionStatement(expr)),
243
490
  true,
244
491
  );
492
+ };
245
493
 
246
- const decode_atomic = (
247
- input: ts.Expression,
248
- atomic: Atomic.Literal,
249
- tags: IMetadataTag[],
250
- ): ts.Block => {
251
- if (atomic === "string") return decode_bytes("string")(input);
252
-
253
- const out = (method: string): ts.Block =>
254
- ts.factory.createBlock(
255
- [
256
- ts.factory.createCallExpression(
257
- IdentifierFactory.access(WRITER())(method),
258
- undefined,
259
- [input],
494
+ const decode_array =
495
+ (project: IProject) =>
496
+ (importer: FunctionImporter) =>
497
+ (index: number) =>
498
+ (
499
+ input: ts.Expression,
500
+ array: MetadataArray,
501
+ explore: FeatureProgrammer.IExplore,
502
+ tags: IMetadataTag[],
503
+ ): ts.Block => {
504
+ const wire = get_standalone_wire(array.value, tags);
505
+ const forLoop = (index: number | null) =>
506
+ ts.factory.createForOfStatement(
507
+ undefined,
508
+ ts.factory.createVariableDeclarationList(
509
+ [ts.factory.createVariableDeclaration("elem")],
510
+ ts.NodeFlags.Const,
260
511
  ),
261
- ].map((exp) => ts.factory.createExpressionStatement(exp)),
262
- true,
512
+ input,
513
+ decode(project)(importer)(index)(
514
+ ts.factory.createIdentifier("elem"),
515
+ array.value,
516
+ explore,
517
+ tags,
518
+ ),
519
+ );
520
+ const length = (block: ts.Block) =>
521
+ ts.factory.createBlock(
522
+ [
523
+ ts.factory.createIfStatement(
524
+ ts.factory.createStrictInequality(
525
+ ts.factory.createNumericLiteral(0),
526
+ IdentifierFactory.access(input)("length"),
527
+ ),
528
+ block,
529
+ ),
530
+ ],
531
+ true,
532
+ );
533
+
534
+ if (wire === ProtobufWire.LEN)
535
+ return length(ts.factory.createBlock([forLoop(index)], true));
536
+ return length(
537
+ ts.factory.createBlock(
538
+ [
539
+ ts.factory.createExpressionStatement(
540
+ decode_tag(ProtobufWire.LEN)(index),
541
+ ),
542
+ ts.factory.createExpressionStatement(
543
+ ts.factory.createCallExpression(
544
+ IdentifierFactory.access(WRITER())("fork"),
545
+ undefined,
546
+ undefined,
547
+ ),
548
+ ),
549
+ forLoop(null),
550
+ ts.factory.createExpressionStatement(
551
+ ts.factory.createCallExpression(
552
+ IdentifierFactory.access(WRITER())("ldelim"),
553
+ undefined,
554
+ undefined,
555
+ ),
556
+ ),
557
+ ],
558
+ true,
559
+ ),
263
560
  );
264
- if (atomic === "boolean") return out("bool");
561
+ };
265
562
 
266
- const type: IMetadataTag.INumberType | undefined = tags.find(
267
- (tag) => tag.kind === "type",
268
- ) as IMetadataTag.INumberType | undefined;
269
- if (atomic === "bigint")
270
- return out(type?.value === "uint64" ? "uint64" : "int64");
271
- else if (type === undefined || type?.value === "double")
272
- return out("double");
273
- else if (type.value === "float") return out("float");
274
- return out(
275
- type.value === "uint32" || type.value === "uint"
276
- ? "uint32"
277
- : type.value === "int32" || type.value === "int"
278
- ? "int32"
279
- : type.value === "int64"
280
- ? "int64"
281
- : "uint64",
282
- );
283
- };
563
+ const decode_atomic =
564
+ (index: number | null) =>
565
+ (
566
+ input: ts.Expression,
567
+ atomic: Atomic.Literal,
568
+ tags: IMetadataTag[],
569
+ ): ts.Block => {
570
+ if (atomic === "string")
571
+ return decode_bytes("string")(index!)(input);
572
+
573
+ const out =
574
+ (wire: ProtobufWire) =>
575
+ (method: string): ts.Block =>
576
+ ts.factory.createBlock(
577
+ [
578
+ ...(index !== null
579
+ ? [decode_tag(wire)(index)]
580
+ : []),
581
+ ts.factory.createCallExpression(
582
+ IdentifierFactory.access(WRITER())(method),
583
+ undefined,
584
+ [input],
585
+ ),
586
+ ].map((exp) =>
587
+ ts.factory.createExpressionStatement(exp),
588
+ ),
589
+ true,
590
+ );
591
+ if (atomic === "boolean") return out(ProtobufWire.VARIANT)("bool");
592
+
593
+ const type: IMetadataTag.INumberType | undefined = tags.find(
594
+ (tag) => tag.kind === "type",
595
+ ) as IMetadataTag.INumberType | undefined;
596
+ if (atomic === "bigint")
597
+ return out(ProtobufWire.VARIANT)(
598
+ type?.value === "uint64" ? "uint64" : "int64",
599
+ );
600
+ else if (type === undefined || type?.value === "double")
601
+ return out(ProtobufWire.I64)("double");
602
+ else if (type.value === "float")
603
+ return out(ProtobufWire.I32)("float");
604
+ return out(ProtobufWire.VARIANT)(
605
+ type.value === "uint32" || type.value === "uint"
606
+ ? "uint32"
607
+ : type.value === "int32" || type.value === "int"
608
+ ? "int32"
609
+ : type.value === "int64"
610
+ ? "int64"
611
+ : "uint64",
612
+ );
613
+ };
284
614
 
285
615
  const decode_bytes =
286
616
  (method: "bytes" | "string") =>
617
+ (index: number) =>
287
618
  (input: ts.Expression): ts.Block =>
288
619
  ts.factory.createBlock(
289
620
  [
290
- ts.factory.createCallExpression(
291
- IdentifierFactory.access(WRITER())("uint32"),
292
- undefined,
293
- [IdentifierFactory.access(input)("length")],
294
- ),
621
+ decode_tag(ProtobufWire.LEN)(index),
295
622
  ts.factory.createCallExpression(
296
623
  IdentifierFactory.access(WRITER())(method),
297
624
  undefined,
@@ -310,37 +637,139 @@ export namespace ProtobufEncodeProgrammer {
310
637
  [ts.factory.createNumericLiteral((index << 3) | wire)],
311
638
  );
312
639
 
640
+ const get_standalone_wire = (
641
+ meta: Metadata,
642
+ tags: IMetadataTag[],
643
+ ): ProtobufWire => {
644
+ if (
645
+ meta.arrays.length ||
646
+ meta.objects.length ||
647
+ meta.maps.length ||
648
+ meta.natives.length
649
+ )
650
+ return ProtobufWire.LEN;
651
+
652
+ const v = ProtobufUtil.atomics(meta)[0]!;
653
+ if (v === "string") return ProtobufWire.LEN;
654
+ else if (v === "boolean" || v === "bigint") return ProtobufWire.VARIANT;
655
+
656
+ const type: IMetadataTag.INumberType | undefined = tags.find(
657
+ (t) => t.kind === "type",
658
+ ) as IMetadataTag.INumberType | undefined;
659
+ if (type === undefined) return ProtobufWire.I64;
660
+ else if (type.value === "float") return ProtobufWire.I32;
661
+ return ProtobufWire.VARIANT;
662
+ };
663
+
313
664
  /* -----------------------------------------------------------
314
665
  EXPLORERS
315
666
  ----------------------------------------------------------- */
316
667
  const explore_objects =
317
668
  (project: IProject) =>
318
- (config: FeatureProgrammer.IConfig) =>
319
669
  (importer: FunctionImporter) =>
670
+ (level: number) =>
671
+ (index: number | null) =>
320
672
  (
321
673
  input: ts.Expression,
322
- meta: Metadata,
674
+ targets: MetadataObject[],
323
675
  explore: FeatureProgrammer.IExplore,
324
- ) =>
325
- meta.objects.length === 1
326
- ? decode_object(project)(config)(importer)(
327
- input,
328
- meta.objects[0]!,
329
- explore,
330
- )
331
- : ts.factory.createCallExpression(
332
- ts.factory.createIdentifier(
333
- importer.useLocal(
334
- `${config.prefix}u${meta.union_index!}`,
335
- ),
336
- ),
337
- undefined,
338
- FeatureProgrammer.argumentsArray(config)(explore)(input),
339
- );
676
+ tags: IMetadataTag[],
677
+ ): ts.Block => {
678
+ if (targets.length === 1)
679
+ return decode_object(project)(importer)(index)(
680
+ input,
681
+ targets[0]!,
682
+ explore,
683
+ tags,
684
+ );
685
+
686
+ const expected: string = `(${targets
687
+ .map((t) => t.name)
688
+ .join(" | ")})`;
689
+
690
+ // POSSIBLE TO SPECIALIZE?
691
+ const specList = UnionPredicator.object(targets);
692
+ if (specList.length === 0) {
693
+ const condition: ts.Expression = decode_union_object(
694
+ IsProgrammer.decode_object(importer),
695
+ )((i, o, e) =>
696
+ ExpressionFactory.selfCall(
697
+ decode_object(project)(importer)(index)(i, o, e, tags),
698
+ ),
699
+ )((expr) => expr)((value, expected) =>
700
+ create_throw_error(importer)(expected)(value),
701
+ )(input, targets, explore);
702
+ return StatementFactory.block(condition);
703
+ }
704
+ const remained: MetadataObject[] = targets.filter(
705
+ (t) => specList.find((s) => s.object === t) === undefined,
706
+ );
707
+
708
+ // DO SPECIALIZE
709
+ const condition: ts.IfStatement = specList
710
+ .filter((spec) => spec.property.key.getSoleLiteral() !== null)
711
+ .map((spec, i, array) => {
712
+ const key: string = spec.property.key.getSoleLiteral()!;
713
+ const accessor: ts.Expression =
714
+ IdentifierFactory.access(input)(key);
715
+ const pred: ts.Expression = spec.neighbour
716
+ ? IsProgrammer.decode(project)(importer)(
717
+ accessor,
718
+ spec.property.value,
719
+ {
720
+ ...explore,
721
+ tracable: false,
722
+ postfix: IdentifierFactory.postfix(key),
723
+ },
724
+ tags,
725
+ [],
726
+ )
727
+ : ExpressionFactory.isRequired(accessor);
728
+ return ts.factory.createIfStatement(
729
+ pred,
730
+ ts.factory.createReturnStatement(
731
+ ExpressionFactory.selfCall(
732
+ decode_object(project)(importer)(index)(
733
+ input,
734
+ spec.object,
735
+ explore,
736
+ tags,
737
+ ),
738
+ ),
739
+ ),
740
+ i === array.length - 1
741
+ ? remained.length
742
+ ? ts.factory.createReturnStatement(
743
+ ExpressionFactory.selfCall(
744
+ explore_objects(project)(importer)(
745
+ level + 1,
746
+ )(index)(
747
+ input,
748
+ remained,
749
+ explore,
750
+ tags,
751
+ ),
752
+ ),
753
+ )
754
+ : create_throw_error(importer)(expected)(input)
755
+ : undefined,
756
+ );
757
+ })
758
+ .reverse()
759
+ .reduce((a, b) =>
760
+ ts.factory.createIfStatement(
761
+ b.expression,
762
+ b.thenStatement,
763
+ a,
764
+ ),
765
+ );
766
+
767
+ // RETURNS WITH CONDITIONS
768
+ return ts.factory.createBlock([condition], true);
769
+ };
340
770
 
341
771
  const explore_arrays =
342
772
  (project: IProject) =>
343
- (config: FeatureProgrammer.IConfig) =>
344
773
  (importer: FunctionImporter) =>
345
774
  (index: number) =>
346
775
  (
@@ -348,37 +777,43 @@ export namespace ProtobufEncodeProgrammer {
348
777
  elements: MetadataArray[],
349
778
  explore: FeatureProgrammer.IExplore,
350
779
  tags: IMetadataTag[],
351
- ): ts.Expression =>
352
- explore_array_like_union_types(config)(importer)(
353
- UnionExplorer.array({
354
- checker: IsProgrammer.decode(project)(importer),
355
- decoder: (input, target, explore, tags) =>
356
- ts.factory.createCallExpression(
357
- ts.factory.createArrowFunction(
358
- undefined,
359
- undefined,
360
- [],
361
- undefined,
362
- undefined,
363
- decode_array(project)(config)(importer)(index)(
364
- input,
365
- target,
366
- explore,
367
- tags,
368
- ),
369
- ),
370
- undefined,
371
- undefined,
372
- ),
373
- empty: ts.factory.createStringLiteral("[]"),
374
- success: ts.factory.createTrue(),
375
- failure: (input, expected) =>
376
- create_throw_error(importer)(expected)(input),
377
- }),
378
- )(input, elements, explore, tags);
780
+ ): ts.Block =>
781
+ elements.length === 1
782
+ ? decode_array(project)(importer)(index)(
783
+ input,
784
+ elements[0]!,
785
+ explore,
786
+ tags,
787
+ )
788
+ : explore_array_like_union_types(importer)(
789
+ UnionExplorer.array({
790
+ checker: IsProgrammer.decode(project)(importer),
791
+ decoder: (input, target, explore, tags) =>
792
+ ts.factory.createCallExpression(
793
+ ts.factory.createArrowFunction(
794
+ undefined,
795
+ undefined,
796
+ [],
797
+ undefined,
798
+ undefined,
799
+ decode_array(project)(importer)(index)(
800
+ input,
801
+ target,
802
+ explore,
803
+ tags,
804
+ ),
805
+ ),
806
+ undefined,
807
+ undefined,
808
+ ),
809
+ empty: ts.factory.createStringLiteral("[]"),
810
+ success: ts.factory.createTrue(),
811
+ failure: (input, expected) =>
812
+ create_throw_error(importer)(expected)(input),
813
+ }),
814
+ )(input, elements, explore, tags);
379
815
 
380
816
  const explore_array_like_union_types =
381
- (config: FeatureProgrammer.IConfig) =>
382
817
  (importer: FunctionImporter) =>
383
818
  <T extends MetadataArray | MetadataTuple>(
384
819
  factory: (
@@ -396,17 +831,19 @@ export namespace ProtobufEncodeProgrammer {
396
831
  elements: T[],
397
832
  explore: FeatureProgrammer.IExplore,
398
833
  tags: IMetadataTag[],
399
- ): ts.Expression => {
834
+ ): ts.Block => {
400
835
  const arrow =
401
836
  (parameters: ts.ParameterDeclaration[]) =>
402
837
  (explore: FeatureProgrammer.IExplore) =>
403
838
  (input: ts.Expression): ts.ArrowFunction =>
404
839
  factory(parameters)(input, elements, explore, tags, []);
405
840
  if (elements.every((e) => e.recursive === false))
406
- ts.factory.createCallExpression(
407
- arrow([])(explore)(input),
408
- undefined,
409
- [],
841
+ return StatementFactory.block(
842
+ ts.factory.createCallExpression(
843
+ arrow([])(explore)(input),
844
+ undefined,
845
+ [],
846
+ ),
410
847
  );
411
848
 
412
849
  explore = {
@@ -414,31 +851,39 @@ export namespace ProtobufEncodeProgrammer {
414
851
  source: "function",
415
852
  from: "array",
416
853
  };
417
- return ts.factory.createCallExpression(
418
- ts.factory.createIdentifier(
419
- importer.emplaceUnion(
420
- config.prefix,
421
- elements.map((e) => e.name).join(" | "),
422
- () =>
423
- arrow(
424
- FeatureProgrammer.parameterDeclarations(config)(
425
- TypeFactory.keyword("any"),
426
- )(ts.factory.createIdentifier("input")),
427
- )({
428
- ...explore,
429
- postfix: "",
430
- })(ts.factory.createIdentifier("input")),
854
+ return StatementFactory.block(
855
+ ts.factory.createCallExpression(
856
+ ts.factory.createIdentifier(
857
+ importer.emplaceUnion(
858
+ PREFIX,
859
+ elements.map((e) => e.name).join(" | "),
860
+ () =>
861
+ arrow(
862
+ FeatureProgrammer.parameterDeclarations(
863
+ CONFIG,
864
+ )(TypeFactory.keyword("any"))(
865
+ ts.factory.createIdentifier("input"),
866
+ ),
867
+ )({
868
+ ...explore,
869
+ postfix: "",
870
+ })(ts.factory.createIdentifier("input")),
871
+ ),
431
872
  ),
873
+ undefined,
874
+ FeatureProgrammer.argumentsArray(CONFIG)(explore)(input),
432
875
  ),
433
- undefined,
434
- FeatureProgrammer.argumentsArray(config)(explore)(input),
435
876
  );
436
877
  };
437
878
 
438
879
  /* -----------------------------------------------------------
439
880
  CONFIGURATIONS
440
881
  ----------------------------------------------------------- */
441
- // const PREFIX = "$pe";
882
+ const PREFIX = "$pe";
883
+ const CONFIG = {
884
+ path: false,
885
+ trace: false,
886
+ };
442
887
 
443
888
  const create_throw_error =
444
889
  (importer: FunctionImporter) =>
@@ -471,7 +916,6 @@ const WRITER = () => ts.factory.createIdentifier("writer");
471
916
 
472
917
  interface IUnion {
473
918
  type: string;
474
- wire: () => ProtobufWire;
475
919
  is: () => ts.Expression;
476
920
  value: (index: number | null) => ts.Block;
477
921
  }