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

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