json-as 1.0.7 → 1.0.9

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 (42) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +18 -2
  3. package/asconfig.json +1 -2
  4. package/assembly/__benches__/abc.bench.ts +5 -5
  5. package/assembly/__benches__/large.bench.ts +5 -51
  6. package/assembly/{custom → __benches__/lib}/bench.ts +4 -0
  7. package/assembly/__benches__/medium.bench.ts +3 -3
  8. package/assembly/__benches__/small.bench.ts +1 -1
  9. package/assembly/__benches__/vec3.bench.ts +3 -49
  10. package/assembly/__tests__/custom.spec.ts +4 -3
  11. package/assembly/__tests__/hierarchy.spec.ts +55 -0
  12. package/assembly/__tests__/lib/index.ts +1 -0
  13. package/assembly/custom/util.ts +0 -4
  14. package/assembly/deserialize/simple/array/box.ts +45 -0
  15. package/assembly/deserialize/simple/array/object.ts +28 -0
  16. package/assembly/deserialize/simple/array.ts +8 -0
  17. package/assembly/index.ts +39 -41
  18. package/assembly/serialize/simd/string.ts +12 -12
  19. package/assembly/test.ts +46 -133
  20. package/assembly/util/idofd.ts +6 -0
  21. package/bench/abc.bench.ts +1 -1
  22. package/bench/large.bench.ts +3 -3
  23. package/bench/lib/bench.ts +12 -0
  24. package/bench/medium.bench.ts +1 -1
  25. package/bench/runners/assemblyscript.js +28 -0
  26. package/bench/small.bench.ts +1 -1
  27. package/bench/tsconfig.json +12 -0
  28. package/bench/vec3.bench.ts +1 -1
  29. package/package.json +3 -4
  30. package/run-bench.as.sh +44 -18
  31. package/run-bench.js.sh +32 -6
  32. package/run-tests.sh +1 -1
  33. package/transform/lib/index.js +381 -122
  34. package/transform/lib/index.js.map +1 -1
  35. package/transform/lib/types.js +1 -0
  36. package/transform/lib/types.js.map +1 -1
  37. package/transform/src/index.ts +430 -117
  38. package/transform/src/types.ts +1 -0
  39. package/assembly/__benches__/lib/index.ts +0 -26
  40. package/assembly/custom/memory.ts +0 -25
  41. package/assembly/custom/sink.ts +0 -231
  42. package/assembly/custom/types.ts +0 -5
@@ -7,7 +7,9 @@ import { fileURLToPath } from "url";
7
7
  import { Property, PropertyFlags, Schema } from "./types.js";
8
8
  import { getClasses, getImportedClass } from "./linker.js";
9
9
  let indent = " ";
10
+ const DEBUG = process.env["JSON_DEBUG"];
10
11
  class JSONTransform extends Visitor {
12
+ static SN = new JSONTransform();
11
13
  program;
12
14
  baseDir;
13
15
  parser;
@@ -29,7 +31,12 @@ class JSONTransform extends Visitor {
29
31
  this.schema.node = node;
30
32
  this.schema.name = node.name.text;
31
33
  this.schemas.push(this.schema);
32
- if (process.env["JSON_DEBUG"])
34
+ let SERIALIZE = "__SERIALIZE(ptr: usize): void {\n";
35
+ let INITIALIZE = "@inline __INITIALIZE(): this {\n";
36
+ let DESERIALIZE = "__DESERIALIZE<T>(srcStart: usize, srcEnd: usize, out: T): T {\n";
37
+ let DESERIALIZE_CUSTOM = "";
38
+ let SERIALIZE_CUSTOM = "";
39
+ if (DEBUG)
33
40
  console.log("Created schema: " + this.schema.name + " in file " + node.range.source.normalizedPath);
34
41
  const members = [...node.members.filter((v) => v.kind === 54 && v.flags !== 32 && v.flags !== 512 && v.flags !== 1024 && !v.decorators?.some((decorator) => decorator.name.text === "omit"))];
35
42
  const serializers = [...node.members.filter((v) => v.kind === 58 && v.decorators && v.decorators.some((e) => e.name.text.toLowerCase() === "serializer"))];
@@ -39,6 +46,7 @@ class JSONTransform extends Visitor {
39
46
  if (deserializers.length > 1)
40
47
  throwError("Multiple deserializers detected for class " + node.name.text + " but schemas can only have one deserializer!", deserializers[1].range);
41
48
  if (serializers.length) {
49
+ this.schema.custom = true;
42
50
  const serializer = serializers[0];
43
51
  if (serializer.signature.parameters.length > 1)
44
52
  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);
@@ -49,20 +57,15 @@ class JSONTransform extends Visitor {
49
57
  if (!serializer.decorators.some((v) => v.name.text == "inline")) {
50
58
  serializer.decorators.push(Node.createDecorator(Node.createIdentifierExpression("inline", serializer.range), null, serializer.range));
51
59
  }
52
- let SERIALIZER = "";
53
- SERIALIZER += " __SERIALIZE_CUSTOM(): void {\n";
54
- SERIALIZER += " const data = this." + serializer.name.text + "(" + (serializer.signature.parameters.length ? "this" : "") + ");\n";
55
- SERIALIZER += " const dataSize = data.length << 1;\n";
56
- SERIALIZER += " memory.copy(bs.offset, changetype<usize>(data), dataSize);\n";
57
- SERIALIZER += " bs.offset += dataSize;\n";
58
- SERIALIZER += " }\n";
59
- if (process.env["JSON_DEBUG"])
60
- console.log(SERIALIZER);
61
- const SERIALIZER_METHOD = SimpleParser.parseClassMember(SERIALIZER, node);
62
- if (!node.members.find((v) => v.name.text == "__SERIALIZE_CUSTOM"))
63
- node.members.push(SERIALIZER_METHOD);
60
+ SERIALIZE_CUSTOM += " __SERIALIZE(ptr: usize): void {\n";
61
+ SERIALIZE_CUSTOM += " const data = this." + serializer.name.text + "(" + (serializer.signature.parameters.length ? "this" : "") + ");\n";
62
+ SERIALIZE_CUSTOM += " const dataSize = data.length << 1;\n";
63
+ SERIALIZE_CUSTOM += " memory.copy(bs.offset, changetype<usize>(data), dataSize);\n";
64
+ SERIALIZE_CUSTOM += " bs.offset += dataSize;\n";
65
+ SERIALIZE_CUSTOM += " }\n";
64
66
  }
65
67
  if (deserializers.length) {
68
+ this.schema.custom = true;
66
69
  const deserializer = deserializers[0];
67
70
  if (!deserializer.signature.parameters.length)
68
71
  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);
@@ -75,15 +78,9 @@ class JSONTransform extends Visitor {
75
78
  if (!deserializer.decorators.some((v) => v.name.text == "inline")) {
76
79
  deserializer.decorators.push(Node.createDecorator(Node.createIdentifierExpression("inline", deserializer.range), null, deserializer.range));
77
80
  }
78
- let DESERIALIZER = "";
79
- DESERIALIZER += " __DESERIALIZE_CUSTOM(data: string): this {\n";
80
- DESERIALIZER += " return this." + deserializer.name.text + "(data);\n";
81
- DESERIALIZER += " }\n";
82
- if (process.env["JSON_DEBUG"])
83
- console.log(DESERIALIZER);
84
- const DESERIALIZER_METHOD = SimpleParser.parseClassMember(DESERIALIZER, node);
85
- if (!node.members.find((v) => v.name.text == "__DESERIALIZE_CUSTOM"))
86
- node.members.push(DESERIALIZER_METHOD);
81
+ DESERIALIZE_CUSTOM += " __DESERIALIZE<T>(srcStart: usize, srcEnd: usize, out: T): T {\n";
82
+ DESERIALIZE_CUSTOM += " return inline.always(this." + deserializer.name.text + "(changetype<string>(srcStart)));\n";
83
+ DESERIALIZE_CUSTOM += " }\n";
87
84
  }
88
85
  if (node.extendsType) {
89
86
  const extendsName = node.extendsType?.name.identifier.text;
@@ -91,7 +88,7 @@ class JSONTransform extends Visitor {
91
88
  if (!this.schema.parent) {
92
89
  const internalSearch = getClasses(node.range.source).find((v) => v.name.text == extendsName);
93
90
  if (internalSearch) {
94
- if (process.env["JSON_DEBUG"])
91
+ if (DEBUG)
95
92
  console.log("Found " + extendsName + " internally");
96
93
  this.visitClassDeclaration(internalSearch);
97
94
  this.visitClassDeclaration(node);
@@ -99,7 +96,7 @@ class JSONTransform extends Visitor {
99
96
  }
100
97
  const externalSearch = getImportedClass(extendsName, node.range.source, this.parser);
101
98
  if (externalSearch) {
102
- if (process.env["JSON_DEBUG"])
99
+ if (DEBUG)
103
100
  console.log("Found " + extendsName + " externally");
104
101
  this.visitClassDeclaration(externalSearch);
105
102
  this.visitClassDeclaration(node);
@@ -172,9 +169,6 @@ class JSONTransform extends Visitor {
172
169
  }
173
170
  if (!this.schema.static)
174
171
  this.schema.members = sortMembers(this.schema.members);
175
- let SERIALIZE = "__SERIALIZE(ptr: usize): void {\n";
176
- let INITIALIZE = "@inline __INITIALIZE(): this {\n";
177
- let DESERIALIZE = "__DESERIALIZE(keyStart: usize, keyEnd: usize, valStart: usize, valEnd: usize, ptr: usize): void {\n switch (<u32>keyEnd - <u32>keyStart) {\n";
178
172
  indent = " ";
179
173
  if (this.schema.static == false) {
180
174
  if (this.schema.members.some((v) => v.flags.has(PropertyFlags.OmitNull))) {
@@ -282,88 +276,315 @@ class JSONTransform extends Visitor {
282
276
  }
283
277
  }
284
278
  }
285
- let sortedMembers = [];
286
- let len = -1;
287
- this.schema.members
288
- .slice()
289
- .sort((a, b) => (a.alias?.length || a.name.length) - (b.alias?.length || b.name.length))
290
- .forEach((member) => {
291
- const _nameLength = member.alias?.length || member.name.length;
292
- if (_nameLength === len) {
293
- sortedMembers[sortedMembers.length - 1].push(member);
294
- }
295
- else {
296
- sortedMembers.push([member]);
297
- len = _nameLength;
298
- }
299
- });
300
- sortedMembers = sortedMembers.sort((a, b) => b.length - a.length);
301
- indentInc();
302
- for (const memberGroup of sortedMembers) {
303
- const memberLen = (memberGroup[0].alias || memberGroup[0].name).length << 1;
304
- DESERIALIZE += `${indent}case ${memberLen}: {\n`;
305
- indentInc();
306
- if (memberLen == 2)
307
- DESERIALIZE += `${indent}switch (load<u16>(keyStart)) {\n`;
308
- else if (memberLen == 4)
309
- DESERIALIZE += `${indent}switch (load<u32>(keyStart)) {\n`;
310
- else if (memberLen == 6)
311
- DESERIALIZE += `${indent}let code = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n`;
312
- else if (memberLen == 8)
313
- DESERIALIZE += `${indent}let code = load<u64>(keyStart);\n`;
279
+ const sortedMembers = {
280
+ string: [],
281
+ number: [],
282
+ boolean: [],
283
+ null: [],
284
+ array: [],
285
+ object: [],
286
+ };
287
+ for (const member of this.schema.members) {
288
+ if (member.type.endsWith(" | null"))
289
+ sortedMembers.null.push(member);
290
+ if (isString(member.type) || member.type == "JSON.Raw")
291
+ sortedMembers.string.push(member);
292
+ else if (isBoolean(member.type) || member.type.startsWith("JSON.Box<bool"))
293
+ sortedMembers.boolean.push(member);
294
+ else if (isPrimitive(member.type) || member.type.startsWith("JSON.Box<"))
295
+ sortedMembers.number.push(member);
296
+ else if (isArray(member.type))
297
+ sortedMembers.array.push(member);
314
298
  else
315
- DESERIALIZE += toMemCDecl(memberLen, indent);
316
- for (let i = 0; i < memberGroup.length; i++) {
317
- const member = memberGroup[i];
318
- const memberName = member.alias || member.name;
319
- const dst = this.schemas.find(v => v.name == member.type)
320
- ? "load<usize>(ptr + offsetof<this>(\"" + member.name + "\"))"
321
- : "0";
322
- if (memberLen == 2) {
323
- DESERIALIZE += `${indent} case ${memberName.charCodeAt(0)}: { // ${memberName}\n`;
324
- DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd, ${dst}), offsetof<this>(${JSON.stringify(member.name)}));\n`;
325
- DESERIALIZE += `${indent} return;\n`;
326
- DESERIALIZE += `${indent} }\n`;
327
- }
328
- else if (memberLen == 4) {
329
- DESERIALIZE += `${indent} case ${toU32(memberName)}: { // ${memberName}\n`;
330
- DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd, ${dst}), offsetof<this>(${JSON.stringify(member.name)}));\n`;
331
- DESERIALIZE += `${indent} return;\n`;
332
- DESERIALIZE += `${indent} }\n`;
333
- }
334
- else if (memberLen == 6) {
335
- DESERIALIZE += i == 0 ? indent : "";
336
- DESERIALIZE += `if (code == ${toU48(memberName)}) { // ${memberName}\n`;
337
- DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd, ${dst}), offsetof<this>(${JSON.stringify(member.name)}));\n`;
338
- DESERIALIZE += `${indent} return;\n`;
339
- DESERIALIZE += `${indent}}${i < memberGroup.length - 1 ? " else " : "\n"}`;
340
- }
341
- else if (memberLen == 8) {
342
- DESERIALIZE += i == 0 ? indent : "";
343
- DESERIALIZE += `if (code == ${toU64(memberName)}) { // ${memberName}\n`;
344
- DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd, ${dst}), offsetof<this>(${JSON.stringify(member.name)}));\n`;
345
- DESERIALIZE += `${indent} return;\n`;
346
- DESERIALIZE += `${indent}}${i < memberGroup.length - 1 ? " else " : "\n"}`;
299
+ sortedMembers.object.push(member);
300
+ }
301
+ indent = "";
302
+ let shouldGroup = false;
303
+ DESERIALIZE += indent + " let keyStart: usize = 0;\n";
304
+ if (shouldGroup || DEBUG)
305
+ DESERIALIZE += indent + " let keyEnd: usize = 0;\n";
306
+ DESERIALIZE += indent + " let isKey = false;\n";
307
+ if (sortedMembers.object.length || sortedMembers.array.length)
308
+ DESERIALIZE += indent + " let depth: i32 = 0;\n";
309
+ DESERIALIZE += indent + " let lastIndex: usize = 0;\n\n";
310
+ DESERIALIZE += indent + " while (srcStart < srcEnd && JSON.Util.isSpace(load<u16>(srcStart))) srcStart += 2;\n";
311
+ DESERIALIZE += indent + " while (srcEnd > srcStart && JSON.Util.isSpace(load<u16>(srcEnd - 2))) srcEnd -= 2;\n";
312
+ DESERIALIZE += indent + ' if (srcStart - srcEnd == 0) throw new Error("Input string had zero length or was all whitespace");\n';
313
+ DESERIALIZE += indent + " if (load<u16>(srcStart) != 123) throw new Error(\"Expected '{' at start of object at position \" + (srcEnd - srcStart).toString());\n";
314
+ DESERIALIZE += indent + " if (load<u16>(srcEnd - 2) != 125) throw new Error(\"Expected '}' at end of object at position \" + (srcEnd - srcStart).toString());\n";
315
+ DESERIALIZE += indent + " srcStart += 2;\n\n";
316
+ DESERIALIZE += indent + " while (srcStart < srcEnd) {\n";
317
+ DESERIALIZE += indent + " let code = load<u16>(srcStart);\n";
318
+ DESERIALIZE += indent + " while (JSON.Util.isSpace(code)) code = load<u16>(srcStart += 2);\n";
319
+ DESERIALIZE += indent + " if (keyStart == 0) {\n";
320
+ DESERIALIZE += indent + " if (code == 34 && load<u16>(srcStart - 2) !== 92) {\n";
321
+ DESERIALIZE += indent + " if (isKey) {\n";
322
+ DESERIALIZE += indent + " keyStart = lastIndex;\n";
323
+ if (shouldGroup || DEBUG)
324
+ DESERIALIZE += indent + " keyEnd = srcStart;\n";
325
+ DESERIALIZE += indent + " while (JSON.Util.isSpace((code = load<u16>((srcStart += 2))))) {}\n";
326
+ DESERIALIZE += indent + " if (code !== 58) throw new Error(\"Expected ':' after key at position \" + (srcEnd - srcStart).toString());\n";
327
+ DESERIALIZE += indent + " isKey = false;\n";
328
+ DESERIALIZE += indent + " } else {\n";
329
+ DESERIALIZE += indent + " isKey = true;\n";
330
+ DESERIALIZE += indent + " lastIndex = srcStart + 2;\n";
331
+ DESERIALIZE += indent + " }\n";
332
+ DESERIALIZE += indent + " }\n";
333
+ DESERIALIZE += indent + " srcStart += 2;\n";
334
+ DESERIALIZE += indent + " } else {\n";
335
+ const groupMembers = (members) => {
336
+ let sorted = [];
337
+ let len = -1;
338
+ members
339
+ .slice()
340
+ .sort((a, b) => (a.alias?.length || a.name.length) - (b.alias?.length || b.name.length))
341
+ .forEach((member) => {
342
+ const _nameLength = member.alias?.length || member.name.length;
343
+ if (_nameLength === len) {
344
+ sorted[sorted.length - 1].push(member);
347
345
  }
348
346
  else {
349
- DESERIALIZE += i == 0 ? indent : "";
350
- DESERIALIZE += `if (${toMemCCheck(memberName)}) { // ${memberName}\n`;
351
- DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd, ${dst}), offsetof<this>(${JSON.stringify(member.name)}));\n`;
352
- DESERIALIZE += `${indent} return;\n`;
353
- DESERIALIZE += `${indent}}${i < memberGroup.length - 1 ? " else " : "\n"}`;
347
+ sorted.push([member]);
348
+ len = _nameLength;
354
349
  }
355
- }
356
- if (memberLen < 6) {
357
- DESERIALIZE += `${indent}}\n`;
358
- }
359
- indentDec();
360
- DESERIALIZE += `${indent} return;\n`;
361
- DESERIALIZE += `${indent}}\n`;
350
+ });
351
+ sorted = sorted.sort((a, b) => b.length - a.length);
352
+ return sorted;
353
+ };
354
+ const generateComparisions = (members) => {
355
+ if (members.some((m) => (m.alias || m.name).length << 1 == 2)) {
356
+ DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
357
+ }
358
+ if (members.some((m) => (m.alias || m.name).length << 1 == 4)) {
359
+ DESERIALIZE += " const code32 = load<u32>(keyStart);\n";
360
+ }
361
+ if (members.some((m) => (m.alias || m.name).length << 1 == 6)) {
362
+ DESERIALIZE += " const code48 = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n";
363
+ }
364
+ if (members.some((m) => (m.alias || m.name).length << 1 == 8)) {
365
+ DESERIALIZE += " const code64 = load<u64>(keyStart);\n";
366
+ }
367
+ if (members.some((m) => (m.alias || m.name).length << 1 > 8)) {
368
+ DESERIALIZE += toMemCDecl(Math.max(...members.map((m) => (m.alias || m.name).length << 1)), " ");
369
+ }
370
+ const complex = isStruct(members[0].type) || members[0].type != "JSON.Obj" || isArray(members[0].type);
371
+ const firstMemberName = members[0].alias || members[0].name;
372
+ DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
373
+ DESERIALIZE += indent + " store<" + members[0].type + ">(changetype<usize>(out), JSON.__deserialize<" + members[0].type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(firstMemberName) + "));\n";
374
+ if (!complex)
375
+ DESERIALIZE += indent + " srcStart += 2;\n";
376
+ DESERIALIZE += indent + " keyStart = 0;\n";
377
+ DESERIALIZE += indent + " break;\n";
378
+ DESERIALIZE += indent + " }";
379
+ for (let i = 1; i < members.length; i++) {
380
+ const member = members[i];
381
+ const memberName = member.alias || member.name;
382
+ DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
383
+ DESERIALIZE += indent + " store<" + members[0].type + ">(changetype<usize>(out), JSON.__deserialize<" + members[0].type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(memberName) + "));\n";
384
+ if (isString(members[0].type))
385
+ DESERIALIZE += indent + " srcStart += 4;\n";
386
+ else if (!complex)
387
+ DESERIALIZE += indent + " srcStart += 2;\n";
388
+ DESERIALIZE += indent + " keyStart = 0;\n";
389
+ DESERIALIZE += indent + " break;\n";
390
+ DESERIALIZE += indent + " }";
391
+ }
392
+ DESERIALIZE += " else {\n";
393
+ DESERIALIZE += indent + ' throw new Error("Unexpected key in JSON object \'" + String.fromCharCode(load<u16>(srcStart)) + "\' at position " + (srcEnd - srcStart).toString());\n';
394
+ DESERIALIZE += indent + " }\n";
395
+ };
396
+ let mbElse = " ";
397
+ if (sortedMembers.string.length) {
398
+ DESERIALIZE += mbElse + "if (code == 34) {\n";
399
+ DESERIALIZE += " lastIndex = srcStart;\n";
400
+ DESERIALIZE += " srcStart += 2;\n";
401
+ DESERIALIZE += " while (srcStart < srcEnd) {\n";
402
+ DESERIALIZE += " const code = load<u16>(srcStart);\n";
403
+ DESERIALIZE += " if (code == 34 && load<u16>(srcStart - 2) !== 92) {\n";
404
+ DESERIALIZE += " srcStart += 2;\n";
405
+ generateComparisions(sortedMembers.string);
406
+ DESERIALIZE += " }\n";
407
+ DESERIALIZE += " srcStart += 2;\n";
408
+ DESERIALIZE += " }\n";
409
+ DESERIALIZE += " }\n";
410
+ mbElse = " else ";
411
+ }
412
+ if (sortedMembers.number.length) {
413
+ DESERIALIZE += mbElse + "if (code - 48 <= 9 || code == 45) {\n";
414
+ DESERIALIZE += " lastIndex = srcStart;\n";
415
+ DESERIALIZE += " srcStart += 2;\n";
416
+ DESERIALIZE += " while (srcStart < srcEnd) {\n";
417
+ DESERIALIZE += " const code = load<u16>(srcStart);\n";
418
+ DESERIALIZE += " if (code == 44 || code == 125 || JSON.Util.isSpace(code)) {\n";
419
+ generateComparisions(sortedMembers.number);
420
+ DESERIALIZE += " }\n";
421
+ DESERIALIZE += " srcStart += 2;\n";
422
+ DESERIALIZE += " }\n";
423
+ DESERIALIZE += " }";
424
+ mbElse = " else ";
425
+ }
426
+ if (sortedMembers.object.length) {
427
+ DESERIALIZE += mbElse + "if (code == 123) {\n";
428
+ DESERIALIZE += " lastIndex = srcStart;\n";
429
+ DESERIALIZE += " depth++;\n";
430
+ DESERIALIZE += " srcStart += 2;\n";
431
+ DESERIALIZE += " while (srcStart < srcEnd) {\n";
432
+ DESERIALIZE += " const code = load<u16>(srcStart);\n";
433
+ DESERIALIZE += " if (code == 34) {\n";
434
+ DESERIALIZE += " srcStart += 2;\n";
435
+ DESERIALIZE += " while (!(load<u16>(srcStart) == 34 && load<u16>(srcStart - 2) != 92)) srcStart += 2;\n";
436
+ DESERIALIZE += " } else if (code == 125) {\n";
437
+ DESERIALIZE += " if (--depth == 0) {\n";
438
+ DESERIALIZE += " srcStart += 2;\n";
439
+ indent = " ";
440
+ generateComparisions(sortedMembers.object);
441
+ indent = "";
442
+ DESERIALIZE += " }\n";
443
+ DESERIALIZE += " } else if (code == 123) depth++;\n";
444
+ DESERIALIZE += " srcStart += 2;\n";
445
+ DESERIALIZE += " }\n";
446
+ DESERIALIZE += " }";
447
+ mbElse = " else ";
448
+ }
449
+ if (sortedMembers.array.length) {
450
+ DESERIALIZE += mbElse + "if (code == 91) {\n";
451
+ DESERIALIZE += " lastIndex = srcStart;\n";
452
+ DESERIALIZE += " depth++;\n";
453
+ DESERIALIZE += " srcStart += 2;\n";
454
+ DESERIALIZE += " while (srcStart < srcEnd) {\n";
455
+ DESERIALIZE += " const code = load<u16>(srcStart);\n";
456
+ DESERIALIZE += " if (code == 34) {\n";
457
+ DESERIALIZE += " srcStart += 2;\n";
458
+ DESERIALIZE += " while (!(load<u16>(srcStart) == 34 && load<u16>(srcStart - 2) != 92)) srcStart += 2;\n";
459
+ DESERIALIZE += " } else if (code == 93) {\n";
460
+ DESERIALIZE += " if (--depth == 0) {\n";
461
+ DESERIALIZE += " srcStart += 2;\n";
462
+ indent = " ";
463
+ generateComparisions(sortedMembers.array);
464
+ indent = "";
465
+ DESERIALIZE += " }\n";
466
+ DESERIALIZE += " } else if (code == 91) depth++;\n";
467
+ DESERIALIZE += " srcStart += 2;\n";
468
+ DESERIALIZE += " }\n";
469
+ DESERIALIZE += " }";
470
+ mbElse = " else ";
471
+ }
472
+ if (sortedMembers.boolean.length) {
473
+ DESERIALIZE += mbElse + "if (code == 116) {\n";
474
+ DESERIALIZE += " if (load<u64>(srcStart) == 28429475166421108) {\n";
475
+ DESERIALIZE += " srcStart += 8;\n";
476
+ if (sortedMembers.boolean.some((m) => (m.alias || m.name).length << 1 == 2)) {
477
+ DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
478
+ }
479
+ if (sortedMembers.boolean.some((m) => (m.alias || m.name).length << 1 == 4)) {
480
+ DESERIALIZE += " const code32 = load<u32>(keyStart);\n";
481
+ }
482
+ if (sortedMembers.boolean.some((m) => (m.alias || m.name).length << 1 == 6)) {
483
+ DESERIALIZE += " const code48 = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n";
484
+ }
485
+ if (sortedMembers.boolean.some((m) => (m.alias || m.name).length << 1 == 8)) {
486
+ DESERIALIZE += " const code64 = load<u64>(keyStart);\n";
487
+ }
488
+ if (sortedMembers.boolean.some((m) => (m.alias || m.name).length << 1 > 8)) {
489
+ DESERIALIZE += toMemCDecl(Math.max(...sortedMembers.boolean.map((m) => (m.alias || m.name).length << 1)), " ");
490
+ }
491
+ const firstMemberName = sortedMembers.boolean[0].alias || sortedMembers.boolean[0].name;
492
+ DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
493
+ DESERIALIZE += indent + " store<" + sortedMembers.boolean[0].type + ">(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(sortedMembers.boolean[0].name) + "));\n";
494
+ DESERIALIZE += indent + " srcStart += 2;\n";
495
+ DESERIALIZE += indent + " keyStart = 0;\n";
496
+ DESERIALIZE += indent + " break;\n";
497
+ DESERIALIZE += indent + " }";
498
+ for (let i = 1; i < sortedMembers.boolean.length; i++) {
499
+ const member = sortedMembers.boolean[i];
500
+ const memberName = member.alias || member.name;
501
+ DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
502
+ DESERIALIZE += indent + " store<" + sortedMembers.boolean[0].type + ">(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(sortedMembers.boolean[0].name) + "));\n";
503
+ DESERIALIZE += indent + " srcStart += 2;\n";
504
+ DESERIALIZE += indent + " keyStart = 0;\n";
505
+ DESERIALIZE += indent + " break;\n";
506
+ DESERIALIZE += indent + " }";
507
+ }
508
+ DESERIALIZE += " else {\n";
509
+ DESERIALIZE += indent + ' throw new Error("Unexpected key in JSON object \'" + String.fromCharCode(load<u16>(srcStart)) + "\' at position " + (srcEnd - srcStart).toString());\n';
510
+ DESERIALIZE += indent + " }\n";
511
+ DESERIALIZE += " }";
512
+ mbElse = " else ";
513
+ DESERIALIZE += " else if (load<u64>(srcStart, 2) == 28429466576093281) {\n";
514
+ DESERIALIZE += " srcStart += 10;\n";
515
+ DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
516
+ DESERIALIZE += indent + " store<" + sortedMembers.boolean[0].type + ">(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(sortedMembers.boolean[0].name) + "));\n";
517
+ DESERIALIZE += indent + " srcStart += 2;\n";
518
+ DESERIALIZE += indent + " keyStart = 0;\n";
519
+ DESERIALIZE += indent + " break;\n";
520
+ DESERIALIZE += indent + " }";
521
+ for (let i = 1; i < sortedMembers.boolean.length; i++) {
522
+ const member = sortedMembers.boolean[i];
523
+ const memberName = member.alias || member.name;
524
+ DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
525
+ DESERIALIZE += indent + " store<" + sortedMembers.boolean[0].type + ">(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(sortedMembers.boolean[0].name) + "));\n";
526
+ DESERIALIZE += indent + " srcStart += 2;\n";
527
+ DESERIALIZE += indent + " keyStart = 0;\n";
528
+ DESERIALIZE += indent + " break;\n";
529
+ DESERIALIZE += indent + " }";
530
+ }
531
+ DESERIALIZE += " else {\n";
532
+ DESERIALIZE += indent + ' throw new Error("Unexpected key in JSON object \'" + String.fromCharCode(load<u16>(srcStart)) + "\' at position " + (srcEnd - srcStart).toString());\n';
533
+ DESERIALIZE += indent + " }\n";
534
+ DESERIALIZE += " }\n";
535
+ DESERIALIZE += " }";
362
536
  }
537
+ if (sortedMembers.null.length) {
538
+ DESERIALIZE += mbElse + "if (code == 110) {\n";
539
+ DESERIALIZE += " if (load<u64>(srcStart) == 30399761348886638) {\n";
540
+ DESERIALIZE += " srcStart += 8;\n";
541
+ if (sortedMembers.null.some((m) => (m.alias || m.name).length << 1 == 2)) {
542
+ DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
543
+ }
544
+ if (sortedMembers.null.some((m) => (m.alias || m.name).length << 1 == 4)) {
545
+ DESERIALIZE += " const code32 = load<u32>(keyStart);\n";
546
+ }
547
+ if (sortedMembers.null.some((m) => (m.alias || m.name).length << 1 == 6)) {
548
+ DESERIALIZE += " const code48 = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n";
549
+ }
550
+ if (sortedMembers.null.some((m) => (m.alias || m.name).length << 1 == 8)) {
551
+ DESERIALIZE += " const code64 = load<u64>(keyStart);\n";
552
+ }
553
+ if (sortedMembers.null.some((m) => (m.alias || m.name).length << 1 > 8)) {
554
+ DESERIALIZE += toMemCDecl(Math.max(...sortedMembers.null.map((m) => (m.alias || m.name).length << 1)), " ");
555
+ }
556
+ const firstMemberName = sortedMembers.null[0].alias || sortedMembers.null[0].name;
557
+ DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
558
+ DESERIALIZE += indent + " store<" + sortedMembers.null[0].type + ">(changetype<usize>(out), null, offsetof<this>(" + JSON.stringify(sortedMembers.null[0].name) + "));\n";
559
+ DESERIALIZE += indent + " srcStart += 2;\n";
560
+ DESERIALIZE += indent + " keyStart = 0;\n";
561
+ DESERIALIZE += indent + " break;\n";
562
+ DESERIALIZE += indent + " }";
563
+ for (let i = 1; i < sortedMembers.null.length; i++) {
564
+ const member = sortedMembers.null[i];
565
+ const memberName = member.alias || member.name;
566
+ DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
567
+ DESERIALIZE += indent + " store<" + sortedMembers.null[0].type + ">(changetype<usize>(out), null, offsetof<this>(" + JSON.stringify(sortedMembers.null[0].name) + "));\n";
568
+ DESERIALIZE += indent + " srcStart += 2;\n";
569
+ DESERIALIZE += indent + " keyStart = 0;\n";
570
+ DESERIALIZE += indent + " break;\n";
571
+ DESERIALIZE += indent + " }";
572
+ }
573
+ DESERIALIZE += " else {\n";
574
+ DESERIALIZE += indent + ' throw new Error("Unexpected key in JSON object \'" + String.fromCharCode(load<u16>(srcStart)) + "\' at position " + (srcEnd - srcStart).toString());\n';
575
+ DESERIALIZE += indent + " }\n";
576
+ DESERIALIZE += " }";
577
+ DESERIALIZE += "\n }";
578
+ mbElse = " else ";
579
+ }
580
+ DESERIALIZE += " else {\n";
581
+ DESERIALIZE += " srcStart += 2;\n";
582
+ DESERIALIZE += "}\n";
583
+ DESERIALIZE += "\n }\n";
363
584
  indentDec();
364
- DESERIALIZE += `${indent}}\n`;
585
+ DESERIALIZE += ` }\n`;
365
586
  indentDec();
366
- DESERIALIZE += `${indent}}\n`;
587
+ DESERIALIZE += ` return out;\n}\n`;
367
588
  indent = " ";
368
589
  this.schema.byteSize += 2;
369
590
  SERIALIZE += indent + "store<u16>(bs.offset, 125, 0); // }\n";
@@ -372,14 +593,14 @@ class JSONTransform extends Visitor {
372
593
  SERIALIZE = SERIALIZE.slice(0, 32) + indent + "bs.proposeSize(" + this.schema.byteSize + ");\n" + SERIALIZE.slice(32);
373
594
  INITIALIZE += " return this;\n";
374
595
  INITIALIZE += "}";
375
- if (process.env["JSON_DEBUG"]) {
376
- console.log(SERIALIZE);
596
+ if (DEBUG) {
597
+ console.log(SERIALIZE_CUSTOM ? SERIALIZE_CUSTOM : SERIALIZE);
377
598
  console.log(INITIALIZE);
378
- console.log(DESERIALIZE);
599
+ console.log(DESERIALIZE_CUSTOM || DESERIALIZE);
379
600
  }
380
- const SERIALIZE_METHOD = SimpleParser.parseClassMember(SERIALIZE, node);
601
+ const SERIALIZE_METHOD = SimpleParser.parseClassMember(SERIALIZE_CUSTOM ? SERIALIZE_CUSTOM : SERIALIZE, node);
381
602
  const INITIALIZE_METHOD = SimpleParser.parseClassMember(INITIALIZE, node);
382
- const DESERIALIZE_METHOD = SimpleParser.parseClassMember(DESERIALIZE, node);
603
+ const DESERIALIZE_METHOD = SimpleParser.parseClassMember(DESERIALIZE_CUSTOM || DESERIALIZE, node);
383
604
  if (!node.members.find((v) => v.name.text == "__SERIALIZE"))
384
605
  node.members.push(SERIALIZE_METHOD);
385
606
  if (!node.members.find((v) => v.name.text == "__INITIALIZE"))
@@ -391,8 +612,8 @@ class JSONTransform extends Visitor {
391
612
  generateEmptyMethods(node) {
392
613
  let SERIALIZE_EMPTY = "@inline __SERIALIZE(ptr: usize): void {\n bs.proposeSize(4);\n store<u32>(bs.offset, 8192123);\n bs.offset += 4;\n}";
393
614
  let INITIALIZE_EMPTY = "@inline __INITIALIZE(): this {\n return this;\n}";
394
- let DESERIALIZE_EMPTY = "@inline __DESERIALIZE(keyStart: usize, keyEnd: usize, valStart: usize, valEnd: usize, ptr: usize): void {\n return false;\n}";
395
- if (process.env["JSON_DEBUG"]) {
615
+ let DESERIALIZE_EMPTY = "@inline __DESERIALIZE(srcStart: usize, srcEnd: usize): this {\n return this;\n}";
616
+ if (DEBUG) {
396
617
  console.log(SERIALIZE_EMPTY);
397
618
  console.log(INITIALIZE_EMPTY);
398
619
  console.log(DESERIALIZE_EMPTY);
@@ -429,7 +650,7 @@ class JSONTransform extends Visitor {
429
650
  }
430
651
  const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("bs", node.range, false), null, node.range)], Node.createStringLiteralExpression(bsPath, node.range), node.range);
431
652
  this.topStatements.push(replaceNode);
432
- if (process.env["JSON_DEBUG"])
653
+ if (DEBUG)
433
654
  console.log("Added as-bs import: " + toString(replaceNode) + "\n");
434
655
  }
435
656
  if (!jsonImport) {
@@ -438,7 +659,7 @@ class JSONTransform extends Visitor {
438
659
  }
439
660
  const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("JSON", node.range, false), null, node.range)], Node.createStringLiteralExpression(jsonPath, node.range), node.range);
440
661
  this.topStatements.push(replaceNode);
441
- if (process.env["JSON_DEBUG"])
662
+ if (DEBUG)
442
663
  console.log("Added json-as import: " + toString(replaceNode) + "\n");
443
664
  }
444
665
  }
@@ -490,7 +711,7 @@ class JSONTransform extends Visitor {
490
711
  }
491
712
  export default class Transformer extends Transform {
492
713
  afterParse(parser) {
493
- const transformer = new JSONTransform();
714
+ const transformer = JSONTransform.SN;
494
715
  const sources = parser.sources
495
716
  .filter((source) => {
496
717
  const p = source.internalPath;
@@ -577,17 +798,17 @@ function toMemCDecl(n, indent) {
577
798
  let offset = 0;
578
799
  let index = 0;
579
800
  while (n >= 8) {
580
- out += `${indent}const code${index++} = load<u64>(keyStart, ${offset});\n`;
801
+ out += `${indent}const codeS${(index += 8)} = load<u64>(keyStart, ${offset});\n`;
581
802
  offset += 8;
582
803
  n -= 8;
583
804
  }
584
805
  while (n >= 4) {
585
- out += `${indent}const code${index++} = load<u32>(keyStart, ${offset});\n`;
806
+ out += `${indent}const codeS${(index += 4)} = load<u32>(keyStart, ${offset});\n`;
586
807
  offset += 4;
587
808
  n -= 4;
588
809
  }
589
810
  if (n == 1)
590
- out += `${indent}const code${index++} = load<u16>(keyStart, ${offset});\n`;
811
+ out += `${indent}const codeS${(index += 1)} = load<u16>(keyStart, ${offset});\n`;
591
812
  return out;
592
813
  }
593
814
  function toMemCCheck(data) {
@@ -596,17 +817,17 @@ function toMemCCheck(data) {
596
817
  let offset = 0;
597
818
  let index = 0;
598
819
  while (n >= 8) {
599
- out += ` && code${index++} == ${toU64(data, offset >> 1)}`;
820
+ out += ` && codeS${(index += 8)} == ${toU64(data, offset >> 1)}`;
600
821
  offset += 8;
601
822
  n -= 8;
602
823
  }
603
824
  while (n >= 4) {
604
- out += ` && code${index++} == ${toU32(data, offset >> 1)}`;
825
+ out += ` && codeS${(index += 4)} == ${toU32(data, offset >> 1)}`;
605
826
  offset += 4;
606
827
  n -= 4;
607
828
  }
608
829
  if (n == 1)
609
- out += ` && code${index++} == ${toU16(data, offset >> 1)}`;
830
+ out += ` && codeS${(index += 1)} == ${toU16(data, offset >> 1)}`;
610
831
  return out.slice(4);
611
832
  }
612
833
  function strToNum(data, simd = false, offset = 0) {
@@ -635,10 +856,6 @@ function strToNum(data, simd = false, offset = 0) {
635
856
  }
636
857
  return out;
637
858
  }
638
- function isPrimitive(type) {
639
- const primitiveTypes = ["u8", "u16", "u32", "u64", "i8", "i16", "i32", "i64", "f32", "f64", "bool", "boolean"];
640
- return primitiveTypes.some((v) => type.startsWith(v));
641
- }
642
859
  function throwError(message, range) {
643
860
  const err = new Error();
644
861
  err.stack = `${message}\n at ${range.source.normalizedPath}:${range.source.lineAt(range.start)}:${range.source.columnAt()}\n`;
@@ -672,4 +889,46 @@ function sizeof(type) {
672
889
  else
673
890
  return 0;
674
891
  }
892
+ function isPrimitive(type) {
893
+ const primitiveTypes = ["u8", "u16", "u32", "u64", "i8", "i16", "i32", "i64", "f32", "f64", "bool", "boolean"];
894
+ return primitiveTypes.some((v) => type.startsWith(v));
895
+ }
896
+ function isBoolean(type) {
897
+ return type == "bool" || type == "boolean";
898
+ }
899
+ function isStruct(type) {
900
+ type = stripNull(type);
901
+ return JSONTransform.SN.schemas.some((v) => v.name == type) || JSONTransform.SN.schema.name == type;
902
+ }
903
+ function isString(type) {
904
+ return stripNull(type) == "string" || stripNull(type) == "String";
905
+ }
906
+ function isArray(type) {
907
+ return type.startsWith("Array<");
908
+ }
909
+ function stripNull(type) {
910
+ if (type.endsWith(" | null")) {
911
+ return type.slice(0, type.length - 7);
912
+ }
913
+ return type;
914
+ }
915
+ function getComparision(data) {
916
+ switch (data.length << 1) {
917
+ case 2: {
918
+ return "code16 == " + data.charCodeAt(0);
919
+ }
920
+ case 4: {
921
+ return "code32 == " + toU32(data);
922
+ }
923
+ case 6: {
924
+ return "code48 == " + toU48(data);
925
+ }
926
+ case 8: {
927
+ return "code64 == " + toU64(data);
928
+ }
929
+ default: {
930
+ return toMemCCheck(data);
931
+ }
932
+ }
933
+ }
675
934
  //# sourceMappingURL=index.js.map