json-as 1.3.9 → 1.5.0

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 (122) hide show
  1. package/CHANGELOG.md +60 -19
  2. package/README.md +120 -21
  3. package/assembly/custom/chars.ts +39 -78
  4. package/assembly/deserialize/index/arbitrary.ts +28 -10
  5. package/assembly/deserialize/index/float.ts +2 -4
  6. package/assembly/deserialize/index/integer.ts +2 -4
  7. package/assembly/deserialize/index/object.ts +6 -1
  8. package/assembly/deserialize/index/string.ts +2 -7
  9. package/assembly/deserialize/index/unsigned.ts +2 -4
  10. package/assembly/deserialize/naive/array/arbitrary.ts +3 -136
  11. package/assembly/deserialize/naive/array/array.ts +30 -1
  12. package/assembly/deserialize/naive/array/integer.ts +2 -7
  13. package/assembly/deserialize/naive/array/map.ts +10 -14
  14. package/assembly/deserialize/naive/array/object.ts +10 -14
  15. package/assembly/deserialize/naive/array/struct.ts +19 -1
  16. package/assembly/deserialize/naive/bool.ts +1 -5
  17. package/assembly/deserialize/naive/date.ts +1 -2
  18. package/assembly/deserialize/naive/float.ts +4 -11
  19. package/assembly/deserialize/naive/integer.ts +2 -4
  20. package/assembly/deserialize/naive/map.ts +42 -205
  21. package/assembly/deserialize/naive/object.ts +291 -174
  22. package/assembly/deserialize/naive/raw.ts +1 -5
  23. package/assembly/deserialize/naive/set.ts +3 -6
  24. package/assembly/deserialize/naive/staticarray.ts +2 -4
  25. package/assembly/deserialize/naive/string.ts +68 -24
  26. package/assembly/deserialize/naive/typedarray.ts +1 -2
  27. package/assembly/deserialize/naive/unsigned.ts +2 -4
  28. package/assembly/deserialize/simd/array/integer.ts +5 -13
  29. package/assembly/deserialize/simd/float.ts +5 -12
  30. package/assembly/deserialize/simd/integer.ts +6 -15
  31. package/assembly/deserialize/simd/string.ts +21 -43
  32. package/assembly/deserialize/swar/array/arbitrary.ts +1 -2
  33. package/assembly/deserialize/swar/array/array.ts +2 -4
  34. package/assembly/deserialize/swar/array/bool.ts +2 -4
  35. package/assembly/deserialize/swar/array/box.ts +1 -2
  36. package/assembly/deserialize/swar/array/float.ts +8 -21
  37. package/assembly/deserialize/swar/array/generic.ts +2 -4
  38. package/assembly/deserialize/swar/array/integer.ts +13 -27
  39. package/assembly/deserialize/swar/array/map.ts +1 -2
  40. package/assembly/deserialize/swar/array/object.ts +2 -4
  41. package/assembly/deserialize/swar/array/raw.ts +1 -2
  42. package/assembly/deserialize/swar/array/shared.ts +9 -21
  43. package/assembly/deserialize/swar/array/string.ts +4 -10
  44. package/assembly/deserialize/swar/array/struct.ts +3 -9
  45. package/assembly/deserialize/swar/array.ts +1 -3
  46. package/assembly/deserialize/swar/float.ts +7 -17
  47. package/assembly/deserialize/swar/integer.ts +6 -15
  48. package/assembly/deserialize/swar/string.ts +40 -54
  49. package/assembly/deserialize/swar/typedarray.ts +4 -4
  50. package/assembly/index.d.ts +259 -21
  51. package/assembly/index.ts +1704 -266
  52. package/assembly/serialize/index/arbitrary.ts +70 -4
  53. package/assembly/serialize/index/jsonarray.ts +51 -0
  54. package/assembly/serialize/index/object.ts +39 -14
  55. package/assembly/serialize/index/string.ts +1 -2
  56. package/assembly/serialize/index/typedarray.ts +1 -2
  57. package/assembly/serialize/index.ts +1 -0
  58. package/assembly/serialize/naive/array.ts +23 -34
  59. package/assembly/serialize/naive/bool.ts +0 -1
  60. package/assembly/serialize/naive/float.ts +16 -25
  61. package/assembly/serialize/naive/integer.ts +1 -5
  62. package/assembly/serialize/naive/raw.ts +1 -2
  63. package/assembly/serialize/naive/set.ts +0 -4
  64. package/assembly/serialize/naive/staticarray.ts +0 -5
  65. package/assembly/serialize/naive/string.ts +11 -7
  66. package/assembly/serialize/naive/typedarray.ts +0 -6
  67. package/assembly/serialize/simd/string.ts +1 -3
  68. package/assembly/serialize/swar/string.ts +2 -4
  69. package/assembly/util/atoi-fast.ts +4 -14
  70. package/assembly/util/atoi.ts +1 -2
  71. package/assembly/util/bytes.ts +1 -2
  72. package/assembly/util/idofd.ts +1 -2
  73. package/assembly/util/isSpace.ts +1 -2
  74. package/assembly/util/itoa-fast.ts +9 -15
  75. package/assembly/util/nextPowerOf2.ts +1 -2
  76. package/assembly/util/parsefloat-fast.ts +4 -7
  77. package/assembly/util/ptrToStr.ts +1 -2
  78. package/assembly/util/scanValueEnd.ts +1 -2
  79. package/assembly/util/scanValueEndSimd.ts +198 -0
  80. package/assembly/util/scanValueEndSwar.ts +184 -0
  81. package/assembly/util/scientific.ts +8 -14
  82. package/assembly/util/simd-int.ts +4 -8
  83. package/assembly/util/snp.ts +2 -7
  84. package/assembly/util/stringScan.ts +2 -4
  85. package/assembly/util/swar-int.ts +8 -16
  86. package/assembly/util/swar.ts +2 -4
  87. package/lib/as-bs.ts +57 -42
  88. package/package.json +27 -10
  89. package/transform/lib/builder.d.ts +0 -1
  90. package/transform/lib/builder.js +0 -1
  91. package/transform/lib/index.d.ts +0 -1
  92. package/transform/lib/index.js +617 -326
  93. package/transform/lib/linkers/alias.d.ts +0 -1
  94. package/transform/lib/linkers/alias.js +0 -1
  95. package/transform/lib/linkers/custom.d.ts +0 -1
  96. package/transform/lib/linkers/custom.js +0 -1
  97. package/transform/lib/linkers/imports.d.ts +0 -1
  98. package/transform/lib/linkers/imports.js +0 -1
  99. package/transform/lib/types.d.ts +4 -2
  100. package/transform/lib/types.js +5 -1
  101. package/transform/lib/util.d.ts +0 -1
  102. package/transform/lib/util.js +0 -1
  103. package/transform/lib/visitor.d.ts +0 -1
  104. package/transform/lib/visitor.js +0 -1
  105. package/assembly/util/dragonbox-cache.ts +0 -445
  106. package/assembly/util/dragonbox.ts +0 -660
  107. package/transform/lib/builder.d.ts.map +0 -1
  108. package/transform/lib/builder.js.map +0 -1
  109. package/transform/lib/index.d.ts.map +0 -1
  110. package/transform/lib/index.js.map +0 -1
  111. package/transform/lib/linkers/alias.d.ts.map +0 -1
  112. package/transform/lib/linkers/alias.js.map +0 -1
  113. package/transform/lib/linkers/custom.d.ts.map +0 -1
  114. package/transform/lib/linkers/custom.js.map +0 -1
  115. package/transform/lib/linkers/imports.d.ts.map +0 -1
  116. package/transform/lib/linkers/imports.js.map +0 -1
  117. package/transform/lib/types.d.ts.map +0 -1
  118. package/transform/lib/types.js.map +0 -1
  119. package/transform/lib/util.d.ts.map +0 -1
  120. package/transform/lib/util.js.map +0 -1
  121. package/transform/lib/visitor.d.ts.map +0 -1
  122. package/transform/lib/visitor.js.map +0 -1
@@ -21,8 +21,7 @@ import {
21
21
  * @param srcEnd Pointer just past the last code unit.
22
22
  * @returns The parsed value, truncated to `T`.
23
23
  */
24
- // @ts-expect-error: @inline is a valid decorator
25
- @inline export function deserializeInteger<T extends number>(
24
+ export function deserializeInteger<T extends number>(
26
25
  srcStart: usize,
27
26
  srcEnd: usize,
28
27
  ): T {
@@ -46,8 +45,7 @@ import {
46
45
  * @param dstOffset Byte offset of the field within `dstObj`.
47
46
  * @returns The source position immediately after the last digit consumed.
48
47
  */
49
- // @ts-expect-error: @inline is a valid decorator
50
- @inline export function deserializeIntegerField<T extends number>(
48
+ export function deserializeIntegerField<T extends number>(
51
49
  srcStart: usize,
52
50
  srcEnd: usize,
53
51
  dstObj: usize,
@@ -1 +1,6 @@
1
- export { deserializeObject } from "../naive/object";
1
+ export {
2
+ deserializeObject,
3
+ deserializeJsonArray,
4
+ setParseSrc,
5
+ getParseSrc,
6
+ } from "../naive/object";
@@ -12,11 +12,7 @@ import {
12
12
  deserializeStringField_SWAR,
13
13
  } from "../swar/string";
14
14
 
15
-
16
- @inline export function deserializeString(
17
- srcStart: usize,
18
- srcEnd: usize,
19
- ): string {
15
+ export function deserializeString(srcStart: usize, srcEnd: usize): string {
20
16
  if (JSON_MODE == JSONMode.SIMD) {
21
17
  return deserializeString_SIMD(srcStart, srcEnd);
22
18
  } else if (JSON_MODE == JSONMode.NAIVE) {
@@ -26,8 +22,7 @@ import {
26
22
  }
27
23
  }
28
24
 
29
-
30
- @inline export function deserializeStringField<T extends string | null>(
25
+ export function deserializeStringField<T extends string | null>(
31
26
  srcStart: usize,
32
27
  srcEnd: usize,
33
28
  dstObj: usize,
@@ -21,8 +21,7 @@ import {
21
21
  * @param srcEnd Pointer just past the last code unit.
22
22
  * @returns The parsed value, truncated to `T`.
23
23
  */
24
- // @ts-expect-error: @inline is a valid decorator
25
- @inline export function deserializeUnsigned<T extends number>(
24
+ export function deserializeUnsigned<T extends number>(
26
25
  srcStart: usize,
27
26
  srcEnd: usize,
28
27
  ): T {
@@ -46,8 +45,7 @@ import {
46
45
  * @param dstOffset Byte offset of the field within `dstObj`.
47
46
  * @returns The source position immediately after the last digit consumed.
48
47
  */
49
- // @ts-expect-error: @inline is a valid decorator
50
- @inline export function deserializeUnsignedField<T extends number>(
48
+ export function deserializeUnsignedField<T extends number>(
51
49
  srcStart: usize,
52
50
  srcEnd: usize,
53
51
  dstObj: usize,
@@ -1,18 +1,5 @@
1
- import {
2
- BACK_SLASH,
3
- BRACE_LEFT,
4
- BRACE_RIGHT,
5
- BRACKET_LEFT,
6
- BRACKET_RIGHT,
7
- CHAR_F,
8
- CHAR_N,
9
- CHAR_T,
10
- COMMA,
11
- QUOTE,
12
- } from "../../../custom/chars";
13
1
  import { JSON } from "../../../";
14
- import { isSpace, scanStringEnd } from "../../../util";
15
- import { ptrToStr } from "../../../util/ptrToStr";
2
+ import { parseArrayBody } from "../object";
16
3
 
17
4
  export function deserializeArbitraryArray(
18
5
  srcStart: usize,
@@ -22,127 +9,7 @@ export function deserializeArbitraryArray(
22
9
  const out = changetype<JSON.Value[]>(
23
10
  dst || changetype<usize>(instantiate<JSON.Value[]>()),
24
11
  );
25
- let lastIndex: usize = 0;
26
- let depth: u32 = 0;
27
- // if (load<u16>(srcStart) != BRACKET_LEFT)
28
- srcStart += 2;
29
- while (srcStart < srcEnd) {
30
- const code = load<u16>(srcStart);
31
- // console.log("code: " + String.fromCharCode(code));
32
- if (code == BRACE_LEFT) {
33
- lastIndex = srcStart;
34
- depth++;
35
- srcStart += 2;
36
- while (srcStart < srcEnd) {
37
- const code = load<u16>(srcStart);
38
- if (code == BRACE_RIGHT) {
39
- if (--depth == 0) {
40
- // @ts-ignore: type
41
- out.push(JSON.__deserialize<JSON.Value>(lastIndex, srcStart + 2));
42
- // console.log("Value (object): " + ptrToStr(lastIndex, srcStart + 2));
43
- break;
44
- }
45
- } else if (code == BRACE_LEFT) depth++;
46
- srcStart += 2;
47
- }
48
- } else if (code == QUOTE) {
49
- lastIndex = srcStart;
50
- srcStart = scanStringEnd(srcStart, srcEnd);
51
- if (srcStart >= srcEnd)
52
- throw new Error("Unterminated string in JSON array");
53
- // @ts-ignore: exists
54
- out.push(JSON.__deserialize<JSON.Value>(lastIndex, srcStart + 2));
55
- srcStart += 2;
56
- // console.log("next: " + String.fromCharCode(load<u16>(srcStart)));
57
- } else if (code - 48 <= 9 || code == 45) {
58
- // console.log("trigger int")
59
- lastIndex = srcStart;
60
- srcStart += 2;
61
- while (srcStart < srcEnd) {
62
- const code = load<u16>(srcStart);
63
- if (code == COMMA || code == BRACKET_RIGHT || isSpace(code)) {
64
- // @ts-ignore: type
65
- out.push(JSON.__deserialize<JSON.Value>(lastIndex, srcStart));
66
- // console.log("Value (number): " + ptrToStr(lastIndex, srcStart));
67
- break;
68
- }
69
- srcStart += 2;
70
- }
71
- // console.log("next: " + String.fromCharCode(load<u16>(srcStart)));
72
- } else if (code == BRACE_LEFT) {
73
- lastIndex = srcStart;
74
- depth++;
75
- srcStart += 2;
76
- while (srcStart < srcEnd) {
77
- const code = load<u16>(srcStart);
78
- if (code == BRACE_RIGHT) {
79
- if (--depth == 0) {
80
- // @ts-ignore: type
81
- out.push(JSON.__deserialize<JSON.Value>(lastIndex, srcStart + 2));
82
- // console.log("Value (object): " + ptrToStr(lastIndex, srcStart + 2));
83
- while (isSpace(load<u16>((srcStart += 2)))) {
84
- /* empty */
85
- }
86
- break;
87
- }
88
- } else if (code == BRACE_LEFT) depth++;
89
- srcStart += 2;
90
- }
91
- } else if (code == BRACKET_LEFT) {
92
- lastIndex = srcStart;
93
- depth++;
94
- srcStart += 2;
95
- while (srcStart < srcEnd) {
96
- const code = load<u16>(srcStart);
97
- if (code == QUOTE) {
98
- srcStart = scanStringEnd(srcStart, srcEnd);
99
- if (srcStart >= srcEnd)
100
- throw new Error("Unterminated string in JSON array");
101
- } else if (code == BRACKET_RIGHT) {
102
- if (--depth == 0) {
103
- // @ts-ignore: type
104
- out.push(JSON.__deserialize<JSON.Value>(lastIndex, srcStart + 2));
105
- // console.log("Value (array): " + ptrToStr(lastIndex, srcStart + 2));
106
- while (isSpace(load<u16>((srcStart += 2)))) {
107
- /* empty */
108
- }
109
- break;
110
- }
111
- } else if (code == BRACKET_LEFT) depth++;
112
- srcStart += 2;
113
- }
114
- } else if (code == CHAR_T) {
115
- if (load<u64>(srcStart) == 28429475166421108) {
116
- // @ts-ignore: type
117
- out.push(JSON.__deserialize<JSON.Value>(srcStart, (srcStart += 8)));
118
- // console.log("Value (bool): " + ptrToStr(srcStart - 8, srcStart));
119
- // while (isSpace(load<u16>((srcStart += 2)))) {
120
- // /* empty */
121
- // }
122
- // console.log("next: " + String.fromCharCode(load<u16>(srcStart)));
123
- }
124
- } else if (code == CHAR_F) {
125
- if (load<u64>(srcStart, 2) == 28429466576093281) {
126
- // @ts-ignore: type
127
- out.push(JSON.__deserialize<JSON.Value>(srcStart, (srcStart += 10)));
128
- // console.log("Value (bool): " + ptrToStr(srcStart - 10, srcStart));
129
- // while (isSpace(load<u16>((srcStart += 2)))) {
130
- // /* empty */
131
- // }
132
- // console.log("next: " + String.fromCharCode(load<u16>(srcStart)));
133
- }
134
- } else if (code == CHAR_N) {
135
- if (load<u64>(srcStart) == 30399761348886638) {
136
- // console.log("Value (null): " + ptrToStr(srcStart, srcStart + 8));
137
- // @ts-ignore: type
138
- out.push(JSON.__deserialize<JSON.Value>(srcStart, (srcStart += 8)));
139
- // while (isSpace(load<u16>((srcStart += 2)))) {
140
- // /* empty */
141
- // }
142
- }
143
- }
144
- srcStart += 2;
145
- }
146
- // @ts-ignore: type
12
+ // Skip the opening '[' and parse elements single-pass until the matching ']'.
13
+ parseArrayBody(out, srcStart + 2, srcEnd);
147
14
  return out;
148
15
  }
@@ -1,5 +1,6 @@
1
1
  import { BRACKET_LEFT, BRACKET_RIGHT } from "../../../custom/chars";
2
2
  import { JSON } from "../../../";
3
+ import { parseArrayBody } from "../object";
3
4
 
4
5
  export function deserializeArrayArray<T extends unknown[][]>(
5
6
  srcStart: usize,
@@ -9,9 +10,37 @@ export function deserializeArrayArray<T extends unknown[][]>(
9
10
  const out = changetype<nonnull<T>>(
10
11
  dst || changetype<usize>(instantiate<T>()),
11
12
  );
13
+
14
+ // Compile-time: is each inner array a dynamic JSON.Value[] (vs a typed array)?
15
+ let arbitraryInner = false;
16
+ if (isManaged<valueof<valueof<T>>>() || isReference<valueof<valueof<T>>>()) {
17
+ // @ts-ignore: instanceof on the (reference) inner element type
18
+ arbitraryInner =
19
+ changetype<nonnull<valueof<valueof<T>>>>(0) instanceof JSON.Value;
20
+ }
21
+
22
+ srcStart += 2; // skip the outer '['
23
+
24
+ if (isReference<valueof<valueof<T>>>() && arbitraryInner) {
25
+ // Single-pass: each inner `[...]` is a JSON.Value[] parsed in one scan
26
+ // (this also correctly skips ']' inside strings, unlike the depth scan).
27
+ while (srcStart < srcEnd) {
28
+ if (load<u16>(srcStart) == BRACKET_LEFT) {
29
+ const inner = instantiate<JSON.Value[]>();
30
+ srcStart = parseArrayBody(inner, srcStart + 2, srcEnd);
31
+ // @ts-ignore: valueof<T> is JSON.Value[] in this branch
32
+ out.push(changetype<valueof<T>>(changetype<usize>(inner)));
33
+ } else {
34
+ srcStart += 2;
35
+ }
36
+ }
37
+ return out;
38
+ }
39
+
40
+ // Typed inner arrays: scan each element's bounds, then hand the exact range
41
+ // to its generated (bounds-taking) deserializer.
12
42
  let lastIndex: usize = 0;
13
43
  let depth: u32 = 0;
14
- srcStart += 2;
15
44
  while (srcStart < srcEnd - 2) {
16
45
  const code = load<u16>(srcStart);
17
46
  if (code == BRACKET_LEFT && depth++ == 0) {
@@ -2,14 +2,9 @@ import { atoi, isSpace } from "../../../util";
2
2
  import { COMMA, BRACKET_LEFT, BRACKET_RIGHT } from "../../../custom/chars";
3
3
 
4
4
  // Strict RFC 8259 integer-token check over [start, end): optional minus (signed
5
- // types only), then a lone `0` or [1-9] digits no leading zeros, fraction,
5
+ // types only), then a lone `0` or [1-9] digits - no leading zeros, fraction,
6
6
  // exponent, or trailing garbage. Throws otherwise.
7
- // @ts-ignore: inline
8
- @inline function validateJSONInteger(
9
- start: usize,
10
- end: usize,
11
- signed: bool,
12
- ): void {
7
+ function validateJSONInteger(start: usize, end: usize, signed: bool): void {
13
8
  let ptr = start;
14
9
  if (ptr < end && load<u16>(ptr) == 45) {
15
10
  if (!signed) throw new Error("Invalid JSON number: minus on unsigned");
@@ -1,11 +1,7 @@
1
- import {
2
- BRACE_LEFT,
3
- BRACE_RIGHT,
4
- BRACKET_LEFT,
5
- BRACKET_RIGHT,
6
- } from "../../../custom/chars";
1
+ import { BRACE_LEFT, BRACKET_LEFT, BRACKET_RIGHT } from "../../../custom/chars";
7
2
  import { JSON } from "../../..";
8
3
  import { isSpace } from "util/string";
4
+ import { deserializeMapBody } from "../map";
9
5
 
10
6
  export function deserializeMapArray<T extends Map<any, any>[]>(
11
7
  srcStart: usize,
@@ -15,8 +11,6 @@ export function deserializeMapArray<T extends Map<any, any>[]>(
15
11
  const out = changetype<nonnull<T>>(
16
12
  dst || changetype<usize>(instantiate<T>()),
17
13
  );
18
- let lastIndex: usize = 0;
19
- let depth: u32 = 0;
20
14
 
21
15
  while (srcEnd > srcStart && isSpace(load<u16>(srcEnd - 2))) srcEnd -= 2;
22
16
 
@@ -34,14 +28,16 @@ export function deserializeMapArray<T extends Map<any, any>[]>(
34
28
  (srcEnd - srcStart).toString(),
35
29
  );
36
30
 
31
+ // Each `{...}` map element is parsed in a single pass via deserializeMapBody,
32
+ // which reports where it ended - no separate scan to find the closing brace.
37
33
  while (srcStart < srcEnd) {
38
- const code = load<u16>(srcStart);
39
- if (code == BRACE_LEFT && depth++ == 0) {
40
- lastIndex = srcStart;
41
- } else if (code == BRACE_RIGHT && --depth == 0) {
42
- out.push(JSON.__deserialize<valueof<T>>(lastIndex, (srcStart += 2)));
34
+ if (load<u16>(srcStart) == BRACE_LEFT) {
35
+ const m = instantiate<valueof<T>>();
36
+ srcStart = deserializeMapBody<valueof<T>>(srcStart, srcEnd, m);
37
+ out.push(m);
38
+ } else {
39
+ srcStart += 2;
43
40
  }
44
- srcStart += 2;
45
41
  }
46
42
  return out;
47
43
  }
@@ -1,11 +1,7 @@
1
- import {
2
- BRACE_LEFT,
3
- BRACE_RIGHT,
4
- BRACKET_LEFT,
5
- BRACKET_RIGHT,
6
- } from "../../../custom/chars";
1
+ import { BRACE_LEFT, BRACKET_LEFT, BRACKET_RIGHT } from "../../../custom/chars";
7
2
  import { JSON } from "../../..";
8
3
  import { isSpace } from "util/string";
4
+ import { parseObjectBody } from "../object";
9
5
 
10
6
  export function deserializeObjectArray<T extends unknown[]>(
11
7
  srcStart: usize,
@@ -15,8 +11,6 @@ export function deserializeObjectArray<T extends unknown[]>(
15
11
  const out = changetype<nonnull<T>>(
16
12
  dst || changetype<usize>(instantiate<T>()),
17
13
  );
18
- let lastIndex: usize = 0;
19
- let depth: u32 = 0;
20
14
 
21
15
  while (srcEnd > srcStart && isSpace(load<u16>(srcEnd - 2))) srcEnd -= 2;
22
16
 
@@ -34,14 +28,16 @@ export function deserializeObjectArray<T extends unknown[]>(
34
28
  (srcEnd - srcStart).toString(),
35
29
  );
36
30
 
31
+ // Each `{...}` element is parsed in a single pass via parseObjectBody, which
32
+ // reports where it ended - no separate scan to find the closing brace.
37
33
  while (srcStart < srcEnd) {
38
- const code = load<u16>(srcStart);
39
- if (code == BRACE_LEFT && depth++ == 0) {
40
- lastIndex = srcStart;
41
- } else if (code == BRACE_RIGHT && --depth == 0) {
42
- out.push(JSON.__deserialize<valueof<T>>(lastIndex, (srcStart += 2)));
34
+ if (load<u16>(srcStart) == BRACE_LEFT) {
35
+ const obj = new JSON.Obj();
36
+ srcStart = parseObjectBody(obj, srcStart + 2, srcEnd);
37
+ out.push(changetype<valueof<T>>(changetype<usize>(obj)));
38
+ } else {
39
+ srcStart += 2;
43
40
  }
44
- srcStart += 2;
45
41
  }
46
42
  return out;
47
43
  }
@@ -34,14 +34,32 @@ export function deserializeStructArray<T extends unknown[]>(
34
34
  (srcEnd - srcStart).toString(),
35
35
  );
36
36
 
37
+ // Reuse existing element slots when `dst` already holds elements (no per-call
38
+ // allocation on a reused array); fall back to push for fresh/extra slots and
39
+ // trim any leftovers from a previous, longer parse.
40
+ let index = 0;
37
41
  while (srcStart < srcEnd) {
38
42
  const code = load<u16>(srcStart);
39
43
  if (code == BRACE_LEFT && depth++ == 0) {
40
44
  lastIndex = srcStart;
41
45
  } else if (code == BRACE_RIGHT && --depth == 0) {
42
- out.push(JSON.__deserialize<valueof<T>>(lastIndex, (srcStart += 2)));
46
+ const valueEnd = (srcStart += 2);
47
+ if (<usize>index < <usize>out.length) {
48
+ const slot = changetype<usize>(unchecked(out[index]));
49
+ if (slot != 0) {
50
+ JSON.__deserialize<valueof<T>>(lastIndex, valueEnd, slot);
51
+ } else {
52
+ unchecked(
53
+ (out[index] = JSON.__deserialize<valueof<T>>(lastIndex, valueEnd)),
54
+ );
55
+ }
56
+ } else {
57
+ out.push(JSON.__deserialize<valueof<T>>(lastIndex, valueEnd));
58
+ }
59
+ index++;
43
60
  }
44
61
  srcStart += 2;
45
62
  }
63
+ if (<usize>index < <usize>out.length) out.length = index;
46
64
  return out;
47
65
  }
@@ -1,8 +1,4 @@
1
- // @ts-ignore: inline
2
- @inline export function deserializeBoolean(
3
- srcStart: usize,
4
- srcEnd: usize,
5
- ): boolean {
1
+ export function deserializeBoolean(srcStart: usize, srcEnd: usize): boolean {
6
2
  const block = load<u64>(srcStart);
7
3
  if (block == 28429475166421108) return true;
8
4
  else if (block == 32370086184550502 && load<u16>(srcStart, 8) == 101)
@@ -1,7 +1,6 @@
1
1
  import { ptrToStr } from "../../util/ptrToStr";
2
2
 
3
- // @ts-ignore: inline
4
- @inline export function deserializeDate(srcStart: usize, srcEnd: usize): Date {
3
+ export function deserializeDate(srcStart: usize, srcEnd: usize): Date {
5
4
  // Use AssemblyScript's date parser
6
5
  const d = Date.fromString(ptrToStr(srcStart + 2, srcEnd - 2));
7
6
 
@@ -7,8 +7,7 @@ import { isSpace } from "../../util";
7
7
  // garbage. f64.parse alone is lenient (parses a numeric prefix and ignores the
8
8
  // rest), so this guard is what makes the naive value path reject malformed
9
9
  // numbers like `0e`, `-01`, `1.`, `2.e3`, `0x42`.
10
- // @ts-ignore: inline
11
- @inline function validateJSONNumber(srcStart: usize, srcEnd: usize): void {
10
+ function validateJSONNumber(srcStart: usize, srcEnd: usize): void {
12
11
  let ptr = srcStart;
13
12
  while (ptr < srcEnd && isSpace(load<u16>(ptr))) ptr += 2;
14
13
  let end = srcEnd;
@@ -62,11 +61,7 @@ import { isSpace } from "../../util";
62
61
  if (ptr != end) throw new Error("Invalid JSON number: trailing characters");
63
62
  }
64
63
 
65
- // @ts-ignore: inline
66
- @inline export function deserializeFloat_NAIVE<T>(
67
- srcStart: usize,
68
- srcEnd: usize,
69
- ): T {
64
+ export function deserializeFloat_NAIVE<T>(srcStart: usize, srcEnd: usize): T {
70
65
  validateJSONNumber(srcStart, srcEnd);
71
66
  // @ts-ignore
72
67
  const type: T = 0;
@@ -76,8 +71,7 @@ import { isSpace } from "../../util";
76
71
  return f32.parse(ptrToStr(srcStart, srcEnd));
77
72
  }
78
73
 
79
- // @ts-ignore: inline
80
- @inline function scanFloatEnd(srcStart: usize, srcEnd: usize): usize {
74
+ function scanFloatEnd(srcStart: usize, srcEnd: usize): usize {
81
75
  let ptr = srcStart;
82
76
  if (ptr < srcEnd && load<u16>(ptr) == 45) ptr += 2; // optional minus
83
77
 
@@ -115,8 +109,7 @@ import { isSpace } from "../../util";
115
109
  return ptr;
116
110
  }
117
111
 
118
- // @ts-ignore: inline
119
- @inline export function deserializeFloatField_NAIVE<T extends number>(
112
+ export function deserializeFloatField_NAIVE<T extends number>(
120
113
  srcStart: usize,
121
114
  srcEnd: usize,
122
115
  dstObj: usize,
@@ -1,15 +1,13 @@
1
1
  import { atoi } from "../../util/atoi";
2
2
 
3
- // @ts-ignore: inline
4
- @inline export function deserializeInteger_NAIVE<T extends number>(
3
+ export function deserializeInteger_NAIVE<T extends number>(
5
4
  srcStart: usize,
6
5
  srcEnd: usize,
7
6
  ): T {
8
7
  return atoi<T>(srcStart, srcEnd);
9
8
  }
10
9
 
11
- // @ts-ignore: inline
12
- @inline export function deserializeIntegerField_NAIVE<T extends number>(
10
+ export function deserializeIntegerField_NAIVE<T extends number>(
13
11
  srcStart: usize,
14
12
  srcEnd: usize,
15
13
  dstObj: usize,