typia 5.2.6 → 5.3.0-dev.20231112

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