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
@@ -0,0 +1,144 @@
1
+ import { $strlen } from "./$strlen";
2
+ import { IProtobufWriter } from "./IProtobufWriter";
3
+
4
+ export class $ProtobufSizer implements IProtobufWriter {
5
+ /**
6
+ * Total length.
7
+ */
8
+ public len: number;
9
+
10
+ /**
11
+ * Position stack.
12
+ */
13
+ public readonly pos: Array<number>;
14
+
15
+ /**
16
+ * Variable length list.
17
+ */
18
+ public readonly varlen: Array<number>;
19
+
20
+ /**
21
+ * Variable length index stack.
22
+ */
23
+ public readonly varlenidx: Array<number>;
24
+
25
+ public constructor(length: number = 0) {
26
+ this.len = length;
27
+ this.pos = [];
28
+ this.varlen = [];
29
+ this.varlenidx = [];
30
+ }
31
+
32
+ public bool(): void {
33
+ this.len += 1;
34
+ }
35
+ public int32(value: number): void {
36
+ if (value < 0) {
37
+ // 10 bytes to encode negative number
38
+ this.len += 10;
39
+ } else {
40
+ this.varint32(value);
41
+ }
42
+ }
43
+ public sint32(value: number): void {
44
+ this.varint32((value << 1) ^ (value >> 31));
45
+ }
46
+ public uint32(value: number): void {
47
+ this.varint32(value);
48
+ }
49
+
50
+ public int64(value: bigint | number): void {
51
+ this.varint64(typeof value === "number" ? BigInt(value) : value);
52
+ }
53
+ public sint64(value: bigint | number): void {
54
+ if (typeof value === "number") value = BigInt(value);
55
+ this.varint64((value << BigInt(1)) ^ (value >> BigInt(63)));
56
+ }
57
+ public uint64(value: bigint | number): void {
58
+ this.varint64(typeof value === "number" ? BigInt(value) : value);
59
+ }
60
+
61
+ // public fixed32(_value: number): void {
62
+ // this.len += 4;
63
+ // }
64
+ // public sfixed32(_value: number): void {
65
+ // this.len += 4;
66
+ // }
67
+ // public fixed64(_value: number | bigint): void {
68
+ // this.len += 8;
69
+ // }
70
+ // public sfixed64(_value: number | bigint): void {
71
+ // this.len += 8;
72
+ // }
73
+ public float(_value: number): void {
74
+ this.len += 4;
75
+ }
76
+ public double(_value: number): void {
77
+ this.len += 8;
78
+ }
79
+
80
+ public bytes(value: Uint8Array): void {
81
+ this.uint32(value.byteLength);
82
+ this.len += value.byteLength;
83
+ }
84
+ public string(value: string): void {
85
+ const len: number = $strlen(value);
86
+ this.varlen.push(len);
87
+ this.uint32(len);
88
+ this.len += len;
89
+ }
90
+
91
+ public fork(): void {
92
+ this.pos.push(this.len); // save current position
93
+ this.varlenidx.push(this.varlen.length); // save current index in varlen array
94
+ this.varlen.push(0); // add 0 length to varlen array (to be updated in ldelim())
95
+ }
96
+
97
+ public ldelim(): void {
98
+ if (!(this.pos.length && this.varlenidx.length))
99
+ throw new Error("Missing fork() before ldelim() call.");
100
+
101
+ const endPos = this.len; // current position is end position
102
+ const startPos = this.pos.pop()!; // get start position from stack
103
+ const idx = this.varlenidx.pop()!; // get varlen index from stack
104
+ const len = endPos - startPos; // calculate length
105
+
106
+ this.varlen[idx] = len; // update variable length
107
+ this.uint32(len); // add uint32 that should be called in fork()
108
+ }
109
+
110
+ public reset(): void {
111
+ this.len = 0;
112
+ // re-use arrays
113
+ this.pos.length = 0;
114
+ this.varlen.length = 0;
115
+ this.varlenidx.length = 0;
116
+ }
117
+
118
+ private varint32(value: number): void {
119
+ this.len +=
120
+ value < 0
121
+ ? 10 // 10 bits with leading 1's
122
+ : value < 0x80
123
+ ? 1
124
+ : value < 0x4000
125
+ ? 2
126
+ : value < 0x200000
127
+ ? 3
128
+ : value < 0x10000000
129
+ ? 4
130
+ : 5;
131
+ }
132
+
133
+ private varint64(val: bigint): void {
134
+ val = BigInt.asUintN(64, val);
135
+ while (val > NX7F) {
136
+ ++this.len;
137
+ val = val >> ND07;
138
+ }
139
+ ++this.len;
140
+ }
141
+ }
142
+
143
+ const ND07 = BigInt(7);
144
+ const NX7F = BigInt(0x7f);
@@ -0,0 +1,152 @@
1
+ import { $ProtobufSizer } from "./$ProtobufSizer";
2
+ import { IProtobufWriter } from "./IProtobufWriter";
3
+
4
+ export class $ProtobufWriter implements IProtobufWriter {
5
+ /**
6
+ * Related sizer
7
+ */
8
+ private readonly sizer: $ProtobufSizer;
9
+
10
+ /**
11
+ * Current pointer.
12
+ */
13
+ private ptr: number;
14
+
15
+ /**
16
+ * Protobuf buffer.
17
+ */
18
+ private buf: Uint8Array;
19
+
20
+ /**
21
+ * DataView for buffer.
22
+ */
23
+ private view: DataView;
24
+
25
+ /**
26
+ * Index in varlen array from sizer.
27
+ */
28
+ private varlenidx: number;
29
+
30
+ constructor(sizer: $ProtobufSizer) {
31
+ this.sizer = sizer;
32
+ this.buf = new Uint8Array(sizer.len);
33
+ this.view = new DataView(this.buf.buffer);
34
+ this.ptr = 0;
35
+ this.varlenidx = 0;
36
+ }
37
+
38
+ buffer(): Uint8Array {
39
+ return this.buf;
40
+ }
41
+
42
+ bool(value: boolean): void {
43
+ this.byte(value ? 1 : 0);
44
+ }
45
+
46
+ byte(value: number): void {
47
+ this.buf[this.ptr++] = value & 255;
48
+ }
49
+
50
+ int32(value: number): void {
51
+ if (value < 0) this.int64(value);
52
+ else this.variant32(value >>> 0);
53
+ }
54
+
55
+ sint32(value: number): void {
56
+ this.variant32((value << 1) ^ (value >> 31));
57
+ }
58
+
59
+ uint32(value: number): void {
60
+ this.variant32(value);
61
+ }
62
+
63
+ sint64(value: number | bigint): void {
64
+ value = BigInt(value);
65
+ this.variant64((value << ND01) ^ (value >> ND63));
66
+ }
67
+
68
+ int64(value: number | bigint): void {
69
+ this.variant64(BigInt(value));
70
+ }
71
+
72
+ uint64(value: number | bigint): void {
73
+ this.variant64(BigInt(value));
74
+ }
75
+
76
+ float(val: number): void {
77
+ this.view.setFloat32(this.ptr, val, true);
78
+ this.ptr += 4;
79
+ }
80
+
81
+ double(val: number): void {
82
+ this.view.setFloat64(this.ptr, val, true);
83
+ this.ptr += 8;
84
+ }
85
+
86
+ bytes(value: Uint8Array): void {
87
+ this.fork();
88
+ this.uint32(value.byteLength);
89
+ for (let i = 0; i < value.byteLength; i++)
90
+ this.buf[this.ptr++] = value[i]!;
91
+ }
92
+
93
+ string(value: string): void {
94
+ const len: number = this.varlen(); // use precomputed length
95
+ this.uint32(len);
96
+
97
+ const binary: Uint8Array = utf8.encode(value);
98
+ for (let i = 0; i < binary.byteLength; i++)
99
+ this.buf[this.ptr++] = binary[i]!;
100
+ }
101
+
102
+ fork(): void {
103
+ this.uint32(this.varlen()); // use precomputed length
104
+ }
105
+
106
+ ldelim(): void {
107
+ // nothing to do - all dirty work done by sizer
108
+ }
109
+
110
+ finish(): Uint8Array {
111
+ return this.buf;
112
+ }
113
+
114
+ reset(): void {
115
+ this.buf = new Uint8Array(this.sizer.len);
116
+ this.view = new DataView(this.buf.buffer);
117
+ this.ptr = 0;
118
+ this.varlenidx = 0;
119
+ }
120
+
121
+ private variant32(val: number): void {
122
+ while (val > 0x7f) {
123
+ this.buf[this.ptr++] = (val & 0x7f) | 0x80;
124
+ val = val >>> 7;
125
+ }
126
+ this.buf[this.ptr++] = val;
127
+ }
128
+
129
+ private variant64(val: bigint): void {
130
+ val = BigInt.asUintN(64, val);
131
+ while (val > NX7F) {
132
+ this.buf[this.ptr++] = Number((val & NX7F) | NX80);
133
+ val = val >> ND07; // @todo
134
+ // (val / (128n) % 2n === 1n)
135
+ }
136
+ this.buf[this.ptr++] = Number(val);
137
+ }
138
+
139
+ private varlen(): number {
140
+ return this.varlenidx >= this.sizer.varlen.length
141
+ ? 0
142
+ : this.sizer.varlen[this.varlenidx++]!;
143
+ }
144
+ }
145
+
146
+ const utf8 = new TextEncoder();
147
+
148
+ const ND01 = BigInt(1);
149
+ const ND07 = BigInt(7);
150
+ const ND63 = BigInt(63);
151
+ const NX7F = BigInt(0x7f);
152
+ const NX80 = BigInt(0x80);
@@ -0,0 +1,18 @@
1
+ export interface IProtobufWriter {
2
+ bool(value: boolean): void;
3
+ int32(value: number): void;
4
+ sint32(value: number): void;
5
+ uint32(value: number): void;
6
+
7
+ int64(value: bigint | number): void;
8
+ sint64(value: bigint | number): void;
9
+ uint64(value: bigint | number): void;
10
+
11
+ float(value: number): void;
12
+ double(value: number): void;
13
+ bytes(value: Uint8Array): void;
14
+ string(value: string): void;
15
+
16
+ fork(): void;
17
+ ldelim(): void;
18
+ }
@@ -1,9 +1,10 @@
1
- import { Writer } from "protobufjs";
2
-
3
1
  import { RandomGenerator } from "../utils/RandomGenerator";
4
2
 
5
3
  import { IValidation } from "../IValidation";
6
4
  import { TypeGuardError } from "../TypeGuardError";
5
+ import { $ProtobufReader } from "./$ProtobufReader";
6
+ import { $ProtobufSizer } from "./$ProtobufSizer";
7
+ import { $ProtobufWriter } from "./$ProtobufWriter";
7
8
  import { $any } from "./$any";
8
9
  import { $every } from "./$every";
9
10
  import { $guard } from "./$guard";
@@ -101,14 +102,20 @@ export namespace Namespace {
101
102
  string: $string,
102
103
  tail: $tail,
103
104
  rest: $rest,
104
- throws: $throws(method),
105
+ throws: $throws(`json.${method}`),
105
106
  });
106
107
  }
107
108
 
108
109
  export namespace protobuf {
110
+ export const decode = (method: string) => ({
111
+ Reader: $ProtobufReader,
112
+ throws: $throws(`protobuf.${method}`),
113
+ });
114
+
109
115
  export const encode = (method: string) => ({
110
- Writer: Writer,
111
- strl: $strlen,
116
+ Sizer: $ProtobufSizer,
117
+ Writer: $ProtobufWriter,
118
+ strlen: $strlen,
112
119
  throws: $throws(method),
113
120
  });
114
121
  }
@@ -116,13 +123,13 @@ export namespace Namespace {
116
123
  export namespace misc {
117
124
  export const clone = (method: string) => ({
118
125
  ...is(),
119
- throws: $throws(method),
126
+ throws: $throws(`misc.${method}`),
120
127
  any: $any,
121
128
  });
122
129
 
123
130
  export const prune = (method: string) => ({
124
131
  ...is(),
125
- throws: $throws(method),
132
+ throws: $throws(`misc.${method}`),
126
133
  });
127
134
  }
128
135
 
@@ -278,9 +278,9 @@ export namespace FeatureProgrammer {
278
278
  (collection: MetadataCollection) =>
279
279
  collection
280
280
  .objects()
281
- .map((obj, i) =>
281
+ .map((obj) =>
282
282
  StatementFactory.constant(
283
- `${config.prefix}o${i}`,
283
+ `${config.prefix}o${obj.index}`,
284
284
  ts.factory.createArrowFunction(
285
285
  undefined,
286
286
  undefined,
@@ -32,7 +32,6 @@ export namespace CloneJoiner {
32
32
  if (dynamic.length === 0) return literal;
33
33
 
34
34
  const key = ts.factory.createIdentifier("key");
35
- const value = ts.factory.createIdentifier("value");
36
35
  const output = ts.factory.createIdentifier("output");
37
36
 
38
37
  const statements: ts.Statement[] = dynamic.map((entry) =>
@@ -72,30 +71,7 @@ export namespace CloneJoiner {
72
71
  ),
73
72
  ts.factory.createForOfStatement(
74
73
  undefined,
75
- ts.factory.createVariableDeclarationList(
76
- [
77
- ts.factory.createVariableDeclaration(
78
- ts.factory.createArrayBindingPattern([
79
- ts.factory.createBindingElement(
80
- undefined,
81
- undefined,
82
- key,
83
- undefined,
84
- ),
85
- ts.factory.createBindingElement(
86
- undefined,
87
- undefined,
88
- value,
89
- undefined,
90
- ),
91
- ]),
92
- undefined,
93
- undefined,
94
- undefined,
95
- ),
96
- ],
97
- ts.NodeFlags.Const,
98
- ),
74
+ StatementFactory.entry("key")("value"),
99
75
  ts.factory.createCallExpression(
100
76
  ts.factory.createIdentifier("Object.entries"),
101
77
  undefined,
@@ -29,7 +29,10 @@ export class FunctionImporter {
29
29
  return this.local_.has(name);
30
30
  }
31
31
 
32
- public declare(modulo: ts.LeftHandSideExpression): ts.Statement[] {
32
+ public declare(
33
+ modulo: ts.LeftHandSideExpression,
34
+ includeUnions: boolean = true,
35
+ ): ts.Statement[] {
33
36
  return [
34
37
  ...[...this.used_].map((name) =>
35
38
  StatementFactory.constant(
@@ -44,12 +47,20 @@ export class FunctionImporter {
44
47
  )(name),
45
48
  ),
46
49
  ),
47
- ...[...this.unions_.values()].map(([key, arrow]) =>
48
- StatementFactory.constant(key, arrow),
49
- ),
50
+ ...(includeUnions === true
51
+ ? [...this.unions_.values()].map(([key, arrow]) =>
52
+ StatementFactory.constant(key, arrow),
53
+ )
54
+ : []),
50
55
  ];
51
56
  }
52
57
 
58
+ public declareUnions(): ts.Statement[] {
59
+ return [...this.unions_.values()].map(([key, arrow]) =>
60
+ StatementFactory.constant(key, arrow),
61
+ );
62
+ }
63
+
53
64
  public increment(): number {
54
65
  return ++this.sequence_;
55
66
  }
@@ -1,28 +1,34 @@
1
1
  export const enum ProtobufWire {
2
2
  /**
3
- * integers
4
- * bool
5
- * enum
3
+ * - integers
4
+ * - bool
5
+ * - enum
6
6
  */
7
- VARINT = 0,
7
+ VARIANT = 0,
8
8
 
9
9
  /**
10
- * fixed64
11
- * sfixed64
12
- * double
10
+ * - fixed64
11
+ * - sfixed64
12
+ * - double
13
13
  */
14
14
  I64 = 1,
15
15
 
16
16
  /**
17
- * string
18
- * bytes
19
- * mebedded messages
20
- * packed repeated fields
17
+ * - string
18
+ * - bytes
19
+ * - mebedded messages
20
+ * - packed repeated fields
21
21
  */
22
22
  LEN = 2,
23
23
 
24
+ START_GROUP = 3,
25
+
26
+ END_GROUP = 4,
27
+
24
28
  /**
25
- * fixed, sfixed32, float
29
+ * - fixed
30
+ * - sfixed32
31
+ * - float
26
32
  */
27
33
  I32 = 5,
28
34
  }
@@ -73,9 +73,9 @@ export namespace UnionExplorer {
73
73
  );
74
74
 
75
75
  // DO SPECIALIZE
76
- const conditions: ts.IfStatement[] = specList
76
+ const condition: ts.IfStatement = specList
77
77
  .filter((spec) => spec.property.key.getSoleLiteral() !== null)
78
- .map((spec) => {
78
+ .map((spec, i, array) => {
79
79
  const key: string = spec.property.key.getSoleLiteral()!;
80
80
  const accessor: ts.Expression =
81
81
  IdentifierFactory.access(input)(key);
@@ -105,21 +105,8 @@ export namespace UnionExplorer {
105
105
  jsDocTags,
106
106
  ),
107
107
  ),
108
- );
109
- });
110
-
111
- // RETURNS WITH CONDITIONS
112
- return ts.factory.createCallExpression(
113
- ts.factory.createArrowFunction(
114
- undefined,
115
- undefined,
116
- [],
117
- undefined,
118
- undefined,
119
- ts.factory.createBlock(
120
- [
121
- ...conditions,
122
- remained.length
108
+ i === array.length - 1
109
+ ? remained.length
123
110
  ? ts.factory.createReturnStatement(
124
111
  object(config, level + 1)(
125
112
  input,
@@ -133,10 +120,28 @@ export namespace UnionExplorer {
133
120
  input,
134
121
  expected,
135
122
  explore,
136
- ),
137
- ],
138
- true,
123
+ )
124
+ : undefined,
125
+ );
126
+ })
127
+ .reverse()
128
+ .reduce((a, b) =>
129
+ ts.factory.createIfStatement(
130
+ b.expression,
131
+ b.thenStatement,
132
+ a,
139
133
  ),
134
+ );
135
+
136
+ // RETURNS WITH CONDITIONS
137
+ return ts.factory.createCallExpression(
138
+ ts.factory.createArrowFunction(
139
+ undefined,
140
+ undefined,
141
+ [],
142
+ undefined,
143
+ undefined,
144
+ ts.factory.createBlock([condition], true),
140
145
  ),
141
146
  undefined,
142
147
  undefined,
@@ -12,6 +12,7 @@ const disable = (importer: FunctionImporter): MethodOnly<FunctionImporter> => ({
12
12
  useLocal: (name: string): string => importer.useLocal(name),
13
13
  hasLocal: (name: string): boolean => importer.hasLocal(name),
14
14
  declare: (_modulo: ts.LeftHandSideExpression): ts.Statement[] => [],
15
+ declareUnions: (): ts.Statement[] => [],
15
16
  increment: (): number => importer.increment(),
16
17
  emplaceUnion: (
17
18
  prefix: string,
@@ -55,13 +55,24 @@ const iterate =
55
55
  (input: ts.Expression, unions: IUnion[], expected: string) =>
56
56
  ts.factory.createBlock(
57
57
  [
58
- ...unions.map((u) =>
59
- ts.factory.createIfStatement(
60
- u.is(),
61
- ts.factory.createReturnStatement(u.value()),
58
+ unions
59
+ .map((u, i) =>
60
+ ts.factory.createIfStatement(
61
+ u.is(),
62
+ ts.factory.createReturnStatement(u.value()),
63
+ i === unions.length - 1
64
+ ? escaper(input, expected)
65
+ : undefined,
66
+ ),
67
+ )
68
+ .reverse()
69
+ .reduce((a, b) =>
70
+ ts.factory.createIfStatement(
71
+ b.expression,
72
+ b.thenStatement,
73
+ a,
74
+ ),
62
75
  ),
63
- ),
64
- escaper(input, expected),
65
76
  ],
66
77
  true,
67
78
  );