json-as 1.2.3 → 1.2.5

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 (62) hide show
  1. package/.claude/settings.local.json +9 -0
  2. package/ARCHITECTURE.md +320 -0
  3. package/CONTRIBUTING.md +238 -0
  4. package/LICENSE +2 -2
  5. package/README.md +34 -2
  6. package/TODO +1 -0
  7. package/assembly/custom/chars.ts +9 -0
  8. package/assembly/deserialize/simd/string.ts +6 -41
  9. package/assembly/deserialize/simple/set.ts +169 -0
  10. package/assembly/deserialize/simple/staticarray/array.ts +37 -0
  11. package/assembly/deserialize/simple/staticarray/bool.ts +39 -0
  12. package/assembly/deserialize/simple/staticarray/float.ts +44 -0
  13. package/assembly/deserialize/simple/staticarray/integer.ts +44 -0
  14. package/assembly/deserialize/simple/staticarray/string.ts +45 -0
  15. package/assembly/deserialize/simple/staticarray/struct.ts +47 -0
  16. package/assembly/deserialize/simple/staticarray.ts +28 -0
  17. package/assembly/deserialize/swar/string.ts +6 -5
  18. package/assembly/index.ts +337 -143
  19. package/assembly/serialize/simd/string.ts +14 -17
  20. package/assembly/serialize/simple/set.ts +34 -0
  21. package/assembly/serialize/simple/staticarray.ts +30 -0
  22. package/assembly/serialize/swar/string.ts +50 -36
  23. package/assembly/test.ts +20 -38
  24. package/assembly/util/swar.ts +2 -2
  25. package/eslint.config.js +77 -0
  26. package/lib/as-bs.ts +143 -50
  27. package/package.json +18 -5
  28. package/transform/lib/builder.d.ts +87 -0
  29. package/transform/lib/builder.d.ts.map +1 -0
  30. package/transform/lib/builder.js +169 -169
  31. package/transform/lib/builder.js.map +1 -1
  32. package/transform/lib/index.d.ts +32 -0
  33. package/transform/lib/index.d.ts.map +1 -0
  34. package/transform/lib/index.js +40 -18
  35. package/transform/lib/index.js.map +1 -1
  36. package/transform/lib/linkers/alias.d.ts +12 -0
  37. package/transform/lib/linkers/alias.d.ts.map +1 -0
  38. package/transform/lib/linkers/alias.js +1 -1
  39. package/transform/lib/linkers/alias.js.map +1 -1
  40. package/transform/lib/linkers/custom.d.ts +10 -0
  41. package/transform/lib/linkers/custom.d.ts.map +1 -0
  42. package/transform/lib/linkers/imports.d.ts +3 -0
  43. package/transform/lib/linkers/imports.d.ts.map +1 -0
  44. package/transform/lib/linkers/imports.js +1 -1
  45. package/transform/lib/linkers/imports.js.map +1 -1
  46. package/transform/lib/types.d.ts +66 -0
  47. package/transform/lib/types.d.ts.map +1 -0
  48. package/transform/lib/types.js +6 -5
  49. package/transform/lib/types.js.map +1 -1
  50. package/transform/lib/util.d.ts +18 -0
  51. package/transform/lib/util.d.ts.map +1 -0
  52. package/transform/lib/util.js +4 -4
  53. package/transform/lib/util.js.map +1 -1
  54. package/transform/lib/visitor.d.ts +84 -0
  55. package/transform/lib/visitor.d.ts.map +1 -0
  56. package/transform/lib/visitor.js +76 -76
  57. package/transform/lib/visitor.js.map +1 -1
  58. package/transform/tsconfig.json +29 -2
  59. package/assembly/serialize/swar/number.ts +0 -0
  60. package/assembly/test.mask.ts +0 -87
  61. package/transform/lib/linkers/classes.js +0 -36
  62. package/transform/lib/linkers/classes.js.map +0 -1
@@ -3,7 +3,7 @@ import { BACK_SLASH } from "../../custom/chars";
3
3
  import { DESERIALIZE_ESCAPE_TABLE, ESCAPE_HEX_TABLE } from "../../globals/tables";
4
4
  import { hex4_to_u16_swar } from "../../util/swar";
5
5
 
6
- // @ts-ignore: decorator allowed
6
+ // @ts-expect-error: @lazy is a valid decorator
7
7
  @lazy const SPLAT_5C = i16x8.splat(0x5C); // \
8
8
 
9
9
  // Overflow Pattern for Unicode Escapes (READ)
@@ -71,15 +71,17 @@ export function deserializeString_SIMD(srcStart: usize, srcEnd: usize): string {
71
71
  const block = load<v128>(srcStart);
72
72
  store<v128>(bs.offset, block);
73
73
 
74
- const eq5C = i16x8.eq(load<v128>(srcStart), SPLAT_5C);
75
- let mask = i16x8.bitmask(eq5C);
74
+ const eq5C = i16x8.eq(block, SPLAT_5C);
75
+
76
76
  // Early exit
77
- if (mask === 0) {
77
+ if (!v128.any_true(eq5C)) {
78
78
  srcStart += 16;
79
79
  bs.offset += 16;
80
80
  continue;
81
81
  }
82
82
 
83
+ let mask = i16x8.bitmask(eq5C);
84
+
83
85
  let srcChg: usize = 0;
84
86
  let lastLane: usize = 0;
85
87
  do {
@@ -157,40 +159,3 @@ export function deserializeString_SIMD(srcStart: usize, srcEnd: usize): string {
157
159
 
158
160
  return bs.out<string>();
159
161
  }
160
-
161
- /**
162
- * Computes a per-lane mask identifying UTF-16 code units whose **low byte**
163
- * is the ASCII backslash (`'\\'`, 0x5C).
164
- *
165
- * The mask is produced in two stages:
166
- * 1. Detects bytes equal to 0x5C using a SWAR equality test.
167
- * 2. Clears matches where 0x5C appears in the **high byte** of a UTF-16 code unit,
168
- * ensuring only valid low-byte backslashes are reported.
169
- *
170
- * Each matching lane sets itself to 0x80.
171
- */
172
- // @ts-ignore: decorator
173
- @inline function backslash_mask(block: u64): u64 {
174
- const b = block ^ 0x005C_005C_005C_005C;
175
- const backslash_mask = (b - 0x0001_0001_0001_0001) & ~b & 0x0080_0080_0080_0080;
176
- const high_byte_mask =
177
- ~(((block - 0x0100_0100_0100_0100) & ~block & 0x8000_8000_8000_8000)
178
- ^ 0x8000_8000_8000_8000) >> 8;
179
- return backslash_mask & high_byte_mask;
180
- }
181
-
182
- /**
183
- * Computes a per-lane mask identifying UTF-16 code units whose **low byte**
184
- * is the ASCII backslash (`'\\'`, 0x5C).
185
- *
186
- * Each matching lane sets itself to 0x80.
187
- *
188
- * WARNING: The low byte of a code unit *may* be a backslash, thus triggering false positives!
189
- * This is useful for a hot path where it is possible to detect the false positive scalarly.
190
- */
191
- // @ts-ignore: decorator
192
- @inline function backslash_mask_unsafe(block: u64): u64 {
193
- const b = block ^ 0x005C_005C_005C_005C;
194
- const backslash_mask = (b - 0x0001_0001_0001_0001) & ~b & 0x0080_0080_0080_0080;
195
- return backslash_mask;
196
- }
@@ -0,0 +1,169 @@
1
+ import { JSON } from "../..";
2
+ import { BACK_SLASH, BRACKET_LEFT, BRACKET_RIGHT, BRACE_LEFT, BRACE_RIGHT, CHAR_F, CHAR_N, CHAR_T, COMMA, QUOTE } from "../../custom/chars";
3
+ import { isSpace, atoi } from "../../util";
4
+
5
+ export function deserializeSet<T extends Set<any>>(srcStart: usize, srcEnd: usize, dst: usize): T {
6
+ const out = changetype<nonnull<T>>(dst || changetype<usize>(instantiate<T>()));
7
+
8
+ while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
9
+ while (srcEnd > srcStart && isSpace(load<u16>(srcEnd - 2))) srcEnd -= 2;
10
+
11
+ if (srcStart >= srcEnd) throw new Error("Input string had zero length or was all whitespace");
12
+ if (load<u16>(srcStart) != BRACKET_LEFT) throw new Error("Expected '[' at start of set");
13
+ if (load<u16>(srcEnd - 2) != BRACKET_RIGHT) throw new Error("Expected ']' at end of set");
14
+
15
+ srcStart += 2;
16
+
17
+ while (srcStart < srcEnd - 2) {
18
+ let code = load<u16>(srcStart);
19
+ while (isSpace(code)) code = load<u16>((srcStart += 2));
20
+
21
+ // @ts-ignore: type
22
+ if (isString<indexof<T>>()) {
23
+ if (code == QUOTE) {
24
+ const lastIndex = srcStart;
25
+ srcStart += 2;
26
+ while (srcStart < srcEnd) {
27
+ const c = load<u16>(srcStart);
28
+ if (c == QUOTE && load<u16>(srcStart - 2) != BACK_SLASH) {
29
+ // @ts-ignore: type
30
+ out.add(JSON.__deserialize<indexof<T>>(lastIndex, srcStart + 2));
31
+ srcStart += 2;
32
+ break;
33
+ }
34
+ srcStart += 2;
35
+ }
36
+ }
37
+ // @ts-ignore: type
38
+ } else if (isBoolean<indexof<T>>()) {
39
+ if (code == CHAR_T) {
40
+ // @ts-ignore: type
41
+ out.add(<indexof<T>>true);
42
+ srcStart += 8;
43
+ } else if (code == CHAR_F) {
44
+ // @ts-ignore: type
45
+ out.add(<indexof<T>>false);
46
+ srcStart += 10;
47
+ }
48
+ // @ts-ignore: type
49
+ } else if (isInteger<indexof<T>>()) {
50
+ if (code - 48 <= 9 || code == 45) {
51
+ const lastIndex = srcStart;
52
+ srcStart += 2;
53
+ while (srcStart < srcEnd) {
54
+ const c = load<u16>(srcStart);
55
+ if (c == COMMA || c == BRACKET_RIGHT || isSpace(c)) {
56
+ // @ts-ignore: type
57
+ out.add(atoi<indexof<T>>(lastIndex, srcStart));
58
+ break;
59
+ }
60
+ srcStart += 2;
61
+ }
62
+ }
63
+ // @ts-ignore: type
64
+ } else if (isFloat<indexof<T>>()) {
65
+ if (code - 48 <= 9 || code == 45) {
66
+ const lastIndex = srcStart;
67
+ srcStart += 2;
68
+ while (srcStart < srcEnd) {
69
+ const c = load<u16>(srcStart);
70
+ if (c == COMMA || c == BRACKET_RIGHT || isSpace(c)) {
71
+ // @ts-ignore: type
72
+ out.add(JSON.__deserialize<indexof<T>>(lastIndex, srcStart));
73
+ break;
74
+ }
75
+ srcStart += 2;
76
+ }
77
+ }
78
+ // @ts-ignore: type
79
+ } else if (isManaged<indexof<T>>() || isReference<indexof<T>>()) {
80
+ // @ts-ignore: type
81
+ const type = changetype<nonnull<indexof<T>>>(0);
82
+ if (code == BRACE_LEFT) {
83
+ // Object
84
+ const lastIndex = srcStart;
85
+ let depth: u32 = 1;
86
+ srcStart += 2;
87
+ while (srcStart < srcEnd) {
88
+ const c = load<u16>(srcStart);
89
+ if (c == QUOTE) {
90
+ srcStart += 2;
91
+ while (!(load<u16>(srcStart) == QUOTE && load<u16>(srcStart - 2) != BACK_SLASH)) srcStart += 2;
92
+ } else if (c == BRACE_RIGHT) {
93
+ if (--depth == 0) {
94
+ srcStart += 2;
95
+ // @ts-ignore: type
96
+ out.add(JSON.__deserialize<indexof<T>>(lastIndex, srcStart));
97
+ break;
98
+ }
99
+ } else if (c == BRACE_LEFT) {
100
+ depth++;
101
+ }
102
+ srcStart += 2;
103
+ }
104
+ } else if (code == BRACKET_LEFT) {
105
+ // Nested array/set
106
+ const lastIndex = srcStart;
107
+ let depth: u32 = 1;
108
+ srcStart += 2;
109
+ while (srcStart < srcEnd) {
110
+ const c = load<u16>(srcStart);
111
+ if (c == BRACKET_RIGHT) {
112
+ if (--depth == 0) {
113
+ srcStart += 2;
114
+ // @ts-ignore: type
115
+ out.add(JSON.__deserialize<indexof<T>>(lastIndex, srcStart));
116
+ break;
117
+ }
118
+ } else if (c == BRACKET_LEFT) {
119
+ depth++;
120
+ }
121
+ srcStart += 2;
122
+ }
123
+ } else if (type instanceof JSON.Raw) {
124
+ // Handle JSON.Raw
125
+ if (code == QUOTE) {
126
+ const lastIndex = srcStart;
127
+ srcStart += 2;
128
+ while (srcStart < srcEnd) {
129
+ const c = load<u16>(srcStart);
130
+ if (c == QUOTE && load<u16>(srcStart - 2) != BACK_SLASH) {
131
+ // @ts-ignore: type
132
+ out.add(JSON.__deserialize<indexof<T>>(lastIndex, srcStart + 2));
133
+ srcStart += 2;
134
+ break;
135
+ }
136
+ srcStart += 2;
137
+ }
138
+ } else if (code - 48 <= 9 || code == 45) {
139
+ const lastIndex = srcStart;
140
+ srcStart += 2;
141
+ while (srcStart < srcEnd) {
142
+ const c = load<u16>(srcStart);
143
+ if (c == COMMA || c == BRACKET_RIGHT || isSpace(c)) {
144
+ // @ts-ignore: type
145
+ out.add(JSON.__deserialize<indexof<T>>(lastIndex, srcStart));
146
+ break;
147
+ }
148
+ srcStart += 2;
149
+ }
150
+ } else if (code == CHAR_T) {
151
+ // @ts-ignore: type
152
+ out.add(JSON.__deserialize<indexof<T>>(srcStart, srcStart + 8));
153
+ srcStart += 8;
154
+ } else if (code == CHAR_F) {
155
+ // @ts-ignore: type
156
+ out.add(JSON.__deserialize<indexof<T>>(srcStart, srcStart + 10));
157
+ srcStart += 10;
158
+ } else if (code == CHAR_N) {
159
+ // @ts-ignore: type
160
+ out.add(JSON.__deserialize<indexof<T>>(srcStart, srcStart + 8));
161
+ srcStart += 8;
162
+ }
163
+ }
164
+ }
165
+ srcStart += 2;
166
+ }
167
+
168
+ return out;
169
+ }
@@ -0,0 +1,37 @@
1
+ import { BRACKET_LEFT, BRACKET_RIGHT } from "../../../custom/chars";
2
+ import { JSON } from "../../../";
3
+
4
+ export function deserializeStaticArrayArray<T extends StaticArray<any>>(srcStart: usize, srcEnd: usize, dst: usize): T {
5
+ let count: i32 = 0;
6
+ let depth: u32 = 0;
7
+ let ptr = srcStart + 2;
8
+ while (ptr < srcEnd - 2) {
9
+ const code = load<u16>(ptr);
10
+ if (code == BRACKET_LEFT && depth++ == 0) {
11
+ // start of nested array
12
+ } else if (code == BRACKET_RIGHT && --depth == 0) {
13
+ count++;
14
+ }
15
+ ptr += 2;
16
+ }
17
+
18
+ const outSize = <usize>count << alignof<valueof<T>>();
19
+ const out = changetype<nonnull<T>>(dst || __new(outSize, idof<T>()));
20
+
21
+ // Second pass: populate values
22
+ let index = 0;
23
+ let lastIndex: usize = 0;
24
+ depth = 0;
25
+ srcStart += 2;
26
+ while (srcStart < srcEnd - 2) {
27
+ const code = load<u16>(srcStart);
28
+ if (code == BRACKET_LEFT && depth++ == 0) {
29
+ lastIndex = srcStart;
30
+ } else if (code == BRACKET_RIGHT && --depth == 0) {
31
+ unchecked((out[index++] = JSON.__deserialize<valueof<T>>(lastIndex, srcStart + 2)));
32
+ }
33
+ srcStart += 2;
34
+ }
35
+
36
+ return out;
37
+ }
@@ -0,0 +1,39 @@
1
+ export function deserializeStaticArrayBoolean<T extends StaticArray<any>>(srcStart: usize, srcEnd: usize, dst: usize): T {
2
+ // First pass: count elements using same logic as Array deserializer
3
+ let count: i32 = 0;
4
+ let ptr = srcStart + 2; // skip [
5
+ while (ptr < srcEnd) {
6
+ const block = load<u64>(ptr);
7
+ if (block == 28429475166421108) {
8
+ count++;
9
+ ptr += 10;
10
+ } else if (block == 32370086184550502 && load<u16>(ptr, 8) == 101) {
11
+ count++;
12
+ ptr += 12;
13
+ } else {
14
+ ptr += 2;
15
+ }
16
+ }
17
+
18
+ // Allocate StaticArray with correct size
19
+ const outSize = <usize>count << alignof<valueof<T>>();
20
+ const out = changetype<nonnull<T>>(dst || __new(outSize, idof<T>()));
21
+
22
+ // Second pass: populate values
23
+ let index = 0;
24
+ srcStart += 2; // skip [
25
+ while (srcStart < srcEnd) {
26
+ const block = load<u64>(srcStart);
27
+ if (block == 28429475166421108) {
28
+ unchecked((out[index++] = <valueof<T>>true));
29
+ srcStart += 10;
30
+ } else if (block == 32370086184550502 && load<u16>(srcStart, 8) == 101) {
31
+ unchecked((out[index++] = <valueof<T>>false));
32
+ srcStart += 12;
33
+ } else {
34
+ srcStart += 2;
35
+ }
36
+ }
37
+
38
+ return out;
39
+ }
@@ -0,0 +1,44 @@
1
+ import { isSpace } from "../../../util";
2
+ import { COMMA, BRACKET_RIGHT } from "../../../custom/chars";
3
+ import { JSON } from "../../..";
4
+
5
+ export function deserializeStaticArrayFloat<T extends StaticArray<any>>(srcStart: usize, srcEnd: usize, dst: usize): T {
6
+ let count: i32 = 0;
7
+ let ptr = srcStart;
8
+ while (ptr < srcEnd) {
9
+ const code = load<u16>(ptr);
10
+ if (code - 48 <= 9 || code == 45) {
11
+ count++;
12
+ ptr += 2;
13
+ while (ptr < srcEnd) {
14
+ const code = load<u16>(ptr);
15
+ if (code == COMMA || code == BRACKET_RIGHT || isSpace(code)) break;
16
+ ptr += 2;
17
+ }
18
+ }
19
+ ptr += 2;
20
+ }
21
+
22
+ const outSize = <usize>count << alignof<valueof<T>>();
23
+ const out = changetype<nonnull<T>>(dst || __new(outSize, idof<T>()));
24
+
25
+ let index = 0;
26
+ while (srcStart < srcEnd) {
27
+ const code = load<u16>(srcStart);
28
+ if (code - 48 <= 9 || code == 45) {
29
+ const lastIndex = srcStart;
30
+ srcStart += 2;
31
+ while (srcStart < srcEnd) {
32
+ const code = load<u16>(srcStart);
33
+ if (code == COMMA || code == BRACKET_RIGHT || isSpace(code)) {
34
+ unchecked((out[index++] = JSON.__deserialize<valueof<T>>(lastIndex, srcStart)));
35
+ break;
36
+ }
37
+ srcStart += 2;
38
+ }
39
+ }
40
+ srcStart += 2;
41
+ }
42
+
43
+ return out;
44
+ }
@@ -0,0 +1,44 @@
1
+ import { atoi, isSpace } from "../../../util";
2
+ import { COMMA, BRACKET_RIGHT } from "../../../custom/chars";
3
+
4
+ export function deserializeStaticArrayInteger<T extends StaticArray<any>>(srcStart: usize, srcEnd: usize, dst: usize): T {
5
+ let count: i32 = 0;
6
+ let ptr = srcStart;
7
+ while (ptr < srcEnd) {
8
+ const code = load<u16>(ptr);
9
+ if (code - 48 <= 9 || code == 45) {
10
+ count++;
11
+ ptr += 2;
12
+ while (ptr < srcEnd) {
13
+ const code = load<u16>(ptr);
14
+ if (code == COMMA || code == BRACKET_RIGHT || isSpace(code)) break;
15
+ ptr += 2;
16
+ }
17
+ }
18
+ ptr += 2;
19
+ }
20
+
21
+ const outSize = <usize>count << alignof<valueof<T>>();
22
+ const out = changetype<nonnull<T>>(dst || __new(outSize, idof<T>()));
23
+
24
+ // Second pass: populate values
25
+ let index = 0;
26
+ while (srcStart < srcEnd) {
27
+ const code = load<u16>(srcStart);
28
+ if (code - 48 <= 9 || code == 45) {
29
+ const lastIndex = srcStart;
30
+ srcStart += 2;
31
+ while (srcStart < srcEnd) {
32
+ const code = load<u16>(srcStart);
33
+ if (code == COMMA || code == BRACKET_RIGHT || isSpace(code)) {
34
+ unchecked((out[index++] = atoi<valueof<T>>(lastIndex, srcStart)));
35
+ break;
36
+ }
37
+ srcStart += 2;
38
+ }
39
+ }
40
+ srcStart += 2;
41
+ }
42
+
43
+ return out;
44
+ }
@@ -0,0 +1,45 @@
1
+ import { JSON } from "../../..";
2
+ import { BACK_SLASH, QUOTE } from "../../../custom/chars";
3
+
4
+ export function deserializeStaticArrayString(srcStart: usize, srcEnd: usize, dst: usize): StaticArray<string> {
5
+ // First pass: count elements using same logic as Array deserializer
6
+ let count: i32 = 0;
7
+ let ptr = srcStart;
8
+ let inString = false;
9
+ while (ptr < srcEnd) {
10
+ const code = load<u16>(ptr);
11
+ if (code == QUOTE) {
12
+ if (!inString) {
13
+ inString = true;
14
+ } else if (load<u16>(ptr - 2) != BACK_SLASH) {
15
+ count++;
16
+ inString = false;
17
+ }
18
+ }
19
+ ptr += 2;
20
+ }
21
+
22
+ // Allocate StaticArray with correct size
23
+ const outSize = <usize>count << alignof<string>();
24
+ const out = changetype<StaticArray<string>>(dst || __new(outSize, idof<StaticArray<string>>()));
25
+
26
+ // Second pass: populate values
27
+ let index = 0;
28
+ let lastPos: usize = 0;
29
+ inString = false;
30
+ while (srcStart < srcEnd) {
31
+ const code = load<u16>(srcStart);
32
+ if (code == QUOTE) {
33
+ if (!inString) {
34
+ inString = true;
35
+ lastPos = srcStart;
36
+ } else if (load<u16>(srcStart - 2) != BACK_SLASH) {
37
+ unchecked((out[index++] = JSON.__deserialize<string>(lastPos, srcStart + 2)));
38
+ inString = false;
39
+ }
40
+ }
41
+ srcStart += 2;
42
+ }
43
+
44
+ return out;
45
+ }
@@ -0,0 +1,47 @@
1
+ import { BRACE_LEFT, BRACE_RIGHT, BRACKET_LEFT, BRACKET_RIGHT } from "../../../custom/chars";
2
+ import { JSON } from "../../..";
3
+ import { isSpace } from "util/string";
4
+
5
+ export function deserializeStaticArrayStruct<T extends StaticArray<any>>(srcStart: usize, srcEnd: usize, dst: usize): T {
6
+ while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
7
+ while (srcEnd > srcStart && isSpace(load<u16>(srcEnd - 2))) srcEnd -= 2;
8
+
9
+ if (srcStart - srcEnd == 0) throw new Error("Input string had zero length or was all whitespace");
10
+
11
+ if (load<u16>(srcStart) != BRACKET_LEFT) throw new Error("Expected '[' at start of object at position " + (srcEnd - srcStart).toString());
12
+ if (load<u16>(srcEnd - 2) != BRACKET_RIGHT) throw new Error("Expected ']' at end of object at position " + (srcEnd - srcStart).toString());
13
+
14
+ // First pass: count elements using same logic as Array deserializer
15
+ let count: i32 = 0;
16
+ let depth: u32 = 0;
17
+ let ptr = srcStart;
18
+ while (ptr < srcEnd) {
19
+ const code = load<u16>(ptr);
20
+ if (code == BRACE_LEFT && depth++ == 0) {
21
+ // start of object
22
+ } else if (code == BRACE_RIGHT && --depth == 0) {
23
+ count++;
24
+ }
25
+ ptr += 2;
26
+ }
27
+
28
+ // Allocate StaticArray with correct size
29
+ const outSize = <usize>count << alignof<valueof<T>>();
30
+ const out = changetype<nonnull<T>>(dst || __new(outSize, idof<T>()));
31
+
32
+ // Second pass: populate values
33
+ let index = 0;
34
+ let lastIndex: usize = 0;
35
+ depth = 0;
36
+ while (srcStart < srcEnd) {
37
+ const code = load<u16>(srcStart);
38
+ if (code == BRACE_LEFT && depth++ == 0) {
39
+ lastIndex = srcStart;
40
+ } else if (code == BRACE_RIGHT && --depth == 0) {
41
+ unchecked((out[index++] = JSON.__deserialize<valueof<T>>(lastIndex, (srcStart += 2))));
42
+ }
43
+ srcStart += 2;
44
+ }
45
+
46
+ return out;
47
+ }
@@ -0,0 +1,28 @@
1
+ import { deserializeStaticArrayInteger } from "./staticarray/integer";
2
+ import { deserializeStaticArrayFloat } from "./staticarray/float";
3
+ import { deserializeStaticArrayBoolean } from "./staticarray/bool";
4
+ import { deserializeStaticArrayString } from "./staticarray/string";
5
+ import { deserializeStaticArrayArray } from "./staticarray/array";
6
+ import { deserializeStaticArrayStruct } from "./staticarray/struct";
7
+
8
+ export function deserializeStaticArray<T extends StaticArray<any>>(srcStart: usize, srcEnd: usize, dst: usize): T {
9
+ if (isString<valueof<T>>()) {
10
+ return <T>deserializeStaticArrayString(srcStart, srcEnd, dst);
11
+ } else if (isBoolean<valueof<T>>()) {
12
+ return deserializeStaticArrayBoolean<T>(srcStart, srcEnd, dst);
13
+ } else if (isInteger<valueof<T>>()) {
14
+ return deserializeStaticArrayInteger<T>(srcStart, srcEnd, dst);
15
+ } else if (isFloat<valueof<T>>()) {
16
+ return deserializeStaticArrayFloat<T>(srcStart, srcEnd, dst);
17
+ } else if (isArrayLike<valueof<T>>()) {
18
+ return deserializeStaticArrayArray<T>(srcStart, srcEnd, dst);
19
+ } else if (isManaged<valueof<T>>() || isReference<valueof<T>>()) {
20
+ const type = changetype<nonnull<valueof<T>>>(0);
21
+ if (isDefined(type.__DESERIALIZE)) {
22
+ return deserializeStaticArrayStruct<T>(srcStart, srcEnd, dst);
23
+ }
24
+ throw new Error("Could not parse static array of type " + nameof<T>() + "!");
25
+ } else {
26
+ throw new Error("Could not parse static array of type " + nameof<T>() + "!");
27
+ }
28
+ }
@@ -30,7 +30,7 @@ import { hex4_to_u16_swar } from "../../util/swar";
30
30
  // -\n- 2 -*-_ - 2
31
31
  // --\n 4 --*_ - 2
32
32
  // ---\n 6 ---* - 0
33
- // Formula: overflow =
33
+ // Formula: overflow =
34
34
 
35
35
  /**
36
36
  * Deserializes strings back into into their original form using SIMD operations
@@ -48,7 +48,8 @@ export function deserializeString_SWAR(srcStart: usize, srcEnd: usize): string {
48
48
  while (srcStart < srcEnd8) {
49
49
  const block = load<u64>(srcStart);
50
50
  store<u64>(bs.offset, block);
51
- let mask = backslash_mask_unsafe(block);
51
+
52
+ let mask = inline.always(backslash_mask_unsafe(block));
52
53
 
53
54
  // Early exit
54
55
  if (mask === 0) {
@@ -138,7 +139,7 @@ export function deserializeString_SWAR(srcStart: usize, srcEnd: usize): string {
138
139
  *
139
140
  * Each matching lane sets itself to 0x80.
140
141
  */
141
- // @ts-ignore: decorator
142
+ // @ts-expect-error: @inline is a valid decorator
142
143
  @inline function backslash_mask(block: u64): u64 {
143
144
  const b = block ^ 0x005C_005C_005C_005C;
144
145
  const backslash_mask = (b - 0x0001_0001_0001_0001) & ~b & 0x0080_0080_0080_0080;
@@ -153,11 +154,11 @@ export function deserializeString_SWAR(srcStart: usize, srcEnd: usize): string {
153
154
  * is the ASCII backslash (`'\\'`, 0x5C).
154
155
  *
155
156
  * Each matching lane sets itself to 0x80.
156
- *
157
+ *
157
158
  * WARNING: The low byte of a code unit *may* be a backslash, thus triggering false positives!
158
159
  * This is useful for a hot path where it is possible to detect the false positive scalarly.
159
160
  */
160
- // @ts-ignore: decorator
161
+ // @ts-expect-error: @inline is a valid decorator
161
162
  @inline function backslash_mask_unsafe(block: u64): u64 {
162
163
  const b = block ^ 0x005C_005C_005C_005C;
163
164
  const backslash_mask = (b - 0x0001_0001_0001_0001) & ~b & 0x0080_0080_0080_0080;