json-as 1.3.1 → 1.3.2

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 (54) hide show
  1. package/CHANGELOG.md +9 -26
  2. package/README.md +41 -18
  3. package/assembly/deserialize/index/arbitrary.ts +1 -1
  4. package/assembly/deserialize/index/array.ts +6 -1
  5. package/assembly/deserialize/index/float.ts +1 -1
  6. package/assembly/deserialize/index/integer.ts +1 -1
  7. package/assembly/deserialize/index/unsigned.ts +1 -1
  8. package/assembly/deserialize/simd/string.ts +17 -13
  9. package/assembly/deserialize/simple/arbitrary.ts +1 -1
  10. package/assembly/deserialize/simple/array/generic.ts +42 -0
  11. package/assembly/deserialize/simple/array.ts +8 -1
  12. package/assembly/deserialize/{float.ts → simple/float.ts} +22 -2
  13. package/assembly/deserialize/{integer.ts → simple/integer.ts} +3 -2
  14. package/assembly/deserialize/simple/map.ts +60 -12
  15. package/assembly/deserialize/simple/object.ts +1 -1
  16. package/assembly/deserialize/simple/set.ts +119 -134
  17. package/assembly/deserialize/simple/staticarray.ts +12 -1
  18. package/assembly/deserialize/simple/string.ts +15 -10
  19. package/assembly/deserialize/simple/struct.ts +7 -157
  20. package/assembly/deserialize/simple/typedarray.ts +1 -1
  21. package/assembly/deserialize/{unsigned.ts → simple/unsigned.ts} +3 -2
  22. package/assembly/deserialize/swar/array/array.ts +42 -7
  23. package/assembly/deserialize/swar/array/bool.ts +5 -2
  24. package/assembly/deserialize/swar/array/float.ts +7 -3
  25. package/assembly/deserialize/swar/array/generic.ts +40 -0
  26. package/assembly/deserialize/swar/array/integer.ts +7 -4
  27. package/assembly/deserialize/swar/array/object.ts +20 -4
  28. package/assembly/deserialize/swar/array/shared.ts +18 -4
  29. package/assembly/deserialize/swar/array/string.ts +5 -2
  30. package/assembly/deserialize/swar/array/struct.ts +20 -4
  31. package/assembly/deserialize/swar/array.ts +56 -2
  32. package/assembly/deserialize/swar/string.ts +249 -371
  33. package/assembly/index.ts +74 -17
  34. package/assembly/serialize/index/arbitrary.ts +3 -3
  35. package/assembly/serialize/index/float.ts +1 -1
  36. package/assembly/serialize/index/object.ts +1 -5
  37. package/assembly/serialize/simd/string.ts +4 -5
  38. package/assembly/serialize/simple/arbitrary.ts +3 -3
  39. package/assembly/serialize/simple/array.ts +17 -6
  40. package/assembly/serialize/simple/float.ts +18 -4
  41. package/assembly/serialize/simple/map.ts +10 -27
  42. package/assembly/serialize/simple/object.ts +1 -5
  43. package/assembly/serialize/simple/set.ts +3 -4
  44. package/assembly/serialize/simple/staticarray.ts +4 -3
  45. package/assembly/serialize/simple/typedarray.ts +9 -7
  46. package/assembly/serialize/swar/string.ts +0 -1
  47. package/assembly/tsconfig.json +3 -2
  48. package/assembly/util/dragonbox-cache.ts +1322 -0
  49. package/assembly/util/dragonbox.ts +596 -0
  50. package/lib/as-bs.ts +10 -7
  51. package/package.json +17 -10
  52. package/transform/lib/index.d.ts.map +1 -1
  53. package/transform/lib/index.js +408 -191
  54. package/transform/lib/index.js.map +1 -1
@@ -358,7 +358,7 @@ export class JSONTransform extends Visitor {
358
358
  this.schema = schema;
359
359
  this.visitedClasses.add(fullClassPath);
360
360
  const codegenMode = getCodegenMode(this.program);
361
- const useFastPath = USE_FAST_PATH && codegenMode !== JSONMode.NAIVE;
361
+ const requestedFastPath = USE_FAST_PATH && codegenMode !== JSONMode.NAIVE;
362
362
  let SERIALIZE = "__SERIALIZE(ptr: usize): void {\n";
363
363
  let INITIALIZE = "@inline __INITIALIZE(): this {\n";
364
364
  let DESERIALIZE = "__DESERIALIZE_SLOW<__JSON_T>(srcStart: usize, srcEnd: usize, out: __JSON_T): usize {\n";
@@ -486,6 +486,12 @@ export class JSONTransform extends Visitor {
486
486
  }
487
487
  if (!this.schema.static)
488
488
  this.schema.members = sortMembers(this.schema.members);
489
+ const hasOmitIfMembers = this.schema.members.some((v) => v.flags.has(PropertyFlags.OmitIf));
490
+ const hasOmitNullMembers = this.schema.members.some((v) => v.flags.has(PropertyFlags.OmitNull));
491
+ const hasOptionalMembers = hasOmitIfMembers || hasOmitNullMembers;
492
+ const supportsFastOptionalPath = requestedFastPath && hasOptionalMembers;
493
+ const hasTypeParams = !!node.typeParameters && node.typeParameters.length > 0;
494
+ const useFastPath = requestedFastPath && !hasTypeParams && (this.schema.static || supportsFastOptionalPath);
489
495
  indent = " ";
490
496
  if (this.schema.static == false) {
491
497
  if (this.schema.members.some((v) => v.flags.has(PropertyFlags.OmitNull))) {
@@ -503,36 +509,34 @@ export class JSONTransform extends Visitor {
503
509
  const aliasName = JSON.stringify(member.alias || member.name);
504
510
  const realName = member.name;
505
511
  const isLast = i == this.schema.members.length - 1;
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
- }
512
+ if (member.value) {
513
+ if (member.value != "null" && member.value != "0" && member.value != "0.0" && member.value != "false") {
514
+ INITIALIZE += ` store<${member.type}>(changetype<usize>(this), ${member.value}, offsetof<this>(${JSON.stringify(member.name)}));\n`;
511
515
  }
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
+ else if (member.generic) {
518
+ INITIALIZE += ` if (isManaged<nonnull<${member.type}>>() || isReference<nonnull<${member.type}>>()) {\n`;
519
+ 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`;
520
+ INITIALIZE += ` if (isDefined(this.${member.name}.__INITIALIZE)) changetype<nonnull<${member.type}>>(this.${member.name}).__INITIALIZE();\n`;
521
+ INITIALIZE += ` }\n`;
522
+ }
523
+ else if (!member.node.type.isNullable) {
524
+ if (this.getSchema(member.type)) {
525
+ 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`;
517
526
  }
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
- }
527
+ else if (member.type.startsWith("Array<")) {
528
+ INITIALIZE += ` store<${member.type}>(changetype<usize>(this), [], offsetof<this>(${JSON.stringify(member.name)}));\n`;
529
+ }
530
+ else if (member.type.startsWith("Map<")) {
531
+ INITIALIZE += ` store<${member.type}>(changetype<usize>(this), new ${member.type}(), offsetof<this>(${JSON.stringify(member.name)}));\n`;
532
+ }
533
+ else if (member.type.startsWith("Set<")) {
534
+ INITIALIZE += ` store<${member.type}>(changetype<usize>(this), new ${member.type}(), offsetof<this>(${JSON.stringify(member.name)}));\n`;
535
+ }
536
+ else if (member.type.startsWith("StaticArray<")) {
537
+ }
538
+ else if (member.type == "string" || member.type == "String") {
539
+ INITIALIZE += ` store<${member.type}>(changetype<usize>(this), "", offsetof<this>(${JSON.stringify(member.name)}));\n`;
536
540
  }
537
541
  }
538
542
  const SIMD_ENABLED = this.program.options.hasFeature(16);
@@ -624,8 +628,10 @@ export class JSONTransform extends Visitor {
624
628
  else {
625
629
  if (member.node.type.isNullable)
626
630
  sortedMembers.null.push(member);
627
- if (isString(type) || type == "JSON.Raw")
631
+ if (isString(type) || type == "Date")
628
632
  sortedMembers.string.push(member);
633
+ else if (type == "JSON.Raw")
634
+ sortedMembers.object.push(member);
629
635
  else if (isBoolean(type) || type.startsWith("JSON.Box<bool"))
630
636
  sortedMembers.boolean.push(member);
631
637
  else if (isPrimitive(type) || type.startsWith("JSON.Box<") || isEnum(type, this.sources.get(this.schema.node.range.source), this.parser))
@@ -665,21 +671,15 @@ export class JSONTransform extends Visitor {
665
671
  const FLOAT_TYPES = ["f32", "f64"];
666
672
  const INTEGER_TYPES = [...UNSIGNED_INTEGER_TYPES, ...SIGNED_INTEGER_TYPES];
667
673
  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) => {
674
+ const getDeserializer = (type, srcPtr, outPtr, member, keyOffset = 0, fastPath = false) => {
675
675
  const out = [];
676
676
  const resolvedType = stripNull(type);
677
+ const resolvedSchema = this.getSchema(resolvedType);
677
678
  const fieldOffset = `offsetof<this>(${JSON.stringify(member.name)})`;
678
- const fieldPtr = `${outPtr} + offsetof<this>(${JSON.stringify(member.name)})`;
679
679
  const valuePtr = keyOffset ? `${srcPtr} + ${keyOffset}` : srcPtr;
680
680
  if (INTEGER_TYPES.includes(resolvedType)) {
681
681
  const helper = SIGNED_INTEGER_TYPES.includes(resolvedType) ? "deserializeIntegerField" : "deserializeUnsignedField";
682
- out.push(`${srcPtr} = ${helper}<${resolvedType}>(${valuePtr}, srcEnd, ${fieldPtr});`);
682
+ out.push(`${srcPtr} = ${helper}<${resolvedType}>(${valuePtr}, srcEnd, ${outPtr}, ${fieldOffset});`);
683
683
  }
684
684
  else if (["string", "String"].includes(resolvedType)) {
685
685
  out.push("{");
@@ -689,125 +689,69 @@ export class JSONTransform extends Visitor {
689
689
  out.push(` ${srcPtr} = ${valuePtr} + 8;`);
690
690
  out.push(" } else {");
691
691
  }
692
- out.push(` ${srcPtr} = ${STRING_FIELD_DESERIALIZER}<${member.type}>(${valuePtr}, srcEnd, ${fieldPtr});`);
692
+ out.push(` ${srcPtr} = ${STRING_FIELD_DESERIALIZER}<${member.type}>(${valuePtr}, srcEnd, ${outPtr} + ${fieldOffset});`);
693
693
  if (member.node.type.isNullable) {
694
694
  out.push(" }");
695
695
  }
696
696
  out.push("}");
697
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)) {
698
+ else if (resolvedType == "Date") {
713
699
  out.push("{");
714
700
  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;`);
701
+ out.push(` if (load<u64>(${valuePtr}) == 30399761348886638) {`);
702
+ out.push(` store<${member.type}>(${outPtr}, changetype<${member.type}>(0), ${fieldOffset});`);
703
+ out.push(` ${srcPtr} = ${valuePtr} + 8;`);
718
704
  out.push(" } else {");
719
705
  }
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});`);
706
+ out.push(` if (load<u16>(${valuePtr}) != 0x22) break;`);
707
+ out.push(` let dateEnd = ${valuePtr} + 2;`);
708
+ out.push(` while (dateEnd < srcEnd) {`);
709
+ out.push(" if (load<u16>(dateEnd) == 0x22 && load<u16>(dateEnd - 2) != 0x5c) break;");
710
+ out.push(" dateEnd += 2;");
724
711
  out.push(" }");
725
- out.push(` ${srcPtr} = changetype<nonnull<${resolvedType}>>(value).__DESERIALIZE<${resolvedType}>(${srcPtr}, srcEnd, value);`);
712
+ out.push(" if (dateEnd >= srcEnd) break;");
713
+ out.push(` store<${resolvedType}>(${outPtr}, JSON.__deserialize<${resolvedType}>(${valuePtr}, dateEnd + 2), ${fieldOffset});`);
714
+ out.push(` ${srcPtr} = dateEnd + 2;`);
726
715
  if (member.node.type.isNullable) {
727
716
  out.push(" }");
728
717
  }
729
718
  out.push("}");
730
719
  }
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("}");
720
+ else if (resolvedType.startsWith("JSON.Box<") || resolvedType.startsWith("Box<")) {
721
+ const innerType = resolvedType.slice(resolvedType.indexOf("<") + 1, -1).trim();
722
+ out.push("{");
723
+ if (member.node.type.isNullable) {
724
+ out.push(` if (load<u64>(${valuePtr}) == 30399761348886638) {`);
725
+ out.push(` store<${member.type}>(${outPtr}, changetype<${member.type}>(0), ${fieldOffset});`);
726
+ out.push(` ${srcPtr} = ${valuePtr} + 8;`);
727
+ out.push(" } else {");
728
+ }
729
+ if (innerType == "bool" || innerType == "boolean") {
730
+ out.push(` if (load<u64>(${valuePtr}) == 28429475166421108) {`);
731
+ out.push(` store<${resolvedType}>(${outPtr}, changetype<${resolvedType}>(JSON.Box.from<${innerType}>(true)), ${fieldOffset});`);
732
+ out.push(` ${srcPtr} = ${valuePtr} + 8;`);
733
+ out.push(" } else if (load<u64>(" + valuePtr + ") == 32370086184550502 && load<u16>(" + valuePtr + ", 8) == 101) {");
734
+ out.push(` store<${resolvedType}>(${outPtr}, changetype<${resolvedType}>(JSON.Box.from<${innerType}>(false)), ${fieldOffset});`);
735
+ out.push(` ${srcPtr} = ${valuePtr} + 10;`);
736
+ out.push(" } else break;");
804
737
  }
805
738
  else {
806
- out.push(`${srcPtr} = deserializeArrayField_SWAR<${resolvedType}>(${srcPtr}, srcEnd, ${fieldPtr});`);
807
- out.push(`if (!${srcPtr}) break;`);
739
+ out.push(` let boxEnd = ${valuePtr};`);
740
+ out.push(" while (boxEnd < srcEnd) {");
741
+ out.push(" const code = load<u16>(boxEnd);");
742
+ out.push(" if (code == 0x2c || code == 0x7d) break;");
743
+ out.push(" boxEnd += 2;");
744
+ out.push(" }");
745
+ out.push(` if (boxEnd <= ${valuePtr}) break;`);
746
+ out.push(` store<${resolvedType}>(${outPtr}, changetype<${resolvedType}>(JSON.Box.from<${innerType}>(JSON.__deserialize<${innerType}>(${valuePtr}, boxEnd))), ${fieldOffset});`);
747
+ out.push(` ${srcPtr} = boxEnd;`);
808
748
  }
749
+ if (member.node.type.isNullable) {
750
+ out.push(" }");
751
+ }
752
+ out.push("}");
809
753
  }
810
- else {
754
+ else if (resolvedType == "JSON.Raw") {
811
755
  out.push("{");
812
756
  out.push(` const valueStart = ${srcPtr};`);
813
757
  out.push(" let depth: i32 = 0;");
@@ -839,41 +783,212 @@ export class JSONTransform extends Visitor {
839
783
  out.push(` ${srcPtr} += 2;`);
840
784
  out.push(" }");
841
785
  out.push(` if (inString || depth != 0 || ${srcPtr} <= valueStart) break;`);
842
- out.push(` store<${resolvedType}>(${outPtr}, JSON.__deserialize<${resolvedType}>(valueStart, ${srcPtr}), ${fieldOffset});`);
786
+ out.push(` store<${member.type}>(${outPtr}, JSON.Raw.from(JSON.Util.ptrToStr(valueStart, ${srcPtr})), ${fieldOffset});`);
843
787
  out.push("}");
844
788
  }
789
+ else if (isBoolean(resolvedType)) {
790
+ out.push(`if (load<u64>(${srcPtr}) == 28429475166421108) {`);
791
+ out.push(` store<${resolvedType}>(${outPtr}, true, ${fieldOffset});`);
792
+ out.push(` ${srcPtr} += 8;`);
793
+ out.push("} else if (load<u64>(" + srcPtr + ") == 32370086184550502 && load<u16>(" + srcPtr + ", 8) == 101) {");
794
+ out.push(` store<${resolvedType}>(${outPtr}, false, ${fieldOffset});`);
795
+ out.push(` ${srcPtr} += 10;`);
796
+ out.push("} else break;");
797
+ }
798
+ else if (FLOAT_TYPES.includes(resolvedType)) {
799
+ out.push(`${srcPtr} = deserializeFloatField<${resolvedType}>(${valuePtr}, srcEnd, ${outPtr}, ${fieldOffset});`);
800
+ }
801
+ else if (resolvedSchema && !resolvedSchema.custom) {
802
+ if (fastPath) {
803
+ out.push("break;");
804
+ return out;
805
+ }
806
+ out.push("{");
807
+ if (member.node.type.isNullable) {
808
+ out.push(` if (load<u64>(${srcPtr}) == 30399761348886638) {`);
809
+ out.push(` store<${resolvedType}>(${outPtr}, changetype<${resolvedType}>(0), ${fieldOffset});`);
810
+ out.push(` ${srcPtr} += 8;`);
811
+ out.push(" } else {");
812
+ }
813
+ out.push(` let value = load<${resolvedType}>(${outPtr}, ${fieldOffset});`);
814
+ out.push(` if (changetype<usize>(value) == 0) {`);
815
+ out.push(` value = changetype<${resolvedType}>(__new(offsetof<nonnull<${resolvedType}>>(), idof<nonnull<${resolvedType}>>()));`);
816
+ out.push(` store<${resolvedType}>(${outPtr}, value, ${fieldOffset});`);
817
+ out.push(" }");
818
+ out.push(` const valueStart = ${valuePtr};`);
819
+ out.push(` const valueEnd = JSON.Util.scanValueEnd(valueStart, srcEnd);`);
820
+ out.push(" if (!valueEnd) break;");
821
+ if (fastPath) {
822
+ out.push(` ${srcPtr} = changetype<nonnull<${resolvedType}>>(value).__DESERIALIZE_FAST<${resolvedType}>(valueStart, valueEnd, value);`);
823
+ }
824
+ else {
825
+ out.push(` ${srcPtr} = changetype<nonnull<${resolvedType}>>(value).__DESERIALIZE_SLOW<${resolvedType}>(valueStart, valueEnd, value);`);
826
+ }
827
+ if (member.node.type.isNullable) {
828
+ out.push(" }");
829
+ }
830
+ out.push("}");
831
+ }
832
+ else if (resolvedType.startsWith("Array<")) {
833
+ out.push("{");
834
+ if (member.node.type.isNullable) {
835
+ out.push(` if (load<u64>(${valuePtr}) == 30399761348886638) {`);
836
+ out.push(` store<${member.type}>(${outPtr}, changetype<${member.type}>(0), ${fieldOffset});`);
837
+ out.push(` ${srcPtr} = ${valuePtr} + 8;`);
838
+ out.push(" } else {");
839
+ }
840
+ out.push(` if (load<u16>(${valuePtr}) == 0x5b && load<u16>(${valuePtr}, 2) == 0x5d) {`);
841
+ out.push(` let value = load<${resolvedType}>(${outPtr}, ${fieldOffset});`);
842
+ if (member.node.type.isNullable) {
843
+ out.push(` if (changetype<usize>(value) == 0) {`);
844
+ out.push(` value = changetype<${resolvedType}>(instantiate<nonnull<${resolvedType}>>());`);
845
+ out.push(` store<${resolvedType}>(${outPtr}, value, ${fieldOffset});`);
846
+ out.push(" }");
847
+ }
848
+ out.push(" value.length = 0;");
849
+ out.push(` ${srcPtr} = ${valuePtr} + 4;`);
850
+ out.push(" } else {");
851
+ if (member.node.type.isNullable) {
852
+ out.push(` ${srcPtr} = deserializeArrayField_SWAR<${resolvedType}>(${valuePtr}, srcEnd, ${outPtr}, ${fieldOffset});`);
853
+ }
854
+ else {
855
+ out.push(` ${srcPtr} = deserializeArrayInto_SWAR<${resolvedType}>(${valuePtr}, srcEnd, load<${resolvedType}>(${outPtr}, ${fieldOffset}));`);
856
+ }
857
+ out.push(` if (!${srcPtr}) break;`);
858
+ out.push(" }");
859
+ if (member.node.type.isNullable) {
860
+ out.push(" }");
861
+ }
862
+ out.push("}");
863
+ }
864
+ else if (resolvedType.startsWith("Map<")) {
865
+ if (member.node.type.isNullable) {
866
+ out.push(`${srcPtr} = deserializeMapField<${resolvedType}>(${srcPtr}, srcEnd, ${outPtr}, ${fieldOffset});`);
867
+ }
868
+ else {
869
+ out.push(`${srcPtr} = deserializeMapInto<${resolvedType}>(${srcPtr}, srcEnd, load<${resolvedType}>(${outPtr}, ${fieldOffset}));`);
870
+ }
871
+ out.push(`if (!${srcPtr}) break;`);
872
+ }
873
+ else if (resolvedType.startsWith("Set<")) {
874
+ if (member.node.type.isNullable) {
875
+ out.push(`${srcPtr} = deserializeSetField<${resolvedType}>(${srcPtr}, srcEnd, ${outPtr}, ${fieldOffset});`);
876
+ }
877
+ else {
878
+ out.push(`${srcPtr} = deserializeSetInto<${resolvedType}>(${srcPtr}, srcEnd, load<${resolvedType}>(${outPtr}, ${fieldOffset}));`);
879
+ }
880
+ out.push(`if (!${srcPtr}) break;`);
881
+ }
882
+ else if (resolvedType.startsWith("StaticArray<")) {
883
+ out.push(`${srcPtr} = deserializeStaticArrayField<${resolvedType}>(${srcPtr}, srcEnd, ${outPtr}, ${fieldOffset});`);
884
+ out.push(`if (!${srcPtr}) break;`);
885
+ }
886
+ else if (resolvedType == "JSON.Value" || resolvedType == "JSON.Obj" || isEnum(resolvedType, this.sources.get(this.schema.node.range.source), this.parser)) {
887
+ out.push("break;");
888
+ }
889
+ else {
890
+ out.push("break;");
891
+ }
845
892
  return out;
846
893
  };
847
894
  indent = " ";
848
- DESERIALIZE_FAST += indent + "const dst = changetype<usize>(out);\n";
895
+ DESERIALIZE_FAST += indent + "const start = srcStart;\n";
849
896
  DESERIALIZE_FAST += indent + "do {\n";
850
897
  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;
898
+ if (supportsFastOptionalPath) {
899
+ DESERIALIZE_FAST += indent + "if (load<u16>(srcStart) !== 0x7b) break; // {\n";
900
+ DESERIALIZE_FAST += indent + "srcStart += 2;\n";
901
+ DESERIALIZE_FAST += indent + "let seenAny = false;\n\n";
902
+ for (let i = 0; i < this.schema.members.length; i++) {
903
+ const member = this.schema.members[i];
904
+ const key = JSON.stringify(member.alias || member.name);
905
+ if (key.length <= 2)
906
+ throw new Error("Key cannot be empty!");
907
+ const firstKeySection = key + ":";
908
+ const nextKeySection = "," + key + ":";
909
+ const firstKeyOffset = firstKeySection.length << 1;
910
+ const nextKeyOffset = nextKeySection.length << 1;
911
+ const resolvedType = stripNull(member.type);
912
+ const inlineStringValue = ["string", "String"].includes(resolvedType);
913
+ const deserializerFirst = getDeserializer(member.type, "srcStart", "changetype<usize>(out)", member, inlineStringValue ? firstKeyOffset : 0, true);
914
+ const deserializerNext = getDeserializer(member.type, "srcStart", "changetype<usize>(out)", member, inlineStringValue ? nextKeyOffset : 0, true);
915
+ const isOptional = member.flags.has(PropertyFlags.OmitNull) || member.flags.has(PropertyFlags.OmitIf);
916
+ if (!deserializerFirst.length || !deserializerNext.length) {
917
+ DESERIALIZE_FAST += indent + "break;\n\n";
918
+ continue;
919
+ }
920
+ DESERIALIZE_FAST += indent + "if (!seenAny) {\n";
921
+ indent += " ";
922
+ DESERIALIZE_FAST += indent + `if ( // ${firstKeySection}\n${(indent += " ")}${getComparisions(firstKeySection, "srcStart", "!=").join("\n" + indent + "|| ")}\n${(indent = indent.slice(0, -2))}) {\n`;
923
+ indent += " ";
924
+ if (isOptional) {
925
+ DESERIALIZE_FAST += indent + "// optional @omitnull field omitted\n";
926
+ }
927
+ else {
928
+ DESERIALIZE_FAST += indent + "break;\n";
929
+ }
930
+ indent = indent.slice(0, -2);
931
+ DESERIALIZE_FAST += indent + "} else {\n";
932
+ indent += " ";
933
+ if (!inlineStringValue)
934
+ DESERIALIZE_FAST += indent + `srcStart += ${firstKeyOffset};\n`;
935
+ DESERIALIZE_FAST += indent + deserializerFirst.join("\n" + indent) + "\n";
936
+ DESERIALIZE_FAST += indent + "seenAny = true;\n";
937
+ indent = indent.slice(0, -2);
938
+ DESERIALIZE_FAST += indent + "}\n";
939
+ indent = indent.slice(0, -2);
940
+ DESERIALIZE_FAST += indent + "} else {\n";
941
+ indent += " ";
942
+ DESERIALIZE_FAST += indent + `if ( // ${nextKeySection}\n${(indent += " ")}${getComparisions(nextKeySection, "srcStart", "!=").join("\n" + indent + "|| ")}\n${(indent = indent.slice(0, -2))}) {\n`;
943
+ indent += " ";
944
+ if (isOptional) {
945
+ DESERIALIZE_FAST += indent + "// optional @omitnull field omitted\n";
946
+ }
947
+ else {
948
+ DESERIALIZE_FAST += indent + "break;\n";
949
+ }
950
+ indent = indent.slice(0, -2);
951
+ DESERIALIZE_FAST += indent + "} else {\n";
952
+ indent += " ";
953
+ if (!inlineStringValue)
954
+ DESERIALIZE_FAST += indent + `srcStart += ${nextKeyOffset};\n`;
955
+ DESERIALIZE_FAST += indent + deserializerNext.join("\n" + indent) + "\n";
956
+ indent = indent.slice(0, -2);
957
+ DESERIALIZE_FAST += indent + "}\n";
958
+ indent = indent.slice(0, -2);
959
+ DESERIALIZE_FAST += indent + "}\n\n";
960
+ }
961
+ }
962
+ else {
963
+ for (let i = 0; i < this.schema.members.length; i++) {
964
+ const member = this.schema.members[i];
965
+ const key = JSON.stringify(member.alias || member.name);
966
+ if (key.length <= 2)
967
+ throw new Error("Key cannot be empty!");
968
+ const keySection = (i == 0 ? "{" : ",") + key + ":";
969
+ DESERIALIZE_FAST += indent + `if ( // ${keySection}\n${(indent += " ")}${getComparisions(keySection, "srcStart", "!=").join("\n" + indent + "|| ")}\n${(indent = indent.slice(0, -2))}) break;\n`;
970
+ const keyOffset = keySection.length << 1;
971
+ const resolvedType = stripNull(member.type);
972
+ const inlineStringValue = ["string", "String"].includes(resolvedType);
973
+ if (!inlineStringValue) {
974
+ DESERIALIZE_FAST += indent + `srcStart += ${keyOffset};\n\n`;
975
+ }
976
+ const deserializer = getDeserializer(member.type, "srcStart", "changetype<usize>(out)", member, inlineStringValue ? keyOffset : 0, true);
977
+ if (!deserializer.length) {
978
+ DESERIALIZE_FAST += indent + "break;\n\n";
979
+ continue;
980
+ }
981
+ DESERIALIZE_FAST += indent + deserializer.join("\n" + indent) + "\n\n";
868
982
  }
869
- DESERIALIZE_FAST += indent + deserializer.join("\n" + indent) + "\n\n";
870
983
  }
871
984
  DESERIALIZE_FAST += indent + "if (load<u16>(srcStart) !== 0x7d) break; // }\n";
872
985
  DESERIALIZE_FAST += indent + "srcStart += 2;\n";
873
986
  DESERIALIZE_FAST += indent + "return srcStart;\n";
874
987
  indent = indent.slice(0, -2);
875
988
  DESERIALIZE_FAST += indent + "} while (false);\n\n";
876
- DESERIALIZE_FAST += indent + 'throw new Error("Failed to parse JSON ");';
989
+ DESERIALIZE_FAST += indent + "if (isDefined(out.__INITIALIZE)) out.__INITIALIZE();\n";
990
+ DESERIALIZE_FAST += indent + "const end = JSON.Util.scanValueEnd(start, srcEnd);\n";
991
+ DESERIALIZE_FAST += indent + "return out.__DESERIALIZE_SLOW(start, end ? end : srcEnd, out);";
877
992
  indent = indent.slice(0, -2);
878
993
  DESERIALIZE_FAST += indent + "}";
879
994
  DESERIALIZE += indent + " let keyStart: usize = 0;\n";
@@ -1107,7 +1222,7 @@ export class JSONTransform extends Visitor {
1107
1222
  generateConsts(group);
1108
1223
  const first = group[0];
1109
1224
  const fName = first.alias || first.name;
1110
- DESERIALIZE += indent + " if (" + (first.generic ? "isDefined(out.__DESERIALIZE) &&" : "") + getComparison(fName) + ") { // " + fName + "\n";
1225
+ DESERIALIZE += indent + " if (" + getComparison(fName) + ") { // " + fName + "\n";
1111
1226
  DESERIALIZE += indent + " store<" + first.type + ">(changetype<usize>(out), JSON.__deserialize<" + first.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(first.name) + "));\n";
1112
1227
  DESERIALIZE += indent + " keyStart = 0;\n";
1113
1228
  DESERIALIZE += indent + " break;\n";
@@ -1115,7 +1230,7 @@ export class JSONTransform extends Visitor {
1115
1230
  for (let i = 1; i < group.length; i++) {
1116
1231
  const mem = group[i];
1117
1232
  const memName = mem.alias || mem.name;
1118
- DESERIALIZE += indent + " else if (" + (mem.generic ? "isDefined(out.__DESERIALIZE) &&" : "") + getComparison(memName) + ") { // " + memName + "\n";
1233
+ DESERIALIZE += indent + " else if (" + getComparison(memName) + ") { // " + memName + "\n";
1119
1234
  DESERIALIZE += indent + " store<" + mem.type + ">(changetype<usize>(out), JSON.__deserialize<" + mem.type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
1120
1235
  DESERIALIZE += indent + " keyStart = 0;\n";
1121
1236
  DESERIALIZE += indent + " break;\n";
@@ -1206,7 +1321,20 @@ export class JSONTransform extends Visitor {
1206
1321
  const first = group[0];
1207
1322
  const fName = first.alias || first.name;
1208
1323
  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";
1324
+ if (first.type.startsWith("JSON.Box<bool") || first.type.startsWith("JSON.Box<boolean") || first.type.startsWith("Box<bool") || first.type.startsWith("Box<boolean")) {
1325
+ DESERIALIZE +=
1326
+ indent +
1327
+ " store<" +
1328
+ first.type +
1329
+ ">(changetype<usize>(out), changetype<" +
1330
+ first.type +
1331
+ ">(JSON.Box.from<bool>(true)), offsetof<this>(" +
1332
+ JSON.stringify(first.name) +
1333
+ "));\n";
1334
+ }
1335
+ else {
1336
+ DESERIALIZE += indent + " store<boolean>(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(first.name) + "));\n";
1337
+ }
1210
1338
  DESERIALIZE += indent + " srcStart += 2;\n";
1211
1339
  DESERIALIZE += indent + " keyStart = 0;\n";
1212
1340
  DESERIALIZE += indent + " break;\n";
@@ -1215,7 +1343,20 @@ export class JSONTransform extends Visitor {
1215
1343
  const mem = group[i];
1216
1344
  const memName = mem.alias || mem.name;
1217
1345
  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";
1346
+ if (mem.type.startsWith("JSON.Box<bool") || mem.type.startsWith("JSON.Box<boolean") || mem.type.startsWith("Box<bool") || mem.type.startsWith("Box<boolean")) {
1347
+ DESERIALIZE +=
1348
+ indent +
1349
+ " store<" +
1350
+ mem.type +
1351
+ ">(changetype<usize>(out), changetype<" +
1352
+ mem.type +
1353
+ ">(JSON.Box.from<bool>(true)), offsetof<this>(" +
1354
+ JSON.stringify(mem.name) +
1355
+ "));\n";
1356
+ }
1357
+ else {
1358
+ DESERIALIZE += indent + " store<boolean>(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
1359
+ }
1219
1360
  DESERIALIZE += indent + " srcStart += 2;\n";
1220
1361
  DESERIALIZE += indent + " keyStart = 0;\n";
1221
1362
  DESERIALIZE += indent + " break;\n";
@@ -1250,7 +1391,20 @@ export class JSONTransform extends Visitor {
1250
1391
  const first = group[0];
1251
1392
  const fName = first.alias || first.name;
1252
1393
  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";
1394
+ if (first.type.startsWith("JSON.Box<bool") || first.type.startsWith("JSON.Box<boolean") || first.type.startsWith("Box<bool") || first.type.startsWith("Box<boolean")) {
1395
+ DESERIALIZE +=
1396
+ indent +
1397
+ " store<" +
1398
+ first.type +
1399
+ ">(changetype<usize>(out), changetype<" +
1400
+ first.type +
1401
+ ">(JSON.Box.from<bool>(false)), offsetof<this>(" +
1402
+ JSON.stringify(first.name) +
1403
+ "));\n";
1404
+ }
1405
+ else {
1406
+ DESERIALIZE += indent + " store<boolean>(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(first.name) + "));\n";
1407
+ }
1254
1408
  DESERIALIZE += indent + " srcStart += 2;\n";
1255
1409
  DESERIALIZE += indent + " keyStart = 0;\n";
1256
1410
  DESERIALIZE += indent + " break;\n";
@@ -1259,7 +1413,20 @@ export class JSONTransform extends Visitor {
1259
1413
  const mem = group[i];
1260
1414
  const memName = mem.alias || mem.name;
1261
1415
  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";
1416
+ if (mem.type.startsWith("JSON.Box<bool") || mem.type.startsWith("JSON.Box<boolean") || mem.type.startsWith("Box<bool") || mem.type.startsWith("Box<boolean")) {
1417
+ DESERIALIZE +=
1418
+ indent +
1419
+ " store<" +
1420
+ mem.type +
1421
+ ">(changetype<usize>(out), changetype<" +
1422
+ mem.type +
1423
+ ">(JSON.Box.from<bool>(false)), offsetof<this>(" +
1424
+ JSON.stringify(mem.name) +
1425
+ "));\n";
1426
+ }
1427
+ else {
1428
+ DESERIALIZE += indent + " store<boolean>(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(mem.name) + "));\n";
1429
+ }
1263
1430
  DESERIALIZE += indent + " srcStart += 2;\n";
1264
1431
  DESERIALIZE += indent + " keyStart = 0;\n";
1265
1432
  DESERIALIZE += indent + " break;\n";
@@ -1340,30 +1507,26 @@ export class JSONTransform extends Visitor {
1340
1507
  SERIALIZE += indent + "bs.offset += 2;\n";
1341
1508
  SERIALIZE += "}";
1342
1509
  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
- }
1510
+ INITIALIZE += " return this;\n";
1511
+ INITIALIZE += "}";
1347
1512
  if (DEBUG > 0) {
1348
1513
  console.log(SERIALIZE_CUSTOM || SERIALIZE);
1349
- if (!useFastPath)
1350
- console.log(INITIALIZE);
1514
+ console.log(INITIALIZE);
1351
1515
  console.log(DESERIALIZE_CUSTOM || DESERIALIZE);
1352
1516
  }
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>");
1354
1517
  const SERIALIZE_METHOD = SimpleParser.parseClassMember(SERIALIZE_CUSTOM || SERIALIZE, node);
1355
- const INITIALIZE_METHOD = !useFastPath ? SimpleParser.parseClassMember(INITIALIZE, node) : null;
1518
+ const INITIALIZE_METHOD = SimpleParser.parseClassMember(INITIALIZE, node);
1356
1519
  const DESERIALIZE_CUSTOM_METHOD = DESERIALIZE_CUSTOM ? SimpleParser.parseClassMember(DESERIALIZE_CUSTOM, node) : null;
1357
- const DESERIALIZE_METHOD = DESERIALIZE_CUSTOM ? null : SimpleParser.parseClassMember(DESERIALIZE_DIRECT, node);
1520
+ const DESERIALIZE_SLOW_METHOD = SimpleParser.parseClassMember(DESERIALIZE, node);
1358
1521
  const DESERIALIZE_FAST_METHOD = useFastPath ? SimpleParser.parseClassMember(DESERIALIZE_FAST, node) : null;
1359
1522
  if (!node.members.find((v) => v.name.text == "__SERIALIZE"))
1360
1523
  node.members.push(SERIALIZE_METHOD);
1361
- if (!useFastPath && INITIALIZE_METHOD && !node.members.find((v) => v.name.text == "__INITIALIZE"))
1524
+ if (INITIALIZE_METHOD && !node.members.find((v) => v.name.text == "__INITIALIZE"))
1362
1525
  node.members.push(INITIALIZE_METHOD);
1363
1526
  if (DESERIALIZE_CUSTOM_METHOD && !node.members.find((v) => v.name.text == "__DESERIALIZE_CUSTOM"))
1364
1527
  node.members.push(DESERIALIZE_CUSTOM_METHOD);
1365
- if (DESERIALIZE_METHOD && !node.members.find((v) => v.name.text == "__DESERIALIZE"))
1366
- node.members.push(DESERIALIZE_METHOD);
1528
+ if (!DESERIALIZE_CUSTOM && DESERIALIZE_SLOW_METHOD && !node.members.find((v) => v.name.text == "__DESERIALIZE_SLOW"))
1529
+ node.members.push(DESERIALIZE_SLOW_METHOD);
1367
1530
  if (!DESERIALIZE_CUSTOM && useFastPath && DESERIALIZE_FAST_METHOD && !node.members.find((v) => v.name.text == "__DESERIALIZE_FAST"))
1368
1531
  node.members.push(DESERIALIZE_FAST_METHOD);
1369
1532
  super.visitClassDeclaration(node);
@@ -1375,23 +1538,21 @@ export class JSONTransform extends Visitor {
1375
1538
  generateEmptyMethods(node) {
1376
1539
  const SERIALIZE_EMPTY = "@inline __SERIALIZE(ptr: usize): void {\n bs.proposeSize(4);\n store<u32>(bs.offset, 8192123);\n bs.offset += 4;\n}";
1377
1540
  const INITIALIZE_EMPTY = "@inline __INITIALIZE(): this {\n return this;\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;
1541
+ const DESERIALIZE_SLOW_EMPTY = "@inline __DESERIALIZE_SLOW<__JSON_T>(srcStart: usize, srcEnd: usize, out: __JSON_T): usize {\n return srcEnd;\n}";
1380
1542
  if (DEBUG > 0) {
1381
1543
  console.log(SERIALIZE_EMPTY);
1382
- if (!useFastPath)
1383
- console.log(INITIALIZE_EMPTY);
1384
- console.log(DESERIALIZE_EMPTY);
1544
+ console.log(INITIALIZE_EMPTY);
1545
+ console.log(DESERIALIZE_SLOW_EMPTY);
1385
1546
  }
1386
1547
  const SERIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(SERIALIZE_EMPTY, node);
1387
- const INITIALIZE_METHOD_EMPTY = !useFastPath ? SimpleParser.parseClassMember(INITIALIZE_EMPTY, node) : null;
1388
- const DESERIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(DESERIALIZE_EMPTY, node);
1548
+ const INITIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(INITIALIZE_EMPTY, node);
1549
+ const DESERIALIZE_SLOW_METHOD_EMPTY = SimpleParser.parseClassMember(DESERIALIZE_SLOW_EMPTY, node);
1389
1550
  if (!node.members.find((v) => v.name.text == "__SERIALIZE"))
1390
1551
  node.members.push(SERIALIZE_METHOD_EMPTY);
1391
- if (!useFastPath && INITIALIZE_METHOD_EMPTY && !node.members.find((v) => v.name.text == "__INITIALIZE"))
1552
+ if (INITIALIZE_METHOD_EMPTY && !node.members.find((v) => v.name.text == "__INITIALIZE"))
1392
1553
  node.members.push(INITIALIZE_METHOD_EMPTY);
1393
- if (!node.members.find((v) => v.name.text == "__DESERIALIZE"))
1394
- node.members.push(DESERIALIZE_METHOD_EMPTY);
1554
+ if (!node.members.find((v) => v.name.text == "__DESERIALIZE_SLOW"))
1555
+ node.members.push(DESERIALIZE_SLOW_METHOD_EMPTY);
1395
1556
  }
1396
1557
  visitImportStatement(node) {
1397
1558
  super.visitImportStatement(node);
@@ -1412,14 +1573,28 @@ export class JSONTransform extends Visitor {
1412
1573
  const deserializeIntegerFieldImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "deserializeIntegerField" || d.name.text == "deserializeIntegerField"));
1413
1574
  const deserializeUnsignedFieldImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "deserializeUnsignedField" || d.name.text == "deserializeUnsignedField"));
1414
1575
  const deserializeFloatFieldImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "deserializeFloatField" || d.name.text == "deserializeFloatField"));
1576
+ const scanValueEndImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "scanValueEnd" || d.name.text == "scanValueEnd"));
1415
1577
  const deserializeArrayField_SWARImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "deserializeArrayField_SWAR" || d.name.text == "deserializeArrayField_SWAR"));
1578
+ const deserializeArrayInto_SWARImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "deserializeArrayInto_SWAR" || d.name.text == "deserializeArrayInto_SWAR"));
1579
+ const deserializeMapFieldImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "deserializeMapField" || d.name.text == "deserializeMapField"));
1580
+ const deserializeMapIntoImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "deserializeMapInto" || d.name.text == "deserializeMapInto"));
1581
+ const deserializeSetFieldImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "deserializeSetField" || d.name.text == "deserializeSetField"));
1582
+ const deserializeSetIntoImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "deserializeSetInto" || d.name.text == "deserializeSetInto"));
1583
+ const deserializeStaticArrayFieldImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "deserializeStaticArrayField" || d.name.text == "deserializeStaticArrayField"));
1416
1584
  const deserializeStringFieldSWARImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "deserializeStringField_SWAR" || d.name.text == "deserializeStringField_SWAR"));
1417
1585
  const deserializeStringFieldSIMDImport = this.imports.find((i) => i.declarations?.find((d) => d.foreignName.text == "deserializeStringField_SIMD" || d.name.text == "deserializeStringField_SIMD"));
1418
1586
  const sourceText = readFileSync(fromPath).toString();
1419
1587
  const hasLocalDeserializeIntegerField = /\bdeserializeIntegerField\b/.test(sourceText);
1420
1588
  const hasLocalDeserializeUnsignedField = /\bdeserializeUnsignedField\b/.test(sourceText);
1421
1589
  const hasLocalDeserializeFloatField = /\bdeserializeFloatField\b/.test(sourceText);
1590
+ const hasLocalScanValueEnd = /\bscanValueEnd\b/.test(sourceText);
1422
1591
  const hasLocaldeserializeArrayField_SWAR = /\bdeserializeArrayField_SWAR\b/.test(sourceText);
1592
+ const hasLocaldeserializeArrayInto_SWAR = /\bdeserializeArrayInto_SWAR\b/.test(sourceText);
1593
+ const hasLocaldeserializeMapField = /\bdeserializeMapField\b/.test(sourceText);
1594
+ const hasLocaldeserializeMapInto = /\bdeserializeMapInto\b/.test(sourceText);
1595
+ const hasLocaldeserializeSetField = /\bdeserializeSetField\b/.test(sourceText);
1596
+ const hasLocaldeserializeSetInto = /\bdeserializeSetInto\b/.test(sourceText);
1597
+ const hasLocaldeserializeStaticArrayField = /\bdeserializeStaticArrayField\b/.test(sourceText);
1423
1598
  const hasLocalDeserializeStringFieldSWAR = /\bdeserializeStringField_SWAR\b/.test(sourceText);
1424
1599
  const hasLocalDeserializeStringFieldSIMD = /\bdeserializeStringField_SIMD\b/.test(sourceText);
1425
1600
  let baseRel = path.posix.join(...path.relative(path.dirname(fromPath), path.join(baseDir)).split(path.sep));
@@ -1448,19 +1623,25 @@ export class JSONTransform extends Visitor {
1448
1623
  console.log("Added import: " + toString(replaceNode) + " to " + node.range.source.normalizedPath + "\n");
1449
1624
  }
1450
1625
  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);
1626
+ const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("deserializeIntegerField", node.range, false), null, node.range)], Node.createStringLiteralExpression(path.posix.join(baseRel, "assembly", "deserialize", "simple", "integer"), node.range), node.range);
1452
1627
  node.range.source.statements.unshift(replaceNode);
1453
1628
  if (DEBUG > 0)
1454
1629
  console.log("Added import: " + toString(replaceNode) + " to " + node.range.source.normalizedPath + "\n");
1455
1630
  }
1456
1631
  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);
1632
+ const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("deserializeUnsignedField", node.range, false), null, node.range)], Node.createStringLiteralExpression(path.posix.join(baseRel, "assembly", "deserialize", "simple", "unsigned"), node.range), node.range);
1458
1633
  node.range.source.statements.unshift(replaceNode);
1459
1634
  if (DEBUG > 0)
1460
1635
  console.log("Added import: " + toString(replaceNode) + " to " + node.range.source.normalizedPath + "\n");
1461
1636
  }
1462
1637
  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);
1638
+ const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("deserializeFloatField", node.range, false), null, node.range)], Node.createStringLiteralExpression(path.posix.join(baseRel, "assembly", "deserialize", "simple", "float"), node.range), node.range);
1639
+ node.range.source.statements.unshift(replaceNode);
1640
+ if (DEBUG > 0)
1641
+ console.log("Added import: " + toString(replaceNode) + " to " + node.range.source.normalizedPath + "\n");
1642
+ }
1643
+ if (!scanValueEndImport && !hasLocalScanValueEnd) {
1644
+ const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("scanValueEnd", node.range, false), null, node.range)], Node.createStringLiteralExpression(path.posix.join(baseRel, "assembly", "deserialize", "swar", "array", "shared"), node.range), node.range);
1464
1645
  node.range.source.statements.unshift(replaceNode);
1465
1646
  if (DEBUG > 0)
1466
1647
  console.log("Added import: " + toString(replaceNode) + " to " + node.range.source.normalizedPath + "\n");
@@ -1471,6 +1652,42 @@ export class JSONTransform extends Visitor {
1471
1652
  if (DEBUG > 0)
1472
1653
  console.log("Added import: " + toString(replaceNode) + " to " + node.range.source.normalizedPath + "\n");
1473
1654
  }
1655
+ if (!deserializeArrayInto_SWARImport && !hasLocaldeserializeArrayInto_SWAR) {
1656
+ const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("deserializeArrayInto_SWAR", node.range, false), null, node.range)], Node.createStringLiteralExpression(path.posix.join(baseRel, "assembly", "deserialize", "swar", "array"), node.range), node.range);
1657
+ node.range.source.statements.unshift(replaceNode);
1658
+ if (DEBUG > 0)
1659
+ console.log("Added import: " + toString(replaceNode) + " to " + node.range.source.normalizedPath + "\n");
1660
+ }
1661
+ if (!deserializeMapFieldImport && !hasLocaldeserializeMapField) {
1662
+ const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("deserializeMapField", node.range, false), null, node.range)], Node.createStringLiteralExpression(path.posix.join(baseRel, "assembly", "deserialize", "simple", "map"), node.range), node.range);
1663
+ node.range.source.statements.unshift(replaceNode);
1664
+ if (DEBUG > 0)
1665
+ console.log("Added import: " + toString(replaceNode) + " to " + node.range.source.normalizedPath + "\n");
1666
+ }
1667
+ if (!deserializeMapIntoImport && !hasLocaldeserializeMapInto) {
1668
+ const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("deserializeMapInto", node.range, false), null, node.range)], Node.createStringLiteralExpression(path.posix.join(baseRel, "assembly", "deserialize", "simple", "map"), node.range), node.range);
1669
+ node.range.source.statements.unshift(replaceNode);
1670
+ if (DEBUG > 0)
1671
+ console.log("Added import: " + toString(replaceNode) + " to " + node.range.source.normalizedPath + "\n");
1672
+ }
1673
+ if (!deserializeSetFieldImport && !hasLocaldeserializeSetField) {
1674
+ const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("deserializeSetField", node.range, false), null, node.range)], Node.createStringLiteralExpression(path.posix.join(baseRel, "assembly", "deserialize", "simple", "set"), node.range), node.range);
1675
+ node.range.source.statements.unshift(replaceNode);
1676
+ if (DEBUG > 0)
1677
+ console.log("Added import: " + toString(replaceNode) + " to " + node.range.source.normalizedPath + "\n");
1678
+ }
1679
+ if (!deserializeSetIntoImport && !hasLocaldeserializeSetInto) {
1680
+ const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("deserializeSetInto", node.range, false), null, node.range)], Node.createStringLiteralExpression(path.posix.join(baseRel, "assembly", "deserialize", "simple", "set"), node.range), node.range);
1681
+ node.range.source.statements.unshift(replaceNode);
1682
+ if (DEBUG > 0)
1683
+ console.log("Added import: " + toString(replaceNode) + " to " + node.range.source.normalizedPath + "\n");
1684
+ }
1685
+ if (!deserializeStaticArrayFieldImport && !hasLocaldeserializeStaticArrayField) {
1686
+ const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("deserializeStaticArrayField", node.range, false), null, node.range)], Node.createStringLiteralExpression(path.posix.join(baseRel, "assembly", "deserialize", "simple", "staticarray"), node.range), node.range);
1687
+ node.range.source.statements.unshift(replaceNode);
1688
+ if (DEBUG > 0)
1689
+ console.log("Added import: " + toString(replaceNode) + " to " + node.range.source.normalizedPath + "\n");
1690
+ }
1474
1691
  const codegenMode = getCodegenMode(this.program);
1475
1692
  if (codegenMode !== JSONMode.SIMD && !deserializeStringFieldSWARImport && !hasLocalDeserializeStringFieldSWAR) {
1476
1693
  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);