json-as 1.2.6 → 1.3.1

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 (135) hide show
  1. package/CHANGELOG.md +417 -0
  2. package/README.md +135 -36
  3. package/assembly/custom/util.ts +24 -70
  4. package/assembly/deserialize/float.ts +181 -0
  5. package/assembly/deserialize/helpers/uint.ts +12 -0
  6. package/assembly/deserialize/index/arbitrary.ts +25 -0
  7. package/assembly/deserialize/index/array.ts +61 -0
  8. package/assembly/deserialize/index/bool.ts +1 -0
  9. package/assembly/deserialize/index/date.ts +1 -0
  10. package/assembly/deserialize/index/float.ts +1 -0
  11. package/assembly/deserialize/index/integer.ts +1 -0
  12. package/assembly/deserialize/index/map.ts +1 -0
  13. package/assembly/deserialize/index/object.ts +1 -0
  14. package/assembly/deserialize/index/raw.ts +1 -0
  15. package/assembly/deserialize/index/set.ts +1 -0
  16. package/assembly/deserialize/index/staticarray.ts +1 -0
  17. package/assembly/deserialize/index/string.ts +15 -0
  18. package/assembly/deserialize/index/struct.ts +1 -0
  19. package/assembly/deserialize/index/typedarray.ts +15 -0
  20. package/assembly/deserialize/index/unsigned.ts +1 -0
  21. package/assembly/deserialize/index.ts +14 -0
  22. package/assembly/deserialize/integer.ts +42 -0
  23. package/assembly/deserialize/simd/array/integer.ts +307 -0
  24. package/assembly/deserialize/simd/string.ts +130 -11
  25. package/assembly/deserialize/simple/arbitrary.ts +5 -12
  26. package/assembly/deserialize/simple/array/arbitrary.ts +12 -36
  27. package/assembly/deserialize/simple/array/array.ts +2 -8
  28. package/assembly/deserialize/simple/array/bool.ts +2 -8
  29. package/assembly/deserialize/simple/array/box.ts +2 -8
  30. package/assembly/deserialize/simple/array/float.ts +2 -8
  31. package/assembly/deserialize/simple/array/integer.ts +2 -8
  32. package/assembly/deserialize/simple/array/map.ts +6 -26
  33. package/assembly/deserialize/simple/array/object.ts +6 -26
  34. package/assembly/deserialize/simple/array/raw.ts +18 -61
  35. package/assembly/deserialize/simple/array/string.ts +5 -10
  36. package/assembly/deserialize/simple/array/struct.ts +6 -26
  37. package/assembly/deserialize/simple/array.ts +2 -5
  38. package/assembly/deserialize/simple/bool.ts +2 -6
  39. package/assembly/deserialize/simple/map.ts +29 -102
  40. package/assembly/deserialize/simple/object.ts +24 -81
  41. package/assembly/deserialize/simple/raw.ts +1 -4
  42. package/assembly/deserialize/simple/set.ts +11 -37
  43. package/assembly/deserialize/simple/staticarray/array.ts +1 -1
  44. package/assembly/deserialize/simple/staticarray/bool.ts +1 -1
  45. package/assembly/deserialize/simple/staticarray/float.ts +1 -1
  46. package/assembly/deserialize/simple/staticarray/integer.ts +1 -1
  47. package/assembly/deserialize/simple/staticarray/string.ts +7 -14
  48. package/assembly/deserialize/simple/staticarray/struct.ts +1 -1
  49. package/assembly/deserialize/simple/staticarray.ts +57 -21
  50. package/assembly/deserialize/simple/string.ts +90 -10
  51. package/assembly/deserialize/simple/struct.ts +25 -121
  52. package/assembly/deserialize/simple/typedarray.ts +94 -0
  53. package/assembly/deserialize/swar/array/arbitrary.ts +8 -0
  54. package/assembly/deserialize/swar/array/array.ts +39 -0
  55. package/assembly/deserialize/swar/array/bool.ts +47 -0
  56. package/assembly/deserialize/swar/array/box.ts +8 -0
  57. package/assembly/deserialize/swar/array/float.ts +39 -0
  58. package/assembly/deserialize/swar/array/integer.ts +461 -0
  59. package/assembly/deserialize/swar/array/map.ts +7 -0
  60. package/assembly/deserialize/swar/array/object.ts +44 -0
  61. package/assembly/deserialize/swar/array/raw.ts +8 -0
  62. package/assembly/deserialize/swar/array/shared.ts +96 -0
  63. package/assembly/deserialize/swar/array/string.ts +39 -0
  64. package/assembly/deserialize/swar/array/struct.ts +44 -0
  65. package/assembly/deserialize/swar/array.ts +49 -0
  66. package/assembly/deserialize/swar/string.ts +648 -15
  67. package/assembly/deserialize/unsigned.ts +75 -0
  68. package/assembly/index.d.ts +1 -3
  69. package/assembly/index.ts +316 -374
  70. package/assembly/serialize/index/arbitrary.ts +75 -0
  71. package/assembly/serialize/index/array.ts +1 -0
  72. package/assembly/serialize/index/bool.ts +1 -0
  73. package/assembly/serialize/index/date.ts +1 -0
  74. package/assembly/serialize/index/float.ts +1 -0
  75. package/assembly/serialize/index/integer.ts +1 -0
  76. package/assembly/serialize/index/map.ts +1 -0
  77. package/assembly/serialize/index/object.ts +46 -0
  78. package/assembly/serialize/index/raw.ts +1 -0
  79. package/assembly/serialize/index/set.ts +1 -0
  80. package/assembly/serialize/index/staticarray.ts +1 -0
  81. package/assembly/serialize/index/string.ts +15 -0
  82. package/assembly/serialize/index/struct.ts +1 -0
  83. package/assembly/serialize/index/typedarray.ts +66 -0
  84. package/assembly/serialize/index.ts +13 -0
  85. package/assembly/serialize/simd/string.ts +4 -13
  86. package/assembly/serialize/simple/arbitrary.ts +6 -0
  87. package/assembly/serialize/simple/raw.ts +1 -5
  88. package/assembly/serialize/simple/string.ts +3 -11
  89. package/assembly/serialize/simple/typedarray.ts +63 -0
  90. package/assembly/serialize/swar/string.ts +6 -21
  91. package/assembly/util/concat.ts +1 -5
  92. package/assembly/util/index.ts +1 -0
  93. package/assembly/util/masks.ts +12 -18
  94. package/assembly/util/memory.ts +0 -0
  95. package/assembly/util/snp.ts +1 -4
  96. package/assembly/util/stringScan.ts +24 -0
  97. package/assembly/util/swar.ts +50 -6
  98. package/lib/as-bs.ts +137 -127
  99. package/package.json +26 -5
  100. package/transform/lib/builder.d.ts.map +1 -1
  101. package/transform/lib/builder.js +5 -13
  102. package/transform/lib/builder.js.map +1 -1
  103. package/transform/lib/index.d.ts +1 -0
  104. package/transform/lib/index.d.ts.map +1 -1
  105. package/transform/lib/index.js +672 -757
  106. package/transform/lib/index.js.map +1 -1
  107. package/transform/lib/linkers/alias.d.ts.map +1 -1
  108. package/transform/lib/linkers/alias.js.map +1 -1
  109. package/transform/lib/linkers/custom.d.ts.map +1 -1
  110. package/transform/lib/linkers/custom.js +8 -9
  111. package/transform/lib/linkers/custom.js.map +1 -1
  112. package/transform/lib/linkers/imports.d.ts.map +1 -1
  113. package/transform/lib/linkers/imports.js.map +1 -1
  114. package/transform/lib/types.d.ts +6 -0
  115. package/transform/lib/types.d.ts.map +1 -1
  116. package/transform/lib/types.js +83 -21
  117. package/transform/lib/types.js.map +1 -1
  118. package/transform/lib/util.d.ts.map +1 -1
  119. package/transform/lib/util.js +1 -1
  120. package/transform/lib/util.js.map +1 -1
  121. package/transform/lib/visitor.d.ts.map +1 -1
  122. package/transform/lib/visitor.js +1 -2
  123. package/transform/lib/visitor.js.map +1 -1
  124. package/.prettierrc +0 -3
  125. package/ARCHITECTURE.md +0 -320
  126. package/CONTRIBUTING.md +0 -238
  127. package/TODO +0 -1
  128. package/assembly/deserialize/simple/float.ts +0 -11
  129. package/assembly/deserialize/simple/integer.ts +0 -9
  130. package/assembly/test.ts +0 -30
  131. package/eslint.config.js +0 -60
  132. package/lib/tsconfig.json +0 -8
  133. package/tools/assemblyscript-eslint-local.js +0 -29
  134. package/tools/assemblyscript-eslint.js +0 -29
  135. package/transform/tsconfig.json +0 -35
@@ -1,4 +1,4 @@
1
- import { Node, Type, } from "assemblyscript/dist/assemblyscript.js";
1
+ import { Node, Type } from "assemblyscript/dist/assemblyscript.js";
2
2
  import { Transform } from "assemblyscript/dist/transform.js";
3
3
  import { readFileSync, writeFileSync } from "fs";
4
4
  import * as path from "path";
@@ -11,14 +11,71 @@ let indent = " ";
11
11
  let id = 0;
12
12
  const WRITE = process.env["JSON_WRITE"]?.trim();
13
13
  const rawValue = process.env["JSON_DEBUG"]?.trim();
14
- const DEBUG = rawValue === "true"
15
- ? 1
16
- : rawValue === "false" || rawValue === ""
17
- ? 0
18
- : isNaN(Number(rawValue))
19
- ? 0
20
- : Number(rawValue);
14
+ const DEBUG = rawValue === "true" ? 1 : rawValue === "false" || rawValue === "" ? 0 : isNaN(Number(rawValue)) ? 0 : Number(rawValue);
21
15
  const STRICT = process.env["JSON_STRICT"] && process.env["JSON_STRICT"] == "true";
16
+ const USE_FAST_PATH = process.env["JSON_USE_FAST_PATH"]?.trim() === "1";
17
+ function needsReferenceLoad(type) {
18
+ return type == "ArrayBuffer" || type == "Int8Array" || type == "Uint8Array" || type == "Uint8ClampedArray" || type == "Int16Array" || type == "Uint16Array" || type == "Int32Array" || type == "Uint32Array" || type == "Int64Array" || type == "Uint64Array" || type == "Float32Array" || type == "Float64Array";
19
+ }
20
+ function getSerializeCall(type, realName) {
21
+ if (type == "ArrayBuffer") {
22
+ return `JSON.__serialize<ArrayBuffer>(load<ArrayBuffer>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`;
23
+ }
24
+ return needsReferenceLoad(type) ? `JSON.__serialize<${type}>(changetype<${type}>(load<usize>(ptr, offsetof<this>(${JSON.stringify(realName)}))));\n` : `JSON.__serialize<${type}>(load<${type}>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`;
25
+ }
26
+ const CUSTOM_JSON_KINDS = new Set(["any", "string", "number", "object", "array", "boolean", "null", "any | null", "string | null", "number | null", "object | null", "array | null", "boolean | null"]);
27
+ function parseCustomJsonKind(method, decoratorName) {
28
+ const decorator = method.decorators?.find((v) => v.name.text.toLowerCase() == decoratorName);
29
+ if (!decorator || !decorator.args || decorator.args.length == 0)
30
+ return "any";
31
+ if (decorator.args.length > 1)
32
+ throwError(`@${decoratorName} accepts at most one argument`, decorator.range);
33
+ const arg = decorator.args[0];
34
+ if (arg.kind != 16 || arg.literalKind != 2) {
35
+ throwError(`@${decoratorName} argument must be a string literal like @${decoratorName}("string")`, arg.range);
36
+ }
37
+ const kind = arg.value;
38
+ if (!CUSTOM_JSON_KINDS.has(kind)) {
39
+ throwError(`Unsupported @${decoratorName} JSON type '${kind}'. Expected one of: any, string, number, object, array, boolean, null`, arg.range);
40
+ }
41
+ return kind;
42
+ }
43
+ function addMemberToCustomBucket(sortedMembers, member, kind) {
44
+ const isNullable = kind.endsWith(" | null");
45
+ const baseKind = isNullable ? kind.slice(0, kind.length - 7) : kind;
46
+ if (isNullable)
47
+ sortedMembers.null.push(member);
48
+ switch (baseKind) {
49
+ case "string":
50
+ sortedMembers.string.push(member);
51
+ break;
52
+ case "number":
53
+ sortedMembers.number.push(member);
54
+ break;
55
+ case "boolean":
56
+ sortedMembers.boolean.push(member);
57
+ break;
58
+ case "null":
59
+ if (!isNullable)
60
+ sortedMembers.null.push(member);
61
+ break;
62
+ case "array":
63
+ sortedMembers.array.push(member);
64
+ break;
65
+ case "object":
66
+ sortedMembers.object.push(member);
67
+ break;
68
+ default:
69
+ sortedMembers.string.push(member);
70
+ sortedMembers.number.push(member);
71
+ sortedMembers.object.push(member);
72
+ sortedMembers.array.push(member);
73
+ sortedMembers.boolean.push(member);
74
+ if (!isNullable)
75
+ sortedMembers.null.push(member);
76
+ break;
77
+ }
78
+ }
22
79
  export class JSONTransform extends Visitor {
23
80
  static SN = new JSONTransform();
24
81
  program;
@@ -30,16 +87,53 @@ export class JSONTransform extends Visitor {
30
87
  imports = [];
31
88
  simdStatements = [];
32
89
  visitedClasses = new Set();
90
+ collectInheritedFieldMembers(node, source, members, visited = new Set()) {
91
+ if (!node.extendsType)
92
+ return;
93
+ const extendsName = source.resolveExtendsName(node);
94
+ if (!extendsName || visited.has(extendsName))
95
+ return;
96
+ visited.add(extendsName);
97
+ let baseDecl = source.getClass(extendsName);
98
+ let baseSource = baseDecl ? source : null;
99
+ if (!baseDecl) {
100
+ const imported = source.getImportedClass(extendsName, this.parser);
101
+ if (imported) {
102
+ baseDecl = imported;
103
+ baseSource = this.sources.get(imported.range.source);
104
+ }
105
+ }
106
+ if (!baseDecl) {
107
+ const available = source.getAvailableClass(extendsName, this.parser);
108
+ if (available) {
109
+ baseDecl = available;
110
+ baseSource = this.sources.get(available.range.source);
111
+ }
112
+ }
113
+ if (!baseDecl || !baseSource)
114
+ return;
115
+ const isDecoratedBase = !!baseDecl.decorators?.some((decorator) => {
116
+ const name = decorator.name.text;
117
+ return name === "json" || name === "serializable";
118
+ });
119
+ if (isDecoratedBase)
120
+ return;
121
+ this.collectInheritedFieldMembers(baseDecl, baseSource, members, visited);
122
+ const inheritedMembers = baseDecl.members.filter((v) => v.kind === 54 && !v.is(32) && !v.is(512) && !v.is(1024) && !v.decorators?.some((decorator) => decorator.name.text === "omit"));
123
+ for (let i = inheritedMembers.length - 1; i >= 0; i--) {
124
+ const inherited = inheritedMembers[i];
125
+ if (!members.some((member) => member.name.text == inherited.name.text)) {
126
+ members.unshift(inherited);
127
+ }
128
+ }
129
+ }
33
130
  visitClassDeclarationRef(node) {
34
131
  if (!node.decorators?.length ||
35
132
  !node.decorators.some((decorator) => {
36
133
  const name = decorator.name.text;
37
134
  return name === "json" || name === "serializable";
38
135
  }))
39
- throw new Error("Class " +
40
- node.name.text +
41
- " is missing an @json or @serializable decorator in " +
42
- node.range.source.internalPath);
136
+ throw new Error("Class " + node.name.text + " is missing an @json or @serializable decorator in " + node.range.source.internalPath);
43
137
  this.visitClassDeclaration(node);
44
138
  }
45
139
  resolveType(type, source, visited = new Set()) {
@@ -48,9 +142,7 @@ export class JSONTransform extends Visitor {
48
142
  return stripped;
49
143
  }
50
144
  visited.add(stripped);
51
- const resolvedType = source.aliases
52
- .find((v) => stripNull(v.name) === stripped)
53
- ?.getBaseType();
145
+ const resolvedType = source.aliases.find((v) => stripNull(v.name) === stripped)?.getBaseType();
54
146
  if (resolvedType) {
55
147
  return this.resolveType(resolvedType, source, visited);
56
148
  }
@@ -89,38 +181,20 @@ export class JSONTransform extends Visitor {
89
181
  return;
90
182
  if (!this.schemas.has(source.internalPath))
91
183
  this.schemas.set(source.internalPath, []);
92
- const members = [
93
- ...node.members.filter((v) => v.kind === 54 &&
94
- v.flags !== 32 &&
95
- v.flags !== 512 &&
96
- v.flags !== 1024 &&
97
- !v.decorators?.some((decorator) => decorator.name.text === "omit")),
98
- ];
99
- const serializers = [
100
- ...node.members.filter((v) => v.kind === 58 &&
101
- v.decorators &&
102
- v.decorators.some((e) => e.name.text.toLowerCase() ===
103
- "serializer")),
104
- ];
105
- const deserializers = [
106
- ...node.members.filter((v) => v.kind === 58 &&
107
- v.decorators &&
108
- v.decorators.some((e) => e.name.text.toLowerCase() ===
109
- "deserializer")),
110
- ];
184
+ const members = [...node.members.filter((v) => v.kind === 54 && !v.is(32) && !v.is(512) && !v.is(1024) && !v.decorators?.some((decorator) => decorator.name.text === "omit"))];
185
+ const serializers = [...node.members.filter((v) => v.kind === 58 && v.decorators && v.decorators.some((e) => e.name.text.toLowerCase() === "serializer") && !v.name.text.startsWith("__try"))];
186
+ const deserializers = [...node.members.filter((v) => v.kind === 58 && v.decorators && v.decorators.some((e) => e.name.text.toLowerCase() === "deserializer") && !v.name.text.startsWith("__try"))];
111
187
  const schema = new Schema();
112
188
  schema.node = node;
113
189
  schema.name = source.getQualifiedName(node);
114
190
  if (node.extendsType) {
191
+ this.collectInheritedFieldMembers(node, source, members);
115
192
  const extendsName = source.resolveExtendsName(node);
116
193
  if (!schema.parent) {
117
194
  const depSearch = schema.deps.find((v) => v.name == extendsName);
118
195
  if (depSearch) {
119
196
  if (DEBUG > 0)
120
- console.log("Found " +
121
- extendsName +
122
- " in dependencies of " +
123
- source.internalPath);
197
+ console.log("Found " + extendsName + " in dependencies of " + source.internalPath);
124
198
  if (!schema.deps.some((v) => v.name == depSearch.name))
125
199
  schema.deps.push(depSearch);
126
200
  schema.parent = depSearch;
@@ -129,26 +203,16 @@ export class JSONTransform extends Visitor {
129
203
  const internalSearch = source.getClass(extendsName);
130
204
  if (internalSearch) {
131
205
  if (DEBUG > 0)
132
- console.log("Found " +
133
- extendsName +
134
- " internally from " +
135
- source.internalPath);
206
+ console.log("Found " + extendsName + " internally from " + source.internalPath);
136
207
  if (!this.visitedClasses.has(source.getFullPath(internalSearch))) {
137
208
  this.visitClassDeclarationRef(internalSearch);
138
- this.schemas
139
- .get(internalSearch.range.source.internalPath)
140
- .push(this.schema);
209
+ this.schemas.get(internalSearch.range.source.internalPath).push(this.schema);
141
210
  this.visitClassDeclaration(node);
142
211
  return;
143
212
  }
144
- const schem = this.schemas
145
- .get(internalSearch.range.source.internalPath)
146
- ?.find((s) => s.name == extendsName);
213
+ const schem = this.schemas.get(internalSearch.range.source.internalPath)?.find((s) => s.name == extendsName);
147
214
  if (!schem)
148
- throw new Error("Could not find schema for " +
149
- internalSearch.name.text +
150
- " in " +
151
- internalSearch.range.source.internalPath);
215
+ throw new Error("Could not find schema for " + internalSearch.name.text + " in " + internalSearch.range.source.internalPath);
152
216
  schema.deps.push(schem);
153
217
  schema.parent = schem;
154
218
  }
@@ -156,10 +220,7 @@ export class JSONTransform extends Visitor {
156
220
  const externalSearch = source.getImportedClass(extendsName, this.parser);
157
221
  if (externalSearch) {
158
222
  if (DEBUG > 0)
159
- console.log("Found " +
160
- externalSearch.name.text +
161
- " externally from " +
162
- source.internalPath);
223
+ console.log("Found " + externalSearch.name.text + " externally from " + source.internalPath);
163
224
  const externalSource = this.sources.get(externalSearch.range.source);
164
225
  if (!this.visitedClasses.has(externalSource.getFullPath(externalSearch))) {
165
226
  this.visitClassDeclarationRef(externalSearch);
@@ -167,17 +228,36 @@ export class JSONTransform extends Visitor {
167
228
  this.visitClassDeclaration(node);
168
229
  return;
169
230
  }
170
- const schem = this.schemas
171
- .get(externalSource.internalPath)
172
- ?.find((s) => s.name == extendsName);
231
+ const schem = this.schemas.get(externalSource.internalPath)?.find((s) => s.name == extendsName);
173
232
  if (!schem)
174
- throw new Error("Could not find schema for " +
175
- externalSearch.name.text +
176
- " in " +
177
- externalSource.internalPath);
233
+ throw new Error("Could not find schema for " + externalSearch.name.text + " in " + externalSource.internalPath);
178
234
  schema.deps.push(schem);
179
235
  schema.parent = schem;
180
236
  }
237
+ else {
238
+ const availableSearch = source.getAvailableClass(extendsName, this.parser);
239
+ if (availableSearch) {
240
+ if (DEBUG > 0)
241
+ console.log("Found " + availableSearch.name.text + " from available sources for " + source.internalPath);
242
+ const availableSource = this.sources.get(availableSearch.range.source);
243
+ if (availableSearch.decorators?.some((decorator) => {
244
+ const name = decorator.name.text;
245
+ return name === "json" || name === "serializable";
246
+ })) {
247
+ if (!this.visitedClasses.has(availableSource.getFullPath(availableSearch))) {
248
+ this.visitClassDeclarationRef(availableSearch);
249
+ this.schemas.get(availableSource.internalPath).push(this.schema);
250
+ this.visitClassDeclaration(node);
251
+ return;
252
+ }
253
+ const schem = this.schemas.get(availableSource.internalPath)?.find((s) => s.name == extendsName);
254
+ if (schem) {
255
+ schema.deps.push(schem);
256
+ schema.parent = schem;
257
+ }
258
+ }
259
+ }
260
+ }
181
261
  }
182
262
  }
183
263
  }
@@ -212,8 +292,7 @@ export class JSONTransform extends Visitor {
212
292
  else if (["JSON.Box", "JSON.Obj", "JSON.Value", "JSON.Raw"].includes(type)) {
213
293
  return types;
214
294
  }
215
- else if (node.isGeneric &&
216
- node.typeParameters.some((p) => p.name.text == type)) {
295
+ else if (node.isGeneric && node.typeParameters.some((p) => p.name.text == type)) {
217
296
  return types;
218
297
  }
219
298
  else if (type == node.name.text) {
@@ -229,10 +308,7 @@ export class JSONTransform extends Visitor {
229
308
  const depSearch = schema.deps.find((v) => v.name == unknownType);
230
309
  if (depSearch) {
231
310
  if (DEBUG > 0)
232
- console.log("Found " +
233
- unknownType +
234
- " in dependencies of " +
235
- source.internalPath);
311
+ console.log("Found " + unknownType + " in dependencies of " + source.internalPath);
236
312
  if (!schema.deps.some((v) => v.name == depSearch.name)) {
237
313
  schema.deps.push(depSearch);
238
314
  }
@@ -241,59 +317,37 @@ export class JSONTransform extends Visitor {
241
317
  const internalSearch = source.getClass(unknownType);
242
318
  if (internalSearch) {
243
319
  if (DEBUG > 0)
244
- console.log("Found " +
245
- unknownType +
246
- " internally from " +
247
- source.internalPath);
320
+ console.log("Found " + unknownType + " internally from " + source.internalPath);
248
321
  if (!this.visitedClasses.has(source.getFullPath(internalSearch))) {
249
322
  this.visitClassDeclarationRef(internalSearch);
250
- const internalSchema = this.schemas
251
- .get(internalSearch.range.source.internalPath)
252
- ?.find((s) => s.name == unknownType);
323
+ const internalSchema = this.schemas.get(internalSearch.range.source.internalPath)?.find((s) => s.name == unknownType);
253
324
  schema.deps.push(internalSchema);
254
- this.schemas
255
- .get(internalSearch.range.source.internalPath)
256
- .push(this.schema);
325
+ this.schemas.get(internalSearch.range.source.internalPath).push(this.schema);
257
326
  this.visitClassDeclaration(node);
258
327
  return;
259
328
  }
260
- const schem = this.schemas
261
- .get(internalSearch.range.source.internalPath)
262
- ?.find((s) => s.name == unknownType);
329
+ const schem = this.schemas.get(internalSearch.range.source.internalPath)?.find((s) => s.name == unknownType);
263
330
  if (!schem)
264
- throw new Error("Could not find schema for " +
265
- internalSearch.name.text +
266
- " in " +
267
- internalSearch.range.source.internalPath);
331
+ throw new Error("Could not find schema for " + internalSearch.name.text + " in " + internalSearch.range.source.internalPath);
268
332
  schema.deps.push(schem);
269
333
  }
270
334
  else {
271
335
  const externalSearch = source.getImportedClass(unknownType, this.parser);
272
336
  if (externalSearch) {
273
337
  if (DEBUG > 0)
274
- console.log("Found " +
275
- externalSearch.name.text +
276
- " externally from " +
277
- source.internalPath);
338
+ console.log("Found " + externalSearch.name.text + " externally from " + source.internalPath);
278
339
  const externalSource = this.sources.get(externalSearch.range.source);
279
340
  if (!this.visitedClasses.has(externalSource.getFullPath(externalSearch))) {
280
341
  this.visitClassDeclarationRef(externalSearch);
281
- const externalSchema = this.schemas
282
- .get(externalSource.internalPath)
283
- ?.find((s) => s.name == unknownType);
342
+ const externalSchema = this.schemas.get(externalSource.internalPath)?.find((s) => s.name == unknownType);
284
343
  schema.deps.push(externalSchema);
285
344
  this.schemas.get(externalSource.internalPath).push(this.schema);
286
345
  this.visitClassDeclaration(node);
287
346
  return;
288
347
  }
289
- const schem = this.schemas
290
- .get(externalSource.internalPath)
291
- ?.find((s) => s.name == unknownType);
348
+ const schem = this.schemas.get(externalSource.internalPath)?.find((s) => s.name == unknownType);
292
349
  if (!schem)
293
- throw new Error("Could not find schema for " +
294
- externalSearch.name.text +
295
- " in " +
296
- externalSource.internalPath);
350
+ throw new Error("Could not find schema for " + externalSearch.name.text + " in " + externalSource.internalPath);
297
351
  schema.deps.push(schem);
298
352
  }
299
353
  }
@@ -303,103 +357,74 @@ export class JSONTransform extends Visitor {
303
357
  this.schemas.get(source.internalPath).push(schema);
304
358
  this.schema = schema;
305
359
  this.visitedClasses.add(fullClassPath);
360
+ const codegenMode = getCodegenMode(this.program);
361
+ const useFastPath = USE_FAST_PATH && codegenMode !== JSONMode.NAIVE;
306
362
  let SERIALIZE = "__SERIALIZE(ptr: usize): void {\n";
307
363
  let INITIALIZE = "@inline __INITIALIZE(): this {\n";
308
- let DESERIALIZE = "__DESERIALIZE<__JSON_T>(srcStart: usize, srcEnd: usize, out: __JSON_T): __JSON_T {\n";
364
+ let DESERIALIZE = "__DESERIALIZE_SLOW<__JSON_T>(srcStart: usize, srcEnd: usize, out: __JSON_T): usize {\n";
365
+ let DESERIALIZE_FAST = "@inline __DESERIALIZE_FAST<__JSON_T>(srcStart: usize, srcEnd: usize, out: __JSON_T): usize {\n";
309
366
  let DESERIALIZE_CUSTOM = "";
310
367
  let SERIALIZE_CUSTOM = "";
311
368
  if (DEBUG > 0)
312
- console.log("Created schema: " +
313
- this.schema.name +
314
- " in file " +
315
- source.normalizedPath +
316
- (this.schema.deps.length
317
- ? " with dependencies:\n " +
318
- this.schema.deps.map((v) => v.name).join("\n ")
319
- : ""));
369
+ console.log("Created schema: " + this.schema.name + " in file " + source.normalizedPath + (this.schema.deps.length ? " with dependencies:\n " + this.schema.deps.map((v) => v.name).join("\n ") : ""));
320
370
  if (serializers.length > 1)
321
- throwError("Multiple serializers detected for class " +
322
- node.name.text +
323
- " but schemas can only have one serializer!", serializers[1].range);
371
+ throwError("Multiple serializers detected for class " + node.name.text + " but schemas can only have one serializer!", serializers[1].range);
324
372
  if (deserializers.length > 1)
325
- throwError("Multiple deserializers detected for class " +
326
- node.name.text +
327
- " but schemas can only have one deserializer!", deserializers[1].range);
373
+ throwError("Multiple deserializers detected for class " + node.name.text + " but schemas can only have one deserializer!", deserializers[1].range);
328
374
  if (serializers.length) {
329
375
  this.schema.custom = true;
330
376
  const serializer = serializers[0];
377
+ const serializerJsonKind = parseCustomJsonKind(serializer, "serializer");
331
378
  const hasCall = CustomTransform.hasCall(serializer);
379
+ this.schema.customJsonKind = serializerJsonKind;
332
380
  CustomTransform.visit(serializer);
333
381
  if (serializer.signature.parameters.length > 1)
334
- throwError("Found too many parameters in custom serializer for " +
335
- this.schema.name +
336
- ", but serializers can only accept one parameter of type '" +
337
- this.schema.name +
338
- "'!", serializer.signature.parameters[1].range);
339
- if (serializer.signature.parameters.length > 0 &&
340
- serializer.signature.parameters[0].type.name.identifier
341
- .text != node.name.text &&
342
- serializer.signature.parameters[0].type.name.identifier
343
- .text != "this")
344
- throwError("Type of parameter for custom serializer does not match! It should be 'string'either be 'this' or '" +
345
- this.schema.name +
346
- "'", serializer.signature.parameters[0].type.range);
347
- if (!serializer.signature.returnType ||
348
- !(serializer.signature.returnType).name.identifier.text.includes("string"))
349
- throwError("Could not find valid return type for serializer in " +
350
- this.schema.name +
351
- "!. Set the return type to type 'string' and try again", serializer.signature.returnType.range);
382
+ throwError("Found too many parameters in custom serializer for " + this.schema.name + ", but serializers can only accept one parameter of type '" + this.schema.name + "'!", serializer.signature.parameters[1].range);
383
+ if (serializer.signature.parameters.length > 0 && serializer.signature.parameters[0].type.name.identifier.text != node.name.text && serializer.signature.parameters[0].type.name.identifier.text != "this")
384
+ throwError("Type of parameter for custom serializer does not match! It should be 'string'either be 'this' or '" + this.schema.name + "'", serializer.signature.parameters[0].type.range);
385
+ if (!serializer.signature.returnType || !serializer.signature.returnType.name.identifier.text.includes("string"))
386
+ throwError("Could not find valid return type for serializer in " + this.schema.name + "!. Set the return type to type 'string' and try again", serializer.signature.returnType.range);
352
387
  if (!serializer.decorators.some((v) => v.name.text == "inline")) {
353
388
  serializer.decorators.push(Node.createDecorator(Node.createIdentifierExpression("inline", serializer.range), null, serializer.range));
354
389
  }
355
390
  SERIALIZE_CUSTOM += " __SERIALIZE(ptr: usize): void {\n";
356
- SERIALIZE_CUSTOM +=
357
- " const data = this." +
358
- serializer.name.text +
359
- "(" +
360
- (serializer.signature.parameters.length ? "this" : "") +
361
- ");\n";
362
- if (hasCall)
363
- SERIALIZE_CUSTOM += " bs.resetState();\n";
391
+ if (hasCall) {
392
+ SERIALIZE_CUSTOM += " const savedOffset = bs.offset;\n";
393
+ SERIALIZE_CUSTOM += " const savedStackSize = bs.stackSize;\n";
394
+ }
395
+ SERIALIZE_CUSTOM += " const self = changetype<this>(ptr);\n";
396
+ SERIALIZE_CUSTOM += " const data = self." + serializer.name.text + "(" + (serializer.signature.parameters.length ? "self" : "") + ");\n";
397
+ if (hasCall) {
398
+ SERIALIZE_CUSTOM += " bs.offset = savedOffset;\n";
399
+ SERIALIZE_CUSTOM += " bs.stackSize = savedStackSize;\n";
400
+ }
364
401
  SERIALIZE_CUSTOM += " const dataSize = data.length << 1;\n";
365
- SERIALIZE_CUSTOM +=
366
- " memory.copy(bs.offset, changetype<usize>(data), dataSize);\n";
402
+ SERIALIZE_CUSTOM += " memory.copy(bs.offset, changetype<usize>(data), dataSize);\n";
367
403
  SERIALIZE_CUSTOM += " bs.offset += dataSize;\n";
368
404
  SERIALIZE_CUSTOM += " }\n";
369
405
  }
370
406
  if (deserializers.length) {
371
407
  this.schema.custom = true;
372
408
  const deserializer = deserializers[0];
409
+ const deserializerJsonKind = parseCustomJsonKind(deserializer, "deserializer");
410
+ if (this.schema.customJsonKind != "any" && deserializerJsonKind != "any" && this.schema.customJsonKind != deserializerJsonKind) {
411
+ throwError(`@serializer and @deserializer JSON types for ${this.schema.name} must match`, deserializer.range);
412
+ }
413
+ if (this.schema.customJsonKind == "any")
414
+ this.schema.customJsonKind = deserializerJsonKind;
373
415
  if (!deserializer.signature.parameters.length)
374
- throwError("Could not find any parameters in custom deserializer for " +
375
- this.schema.name +
376
- ". Deserializers must have one parameter like 'deserializer(data: string): " +
377
- this.schema.name +
378
- " {}'", deserializer.range);
416
+ throwError("Could not find any parameters in custom deserializer for " + this.schema.name + ". Deserializers must have one parameter like 'deserializer(data: string): " + this.schema.name + " {}'", deserializer.range);
379
417
  if (deserializer.signature.parameters.length > 1)
380
- throwError("Found too many parameters in custom deserializer for " +
381
- this.schema.name +
382
- ", but deserializers can only accept one parameter of type 'string'!", deserializer.signature.parameters[1].range);
383
- if (deserializer.signature.parameters[0].type.name
384
- .identifier.text != "string")
418
+ throwError("Found too many parameters in custom deserializer for " + this.schema.name + ", but deserializers can only accept one parameter of type 'string'!", deserializer.signature.parameters[1].range);
419
+ if (deserializer.signature.parameters[0].type.name.identifier.text != "string")
385
420
  throwError("Type of parameter for custom deserializer does not match! It must be 'string'", deserializer.signature.parameters[0].type.range);
386
- if (!deserializer.signature.returnType ||
387
- !((deserializer.signature.returnType).name.identifier.text.includes(this.schema.name) ||
388
- (deserializer.signature.returnType).name.identifier.text.includes("this")))
389
- throwError("Could not find valid return type for deserializer in " +
390
- this.schema.name +
391
- "!. Set the return type to type '" +
392
- this.schema.name +
393
- "' or 'this' and try again", deserializer.signature.returnType.range);
421
+ if (!deserializer.signature.returnType || !(deserializer.signature.returnType.name.identifier.text.includes(this.schema.name) || deserializer.signature.returnType.name.identifier.text.includes("this")))
422
+ throwError("Could not find valid return type for deserializer in " + this.schema.name + "!. Set the return type to type '" + this.schema.name + "' or 'this' and try again", deserializer.signature.returnType.range);
394
423
  if (!deserializer.decorators.some((v) => v.name.text == "inline")) {
395
424
  deserializer.decorators.push(Node.createDecorator(Node.createIdentifierExpression("inline", deserializer.range), null, deserializer.range));
396
425
  }
397
- DESERIALIZE_CUSTOM +=
398
- " __DESERIALIZE<__JSON_T>(srcStart: usize, srcEnd: usize, out: __JSON_T): __JSON_T {\n";
399
- DESERIALIZE_CUSTOM +=
400
- " return inline.always(this." +
401
- deserializer.name.text +
402
- "(JSON.Util.ptrToStr(srcStart, srcEnd)));\n";
426
+ DESERIALIZE_CUSTOM += " @inline __DESERIALIZE_CUSTOM(data: string): this {\n";
427
+ DESERIALIZE_CUSTOM += " return inline.always(this." + deserializer.name.text + "(data));\n";
403
428
  DESERIALIZE_CUSTOM += " }\n";
404
429
  }
405
430
  if (!members.length && !deserializers.length && !serializers.length) {
@@ -422,22 +447,15 @@ export class JSONTransform extends Visitor {
422
447
  mem.value = value;
423
448
  mem.node = member;
424
449
  mem.byteSize = sizeof(mem.type);
450
+ mem.custom = schema.deps.some((dep) => dep?.name == stripNull(type) && dep.custom);
425
451
  this.schema.byteSize += mem.byteSize;
426
452
  if (member.decorators) {
427
453
  for (const decorator of member.decorators) {
428
- const decoratorName = decorator.name.text
429
- .toLowerCase()
430
- .trim();
454
+ const decoratorName = decorator.name.text.toLowerCase().trim();
431
455
  switch (decoratorName) {
432
456
  case "alias": {
433
457
  const arg = decorator.args[0];
434
- if (!arg ||
435
- (arg.kind != 16 &&
436
- arg.literalKind !=
437
- 2 &&
438
- arg.literalKind !=
439
- 1 &&
440
- arg.literalKind != 0))
458
+ if (!arg || (arg.kind != 16 && arg.literalKind != 2 && arg.literalKind != 1 && arg.literalKind != 0))
441
459
  throwError("@alias must have an argument of type string or number", member.range);
442
460
  mem.alias = arg.value.toString();
443
461
  break;
@@ -485,43 +503,40 @@ export class JSONTransform extends Visitor {
485
503
  const aliasName = JSON.stringify(member.alias || member.name);
486
504
  const realName = member.name;
487
505
  const isLast = i == this.schema.members.length - 1;
488
- if (member.value) {
489
- if (member.value != "null" &&
490
- member.value != "0" &&
491
- member.value != "0.0" &&
492
- member.value != "false") {
493
- INITIALIZE += ` store<${member.type}>(changetype<usize>(this), ${member.value}, offsetof<this>(${JSON.stringify(member.name)}));\n`;
494
- }
495
- }
496
- else if (member.generic) {
497
- INITIALIZE += ` if (isManaged<nonnull<${member.type}>>() || isReference<nonnull<${member.type}>>()) {\n`;
498
- INITIALIZE += ` store<${member.type}>(changetype<usize>(this), changetype<nonnull<${member.type}>>(__new(offsetof<nonnull<${member.type}>>(), idof<nonnull<${member.type}>>())), offsetof<this>(${JSON.stringify(member.name)}));\n`;
499
- INITIALIZE += ` if (isDefined(this.${member.name}.__INITIALIZE)) changetype<nonnull<${member.type}>>(this.${member.name}).__INITIALIZE();\n`;
500
- INITIALIZE += ` }\n`;
501
- }
502
- else if (!member.node.type.isNullable) {
503
- if (this.getSchema(member.type)) {
504
- INITIALIZE += ` store<${member.type}>(changetype<usize>(this), changetype<nonnull<${member.type}>>(__new(offsetof<nonnull<${member.type}>>(), idof<nonnull<${member.type}>>())).__INITIALIZE(), offsetof<this>(${JSON.stringify(member.name)}));\n`;
505
- }
506
- else if (member.type.startsWith("Array<")) {
507
- INITIALIZE += ` store<${member.type}>(changetype<usize>(this), [], offsetof<this>(${JSON.stringify(member.name)}));\n`;
508
- }
509
- else if (member.type.startsWith("Map<")) {
510
- INITIALIZE += ` store<${member.type}>(changetype<usize>(this), new ${member.type}(), offsetof<this>(${JSON.stringify(member.name)}));\n`;
511
- }
512
- else if (member.type.startsWith("Set<")) {
513
- INITIALIZE += ` store<${member.type}>(changetype<usize>(this), new ${member.type}(), offsetof<this>(${JSON.stringify(member.name)}));\n`;
506
+ if (!useFastPath) {
507
+ if (member.value) {
508
+ if (member.value != "null" && member.value != "0" && member.value != "0.0" && member.value != "false") {
509
+ INITIALIZE += ` store<${member.type}>(changetype<usize>(this), ${member.value}, offsetof<this>(${JSON.stringify(member.name)}));\n`;
510
+ }
514
511
  }
515
- else if (member.type.startsWith("StaticArray<")) {
512
+ else if (member.generic) {
513
+ INITIALIZE += ` if (isManaged<nonnull<${member.type}>>() || isReference<nonnull<${member.type}>>()) {\n`;
514
+ INITIALIZE += ` store<${member.type}>(changetype<usize>(this), changetype<nonnull<${member.type}>>(__new(offsetof<nonnull<${member.type}>>(), idof<nonnull<${member.type}>>())), offsetof<this>(${JSON.stringify(member.name)}));\n`;
515
+ INITIALIZE += ` if (isDefined(this.${member.name}.__INITIALIZE)) changetype<nonnull<${member.type}>>(this.${member.name}).__INITIALIZE();\n`;
516
+ INITIALIZE += ` }\n`;
516
517
  }
517
- else if (member.type == "string" || member.type == "String") {
518
- INITIALIZE += ` store<${member.type}>(changetype<usize>(this), "", offsetof<this>(${JSON.stringify(member.name)}));\n`;
518
+ else if (!member.node.type.isNullable) {
519
+ if (this.getSchema(member.type)) {
520
+ INITIALIZE += ` store<${member.type}>(changetype<usize>(this), changetype<nonnull<${member.type}>>(__new(offsetof<nonnull<${member.type}>>(), idof<nonnull<${member.type}>>())).__INITIALIZE(), offsetof<this>(${JSON.stringify(member.name)}));\n`;
521
+ }
522
+ else if (member.type.startsWith("Array<")) {
523
+ INITIALIZE += ` store<${member.type}>(changetype<usize>(this), [], offsetof<this>(${JSON.stringify(member.name)}));\n`;
524
+ }
525
+ else if (member.type.startsWith("Map<")) {
526
+ INITIALIZE += ` store<${member.type}>(changetype<usize>(this), new ${member.type}(), offsetof<this>(${JSON.stringify(member.name)}));\n`;
527
+ }
528
+ else if (member.type.startsWith("Set<")) {
529
+ INITIALIZE += ` store<${member.type}>(changetype<usize>(this), new ${member.type}(), offsetof<this>(${JSON.stringify(member.name)}));\n`;
530
+ }
531
+ else if (member.type.startsWith("StaticArray<")) {
532
+ }
533
+ else if (member.type == "string" || member.type == "String") {
534
+ INITIALIZE += ` store<${member.type}>(changetype<usize>(this), "", offsetof<this>(${JSON.stringify(member.name)}));\n`;
535
+ }
519
536
  }
520
537
  }
521
538
  const SIMD_ENABLED = this.program.options.hasFeature(16);
522
- if (!isRegular &&
523
- !member.flags.has(PropertyFlags.OmitIf) &&
524
- !member.flags.has(PropertyFlags.OmitNull))
539
+ if (!isRegular && !member.flags.has(PropertyFlags.OmitIf) && !member.flags.has(PropertyFlags.OmitNull))
525
540
  isRegular = true;
526
541
  if (isRegular && isPure) {
527
542
  const keyPart = (isFirst ? "{" : ",") + aliasName + ":";
@@ -529,9 +544,7 @@ export class JSONTransform extends Visitor {
529
544
  SERIALIZE += this.getStores(keyPart, SIMD_ENABLED)
530
545
  .map((v) => indent + v + "\n")
531
546
  .join("");
532
- SERIALIZE +=
533
- indent +
534
- `JSON.__serialize<${member.type}>(load<${member.type}>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`;
547
+ SERIALIZE += indent + getSerializeCall(member.type, realName);
535
548
  if (isFirst)
536
549
  isFirst = false;
537
550
  }
@@ -541,26 +554,20 @@ export class JSONTransform extends Visitor {
541
554
  SERIALIZE += this.getStores(keyPart, SIMD_ENABLED)
542
555
  .map((v) => indent + v + "\n")
543
556
  .join("");
544
- SERIALIZE +=
545
- indent +
546
- `JSON.__serialize<${member.type}>(load<${member.type}>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`;
557
+ SERIALIZE += indent + getSerializeCall(member.type, realName);
547
558
  if (isFirst)
548
559
  isFirst = false;
549
560
  }
550
561
  else {
551
562
  if (member.flags.has(PropertyFlags.OmitNull)) {
552
- SERIALIZE +=
553
- indent +
554
- `if ((block = load<usize>(ptr, offsetof<this>(${JSON.stringify(realName)}))) !== 0) {\n`;
563
+ SERIALIZE += indent + `if ((block = load<usize>(ptr, offsetof<this>(${JSON.stringify(realName)}))) !== 0) {\n`;
555
564
  indentInc();
556
565
  const keyPart = aliasName + ":";
557
566
  this.schema.byteSize += keyPart.length << 1;
558
567
  SERIALIZE += this.getStores(keyPart, SIMD_ENABLED)
559
568
  .map((v) => indent + v + "\n")
560
569
  .join("");
561
- SERIALIZE +=
562
- indent +
563
- `JSON.__serialize<${member.type}>(load<${member.type}>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`;
570
+ SERIALIZE += indent + getSerializeCall(member.type, realName);
564
571
  if (!isLast) {
565
572
  this.schema.byteSize += 2;
566
573
  SERIALIZE += indent + `store<u16>(bs.offset, 44, 0); // ,\n`;
@@ -574,25 +581,19 @@ export class JSONTransform extends Visitor {
574
581
  if (member.flags.get(PropertyFlags.OmitIf).kind == 14) {
575
582
  const arg = member.flags.get(PropertyFlags.OmitIf);
576
583
  arg.declaration.signature.parameters[0].type = Node.createNamedType(Node.createSimpleTypeName("this", node.range), null, false, node.range);
577
- arg.declaration.signature.returnType.name =
578
- Node.createSimpleTypeName("boolean", arg.declaration.signature.returnType.name
579
- .range);
580
- SERIALIZE +=
581
- indent +
582
- `if (!(${toString(member.flags.get(PropertyFlags.OmitIf))})(this)) {\n`;
584
+ arg.declaration.signature.returnType.name = Node.createSimpleTypeName("boolean", arg.declaration.signature.returnType.name.range);
585
+ SERIALIZE += indent + `if (!(${toString(member.flags.get(PropertyFlags.OmitIf))})(this)) {\n`;
583
586
  }
584
587
  else {
585
- SERIALIZE +=
586
- indent +
587
- `if (${toString(member.flags.get(PropertyFlags.OmitIf))}) {\n`;
588
+ const expression = member.flags.get(PropertyFlags.OmitIf);
589
+ const rendered = expression.kind == 16 && expression.literalKind == 2 ? JSON.stringify(expression.value).slice(1, -1) : toString(expression);
590
+ SERIALIZE += indent + `if (!(${rendered})) {\n`;
588
591
  }
589
592
  indentInc();
590
593
  SERIALIZE += this.getStores(aliasName + ":", SIMD_ENABLED)
591
594
  .map((v) => indent + v + "\n")
592
595
  .join("");
593
- SERIALIZE +=
594
- indent +
595
- `JSON.__serialize<${member.type}>(load<${member.type}>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`;
596
+ SERIALIZE += indent + getSerializeCall(member.type, realName);
596
597
  if (!isLast) {
597
598
  this.schema.byteSize += 2;
598
599
  SERIALIZE += indent + `store<u16>(bs.offset, 44, 0); // ,\n`;
@@ -613,13 +614,12 @@ export class JSONTransform extends Visitor {
613
614
  };
614
615
  for (const member of this.schema.members) {
615
616
  const type = stripNull(member.type);
616
- if (member.custom || member.generic) {
617
- sortedMembers.string.push(member);
618
- sortedMembers.number.push(member);
619
- sortedMembers.object.push(member);
620
- sortedMembers.array.push(member);
621
- sortedMembers.boolean.push(member);
622
- sortedMembers.null.push(member);
617
+ const customDep = this.schema.deps.find((dep) => dep && (dep.name == type || dep.name.endsWith("." + type)) && dep.custom);
618
+ const isCustomType = member.custom || !!customDep;
619
+ if (isCustomType || member.generic) {
620
+ addMemberToCustomBucket(sortedMembers, member, member.generic ? "any" : customDep?.customJsonKind || "any");
621
+ if (member.node.type.isNullable)
622
+ sortedMembers.null.push(member);
623
623
  }
624
624
  else {
625
625
  if (member.node.type.isNullable)
@@ -628,9 +628,7 @@ export class JSONTransform extends Visitor {
628
628
  sortedMembers.string.push(member);
629
629
  else if (isBoolean(type) || type.startsWith("JSON.Box<bool"))
630
630
  sortedMembers.boolean.push(member);
631
- else if (isPrimitive(type) ||
632
- type.startsWith("JSON.Box<") ||
633
- isEnum(type, this.sources.get(this.schema.node.range.source), this.parser))
631
+ else if (isPrimitive(type) || type.startsWith("JSON.Box<") || isEnum(type, this.sources.get(this.schema.node.range.source), this.parser))
634
632
  sortedMembers.number.push(member);
635
633
  else if (isArray(type))
636
634
  sortedMembers.array.push(member);
@@ -638,50 +636,270 @@ export class JSONTransform extends Visitor {
638
636
  sortedMembers.object.push(member);
639
637
  }
640
638
  }
641
- indent = "";
639
+ const getComparisions = (data, ptr, operator) => {
640
+ const dataBytes = data.length << 1;
641
+ let offset = 0;
642
+ const output = [];
643
+ while (offset < dataBytes) {
644
+ const rem = dataBytes - offset;
645
+ if (rem >= 8) {
646
+ output.push(`load<u64>(${ptr}, ${offset}) ${operator} 0x${toU64(data, offset >> 1).toString(16)}`);
647
+ offset += 8;
648
+ continue;
649
+ }
650
+ if (rem >= 4) {
651
+ output.push(`load<u32>(${ptr}, ${offset}) ${operator} 0x${toU32(data, offset >> 1).toString(16)}`);
652
+ offset += 4;
653
+ continue;
654
+ }
655
+ if (rem >= 2) {
656
+ output.push(`load<u16>(${ptr}, ${offset}) ${operator} 0x${data.charCodeAt(offset >> 1).toString(16)}`);
657
+ offset += 2;
658
+ continue;
659
+ }
660
+ }
661
+ return output;
662
+ };
663
+ const UNSIGNED_INTEGER_TYPES = ["u8", "u16", "u32", "u64", "usize"];
664
+ const SIGNED_INTEGER_TYPES = ["i8", "i16", "i32", "i64", "isize"];
665
+ const FLOAT_TYPES = ["f32", "f64"];
666
+ const INTEGER_TYPES = [...UNSIGNED_INTEGER_TYPES, ...SIGNED_INTEGER_TYPES];
667
+ const STRING_FIELD_DESERIALIZER = codegenMode === JSONMode.SIMD ? "deserializeStringField_SIMD" : "deserializeStringField_SWAR";
668
+ const getArrayValueType = (type) => {
669
+ if (type.startsWith("Array<") || type.startsWith("StaticArray<")) {
670
+ return stripNull(type.slice(type.indexOf("<") + 1, -1).trim());
671
+ }
672
+ return null;
673
+ };
674
+ const getDeserializer = (type, srcPtr, outPtr, member, keyOffset = 0) => {
675
+ const out = [];
676
+ const resolvedType = stripNull(type);
677
+ const fieldOffset = `offsetof<this>(${JSON.stringify(member.name)})`;
678
+ const fieldPtr = `${outPtr} + offsetof<this>(${JSON.stringify(member.name)})`;
679
+ const valuePtr = keyOffset ? `${srcPtr} + ${keyOffset}` : srcPtr;
680
+ if (INTEGER_TYPES.includes(resolvedType)) {
681
+ const helper = SIGNED_INTEGER_TYPES.includes(resolvedType) ? "deserializeIntegerField" : "deserializeUnsignedField";
682
+ out.push(`${srcPtr} = ${helper}<${resolvedType}>(${valuePtr}, srcEnd, ${fieldPtr});`);
683
+ }
684
+ else if (["string", "String"].includes(resolvedType)) {
685
+ out.push("{");
686
+ if (member.node.type.isNullable) {
687
+ out.push(` if (load<u64>(${valuePtr}) == 30399761348886638) {`);
688
+ out.push(` store<${member.type}>(${outPtr}, changetype<${member.type}>(0), ${fieldOffset});`);
689
+ out.push(` ${srcPtr} = ${valuePtr} + 8;`);
690
+ out.push(" } else {");
691
+ }
692
+ out.push(` ${srcPtr} = ${STRING_FIELD_DESERIALIZER}<${member.type}>(${valuePtr}, srcEnd, ${fieldPtr});`);
693
+ if (member.node.type.isNullable) {
694
+ out.push(" }");
695
+ }
696
+ out.push("}");
697
+ }
698
+ else if (isBoolean(resolvedType)) {
699
+ out.push("{");
700
+ out.push(` if (load<u64>(${srcPtr}) == 28429475166421108) {`);
701
+ out.push(` store<${resolvedType}>(${outPtr}, true, ${fieldOffset});`);
702
+ out.push(` ${srcPtr} += 8;`);
703
+ out.push(" } else if (load<u64>(" + srcPtr + ") == 32370086184550502 && load<u16>(" + srcPtr + ", 8) == 101) {");
704
+ out.push(` store<${resolvedType}>(${outPtr}, false, ${fieldOffset});`);
705
+ out.push(` ${srcPtr} += 10;`);
706
+ out.push(" } else break;");
707
+ out.push("}");
708
+ }
709
+ else if (FLOAT_TYPES.includes(resolvedType)) {
710
+ out.push(`${srcPtr} = deserializeFloatField<${resolvedType}>(${valuePtr}, srcEnd, ${fieldPtr});`);
711
+ }
712
+ else if (this.getSchema(resolvedType)) {
713
+ out.push("{");
714
+ if (member.node.type.isNullable) {
715
+ out.push(` if (load<u64>(${srcPtr}) == 30399761348886638) {`);
716
+ out.push(` store<${resolvedType}>(${outPtr}, changetype<${resolvedType}>(0), ${fieldOffset});`);
717
+ out.push(` ${srcPtr} += 8;`);
718
+ out.push(" } else {");
719
+ }
720
+ out.push(` let value = load<${resolvedType}>(${outPtr}, ${fieldOffset});`);
721
+ out.push(" if (changetype<usize>(value) == 0) {");
722
+ out.push(` value = changetype<${resolvedType}>(__new(offsetof<nonnull<${resolvedType}>>(), idof<nonnull<${resolvedType}>>()));`);
723
+ out.push(` store<${resolvedType}>(${outPtr}, value, ${fieldOffset});`);
724
+ out.push(" }");
725
+ out.push(` ${srcPtr} = changetype<nonnull<${resolvedType}>>(value).__DESERIALIZE<${resolvedType}>(${srcPtr}, srcEnd, value);`);
726
+ if (member.node.type.isNullable) {
727
+ out.push(" }");
728
+ }
729
+ out.push("}");
730
+ }
731
+ else if (resolvedType.startsWith("Array<")) {
732
+ const valueType = getArrayValueType(resolvedType);
733
+ if (valueType && ["string", "String"].includes(valueType)) {
734
+ out.push("{");
735
+ out.push(` if (load<u16>(${srcPtr}) != 0x5b) break;`);
736
+ out.push(` let value = load<${resolvedType}>(${outPtr}, ${fieldOffset});`);
737
+ out.push(" if (changetype<usize>(value) == 0) {");
738
+ out.push(` value = [];`);
739
+ out.push(` store<${resolvedType}>(${outPtr}, value, ${fieldOffset});`);
740
+ out.push(" }");
741
+ out.push(" let index = 0;");
742
+ out.push(` ${srcPtr} += 2;`);
743
+ out.push(` if (load<u16>(${srcPtr}) == 0x5d) {`);
744
+ out.push(" value.length = 0;");
745
+ out.push(` ${srcPtr} += 2;`);
746
+ out.push(" } else while (true) {");
747
+ out.push(' if (index >= value.length) value.push("");');
748
+ out.push(` ${srcPtr} = ${STRING_FIELD_DESERIALIZER}<${valueType}>(${srcPtr}, srcEnd, value.dataStart + ((<usize>index) << alignof<${valueType}>()));`);
749
+ out.push(" index++;");
750
+ out.push(` const code = load<u16>(${srcPtr});`);
751
+ out.push(" if (code == 0x2c) {");
752
+ out.push(` ${srcPtr} += 2;`);
753
+ out.push(" continue;");
754
+ out.push(" }");
755
+ out.push(" if (code == 0x5d) {");
756
+ out.push(" value.length = index;");
757
+ out.push(` ${srcPtr} += 2;`);
758
+ out.push(" break;");
759
+ out.push(" }");
760
+ out.push(" break;");
761
+ out.push(" }");
762
+ out.push("}");
763
+ }
764
+ else if (valueType && this.getSchema(valueType)) {
765
+ out.push("{");
766
+ out.push(` if (load<u16>(${srcPtr}) != 0x5b) break;`);
767
+ out.push(` let value = load<${resolvedType}>(${outPtr}, ${fieldOffset});`);
768
+ out.push(" if (changetype<usize>(value) == 0) {");
769
+ out.push(` value = [];`);
770
+ out.push(` store<${resolvedType}>(${outPtr}, value, ${fieldOffset});`);
771
+ out.push(" }");
772
+ out.push(" let index = 0;");
773
+ out.push(` ${srcPtr} += 2;`);
774
+ out.push(` if (load<u16>(${srcPtr}) == 0x5d) {`);
775
+ out.push(" value.length = 0;");
776
+ out.push(` ${srcPtr} += 2;`);
777
+ out.push(" } else while (true) {");
778
+ out.push(` let item: ${valueType};`);
779
+ out.push(" if (index < value.length) {");
780
+ out.push(" item = unchecked(value[index]);");
781
+ out.push(" if (changetype<usize>(item) == 0) {");
782
+ out.push(` item = changetype<${valueType}>(__new(offsetof<nonnull<${valueType}>>(), idof<nonnull<${valueType}>>()));`);
783
+ out.push(" unchecked((value[index] = item));");
784
+ out.push(" }");
785
+ out.push(" } else {");
786
+ out.push(` item = changetype<${valueType}>(__new(offsetof<nonnull<${valueType}>>(), idof<nonnull<${valueType}>>()));`);
787
+ out.push(" value.push(item);");
788
+ out.push(" }");
789
+ out.push(` ${srcPtr} = changetype<nonnull<${valueType}>>(item).__DESERIALIZE<${valueType}>(${srcPtr}, srcEnd, item);`);
790
+ out.push(" index++;");
791
+ out.push(` const code = load<u16>(${srcPtr});`);
792
+ out.push(" if (code == 0x2c) {");
793
+ out.push(` ${srcPtr} += 2;`);
794
+ out.push(" continue;");
795
+ out.push(" }");
796
+ out.push(" if (code == 0x5d) {");
797
+ out.push(" value.length = index;");
798
+ out.push(` ${srcPtr} += 2;`);
799
+ out.push(" break;");
800
+ out.push(" }");
801
+ out.push(" break;");
802
+ out.push(" }");
803
+ out.push("}");
804
+ }
805
+ else {
806
+ out.push(`${srcPtr} = deserializeArrayField_SWAR<${resolvedType}>(${srcPtr}, srcEnd, ${fieldPtr});`);
807
+ out.push(`if (!${srcPtr}) break;`);
808
+ }
809
+ }
810
+ else {
811
+ out.push("{");
812
+ out.push(` const valueStart = ${srcPtr};`);
813
+ out.push(" let depth: i32 = 0;");
814
+ out.push(" let inString = false;");
815
+ out.push(` while (${srcPtr} < srcEnd) {`);
816
+ out.push(` const code = load<u16>(${srcPtr});`);
817
+ out.push(" if (inString) {");
818
+ out.push(` if (code == 0x22 && load<u16>(${srcPtr} - 2) != 0x5c) inString = false;`);
819
+ out.push(` ${srcPtr} += 2;`);
820
+ out.push(" continue;");
821
+ out.push(" }");
822
+ out.push(" if (code == 0x22) {");
823
+ out.push(" inString = true;");
824
+ out.push(` ${srcPtr} += 2;`);
825
+ out.push(" continue;");
826
+ out.push(" }");
827
+ out.push(" if (code == 0x7b || code == 0x5b) {");
828
+ out.push(" depth++;");
829
+ out.push(` ${srcPtr} += 2;`);
830
+ out.push(" continue;");
831
+ out.push(" }");
832
+ out.push(" if (code == 0x7d || code == 0x5d) {");
833
+ out.push(" if (depth == 0) break;");
834
+ out.push(" depth--;");
835
+ out.push(` ${srcPtr} += 2;`);
836
+ out.push(" continue;");
837
+ out.push(" }");
838
+ out.push(" if (code == 0x2c && depth == 0) break;");
839
+ out.push(` ${srcPtr} += 2;`);
840
+ out.push(" }");
841
+ out.push(` if (inString || depth != 0 || ${srcPtr} <= valueStart) break;`);
842
+ out.push(` store<${resolvedType}>(${outPtr}, JSON.__deserialize<${resolvedType}>(valueStart, ${srcPtr}), ${fieldOffset});`);
843
+ out.push("}");
844
+ }
845
+ return out;
846
+ };
847
+ indent = " ";
848
+ DESERIALIZE_FAST += indent + "const dst = changetype<usize>(out);\n";
849
+ DESERIALIZE_FAST += indent + "do {\n";
850
+ indent += " ";
851
+ for (let i = 0; i < this.schema.members.length; i++) {
852
+ const member = this.schema.members[i];
853
+ const key = JSON.stringify(member.alias || member.name);
854
+ if (key.length <= 2)
855
+ throw new Error("Key cannot be empty!");
856
+ const keySection = (i == 0 ? "{" : ",") + key + ":";
857
+ DESERIALIZE_FAST += indent + `if ( // ${keySection}\n${(indent += " ")}${getComparisions(keySection, "srcStart", "!=").join("\n" + indent + "|| ")}\n${(indent = indent.slice(0, -2))}) break;\n`;
858
+ const keyOffset = keySection.length << 1;
859
+ const resolvedType = stripNull(member.type);
860
+ const inlineStringValue = ["string", "String"].includes(resolvedType);
861
+ if (!inlineStringValue) {
862
+ DESERIALIZE_FAST += indent + `srcStart += ${keyOffset};\n\n`;
863
+ }
864
+ const deserializer = getDeserializer(member.type, "srcStart", "dst", member, inlineStringValue ? keyOffset : 0);
865
+ if (!deserializer.length) {
866
+ DESERIALIZE_FAST += indent + "break;\n\n";
867
+ continue;
868
+ }
869
+ DESERIALIZE_FAST += indent + deserializer.join("\n" + indent) + "\n\n";
870
+ }
871
+ DESERIALIZE_FAST += indent + "if (load<u16>(srcStart) !== 0x7d) break; // }\n";
872
+ DESERIALIZE_FAST += indent + "srcStart += 2;\n";
873
+ DESERIALIZE_FAST += indent + "return srcStart;\n";
874
+ indent = indent.slice(0, -2);
875
+ DESERIALIZE_FAST += indent + "} while (false);\n\n";
876
+ DESERIALIZE_FAST += indent + 'throw new Error("Failed to parse JSON ");';
877
+ indent = indent.slice(0, -2);
878
+ DESERIALIZE_FAST += indent + "}";
642
879
  DESERIALIZE += indent + " let keyStart: usize = 0;\n";
643
880
  DESERIALIZE += indent + " let keyEnd: usize = 0;\n";
644
881
  DESERIALIZE += indent + " let isKey = false;\n";
645
882
  if (!STRICT || sortedMembers.object.length || sortedMembers.array.length)
646
883
  DESERIALIZE += indent + " let depth: i32 = 0;\n";
647
884
  DESERIALIZE += indent + " let lastIndex: usize = 0;\n\n";
648
- DESERIALIZE +=
649
- indent +
650
- " while (srcStart < srcEnd && JSON.Util.isSpace(load<u16>(srcStart))) srcStart += 2;\n";
651
- DESERIALIZE +=
652
- indent +
653
- " while (srcEnd > srcStart && JSON.Util.isSpace(load<u16>(srcEnd - 2))) srcEnd -= 2;\n";
654
- DESERIALIZE +=
655
- indent +
656
- ' if (srcStart - srcEnd == 0) throw new Error("Input string had zero length or was all whitespace");\n';
657
- DESERIALIZE +=
658
- indent +
659
- " if (load<u16>(srcStart) != 123) throw new Error(\"Expected '{' at start of object at position \" + (srcEnd - srcStart).toString());\n";
660
- DESERIALIZE +=
661
- indent +
662
- " if (load<u16>(srcEnd - 2) != 125) throw new Error(\"Expected '}' at end of object at position \" + (srcEnd - srcStart).toString());\n";
885
+ DESERIALIZE += indent + " while (srcStart < srcEnd && JSON.Util.isSpace(load<u16>(srcStart))) srcStart += 2;\n";
886
+ DESERIALIZE += indent + " while (srcEnd > srcStart && JSON.Util.isSpace(load<u16>(srcEnd - 2))) srcEnd -= 2;\n";
887
+ DESERIALIZE += indent + ' if (srcStart - srcEnd == 0) throw new Error("Input string had zero length or was all whitespace");\n';
888
+ DESERIALIZE += indent + " if (load<u16>(srcStart) != 123) throw new Error(\"Expected '{' at start of object at position \" + (srcEnd - srcStart).toString());\n";
889
+ DESERIALIZE += indent + " if (load<u16>(srcEnd - 2) != 125) throw new Error(\"Expected '}' at end of object at position \" + (srcEnd - srcStart).toString());\n";
663
890
  DESERIALIZE += indent + " srcStart += 2;\n\n";
664
891
  DESERIALIZE += indent + " while (srcStart < srcEnd) {\n";
665
892
  DESERIALIZE += indent + " let code = load<u16>(srcStart);\n";
666
- DESERIALIZE +=
667
- indent +
668
- " while (JSON.Util.isSpace(code)) code = load<u16>(srcStart += 2);\n";
893
+ DESERIALIZE += indent + " while (JSON.Util.isSpace(code)) code = load<u16>(srcStart += 2);\n";
669
894
  DESERIALIZE += indent + " if (keyStart == 0) {\n";
670
- DESERIALIZE +=
671
- indent + " if (code == 34 && load<u16>(srcStart - 2) !== 92) {\n";
895
+ DESERIALIZE += indent + " if (code == 34 && load<u16>(srcStart - 2) !== 92) {\n";
672
896
  DESERIALIZE += indent + " if (isKey) {\n";
673
897
  DESERIALIZE += indent + " keyStart = lastIndex;\n";
674
898
  DESERIALIZE += indent + " keyEnd = srcStart;\n";
675
899
  if (DEBUG > 1)
676
- DESERIALIZE +=
677
- indent +
678
- ' console.log("Key: " + JSON.Util.ptrToStr(keyStart, keyEnd));\n';
679
- DESERIALIZE +=
680
- indent +
681
- " while (JSON.Util.isSpace((code = load<u16>((srcStart += 2))))) {}\n";
682
- DESERIALIZE +=
683
- indent +
684
- " if (code !== 58) throw new Error(\"Expected ':' after key at position \" + (srcEnd - srcStart).toString());\n";
900
+ DESERIALIZE += indent + ' console.log("Key: " + JSON.Util.ptrToStr(keyStart, keyEnd));\n';
901
+ DESERIALIZE += indent + " while (JSON.Util.isSpace((code = load<u16>((srcStart += 2))))) {}\n";
902
+ DESERIALIZE += indent + " if (code !== 58) throw new Error(\"Expected ':' after key at position \" + (srcEnd - srcStart).toString());\n";
685
903
  DESERIALIZE += indent + " isKey = false;\n";
686
904
  DESERIALIZE += indent + " } else {\n";
687
905
  DESERIALIZE += indent + " isKey = true;\n";
@@ -711,9 +929,7 @@ export class JSONTransform extends Visitor {
711
929
  const generateGroups = (members, cb, type) => {
712
930
  if (!members.length) {
713
931
  if (STRICT) {
714
- DESERIALIZE +=
715
- indent +
716
- ' throw new Error("Unexpected key value pair in JSON object \'" + JSON.Util.ptrToStr(keyStart, keyEnd) + ":" + JSON.Util.ptrToStr(lastIndex, srcStart) + "\' at position " + (srcEnd - srcStart).toString());\n';
932
+ DESERIALIZE += indent + ' throw new Error("Unexpected key value pair in JSON object \'" + JSON.Util.ptrToStr(keyStart, keyEnd) + ":" + JSON.Util.ptrToStr(lastIndex, srcStart) + "\' at position " + (srcEnd - srcStart).toString());\n';
717
933
  }
718
934
  else {
719
935
  if (type == "string") {
@@ -723,10 +939,7 @@ export class JSONTransform extends Visitor {
723
939
  DESERIALIZE += indent + " srcStart += 2;\n";
724
940
  }
725
941
  DESERIALIZE += indent + " keyStart = 0;\n";
726
- if (type == "string" ||
727
- type == "object" ||
728
- type == "array" ||
729
- type == "number")
942
+ if (type == "string" || type == "object" || type == "array" || type == "number")
730
943
  DESERIALIZE += indent + " break;\n";
731
944
  }
732
945
  }
@@ -741,9 +954,7 @@ export class JSONTransform extends Visitor {
741
954
  }
742
955
  DESERIALIZE += " default: {\n";
743
956
  if (STRICT) {
744
- DESERIALIZE +=
745
- indent +
746
- ' throw new Error("Unexpected key value pair in JSON object \'" + JSON.Util.ptrToStr(keyStart, keyEnd) + ":" + JSON.Util.ptrToStr(lastIndex, srcStart) + "\' at position " + (srcEnd - srcStart).toString());\n';
957
+ DESERIALIZE += indent + ' throw new Error("Unexpected key value pair in JSON object \'" + JSON.Util.ptrToStr(keyStart, keyEnd) + ":" + JSON.Util.ptrToStr(lastIndex, srcStart) + "\' at position " + (srcEnd - srcStart).toString());\n';
747
958
  }
748
959
  else {
749
960
  if (type == "string") {
@@ -753,10 +964,7 @@ export class JSONTransform extends Visitor {
753
964
  DESERIALIZE += indent + " srcStart += 2;\n";
754
965
  }
755
966
  DESERIALIZE += indent + " keyStart = 0;\n";
756
- if (type == "string" ||
757
- type == "object" ||
758
- type == "array" ||
759
- type == "number")
967
+ if (type == "string" || type == "object" || type == "array" || type == "number")
760
968
  DESERIALIZE += indent + " break;\n";
761
969
  }
762
970
  DESERIALIZE += " }\n";
@@ -773,8 +981,7 @@ export class JSONTransform extends Visitor {
773
981
  DESERIALIZE += " const code32 = load<u32>(keyStart);\n";
774
982
  }
775
983
  if (members.some((m) => (m.alias || m.name).length << 1 == 6)) {
776
- DESERIALIZE +=
777
- " const code48 = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n";
984
+ DESERIALIZE += " const code48 = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n";
778
985
  }
779
986
  if (members.some((m) => (m.alias || m.name).length << 1 == 8)) {
780
987
  DESERIALIZE += " const code64 = load<u64>(keyStart);\n";
@@ -790,34 +997,15 @@ export class JSONTransform extends Visitor {
790
997
  DESERIALIZE += " srcStart += 2;\n";
791
998
  DESERIALIZE += " while (srcStart < srcEnd) {\n";
792
999
  DESERIALIZE += " const code = load<u16>(srcStart);\n";
793
- DESERIALIZE +=
794
- " if (code == 34 && load<u16>(srcStart - 2) !== 92) {\n";
1000
+ DESERIALIZE += " if (code == 34 && load<u16>(srcStart - 2) !== 92) {\n";
795
1001
  if (DEBUG > 1)
796
- DESERIALIZE +=
797
- ' console.log("Value (string, ' +
798
- ++id +
799
- '): " + JSON.Util.ptrToStr(lastIndex, srcStart + 2));';
1002
+ DESERIALIZE += ' console.log("Value (string, ' + ++id + '): " + JSON.Util.ptrToStr(lastIndex, srcStart + 2));';
800
1003
  generateGroups(sortedMembers.string, (group) => {
801
1004
  generateConsts(group);
802
1005
  const first = group[0];
803
1006
  const fName = first.alias || first.name;
804
- DESERIALIZE +=
805
- indent +
806
- " if (" +
807
- (first.generic ? "isString<" + first.type + ">() && " : "") +
808
- getComparison(fName) +
809
- ") { // " +
810
- fName +
811
- "\n";
812
- DESERIALIZE +=
813
- indent +
814
- " store<" +
815
- first.type +
816
- ">(changetype<usize>(out), JSON.__deserialize<" +
817
- first.type +
818
- ">(lastIndex, srcStart + 2), offsetof<this>(" +
819
- JSON.stringify(first.name) +
820
- "));\n";
1007
+ DESERIALIZE += indent + " if (" + (first.generic ? "isString<" + first.type + ">() && " : "") + getComparison(fName) + ") { // " + fName + "\n";
1008
+ DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), JSON.__deserialize<" + first.type + ">(lastIndex, srcStart + 2), offsetof<this>(" + JSON.stringify(first.name) + "));\n";
821
1009
  DESERIALIZE += indent + " srcStart += 4;\n";
822
1010
  DESERIALIZE += indent + " keyStart = 0;\n";
823
1011
  DESERIALIZE += indent + " break;\n";
@@ -825,23 +1013,8 @@ export class JSONTransform extends Visitor {
825
1013
  for (let i = 1; i < group.length; i++) {
826
1014
  const mem = group[i];
827
1015
  const memName = mem.alias || mem.name;
828
- DESERIALIZE +=
829
- indent +
830
- " else if (" +
831
- (mem.generic ? "isString<" + mem.type + ">() && " : "") +
832
- getComparison(memName) +
833
- ") { // " +
834
- memName +
835
- "\n";
836
- DESERIALIZE +=
837
- indent +
838
- " store<" +
839
- mem.type +
840
- ">(changetype<usize>(out), JSON.__deserialize<" +
841
- mem.type +
842
- ">(lastIndex, srcStart + 2), offsetof<this>(" +
843
- JSON.stringify(mem.name) +
844
- "));\n";
1016
+ DESERIALIZE += indent + " else if (" + (mem.generic ? "isString<" + mem.type + ">() && " : "") + getComparison(memName) + ") { // " + memName + "\n";
1017
+ DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), JSON.__deserialize<" + mem.type + ">(lastIndex, srcStart + 2), offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
845
1018
  DESERIALIZE += indent + " srcStart += 4;\n";
846
1019
  DESERIALIZE += indent + " keyStart = 0;\n";
847
1020
  DESERIALIZE += indent + " break;\n";
@@ -849,9 +1022,7 @@ export class JSONTransform extends Visitor {
849
1022
  }
850
1023
  if (STRICT) {
851
1024
  DESERIALIZE += " else {\n";
852
- DESERIALIZE +=
853
- indent +
854
- ' throw new Error("Unexpected key value pair in JSON object \'" + JSON.Util.ptrToStr(keyStart, keyEnd) + ":" + JSON.Util.ptrToStr(lastIndex, srcStart) + "\' at position " + (srcEnd - srcStart).toString());\n';
1025
+ DESERIALIZE += indent + ' throw new Error("Unexpected key value pair in JSON object \'" + JSON.Util.ptrToStr(keyStart, keyEnd) + ":" + JSON.Util.ptrToStr(lastIndex, srcStart) + "\' at position " + (srcEnd - srcStart).toString());\n';
855
1026
  DESERIALIZE += indent + " }\n";
856
1027
  }
857
1028
  else {
@@ -874,40 +1045,15 @@ export class JSONTransform extends Visitor {
874
1045
  DESERIALIZE += " srcStart += 2;\n";
875
1046
  DESERIALIZE += " while (srcStart < srcEnd) {\n";
876
1047
  DESERIALIZE += " const code = load<u16>(srcStart);\n";
877
- DESERIALIZE +=
878
- " if (code == 44 || code == 125 || JSON.Util.isSpace(code)) {\n";
1048
+ DESERIALIZE += " if (code == 44 || code == 125 || JSON.Util.isSpace(code)) {\n";
879
1049
  if (DEBUG > 1)
880
- DESERIALIZE +=
881
- ' console.log("Value (number, ' +
882
- ++id +
883
- '): " + JSON.Util.ptrToStr(lastIndex, srcStart));';
1050
+ DESERIALIZE += ' console.log("Value (number, ' + ++id + '): " + JSON.Util.ptrToStr(lastIndex, srcStart));';
884
1051
  generateGroups(sortedMembers.number, (group) => {
885
1052
  generateConsts(group);
886
1053
  const first = group[0];
887
1054
  const fName = first.alias || first.name;
888
- DESERIALIZE +=
889
- indent +
890
- " if (" +
891
- (first.generic
892
- ? "(isInteger<" +
893
- first.type +
894
- ">() || isFloat<" +
895
- first.type +
896
- ">()) && "
897
- : "") +
898
- getComparison(fName) +
899
- ") { // " +
900
- fName +
901
- "\n";
902
- DESERIALIZE +=
903
- indent +
904
- " store<" +
905
- first.type +
906
- ">(changetype<usize>(out), JSON.__deserialize<" +
907
- first.type +
908
- ">(lastIndex, srcStart), offsetof<this>(" +
909
- JSON.stringify(first.name) +
910
- "));\n";
1055
+ DESERIALIZE += indent + " if (" + (first.generic ? "(isInteger<" + first.type + ">() || isFloat<" + first.type + ">()) && " : "") + getComparison(fName) + ") { // " + fName + "\n";
1056
+ DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), JSON.__deserialize<" + first.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(first.name) + "));\n";
911
1057
  DESERIALIZE += indent + " srcStart += 2;\n";
912
1058
  DESERIALIZE += indent + " keyStart = 0;\n";
913
1059
  DESERIALIZE += indent + " break;\n";
@@ -915,29 +1061,8 @@ export class JSONTransform extends Visitor {
915
1061
  for (let i = 1; i < group.length; i++) {
916
1062
  const mem = group[i];
917
1063
  const memName = mem.alias || mem.name;
918
- DESERIALIZE +=
919
- indent +
920
- " else if (" +
921
- (mem.generic
922
- ? "(isInteger<" +
923
- mem.type +
924
- ">() || isFloat<" +
925
- mem.type +
926
- ">()) && "
927
- : "") +
928
- getComparison(memName) +
929
- ") { // " +
930
- memName +
931
- "\n";
932
- DESERIALIZE +=
933
- indent +
934
- " store<" +
935
- mem.type +
936
- ">(changetype<usize>(out), JSON.__deserialize<" +
937
- mem.type +
938
- ">(lastIndex, srcStart), offsetof<this>(" +
939
- JSON.stringify(mem.name) +
940
- "));\n";
1064
+ DESERIALIZE += indent + " else if (" + (mem.generic ? "(isInteger<" + mem.type + ">() || isFloat<" + mem.type + ">()) && " : "") + getComparison(memName) + ") { // " + memName + "\n";
1065
+ DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), JSON.__deserialize<" + mem.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
941
1066
  DESERIALIZE += indent + " srcStart += 2;\n";
942
1067
  DESERIALIZE += indent + " keyStart = 0;\n";
943
1068
  DESERIALIZE += indent + " break;\n";
@@ -945,9 +1070,7 @@ export class JSONTransform extends Visitor {
945
1070
  }
946
1071
  if (STRICT) {
947
1072
  DESERIALIZE += " else {\n";
948
- DESERIALIZE +=
949
- indent +
950
- ' throw new Error("Unexpected key value pair in JSON object \'" + JSON.Util.ptrToStr(keyStart, keyEnd) + ":" + JSON.Util.ptrToStr(lastIndex, srcStart) + "\' at position " + (srcEnd - srcStart).toString());\n';
1073
+ DESERIALIZE += indent + ' throw new Error("Unexpected key value pair in JSON object \'" + JSON.Util.ptrToStr(keyStart, keyEnd) + ":" + JSON.Util.ptrToStr(lastIndex, srcStart) + "\' at position " + (srcEnd - srcStart).toString());\n';
951
1074
  DESERIALIZE += indent + " }\n";
952
1075
  }
953
1076
  else {
@@ -973,70 +1096,34 @@ export class JSONTransform extends Visitor {
973
1096
  DESERIALIZE += " const code = load<u16>(srcStart);\n";
974
1097
  DESERIALIZE += " if (code == 34) {\n";
975
1098
  DESERIALIZE += " srcStart += 2;\n";
976
- DESERIALIZE +=
977
- " while (!(load<u16>(srcStart) == 34 && load<u16>(srcStart - 2) != 92)) srcStart += 2;\n";
1099
+ DESERIALIZE += " while (!(load<u16>(srcStart) == 34 && load<u16>(srcStart - 2) != 92)) srcStart += 2;\n";
978
1100
  DESERIALIZE += " } else if (code == 125) {\n";
979
1101
  DESERIALIZE += " if (--depth == 0) {\n";
980
1102
  DESERIALIZE += " srcStart += 2;\n";
981
1103
  if (DEBUG > 1)
982
- DESERIALIZE +=
983
- ' console.log("Value (object, ' +
984
- ++id +
985
- '): " + JSON.Util.ptrToStr(lastIndex, srcStart));';
1104
+ DESERIALIZE += ' console.log("Value (object, ' + ++id + '): " + JSON.Util.ptrToStr(lastIndex, srcStart));';
986
1105
  indent = " ";
987
1106
  generateGroups(sortedMembers.object, (group) => {
988
1107
  generateConsts(group);
989
1108
  const first = group[0];
990
1109
  const fName = first.alias || first.name;
991
- DESERIALIZE +=
992
- indent +
993
- " if (" +
994
- (first.generic ? "isDefined(out.__DESERIALIZE) &&" : "") +
995
- getComparison(fName) +
996
- ") { // " +
997
- fName +
998
- "\n";
999
- DESERIALIZE +=
1000
- indent +
1001
- " store<" +
1002
- first.type +
1003
- ">(changetype<usize>(out), JSON.__deserialize<" +
1004
- first.type +
1005
- ">(lastIndex, srcStart), offsetof<this>(" +
1006
- JSON.stringify(first.name) +
1007
- "));\n";
1110
+ DESERIALIZE += indent + " if (" + (first.generic ? "isDefined(out.__DESERIALIZE) &&" : "") + getComparison(fName) + ") { // " + fName + "\n";
1111
+ DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), JSON.__deserialize<" + first.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(first.name) + "));\n";
1008
1112
  DESERIALIZE += indent + " keyStart = 0;\n";
1009
1113
  DESERIALIZE += indent + " break;\n";
1010
1114
  DESERIALIZE += indent + " }";
1011
1115
  for (let i = 1; i < group.length; i++) {
1012
1116
  const mem = group[i];
1013
1117
  const memName = mem.alias || mem.name;
1014
- DESERIALIZE +=
1015
- indent +
1016
- " else if (" +
1017
- (mem.generic ? "isDefined(out.__DESERIALIZE) &&" : "") +
1018
- getComparison(memName) +
1019
- ") { // " +
1020
- memName +
1021
- "\n";
1022
- DESERIALIZE +=
1023
- indent +
1024
- " store<" +
1025
- mem.type +
1026
- ">(changetype<usize>(out), JSON.__deserialize<" +
1027
- mem.type +
1028
- ">(lastIndex, srcStart), offsetof<this>(" +
1029
- JSON.stringify(mem.name) +
1030
- "));\n";
1118
+ DESERIALIZE += indent + " else if (" + (mem.generic ? "isDefined(out.__DESERIALIZE) &&" : "") + getComparison(memName) + ") { // " + memName + "\n";
1119
+ DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), JSON.__deserialize<" + mem.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
1031
1120
  DESERIALIZE += indent + " keyStart = 0;\n";
1032
1121
  DESERIALIZE += indent + " break;\n";
1033
1122
  DESERIALIZE += indent + " }";
1034
1123
  }
1035
1124
  if (STRICT) {
1036
1125
  DESERIALIZE += " else {\n";
1037
- DESERIALIZE +=
1038
- indent +
1039
- ' throw new Error("Unexpected key value pair in JSON object \'" + JSON.Util.ptrToStr(keyStart, keyEnd) + ":" + JSON.Util.ptrToStr(lastIndex, srcStart) + "\' at position " + (srcEnd - srcStart).toString());\n';
1126
+ DESERIALIZE += indent + ' throw new Error("Unexpected key value pair in JSON object \'" + JSON.Util.ptrToStr(keyStart, keyEnd) + ":" + JSON.Util.ptrToStr(lastIndex, srcStart) + "\' at position " + (srcEnd - srcStart).toString());\n';
1040
1127
  DESERIALIZE += indent + " }\n";
1041
1128
  }
1042
1129
  else {
@@ -1063,70 +1150,34 @@ export class JSONTransform extends Visitor {
1063
1150
  DESERIALIZE += " const code = load<u16>(srcStart);\n";
1064
1151
  DESERIALIZE += " if (code == 34) {\n";
1065
1152
  DESERIALIZE += " srcStart += 2;\n";
1066
- DESERIALIZE +=
1067
- " while (!(load<u16>(srcStart) == 34 && load<u16>(srcStart - 2) != 92)) srcStart += 2;\n";
1153
+ DESERIALIZE += " while (!(load<u16>(srcStart) == 34 && load<u16>(srcStart - 2) != 92)) srcStart += 2;\n";
1068
1154
  DESERIALIZE += " } else if (code == 93) {\n";
1069
1155
  DESERIALIZE += " if (--depth == 0) {\n";
1070
1156
  DESERIALIZE += " srcStart += 2;\n";
1071
1157
  if (DEBUG > 1)
1072
- DESERIALIZE +=
1073
- ' console.log("Value (object, ' +
1074
- ++id +
1075
- '): " + JSON.Util.ptrToStr(lastIndex, srcStart));';
1158
+ DESERIALIZE += ' console.log("Value (object, ' + ++id + '): " + JSON.Util.ptrToStr(lastIndex, srcStart));';
1076
1159
  indent = " ";
1077
1160
  generateGroups(sortedMembers.array, (group) => {
1078
1161
  generateConsts(group);
1079
1162
  const first = group[0];
1080
1163
  const fName = first.alias || first.name;
1081
- DESERIALIZE +=
1082
- indent +
1083
- " if (" +
1084
- (first.generic ? "isArray<" + first.type + ">() && " : "") +
1085
- getComparison(fName) +
1086
- ") { // " +
1087
- fName +
1088
- "\n";
1089
- DESERIALIZE +=
1090
- indent +
1091
- " store<" +
1092
- first.type +
1093
- ">(changetype<usize>(out), JSON.__deserialize<" +
1094
- first.type +
1095
- ">(lastIndex, srcStart), offsetof<this>(" +
1096
- JSON.stringify(first.name) +
1097
- "));\n";
1164
+ DESERIALIZE += indent + " if (" + (first.generic ? "isArray<" + first.type + ">() && " : "") + getComparison(fName) + ") { // " + fName + "\n";
1165
+ DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), JSON.__deserialize<" + first.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(first.name) + "));\n";
1098
1166
  DESERIALIZE += indent + " keyStart = 0;\n";
1099
1167
  DESERIALIZE += indent + " break;\n";
1100
1168
  DESERIALIZE += indent + " }";
1101
1169
  for (let i = 1; i < group.length; i++) {
1102
1170
  const mem = group[i];
1103
1171
  const memName = mem.alias || mem.name;
1104
- DESERIALIZE +=
1105
- indent +
1106
- " else if (" +
1107
- (mem.generic ? "isArray" + mem.type + ">() && " : "") +
1108
- getComparison(memName) +
1109
- ") { // " +
1110
- memName +
1111
- "\n";
1112
- DESERIALIZE +=
1113
- indent +
1114
- " store<" +
1115
- mem.type +
1116
- ">(changetype<usize>(out), JSON.__deserialize<" +
1117
- mem.type +
1118
- ">(lastIndex, srcStart), offsetof<this>(" +
1119
- JSON.stringify(mem.name) +
1120
- "));\n";
1172
+ DESERIALIZE += indent + " else if (" + (mem.generic ? "isArray" + mem.type + ">() && " : "") + getComparison(memName) + ") { // " + memName + "\n";
1173
+ DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), JSON.__deserialize<" + mem.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
1121
1174
  DESERIALIZE += indent + " keyStart = 0;\n";
1122
1175
  DESERIALIZE += indent + " break;\n";
1123
1176
  DESERIALIZE += indent + " }";
1124
1177
  }
1125
1178
  if (STRICT) {
1126
1179
  DESERIALIZE += " else {\n";
1127
- DESERIALIZE +=
1128
- indent +
1129
- ' throw new Error("Unexpected key value pair in JSON object \'" + JSON.Util.ptrToStr(keyStart, keyEnd) + ":" + JSON.Util.ptrToStr(lastIndex, srcStart) + "\' at position " + (srcEnd - srcStart).toString());\n';
1180
+ DESERIALIZE += indent + ' throw new Error("Unexpected key value pair in JSON object \'" + JSON.Util.ptrToStr(keyStart, keyEnd) + ":" + JSON.Util.ptrToStr(lastIndex, srcStart) + "\' at position " + (srcEnd - srcStart).toString());\n';
1130
1181
  DESERIALIZE += indent + " }\n";
1131
1182
  }
1132
1183
  else {
@@ -1146,31 +1197,16 @@ export class JSONTransform extends Visitor {
1146
1197
  }
1147
1198
  if (!STRICT || sortedMembers.boolean.length) {
1148
1199
  DESERIALIZE += mbElse + "if (code == 116) {\n";
1149
- DESERIALIZE +=
1150
- " if (load<u64>(srcStart) == 28429475166421108) {\n";
1200
+ DESERIALIZE += " if (load<u64>(srcStart) == 28429475166421108) {\n";
1151
1201
  DESERIALIZE += " srcStart += 8;\n";
1152
1202
  if (DEBUG > 1)
1153
- DESERIALIZE +=
1154
- ' console.log("Value (bool, ' +
1155
- ++id +
1156
- '): " + JSON.Util.ptrToStr(lastIndex, srcStart - 8));';
1203
+ DESERIALIZE += ' console.log("Value (bool, ' + ++id + '): " + JSON.Util.ptrToStr(lastIndex, srcStart - 8));';
1157
1204
  generateGroups(sortedMembers.boolean, (group) => {
1158
1205
  generateConsts(group);
1159
1206
  const first = group[0];
1160
1207
  const fName = first.alias || first.name;
1161
- DESERIALIZE +=
1162
- indent +
1163
- " if (" +
1164
- (first.generic ? "isBoolean<" + first.type + ">() && " : "") +
1165
- getComparison(fName) +
1166
- ") { // " +
1167
- fName +
1168
- "\n";
1169
- DESERIALIZE +=
1170
- indent +
1171
- " store<boolean>(changetype<usize>(out), true, offsetof<this>(" +
1172
- JSON.stringify(first.name) +
1173
- "));\n";
1208
+ DESERIALIZE += indent + " if (" + (first.generic ? "isBoolean<" + first.type + ">() && " : "") + getComparison(fName) + ") { // " + fName + "\n";
1209
+ DESERIALIZE += indent + " store<boolean>(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(first.name) + "));\n";
1174
1210
  DESERIALIZE += indent + " srcStart += 2;\n";
1175
1211
  DESERIALIZE += indent + " keyStart = 0;\n";
1176
1212
  DESERIALIZE += indent + " break;\n";
@@ -1178,19 +1214,8 @@ export class JSONTransform extends Visitor {
1178
1214
  for (let i = 1; i < group.length; i++) {
1179
1215
  const mem = group[i];
1180
1216
  const memName = mem.alias || mem.name;
1181
- DESERIALIZE +=
1182
- indent +
1183
- " else if (" +
1184
- (mem.generic ? "isBoolean<" + mem.type + ">() && " : "") +
1185
- getComparison(memName) +
1186
- ") { // " +
1187
- memName +
1188
- "\n";
1189
- DESERIALIZE +=
1190
- indent +
1191
- " store<boolean>(changetype<usize>(out), true, offsetof<this>(" +
1192
- JSON.stringify(mem.name) +
1193
- "));\n";
1217
+ DESERIALIZE += indent + " else if (" + (mem.generic ? "isBoolean<" + mem.type + ">() && " : "") + getComparison(memName) + ") { // " + memName + "\n";
1218
+ DESERIALIZE += indent + " store<boolean>(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
1194
1219
  DESERIALIZE += indent + " srcStart += 2;\n";
1195
1220
  DESERIALIZE += indent + " keyStart = 0;\n";
1196
1221
  DESERIALIZE += indent + " break;\n";
@@ -1198,9 +1223,7 @@ export class JSONTransform extends Visitor {
1198
1223
  }
1199
1224
  if (STRICT) {
1200
1225
  DESERIALIZE += " else {\n";
1201
- DESERIALIZE +=
1202
- indent +
1203
- ' throw new Error("Unexpected key value pair in JSON object \'" + JSON.Util.ptrToStr(keyStart, keyEnd) + ":" + JSON.Util.ptrToStr(lastIndex, srcStart) + "\' at position " + (srcEnd - srcStart).toString());\n';
1226
+ DESERIALIZE += indent + ' throw new Error("Unexpected key value pair in JSON object \'" + JSON.Util.ptrToStr(keyStart, keyEnd) + ":" + JSON.Util.ptrToStr(lastIndex, srcStart) + "\' at position " + (srcEnd - srcStart).toString());\n';
1204
1227
  DESERIALIZE += indent + " }\n";
1205
1228
  }
1206
1229
  else {
@@ -1213,37 +1236,21 @@ export class JSONTransform extends Visitor {
1213
1236
  }, "boolean");
1214
1237
  DESERIALIZE += " }";
1215
1238
  DESERIALIZE += " else {\n";
1216
- DESERIALIZE +=
1217
- " throw new Error(\"Expected to find 'true' but found '\" + JSON.Util.ptrToStr(lastIndex, srcStart) + \"' instead at position \" + (srcEnd - srcStart).toString());\n";
1239
+ DESERIALIZE += " throw new Error(\"Expected to find 'true' but found '\" + JSON.Util.ptrToStr(lastIndex, srcStart) + \"' instead at position \" + (srcEnd - srcStart).toString());\n";
1218
1240
  DESERIALIZE += " }";
1219
1241
  DESERIALIZE += "\n }";
1220
1242
  mbElse = " else ";
1221
1243
  DESERIALIZE += mbElse + "if (code == 102) {\n";
1222
- DESERIALIZE +=
1223
- " if (load<u64>(srcStart, 2) == 28429466576093281) {\n";
1244
+ DESERIALIZE += " {\n";
1224
1245
  DESERIALIZE += " srcStart += 10;\n";
1225
1246
  if (DEBUG > 1)
1226
- DESERIALIZE +=
1227
- ' console.log("Value (bool, ' +
1228
- ++id +
1229
- '): " + JSON.Util.ptrToStr(lastIndex, srcStart - 10));';
1247
+ DESERIALIZE += ' console.log("Value (bool, ' + ++id + '): " + JSON.Util.ptrToStr(lastIndex, srcStart - 10));';
1230
1248
  generateGroups(sortedMembers.boolean, (group) => {
1231
1249
  generateConsts(group);
1232
1250
  const first = group[0];
1233
1251
  const fName = first.alias || first.name;
1234
- DESERIALIZE +=
1235
- indent +
1236
- " if (" +
1237
- (first.generic ? "isBoolean<" + first.type + ">() && " : "") +
1238
- getComparison(fName) +
1239
- ") { // " +
1240
- fName +
1241
- "\n";
1242
- DESERIALIZE +=
1243
- indent +
1244
- " store<boolean>(changetype<usize>(out), false, offsetof<this>(" +
1245
- JSON.stringify(first.name) +
1246
- "));\n";
1252
+ DESERIALIZE += indent + " if (" + (first.generic ? "isBoolean<" + first.type + ">() && " : "") + getComparison(fName) + ") { // " + fName + "\n";
1253
+ DESERIALIZE += indent + " store<boolean>(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(first.name) + "));\n";
1247
1254
  DESERIALIZE += indent + " srcStart += 2;\n";
1248
1255
  DESERIALIZE += indent + " keyStart = 0;\n";
1249
1256
  DESERIALIZE += indent + " break;\n";
@@ -1251,19 +1258,8 @@ export class JSONTransform extends Visitor {
1251
1258
  for (let i = 1; i < group.length; i++) {
1252
1259
  const mem = group[i];
1253
1260
  const memName = mem.alias || mem.name;
1254
- DESERIALIZE +=
1255
- indent +
1256
- " else if (" +
1257
- (mem.generic ? "isBoolean<" + mem.type + ">() && " : "") +
1258
- getComparison(memName) +
1259
- ") { // " +
1260
- memName +
1261
- "\n";
1262
- DESERIALIZE +=
1263
- indent +
1264
- " store<boolean>(changetype<usize>(out), false, offsetof<this>(" +
1265
- JSON.stringify(mem.name) +
1266
- "));\n";
1261
+ DESERIALIZE += indent + " else if (" + (mem.generic ? "isBoolean<" + mem.type + ">() && " : "") + getComparison(memName) + ") { // " + memName + "\n";
1262
+ DESERIALIZE += indent + " store<boolean>(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
1267
1263
  DESERIALIZE += indent + " srcStart += 2;\n";
1268
1264
  DESERIALIZE += indent + " keyStart = 0;\n";
1269
1265
  DESERIALIZE += indent + " break;\n";
@@ -1271,9 +1267,7 @@ export class JSONTransform extends Visitor {
1271
1267
  }
1272
1268
  if (STRICT) {
1273
1269
  DESERIALIZE += " else {\n";
1274
- DESERIALIZE +=
1275
- indent +
1276
- ' throw new Error("Unexpected key value pair in JSON object \'" + JSON.Util.ptrToStr(keyStart, keyEnd) + ":" + JSON.Util.ptrToStr(lastIndex, srcStart) + "\' at position " + (srcEnd - srcStart).toString());\n';
1270
+ DESERIALIZE += indent + ' throw new Error("Unexpected key value pair in JSON object \'" + JSON.Util.ptrToStr(keyStart, keyEnd) + ":" + JSON.Util.ptrToStr(lastIndex, srcStart) + "\' at position " + (srcEnd - srcStart).toString());\n';
1277
1271
  DESERIALIZE += indent + " }\n";
1278
1272
  }
1279
1273
  else {
@@ -1285,40 +1279,21 @@ export class JSONTransform extends Visitor {
1285
1279
  }
1286
1280
  }, "boolean");
1287
1281
  DESERIALIZE += " }";
1288
- DESERIALIZE += " else {\n";
1289
- DESERIALIZE +=
1290
- " throw new Error(\"Expected to find 'false' but found '\" + JSON.Util.ptrToStr(lastIndex, srcStart) + \"' instead at position \" + (srcEnd - srcStart).toString());\n";
1291
- DESERIALIZE += " }";
1292
1282
  DESERIALIZE += "\n }";
1293
1283
  mbElse = " else ";
1294
1284
  }
1295
1285
  if (!STRICT || sortedMembers.null.length) {
1296
1286
  DESERIALIZE += mbElse + "if (code == 110) {\n";
1297
- DESERIALIZE +=
1298
- " if (load<u64>(srcStart) == 30399761348886638) {\n";
1287
+ DESERIALIZE += " if (load<u64>(srcStart) == 30399761348886638) {\n";
1299
1288
  DESERIALIZE += " srcStart += 8;\n";
1300
1289
  if (DEBUG > 1)
1301
- DESERIALIZE +=
1302
- ' console.log("Value (null, ' +
1303
- ++id +
1304
- '): " + JSON.Util.ptrToStr(lastIndex, srcStart - 8));';
1290
+ DESERIALIZE += ' console.log("Value (null, ' + ++id + '): " + JSON.Util.ptrToStr(lastIndex, srcStart - 8));';
1305
1291
  generateGroups(sortedMembers.null, (group) => {
1306
1292
  generateConsts(group);
1307
1293
  const first = group[0];
1308
1294
  const fName = first.alias || first.name;
1309
- DESERIALIZE +=
1310
- indent +
1311
- " if (" +
1312
- (first.generic ? "isNullable<" + first.type + ">() && " : "") +
1313
- getComparison(fName) +
1314
- ") { // " +
1315
- fName +
1316
- "\n";
1317
- DESERIALIZE +=
1318
- indent +
1319
- " store<usize>(changetype<usize>(out), 0, offsetof<this>(" +
1320
- JSON.stringify(first.name) +
1321
- "));\n";
1295
+ DESERIALIZE += indent + " if (" + (first.generic ? "isNullable<" + first.type + ">() && " : "") + getComparison(fName) + ") { // " + fName + "\n";
1296
+ DESERIALIZE += indent + " store<usize>(changetype<usize>(out), 0, offsetof<this>(" + JSON.stringify(first.name) + "));\n";
1322
1297
  DESERIALIZE += indent + " srcStart += 2;\n";
1323
1298
  DESERIALIZE += indent + " keyStart = 0;\n";
1324
1299
  DESERIALIZE += indent + " break;\n";
@@ -1326,19 +1301,8 @@ export class JSONTransform extends Visitor {
1326
1301
  for (let i = 1; i < group.length; i++) {
1327
1302
  const mem = group[i];
1328
1303
  const memName = mem.alias || mem.name;
1329
- DESERIALIZE +=
1330
- indent +
1331
- " else if (" +
1332
- (mem.generic ? "isNullable<" + mem.type + ">() && " : "") +
1333
- getComparison(memName) +
1334
- ") { // " +
1335
- memName +
1336
- "\n";
1337
- DESERIALIZE +=
1338
- indent +
1339
- " store<usize>(changetype<usize>(out), 0, offsetof<this>(" +
1340
- JSON.stringify(mem.name) +
1341
- "));\n";
1304
+ DESERIALIZE += indent + " else if (" + (mem.generic ? "isNullable<" + mem.type + ">() && " : "") + getComparison(memName) + ") { // " + memName + "\n";
1305
+ DESERIALIZE += indent + " store<usize>(changetype<usize>(out), 0, offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
1342
1306
  DESERIALIZE += indent + " srcStart += 2;\n";
1343
1307
  DESERIALIZE += indent + " keyStart = 0;\n";
1344
1308
  DESERIALIZE += indent + " break;\n";
@@ -1346,9 +1310,7 @@ export class JSONTransform extends Visitor {
1346
1310
  }
1347
1311
  if (STRICT) {
1348
1312
  DESERIALIZE += " else {\n";
1349
- DESERIALIZE +=
1350
- indent +
1351
- ' throw new Error("Unexpected key value pair in JSON object \'" + JSON.Util.ptrToStr(keyStart, keyEnd) + ":" + JSON.Util.ptrToStr(lastIndex, srcStart) + "\' at position " + (srcEnd - srcStart).toString());\n';
1313
+ DESERIALIZE += indent + ' throw new Error("Unexpected key value pair in JSON object \'" + JSON.Util.ptrToStr(keyStart, keyEnd) + ":" + JSON.Util.ptrToStr(lastIndex, srcStart) + "\' at position " + (srcEnd - srcStart).toString());\n';
1352
1314
  DESERIALIZE += indent + " }\n";
1353
1315
  }
1354
1316
  else {
@@ -1371,58 +1333,62 @@ export class JSONTransform extends Visitor {
1371
1333
  indentDec();
1372
1334
  DESERIALIZE += ` }\n`;
1373
1335
  indentDec();
1374
- DESERIALIZE += ` return out;\n}\n`;
1336
+ DESERIALIZE += ` return srcStart;\n}\n`;
1375
1337
  indent = " ";
1376
1338
  this.schema.byteSize += 2;
1377
1339
  SERIALIZE += indent + "store<u16>(bs.offset, 125, 0); // }\n";
1378
1340
  SERIALIZE += indent + "bs.offset += 2;\n";
1379
1341
  SERIALIZE += "}";
1380
- SERIALIZE =
1381
- SERIALIZE.slice(0, 32) +
1382
- indent +
1383
- "bs.proposeSize(" +
1384
- this.schema.byteSize +
1385
- ");\n" +
1386
- SERIALIZE.slice(32);
1387
- INITIALIZE += " return this;\n";
1388
- INITIALIZE += "}";
1342
+ SERIALIZE = SERIALIZE.slice(0, 32) + indent + "bs.proposeSize(" + this.schema.byteSize + ");\n" + SERIALIZE.slice(32);
1343
+ if (!useFastPath) {
1344
+ INITIALIZE += " return this;\n";
1345
+ INITIALIZE += "}";
1346
+ }
1389
1347
  if (DEBUG > 0) {
1390
1348
  console.log(SERIALIZE_CUSTOM || SERIALIZE);
1391
- console.log(INITIALIZE);
1349
+ if (!useFastPath)
1350
+ console.log(INITIALIZE);
1392
1351
  console.log(DESERIALIZE_CUSTOM || DESERIALIZE);
1393
1352
  }
1353
+ const DESERIALIZE_DIRECT = useFastPath ? DESERIALIZE_FAST.replace("@inline __DESERIALIZE_FAST<__JSON_T>(srcStart: usize, srcEnd: usize, out: __JSON_T): usize {", "@inline __DESERIALIZE<__JSON_T>(srcStart: usize, srcEnd: usize, out: __JSON_T): usize {") : DESERIALIZE.replace("__DESERIALIZE_SLOW<__JSON_T>", "__DESERIALIZE<__JSON_T>");
1394
1354
  const SERIALIZE_METHOD = SimpleParser.parseClassMember(SERIALIZE_CUSTOM || SERIALIZE, node);
1395
- const INITIALIZE_METHOD = SimpleParser.parseClassMember(INITIALIZE, node);
1396
- const DESERIALIZE_METHOD = SimpleParser.parseClassMember(DESERIALIZE_CUSTOM || DESERIALIZE, node);
1355
+ const INITIALIZE_METHOD = !useFastPath ? SimpleParser.parseClassMember(INITIALIZE, node) : null;
1356
+ const DESERIALIZE_CUSTOM_METHOD = DESERIALIZE_CUSTOM ? SimpleParser.parseClassMember(DESERIALIZE_CUSTOM, node) : null;
1357
+ const DESERIALIZE_METHOD = DESERIALIZE_CUSTOM ? null : SimpleParser.parseClassMember(DESERIALIZE_DIRECT, node);
1358
+ const DESERIALIZE_FAST_METHOD = useFastPath ? SimpleParser.parseClassMember(DESERIALIZE_FAST, node) : null;
1397
1359
  if (!node.members.find((v) => v.name.text == "__SERIALIZE"))
1398
1360
  node.members.push(SERIALIZE_METHOD);
1399
- if (!node.members.find((v) => v.name.text == "__INITIALIZE"))
1361
+ if (!useFastPath && INITIALIZE_METHOD && !node.members.find((v) => v.name.text == "__INITIALIZE"))
1400
1362
  node.members.push(INITIALIZE_METHOD);
1401
- if (!node.members.find((v) => v.name.text == "__DESERIALIZE"))
1363
+ if (DESERIALIZE_CUSTOM_METHOD && !node.members.find((v) => v.name.text == "__DESERIALIZE_CUSTOM"))
1364
+ node.members.push(DESERIALIZE_CUSTOM_METHOD);
1365
+ if (DESERIALIZE_METHOD && !node.members.find((v) => v.name.text == "__DESERIALIZE"))
1402
1366
  node.members.push(DESERIALIZE_METHOD);
1367
+ if (!DESERIALIZE_CUSTOM && useFastPath && DESERIALIZE_FAST_METHOD && !node.members.find((v) => v.name.text == "__DESERIALIZE_FAST"))
1368
+ node.members.push(DESERIALIZE_FAST_METHOD);
1403
1369
  super.visitClassDeclaration(node);
1404
1370
  }
1405
1371
  getSchema(name) {
1406
1372
  name = stripNull(name);
1407
- return (this.schemas
1408
- .get(this.schema.node.range.source.internalPath)
1409
- .find((s) => s.name == name) || null);
1373
+ return this.schemas.get(this.schema.node.range.source.internalPath).find((s) => s.name == name) || null;
1410
1374
  }
1411
1375
  generateEmptyMethods(node) {
1412
1376
  const SERIALIZE_EMPTY = "@inline __SERIALIZE(ptr: usize): void {\n bs.proposeSize(4);\n store<u32>(bs.offset, 8192123);\n bs.offset += 4;\n}";
1413
1377
  const INITIALIZE_EMPTY = "@inline __INITIALIZE(): this {\n return this;\n}";
1414
- const DESERIALIZE_EMPTY = "@inline __DESERIALIZE<__JSON_T>(srcStart: usize, srcEnd: usize, out: __JSON_T): __JSON_T {\n return out;\n}";
1378
+ const DESERIALIZE_EMPTY = "@inline __DESERIALIZE<__JSON_T>(srcStart: usize, srcEnd: usize, out: __JSON_T): usize {\n return srcEnd;\n}";
1379
+ const useFastPath = USE_FAST_PATH && getCodegenMode(this.program) !== JSONMode.NAIVE;
1415
1380
  if (DEBUG > 0) {
1416
1381
  console.log(SERIALIZE_EMPTY);
1417
- console.log(INITIALIZE_EMPTY);
1382
+ if (!useFastPath)
1383
+ console.log(INITIALIZE_EMPTY);
1418
1384
  console.log(DESERIALIZE_EMPTY);
1419
1385
  }
1420
1386
  const SERIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(SERIALIZE_EMPTY, node);
1421
- const INITIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(INITIALIZE_EMPTY, node);
1387
+ const INITIALIZE_METHOD_EMPTY = !useFastPath ? SimpleParser.parseClassMember(INITIALIZE_EMPTY, node) : null;
1422
1388
  const DESERIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(DESERIALIZE_EMPTY, node);
1423
1389
  if (!node.members.find((v) => v.name.text == "__SERIALIZE"))
1424
1390
  node.members.push(SERIALIZE_METHOD_EMPTY);
1425
- if (!node.members.find((v) => v.name.text == "__INITIALIZE"))
1391
+ if (!useFastPath && INITIALIZE_METHOD_EMPTY && !node.members.find((v) => v.name.text == "__INITIALIZE"))
1426
1392
  node.members.push(INITIALIZE_METHOD_EMPTY);
1427
1393
  if (!node.members.find((v) => v.name.text == "__DESERIALIZE"))
1428
1394
  node.members.push(DESERIALIZE_METHOD_EMPTY);
@@ -1439,56 +1405,84 @@ export class JSONTransform extends Visitor {
1439
1405
  this.baseCWD = this.baseCWD.replaceAll("/", path.sep);
1440
1406
  const baseDir = path.resolve(fileURLToPath(import.meta.url), "..", "..", "..");
1441
1407
  let fromPath = node.range.source.normalizedPath.replaceAll("/", path.sep);
1442
- const isLib = path.dirname(baseDir).endsWith("node_modules");
1443
- if (!isLib &&
1444
- !this.parser.sources.some((s) => s.normalizedPath.startsWith("assembly/index"))) {
1445
- const newPath = path.join(baseDir, "assembly", "index.ts");
1446
- this.parser.parseFile(readFileSync(newPath).toString(), newPath, false);
1447
- }
1448
- else if (isLib &&
1449
- !this.parser.sources.some((s) => s.normalizedPath.startsWith("~lib/json-as/assembly/index"))) {
1450
- const newPath = "~lib/json-as/assembly/index.ts";
1451
- this.parser.parseFile(readFileSync(path.join(baseDir, "assembly", "index.ts")).toString(), newPath, false);
1452
- }
1453
- fromPath = fromPath.startsWith("~lib")
1454
- ? fromPath.slice(5)
1455
- : path.join(this.baseCWD, fromPath);
1408
+ fromPath = fromPath.startsWith("~lib") ? fromPath.slice(5) : path.join(this.baseCWD, fromPath);
1456
1409
  const bsImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "bs" || d.name.text == "bs"));
1457
1410
  const jsonImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "JSON" || d.name.text == "JSON"));
1458
- let baseRel = path.posix.join(...path
1459
- .relative(path.dirname(fromPath), path.join(baseDir))
1460
- .split(path.sep));
1411
+ const atoiImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "atoi" || d.name.text == "atoi"));
1412
+ const deserializeIntegerFieldImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "deserializeIntegerField" || d.name.text == "deserializeIntegerField"));
1413
+ const deserializeUnsignedFieldImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "deserializeUnsignedField" || d.name.text == "deserializeUnsignedField"));
1414
+ const deserializeFloatFieldImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "deserializeFloatField" || d.name.text == "deserializeFloatField"));
1415
+ const deserializeArrayField_SWARImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "deserializeArrayField_SWAR" || d.name.text == "deserializeArrayField_SWAR"));
1416
+ const deserializeStringFieldSWARImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "deserializeStringField_SWAR" || d.name.text == "deserializeStringField_SWAR"));
1417
+ const deserializeStringFieldSIMDImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "deserializeStringField_SIMD" || d.name.text == "deserializeStringField_SIMD"));
1418
+ const sourceText = readFileSync(fromPath).toString();
1419
+ const hasLocalDeserializeIntegerField = /\bdeserializeIntegerField\b/.test(sourceText);
1420
+ const hasLocalDeserializeUnsignedField = /\bdeserializeUnsignedField\b/.test(sourceText);
1421
+ const hasLocalDeserializeFloatField = /\bdeserializeFloatField\b/.test(sourceText);
1422
+ const hasLocaldeserializeArrayField_SWAR = /\bdeserializeArrayField_SWAR\b/.test(sourceText);
1423
+ const hasLocalDeserializeStringFieldSWAR = /\bdeserializeStringField_SWAR\b/.test(sourceText);
1424
+ const hasLocalDeserializeStringFieldSIMD = /\bdeserializeStringField_SIMD\b/.test(sourceText);
1425
+ let baseRel = path.posix.join(...path.relative(path.dirname(fromPath), path.join(baseDir)).split(path.sep));
1461
1426
  if (baseRel.endsWith("json-as")) {
1462
1427
  baseRel = "json-as" + baseRel.slice(baseRel.indexOf("json-as") + 7);
1463
1428
  }
1464
- else if (!baseRel.startsWith(".") &&
1465
- !baseRel.startsWith("/") &&
1466
- !baseRel.startsWith("json-as")) {
1429
+ else if (!baseRel.startsWith(".") && !baseRel.startsWith("/") && !baseRel.startsWith("json-as")) {
1467
1430
  baseRel = "./" + baseRel;
1468
1431
  }
1469
1432
  if (!bsImport) {
1470
- const replaceNode = Node.createImportStatement([
1471
- Node.createImportDeclaration(Node.createIdentifierExpression("bs", node.range, false), null, node.range),
1472
- ], Node.createStringLiteralExpression(path.posix.join(baseRel, "lib", "as-bs"), node.range), node.range);
1433
+ const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("bs", node.range, false), null, node.range)], Node.createStringLiteralExpression(path.posix.join(baseRel, "lib", "as-bs"), node.range), node.range);
1473
1434
  node.range.source.statements.unshift(replaceNode);
1474
1435
  if (DEBUG > 0)
1475
- console.log("Added import: " +
1476
- toString(replaceNode) +
1477
- " to " +
1478
- node.range.source.normalizedPath +
1479
- "\n");
1436
+ console.log("Added import: " + toString(replaceNode) + " to " + node.range.source.normalizedPath + "\n");
1480
1437
  }
1481
1438
  if (!jsonImport) {
1482
- const replaceNode = Node.createImportStatement([
1483
- Node.createImportDeclaration(Node.createIdentifierExpression("JSON", node.range, false), null, node.range),
1484
- ], Node.createStringLiteralExpression(path.posix.join(baseRel, "assembly", "index"), node.range), node.range);
1439
+ const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("JSON", node.range, false), null, node.range)], Node.createStringLiteralExpression(path.posix.join(baseRel, "assembly", "index"), node.range), node.range);
1440
+ node.range.source.statements.unshift(replaceNode);
1441
+ if (DEBUG > 0)
1442
+ console.log("Added import: " + toString(replaceNode) + " to " + node.range.source.normalizedPath + "\n");
1443
+ }
1444
+ if (!atoiImport) {
1445
+ const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("atoi", node.range, false), null, node.range)], Node.createStringLiteralExpression(path.posix.join(baseRel, "assembly", "util", "atoi"), node.range), node.range);
1446
+ node.range.source.statements.unshift(replaceNode);
1447
+ if (DEBUG > 0)
1448
+ console.log("Added import: " + toString(replaceNode) + " to " + node.range.source.normalizedPath + "\n");
1449
+ }
1450
+ if (!deserializeIntegerFieldImport && !hasLocalDeserializeIntegerField) {
1451
+ const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("deserializeIntegerField", node.range, false), null, node.range)], Node.createStringLiteralExpression(path.posix.join(baseRel, "assembly", "deserialize", "integer"), node.range), node.range);
1452
+ node.range.source.statements.unshift(replaceNode);
1453
+ if (DEBUG > 0)
1454
+ console.log("Added import: " + toString(replaceNode) + " to " + node.range.source.normalizedPath + "\n");
1455
+ }
1456
+ if (!deserializeUnsignedFieldImport && !hasLocalDeserializeUnsignedField) {
1457
+ const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("deserializeUnsignedField", node.range, false), null, node.range)], Node.createStringLiteralExpression(path.posix.join(baseRel, "assembly", "deserialize", "unsigned"), node.range), node.range);
1458
+ node.range.source.statements.unshift(replaceNode);
1459
+ if (DEBUG > 0)
1460
+ console.log("Added import: " + toString(replaceNode) + " to " + node.range.source.normalizedPath + "\n");
1461
+ }
1462
+ if (!deserializeFloatFieldImport && !hasLocalDeserializeFloatField) {
1463
+ const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("deserializeFloatField", node.range, false), null, node.range)], Node.createStringLiteralExpression(path.posix.join(baseRel, "assembly", "deserialize", "float"), node.range), node.range);
1464
+ node.range.source.statements.unshift(replaceNode);
1465
+ if (DEBUG > 0)
1466
+ console.log("Added import: " + toString(replaceNode) + " to " + node.range.source.normalizedPath + "\n");
1467
+ }
1468
+ if (!deserializeArrayField_SWARImport && !hasLocaldeserializeArrayField_SWAR) {
1469
+ const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("deserializeArrayField_SWAR", node.range, false), null, node.range)], Node.createStringLiteralExpression(path.posix.join(baseRel, "assembly", "deserialize", "simple", "array"), node.range), node.range);
1470
+ node.range.source.statements.unshift(replaceNode);
1471
+ if (DEBUG > 0)
1472
+ console.log("Added import: " + toString(replaceNode) + " to " + node.range.source.normalizedPath + "\n");
1473
+ }
1474
+ const codegenMode = getCodegenMode(this.program);
1475
+ if (codegenMode !== JSONMode.SIMD && !deserializeStringFieldSWARImport && !hasLocalDeserializeStringFieldSWAR) {
1476
+ const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("deserializeStringField_SWAR", node.range, false), null, node.range)], Node.createStringLiteralExpression(path.posix.join(baseRel, "assembly", "deserialize", "swar", "string"), node.range), node.range);
1485
1477
  node.range.source.statements.unshift(replaceNode);
1486
1478
  if (DEBUG > 0)
1487
- console.log("Added import: " +
1488
- toString(replaceNode) +
1489
- " to " +
1490
- node.range.source.normalizedPath +
1491
- "\n");
1479
+ console.log("Added import: " + toString(replaceNode) + " to " + node.range.source.normalizedPath + "\n");
1480
+ }
1481
+ if (codegenMode === JSONMode.SIMD && !deserializeStringFieldSIMDImport && !hasLocalDeserializeStringFieldSIMD) {
1482
+ const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("deserializeStringField_SIMD", node.range, false), null, node.range)], Node.createStringLiteralExpression(path.posix.join(baseRel, "assembly", "deserialize", "simd", "string"), node.range), node.range);
1483
+ node.range.source.statements.unshift(replaceNode);
1484
+ if (DEBUG > 0)
1485
+ console.log("Added import: " + toString(replaceNode) + " to " + node.range.source.normalizedPath + "\n");
1492
1486
  }
1493
1487
  }
1494
1488
  getStores(data, simd = false) {
@@ -1499,41 +1493,21 @@ export class JSONTransform extends Visitor {
1499
1493
  if (size == "v128" && simd) {
1500
1494
  const index = this.simdStatements.findIndex((v) => v.includes(num));
1501
1495
  const name = "SIMD_" + (index == -1 ? this.simdStatements.length : index);
1502
- if (index && !this.simdStatements.includes(`const ${name} = ${num};`))
1496
+ if (index == -1)
1503
1497
  this.simdStatements.push(`const ${name} = ${num};`);
1504
- out.push("store<v128>(bs.offset, " +
1505
- name +
1506
- ", " +
1507
- offset +
1508
- "); // " +
1509
- data.slice(offset >> 1, (offset >> 1) + 8));
1498
+ out.push("store<v128>(bs.offset, " + name + ", " + offset + "); // " + data.slice(offset >> 1, (offset >> 1) + 8));
1510
1499
  offset += 16;
1511
1500
  }
1512
1501
  if (size == "u64") {
1513
- out.push("store<u64>(bs.offset, " +
1514
- num +
1515
- ", " +
1516
- offset +
1517
- "); // " +
1518
- data.slice(offset >> 1, (offset >> 1) + 4));
1502
+ out.push("store<u64>(bs.offset, " + num + ", " + offset + "); // " + data.slice(offset >> 1, (offset >> 1) + 4));
1519
1503
  offset += 8;
1520
1504
  }
1521
1505
  else if (size == "u32") {
1522
- out.push("store<u32>(bs.offset, " +
1523
- num +
1524
- ", " +
1525
- offset +
1526
- "); // " +
1527
- data.slice(offset >> 1, (offset >> 1) + 2));
1506
+ out.push("store<u32>(bs.offset, " + num + ", " + offset + "); // " + data.slice(offset >> 1, (offset >> 1) + 2));
1528
1507
  offset += 4;
1529
1508
  }
1530
1509
  else if (size == "u16") {
1531
- out.push("store<u16>(bs.offset, " +
1532
- num +
1533
- ", " +
1534
- offset +
1535
- "); // " +
1536
- data.slice(offset >> 1, (offset >> 1) + 1));
1510
+ out.push("store<u16>(bs.offset, " + num + ", " + offset + "); // " + data.slice(offset >> 1, (offset >> 1) + 1));
1537
1511
  offset += 2;
1538
1512
  }
1539
1513
  }
@@ -1541,31 +1515,7 @@ export class JSONTransform extends Visitor {
1541
1515
  return out;
1542
1516
  }
1543
1517
  isValidType(type, node) {
1544
- const validTypes = [
1545
- "string",
1546
- "u8",
1547
- "i8",
1548
- "u16",
1549
- "i16",
1550
- "u32",
1551
- "i32",
1552
- "u64",
1553
- "i64",
1554
- "f32",
1555
- "f64",
1556
- "bool",
1557
- "boolean",
1558
- "Date",
1559
- "JSON.Value",
1560
- "JSON.Obj",
1561
- "JSON.Raw",
1562
- "Value",
1563
- "Obj",
1564
- "Raw",
1565
- ...this.schemas
1566
- .get(this.schema.node.range.source.internalPath)
1567
- .map((v) => v.name),
1568
- ];
1518
+ const validTypes = ["string", "u8", "i8", "u16", "i16", "u32", "i32", "u64", "i64", "f32", "f64", "bool", "boolean", "Date", "JSON.Value", "JSON.Obj", "JSON.Raw", "Value", "Obj", "Raw", ...this.schemas.get(this.schema.node.range.source.internalPath).map((v) => v.name)];
1569
1519
  const baseTypes = ["Array", "StaticArray", "Map", "Set", "JSON.Box", "Box"];
1570
1520
  if (node && node.isGeneric && node.typeParameters)
1571
1521
  validTypes.push(...node.typeParameters.map((v) => v.name.text));
@@ -1575,8 +1525,7 @@ export class JSONTransform extends Visitor {
1575
1525
  return this.isValidType(type.slice(0, type.length - 7), node);
1576
1526
  }
1577
1527
  if (type.includes("<"))
1578
- return (baseTypes.includes(type.slice(0, type.indexOf("<"))) &&
1579
- this.isValidType(type.slice(type.indexOf("<") + 1, type.lastIndexOf(">")), node));
1528
+ return baseTypes.includes(type.slice(0, type.indexOf("<"))) && this.isValidType(type.slice(type.indexOf("<") + 1, type.lastIndexOf(">")), node);
1580
1529
  if (validTypes.includes(type))
1581
1530
  return true;
1582
1531
  return false;
@@ -1589,6 +1538,23 @@ var JSONMode;
1589
1538
  JSONMode[JSONMode["NAIVE"] = 2] = "NAIVE";
1590
1539
  })(JSONMode || (JSONMode = {}));
1591
1540
  let MODE = JSONMode.SWAR;
1541
+ function getCodegenMode(program) {
1542
+ let mode = program.options.hasFeature(16) ? JSONMode.SIMD : JSONMode.SWAR;
1543
+ if (process.env["JSON_MODE"]) {
1544
+ switch (process.env["JSON_MODE"].toLowerCase().trim()) {
1545
+ case "simd":
1546
+ mode = JSONMode.SIMD;
1547
+ break;
1548
+ case "swar":
1549
+ mode = JSONMode.SWAR;
1550
+ break;
1551
+ case "naive":
1552
+ mode = JSONMode.NAIVE;
1553
+ break;
1554
+ }
1555
+ }
1556
+ return mode;
1557
+ }
1592
1558
  export default class Transformer extends Transform {
1593
1559
  afterInitialize(program) {
1594
1560
  if (program.options.hasFeature(16))
@@ -1610,24 +1576,16 @@ export default class Transformer extends Transform {
1610
1576
  }
1611
1577
  }
1612
1578
  program.registerConstantInteger("JSON_MODE", Type.i32, i64_new(MODE));
1613
- if (process.env["JSON_CACHE"]?.trim().toLowerCase() === "true" ||
1614
- process.env["JSON_CACHE"]?.trim().toLowerCase() === "1") {
1579
+ if (process.env["JSON_CACHE"]?.trim().toLowerCase() === "true" || process.env["JSON_CACHE"]?.trim().toLowerCase() === "1") {
1615
1580
  program.registerConstantInteger("JSON_CACHE", Type.bool, i64_one);
1616
1581
  }
1617
1582
  }
1618
1583
  afterParse(parser) {
1619
- const transformer = JSONTransform.SN;
1620
- transformer.schemas = new Map();
1621
- transformer.sources = new SourceSet();
1622
- transformer.visitedClasses = new Set();
1623
- transformer.simdStatements = [];
1584
+ const transformer = new JSONTransform();
1624
1585
  const sources = parser.sources
1625
1586
  .filter((source) => {
1626
1587
  const p = source.internalPath;
1627
- if (p.startsWith("~lib/rt") ||
1628
- p.startsWith("~lib/performance") ||
1629
- p.startsWith("~lib/wasi_") ||
1630
- p.startsWith("~lib/shared/")) {
1588
+ if (p.startsWith("~lib/rt") || p.startsWith("~lib/performance") || p.startsWith("~lib/wasi_") || p.startsWith("~lib/shared/")) {
1631
1589
  return false;
1632
1590
  }
1633
1591
  return !isStdlib(source);
@@ -1688,22 +1646,16 @@ function sortMembers(members) {
1688
1646
  });
1689
1647
  }
1690
1648
  function toU16(data, offset = 0) {
1691
- return data.charCodeAt(offset + 0).toString();
1649
+ return data.charCodeAt(offset + 0);
1692
1650
  }
1693
1651
  function toU32(data, offset = 0) {
1694
- return ((data.charCodeAt(offset + 1) << 16) |
1695
- data.charCodeAt(offset + 0)).toString();
1652
+ return (data.charCodeAt(offset + 1) << 16) | data.charCodeAt(offset + 0);
1696
1653
  }
1697
1654
  function toU48(data, offset = 0) {
1698
- return ((BigInt(data.charCodeAt(offset + 2)) << 32n) |
1699
- (BigInt(data.charCodeAt(offset + 1)) << 16n) |
1700
- BigInt(data.charCodeAt(offset + 0))).toString();
1655
+ return (BigInt(data.charCodeAt(offset + 2)) << 32n) | (BigInt(data.charCodeAt(offset + 1)) << 16n) | BigInt(data.charCodeAt(offset + 0));
1701
1656
  }
1702
1657
  function toU64(data, offset = 0) {
1703
- return ((BigInt(data.charCodeAt(offset + 3)) << 48n) |
1704
- (BigInt(data.charCodeAt(offset + 2)) << 32n) |
1705
- (BigInt(data.charCodeAt(offset + 1)) << 16n) |
1706
- BigInt(data.charCodeAt(offset + 0))).toString();
1658
+ return (BigInt(data.charCodeAt(offset + 3)) << 48n) | (BigInt(data.charCodeAt(offset + 2)) << 32n) | (BigInt(data.charCodeAt(offset + 1)) << 16n) | BigInt(data.charCodeAt(offset + 0));
1707
1659
  }
1708
1660
  function toMemCDecl(n, indent) {
1709
1661
  let out = "";
@@ -1746,34 +1698,12 @@ function strToNum(data, simd = false, offset = 0) {
1746
1698
  const out = [];
1747
1699
  let n = data.length;
1748
1700
  while (n >= 8 && simd) {
1749
- out.push([
1750
- "v128",
1751
- "i16x8(" +
1752
- data.charCodeAt(offset + 0) +
1753
- ", " +
1754
- data.charCodeAt(offset + 1) +
1755
- ", " +
1756
- data.charCodeAt(offset + 2) +
1757
- ", " +
1758
- data.charCodeAt(offset + 3) +
1759
- ", " +
1760
- data.charCodeAt(offset + 4) +
1761
- ", " +
1762
- data.charCodeAt(offset + 5) +
1763
- ", " +
1764
- data.charCodeAt(offset + 6) +
1765
- ", " +
1766
- data.charCodeAt(offset + 7) +
1767
- ")",
1768
- ]);
1701
+ out.push(["v128", "i16x8(" + data.charCodeAt(offset + 0) + ", " + data.charCodeAt(offset + 1) + ", " + data.charCodeAt(offset + 2) + ", " + data.charCodeAt(offset + 3) + ", " + data.charCodeAt(offset + 4) + ", " + data.charCodeAt(offset + 5) + ", " + data.charCodeAt(offset + 6) + ", " + data.charCodeAt(offset + 7) + ")"]);
1769
1702
  offset += 8;
1770
1703
  n -= 8;
1771
1704
  }
1772
1705
  while (n >= 4) {
1773
- const value = (BigInt(data.charCodeAt(offset + 3)) << 48n) |
1774
- (BigInt(data.charCodeAt(offset + 2)) << 32n) |
1775
- (BigInt(data.charCodeAt(offset + 1)) << 16n) |
1776
- BigInt(data.charCodeAt(offset + 0));
1706
+ const value = (BigInt(data.charCodeAt(offset + 3)) << 48n) | (BigInt(data.charCodeAt(offset + 2)) << 32n) | (BigInt(data.charCodeAt(offset + 1)) << 16n) | BigInt(data.charCodeAt(offset + 0));
1777
1707
  out.push(["u64", value.toString()]);
1778
1708
  offset += 4;
1779
1709
  n -= 4;
@@ -1824,20 +1754,7 @@ function sizeof(type) {
1824
1754
  return 0;
1825
1755
  }
1826
1756
  function isPrimitive(type) {
1827
- const primitiveTypes = [
1828
- "u8",
1829
- "u16",
1830
- "u32",
1831
- "u64",
1832
- "i8",
1833
- "i16",
1834
- "i32",
1835
- "i64",
1836
- "f32",
1837
- "f64",
1838
- "bool",
1839
- "boolean",
1840
- ];
1757
+ const primitiveTypes = ["u8", "u16", "u32", "u64", "i8", "i16", "i32", "i64", "f32", "f64", "bool", "boolean"];
1841
1758
  return primitiveTypes.some((v) => type.startsWith(v));
1842
1759
  }
1843
1760
  function isBoolean(type) {
@@ -1847,12 +1764,10 @@ function isString(type) {
1847
1764
  return stripNull(type) == "string" || stripNull(type) == "String";
1848
1765
  }
1849
1766
  function isArray(type) {
1850
- return (type.startsWith("Array<") ||
1851
- type.startsWith("Set<") ||
1852
- type.startsWith("StaticArray<"));
1767
+ return type.startsWith("Array<") || type.startsWith("Set<") || type.startsWith("StaticArray<");
1853
1768
  }
1854
1769
  function isEnum(type, source, parser) {
1855
- return (source.getEnum(type) != null || source.getImportedEnum(type, parser) != null);
1770
+ return source.getEnum(type) != null || source.getImportedEnum(type, parser) != null;
1856
1771
  }
1857
1772
  export function stripNull(type) {
1858
1773
  if (type.endsWith(" | null")) {