json-as 1.3.6 → 1.3.8

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 (155) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/README.md +1 -1
  3. package/assembly/deserialize/helpers/uint.ts +4 -1
  4. package/assembly/deserialize/index/arbitrary.ts +7 -3
  5. package/assembly/deserialize/index/array.ts +42 -17
  6. package/assembly/deserialize/index/bool.ts +1 -1
  7. package/assembly/deserialize/index/date.ts +1 -1
  8. package/assembly/deserialize/index/float.ts +40 -1
  9. package/assembly/deserialize/index/integer.ts +68 -1
  10. package/assembly/deserialize/index/map.ts +1 -1
  11. package/assembly/deserialize/index/object.ts +1 -1
  12. package/assembly/deserialize/index/raw.ts +1 -1
  13. package/assembly/deserialize/index/set.ts +1 -1
  14. package/assembly/deserialize/index/staticarray.ts +4 -1
  15. package/assembly/deserialize/index/string.ts +32 -4
  16. package/assembly/deserialize/index/struct.ts +1 -1
  17. package/assembly/deserialize/index/typedarray.ts +30 -10
  18. package/assembly/deserialize/index/unsigned.ts +78 -1
  19. package/assembly/deserialize/index.ts +1 -0
  20. package/assembly/deserialize/{simple → naive}/array/arbitrary.ts +24 -5
  21. package/assembly/deserialize/{simple → naive}/array/array.ts +8 -2
  22. package/assembly/deserialize/naive/array/bool.ts +68 -0
  23. package/assembly/deserialize/{simple → naive}/array/box.ts +8 -2
  24. package/assembly/deserialize/naive/array/float.ts +63 -0
  25. package/assembly/deserialize/{simple → naive}/array/generic.ts +14 -7
  26. package/assembly/deserialize/naive/array/integer.ts +86 -0
  27. package/assembly/deserialize/naive/array/map.ts +47 -0
  28. package/assembly/deserialize/naive/array/object.ts +47 -0
  29. package/assembly/deserialize/{simple → naive}/array/raw.ts +34 -7
  30. package/assembly/deserialize/naive/array/string.ts +69 -0
  31. package/assembly/deserialize/naive/array/struct.ts +47 -0
  32. package/assembly/deserialize/{simple → naive}/array.ts +15 -10
  33. package/assembly/deserialize/{simple → naive}/bool.ts +6 -2
  34. package/assembly/deserialize/naive/float.ts +135 -0
  35. package/assembly/deserialize/{simple → naive}/integer.ts +10 -2
  36. package/assembly/deserialize/{simple → naive}/map.ts +106 -27
  37. package/assembly/deserialize/{simple → naive}/object.ts +65 -19
  38. package/assembly/deserialize/{simple → naive}/raw.ts +4 -1
  39. package/assembly/deserialize/{simple → naive}/set.ts +49 -19
  40. package/assembly/deserialize/{simple → naive}/staticarray/array.ts +1 -1
  41. package/assembly/deserialize/{simple → naive}/staticarray/bool.ts +1 -1
  42. package/assembly/deserialize/{simple → naive}/staticarray/float.ts +1 -1
  43. package/assembly/deserialize/{simple → naive}/staticarray/integer.ts +1 -1
  44. package/assembly/deserialize/{simple → naive}/staticarray/string.ts +11 -3
  45. package/assembly/deserialize/{simple → naive}/staticarray/struct.ts +1 -2
  46. package/assembly/deserialize/{simple → naive}/staticarray.ts +68 -18
  47. package/assembly/deserialize/naive/string.ts +199 -0
  48. package/assembly/deserialize/{simple → naive}/struct.ts +5 -1
  49. package/assembly/deserialize/{simple → naive}/typedarray.ts +17 -4
  50. package/assembly/deserialize/{simple → naive}/unsigned.ts +10 -15
  51. package/assembly/deserialize/simd/array/integer.ts +339 -62
  52. package/assembly/deserialize/simd/float.ts +303 -0
  53. package/assembly/deserialize/simd/integer.ts +233 -0
  54. package/assembly/deserialize/simd/string.ts +266 -107
  55. package/assembly/deserialize/swar/array/arbitrary.ts +11 -3
  56. package/assembly/deserialize/swar/array/array.ts +40 -9
  57. package/assembly/deserialize/swar/array/bool.ts +28 -5
  58. package/assembly/deserialize/swar/array/box.ts +11 -3
  59. package/assembly/deserialize/swar/array/float.ts +295 -7
  60. package/assembly/deserialize/swar/array/generic.ts +28 -7
  61. package/assembly/deserialize/swar/array/integer.ts +363 -112
  62. package/assembly/deserialize/swar/array/map.ts +11 -3
  63. package/assembly/deserialize/swar/array/object.ts +37 -25
  64. package/assembly/deserialize/swar/array/raw.ts +11 -3
  65. package/assembly/deserialize/swar/array/shared.ts +63 -14
  66. package/assembly/deserialize/swar/array/string.ts +140 -7
  67. package/assembly/deserialize/swar/array/struct.ts +66 -12
  68. package/assembly/deserialize/swar/array.ts +12 -51
  69. package/assembly/deserialize/swar/float.ts +304 -0
  70. package/assembly/deserialize/swar/integer.ts +246 -0
  71. package/assembly/deserialize/swar/string.ts +213 -294
  72. package/assembly/deserialize/swar/typedarray.ts +224 -0
  73. package/assembly/index.d.ts +3 -1
  74. package/assembly/index.ts +402 -261
  75. package/assembly/serialize/index/array.ts +1 -1
  76. package/assembly/serialize/index/bool.ts +1 -1
  77. package/assembly/serialize/index/date.ts +1 -1
  78. package/assembly/serialize/index/float.ts +5 -1
  79. package/assembly/serialize/index/integer.ts +1 -1
  80. package/assembly/serialize/index/map.ts +1 -1
  81. package/assembly/serialize/index/raw.ts +1 -1
  82. package/assembly/serialize/index/set.ts +1 -1
  83. package/assembly/serialize/index/staticarray.ts +1 -1
  84. package/assembly/serialize/index/string.ts +1 -1
  85. package/assembly/serialize/index/struct.ts +1 -1
  86. package/assembly/serialize/index/typedarray.ts +21 -12
  87. package/assembly/serialize/index.ts +1 -0
  88. package/assembly/serialize/naive/array.ts +351 -0
  89. package/assembly/serialize/{simple → naive}/float.ts +4 -1
  90. package/assembly/serialize/naive/integer.ts +19 -0
  91. package/assembly/serialize/{simple → naive}/map.ts +6 -2
  92. package/assembly/serialize/{simple → naive}/raw.ts +5 -1
  93. package/assembly/serialize/{simple → naive}/set.ts +6 -1
  94. package/assembly/serialize/{simple → naive}/staticarray.ts +6 -1
  95. package/assembly/serialize/{simple → naive}/string.ts +1 -2
  96. package/assembly/serialize/{simple → naive}/typedarray.ts +10 -3
  97. package/assembly/serialize/simd/string.ts +6 -2
  98. package/assembly/serialize/swar/string.ts +15 -141
  99. package/assembly/util/atoi-fast.ts +81 -0
  100. package/assembly/util/concat.ts +5 -1
  101. package/assembly/util/dragonbox-cache.ts +443 -2
  102. package/assembly/util/dragonbox.ts +53 -17
  103. package/assembly/util/itoa-fast.ts +241 -0
  104. package/assembly/util/masks.ts +18 -1
  105. package/assembly/util/parsefloat-fast.ts +167 -0
  106. package/assembly/util/scanValueEnd.ts +78 -0
  107. package/assembly/util/scientific.ts +132 -0
  108. package/assembly/util/simd-int.ts +191 -0
  109. package/assembly/util/snp.ts +4 -1
  110. package/assembly/util/swar-int.ts +248 -0
  111. package/assembly/util/swar.ts +13 -3
  112. package/lib/as-bs.ts +27 -6
  113. package/package.json +15 -11
  114. package/transform/lib/builder.d.ts.map +1 -1
  115. package/transform/lib/builder.js +13 -5
  116. package/transform/lib/builder.js.map +1 -1
  117. package/transform/lib/index.d.ts +5 -0
  118. package/transform/lib/index.d.ts.map +1 -1
  119. package/transform/lib/index.js +1046 -340
  120. package/transform/lib/index.js.map +1 -1
  121. package/transform/lib/linkers/alias.d.ts.map +1 -1
  122. package/transform/lib/linkers/alias.js.map +1 -1
  123. package/transform/lib/linkers/custom.d.ts.map +1 -1
  124. package/transform/lib/linkers/custom.js +3 -2
  125. package/transform/lib/linkers/custom.js.map +1 -1
  126. package/transform/lib/linkers/imports.d.ts.map +1 -1
  127. package/transform/lib/linkers/imports.js.map +1 -1
  128. package/transform/lib/types.d.ts.map +1 -1
  129. package/transform/lib/types.js +54 -16
  130. package/transform/lib/types.js.map +1 -1
  131. package/transform/lib/util.d.ts.map +1 -1
  132. package/transform/lib/util.js +1 -1
  133. package/transform/lib/util.js.map +1 -1
  134. package/transform/lib/visitor.d.ts.map +1 -1
  135. package/transform/lib/visitor.js +2 -1
  136. package/transform/lib/visitor.js.map +1 -1
  137. package/assembly/custom/util.ts +0 -310
  138. package/assembly/deserialize/simple/arbitrary.ts +0 -23
  139. package/assembly/deserialize/simple/array/bool.ts +0 -17
  140. package/assembly/deserialize/simple/array/float.ts +0 -28
  141. package/assembly/deserialize/simple/array/integer.ts +0 -27
  142. package/assembly/deserialize/simple/array/map.ts +0 -28
  143. package/assembly/deserialize/simple/array/object.ts +0 -28
  144. package/assembly/deserialize/simple/array/string.ts +0 -23
  145. package/assembly/deserialize/simple/array/struct.ts +0 -28
  146. package/assembly/deserialize/simple/float.ts +0 -201
  147. package/assembly/deserialize/simple/string.ts +0 -132
  148. package/assembly/serialize/simple/arbitrary.ts +0 -79
  149. package/assembly/serialize/simple/array.ts +0 -86
  150. package/assembly/serialize/simple/integer.ts +0 -20
  151. package/assembly/serialize/simple/object.ts +0 -42
  152. /package/assembly/deserialize/{simple → naive}/date.ts +0 -0
  153. /package/assembly/serialize/{simple → naive}/bool.ts +0 -0
  154. /package/assembly/serialize/{simple → naive}/date.ts +0 -0
  155. /package/assembly/serialize/{simple → naive}/struct.ts +0 -0
@@ -0,0 +1,68 @@
1
+ import { isSpace } from "../../../util";
2
+ import {
3
+ COMMA,
4
+ BRACKET_LEFT,
5
+ BRACKET_RIGHT,
6
+ FALSE_WORD_U64,
7
+ TRUE_WORD_U64,
8
+ } from "../../../custom/chars";
9
+
10
+ /**
11
+ * Strict boolean-array deserializer (`bool[]`, every JSON_MODE).
12
+ *
13
+ * Enforces RFC 8259 array structure: `[`-framed, single-comma separated, no
14
+ * leading / trailing / doubled commas, and each element must be exactly the
15
+ * literal `true` or `false`. Throws on any deviation.
16
+ *
17
+ * The token check is SWAR-shaped: one `u64` load matches all four chars of
18
+ * `true`; `false` adds one `u16` load to confirm the trailing `e`.
19
+ */
20
+ export function deserializeBooleanArray<T extends boolean[]>(
21
+ srcStart: usize,
22
+ srcEnd: usize,
23
+ dst: usize,
24
+ ): T {
25
+ const out = changetype<nonnull<T>>(
26
+ dst || changetype<usize>(instantiate<T>()),
27
+ );
28
+ out.length = 0; // dst may arrive pre-sized; re-parse from empty via push
29
+
30
+ while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
31
+ while (srcEnd > srcStart && isSpace(load<u16>(srcEnd - 2))) srcEnd -= 2;
32
+ if (srcStart >= srcEnd || load<u16>(srcStart) != BRACKET_LEFT)
33
+ throw new Error("Invalid JSON array: expected '['");
34
+ if (load<u16>(srcEnd - 2) != BRACKET_RIGHT)
35
+ throw new Error("Invalid JSON array: expected ']'");
36
+ srcStart += 2; // past '['
37
+ srcEnd -= 2; // before ']'
38
+
39
+ while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
40
+ if (srcStart >= srcEnd) return out;
41
+
42
+ while (true) {
43
+ if (srcStart + 8 <= srcEnd && load<u64>(srcStart) == TRUE_WORD_U64) {
44
+ out.push(true);
45
+ srcStart += 8;
46
+ } else if (
47
+ srcStart + 10 <= srcEnd &&
48
+ load<u64>(srcStart) == FALSE_WORD_U64 &&
49
+ load<u16>(srcStart, 8) == 101
50
+ ) {
51
+ out.push(false);
52
+ srcStart += 10;
53
+ } else {
54
+ throw new Error("Invalid JSON array: expected 'true' or 'false'");
55
+ }
56
+
57
+ while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
58
+ if (srcStart >= srcEnd) break;
59
+ if (load<u16>(srcStart) != COMMA)
60
+ throw new Error("Invalid JSON array: expected ',' or ']'");
61
+ srcStart += 2;
62
+ while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
63
+ if (srcStart >= srcEnd)
64
+ throw new Error("Invalid JSON array: trailing comma");
65
+ }
66
+
67
+ return out;
68
+ }
@@ -2,8 +2,14 @@ import { isSpace } from "../../../util";
2
2
  import { COMMA, BRACKET_RIGHT } from "../../../custom/chars";
3
3
  import { JSON } from "../../..";
4
4
 
5
- export function deserializeBoxArray<T extends JSON.Box<any>[]>(srcStart: usize, srcEnd: usize, dst: usize): T {
6
- const out = changetype<nonnull<T>>(dst || changetype<usize>(instantiate<T>()));
5
+ export function deserializeBoxArray<T extends JSON.Box<any>[]>(
6
+ srcStart: usize,
7
+ srcEnd: usize,
8
+ dst: usize,
9
+ ): T {
10
+ const out = changetype<nonnull<T>>(
11
+ dst || changetype<usize>(instantiate<T>()),
12
+ );
7
13
  if (isBoolean<valueof<T>>()) {
8
14
  srcStart += 2; // skip [
9
15
  while (srcStart < srcEnd) {
@@ -0,0 +1,63 @@
1
+ import { isSpace } from "../../../util";
2
+ import { COMMA, BRACKET_LEFT, BRACKET_RIGHT } from "../../../custom/chars";
3
+ import { JSON } from "../../..";
4
+
5
+ /**
6
+ * Strict float-array deserializer (`f64[]` / `f32[]`).
7
+ *
8
+ * Enforces RFC 8259 array structure: `[`-framed, single-comma separated, no
9
+ * leading / trailing / doubled commas, and no garbage between values. Each
10
+ * element token is validated by `deserializeFloat_NAIVE` (via `JSON.__deserialize`),
11
+ * so malformed numbers like `0e` / `-01` / `1.` are rejected here too. Throws on
12
+ * any deviation.
13
+ */
14
+ export function deserializeFloatArray_NAIVE<T extends number[]>(
15
+ srcStart: usize,
16
+ srcEnd: usize,
17
+ dst: usize,
18
+ ): T {
19
+ const out = changetype<nonnull<T>>(
20
+ dst || changetype<usize>(instantiate<T>()),
21
+ );
22
+ // `dst` may arrive pre-sized (e.g. the SWAR fast path presizes then falls
23
+ // back here); we re-parse from scratch via push, so start from empty.
24
+ out.length = 0;
25
+
26
+ // Trim surrounding whitespace and require the enclosing brackets.
27
+ while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
28
+ while (srcEnd > srcStart && isSpace(load<u16>(srcEnd - 2))) srcEnd -= 2;
29
+ if (srcStart >= srcEnd || load<u16>(srcStart) != BRACKET_LEFT)
30
+ throw new Error("Invalid JSON array: expected '['");
31
+ if (load<u16>(srcEnd - 2) != BRACKET_RIGHT)
32
+ throw new Error("Invalid JSON array: expected ']'");
33
+ srcStart += 2; // past '['
34
+ srcEnd -= 2; // before ']'
35
+
36
+ // skip whitespace; an empty body is a valid empty array
37
+ while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
38
+ if (srcStart >= srcEnd) return out;
39
+
40
+ while (true) {
41
+ // value token: runs until whitespace or a comma
42
+ const tokenStart = srcStart;
43
+ while (srcStart < srcEnd) {
44
+ const c = load<u16>(srcStart);
45
+ if (c == COMMA || isSpace(c)) break;
46
+ srcStart += 2;
47
+ }
48
+ if (srcStart == tokenStart)
49
+ throw new Error("Invalid JSON array: missing value");
50
+ out.push(JSON.__deserialize<valueof<T>>(tokenStart, srcStart));
51
+
52
+ while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
53
+ if (srcStart >= srcEnd) break; // end of array body
54
+ if (load<u16>(srcStart) != COMMA)
55
+ throw new Error("Invalid JSON array: expected ',' or ']'");
56
+ srcStart += 2; // past ','
57
+ while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
58
+ if (srcStart >= srcEnd)
59
+ throw new Error("Invalid JSON array: trailing comma");
60
+ }
61
+
62
+ return out;
63
+ }
@@ -1,17 +1,24 @@
1
1
  import { JSON } from "../../..";
2
2
  import { BRACKET_LEFT, BRACKET_RIGHT, COMMA } from "../../../custom/chars";
3
3
  import { isSpace } from "../../../util";
4
- import { scanValueEnd } from "../../swar/array/shared";
5
-
6
- export function deserializeGenericArray<T extends unknown[]>(srcStart: usize, srcEnd: usize, dst: usize): T {
7
- const out = changetype<nonnull<T>>(dst || changetype<usize>(instantiate<T>()));
4
+ import { scanValueEnd } from "../../../util/scanValueEnd";
5
+
6
+ export function deserializeGenericArray<T extends unknown[]>(
7
+ srcStart: usize,
8
+ srcEnd: usize,
9
+ dst: usize,
10
+ ): T {
11
+ const out = changetype<nonnull<T>>(
12
+ dst || changetype<usize>(instantiate<T>()),
13
+ );
8
14
  out.length = 0;
9
15
 
10
- while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
11
16
  while (srcEnd > srcStart && isSpace(load<u16>(srcEnd - 2))) srcEnd -= 2;
12
17
 
13
- if (srcStart >= srcEnd) throw new Error("Input string had zero length or was all whitespace");
14
- if (load<u16>(srcStart) != BRACKET_LEFT) throw new Error("Expected '[' at start of array");
18
+ if (srcStart >= srcEnd)
19
+ throw new Error("Input string had zero length or was all whitespace");
20
+ if (load<u16>(srcStart) != BRACKET_LEFT)
21
+ throw new Error("Expected '[' at start of array");
15
22
  srcStart += 2;
16
23
 
17
24
  while (srcStart < srcEnd) {
@@ -0,0 +1,86 @@
1
+ import { atoi, isSpace } from "../../../util";
2
+ import { COMMA, BRACKET_LEFT, BRACKET_RIGHT } from "../../../custom/chars";
3
+
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,
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 {
13
+ let ptr = start;
14
+ if (ptr < end && load<u16>(ptr) == 45) {
15
+ if (!signed) throw new Error("Invalid JSON number: minus on unsigned");
16
+ ptr += 2;
17
+ }
18
+ if (ptr >= end) throw new Error("Invalid JSON number: expected digit");
19
+ const first = load<u16>(ptr);
20
+ if (first == 48) {
21
+ ptr += 2;
22
+ if (ptr < end && <u32>(load<u16>(ptr) - 48) <= 9)
23
+ throw new Error("Invalid JSON number: leading zero");
24
+ } else if (<u32>(first - 48) <= 9) {
25
+ ptr += 2;
26
+ while (ptr < end && <u32>(load<u16>(ptr) - 48) <= 9) ptr += 2;
27
+ } else {
28
+ throw new Error("Invalid JSON number: expected digit");
29
+ }
30
+ if (ptr != end) throw new Error("Invalid JSON number: not an integer");
31
+ }
32
+
33
+ /**
34
+ * Strict integer-array deserializer (`i8[]`..`i64[]`, `u8[]`..`u64[]`).
35
+ *
36
+ * Enforces RFC 8259 array structure: `[`-framed, single-comma separated, no
37
+ * leading / trailing / doubled commas, and each element must be a valid JSON
38
+ * integer (no leading zeros, fraction, or exponent). Throws on any deviation.
39
+ */
40
+ export function deserializeIntegerArray_NAIVE<T extends number[]>(
41
+ srcStart: usize,
42
+ srcEnd: usize,
43
+ dst: usize,
44
+ ): T {
45
+ const out = changetype<nonnull<T>>(
46
+ dst || changetype<usize>(instantiate<T>()),
47
+ );
48
+ out.length = 0; // dst may arrive pre-sized; re-parse from empty via push
49
+
50
+ while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
51
+ while (srcEnd > srcStart && isSpace(load<u16>(srcEnd - 2))) srcEnd -= 2;
52
+ if (srcStart >= srcEnd || load<u16>(srcStart) != BRACKET_LEFT)
53
+ throw new Error("Invalid JSON array: expected '['");
54
+ if (load<u16>(srcEnd - 2) != BRACKET_RIGHT)
55
+ throw new Error("Invalid JSON array: expected ']'");
56
+ srcStart += 2; // past '['
57
+ srcEnd -= 2; // before ']'
58
+
59
+ while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
60
+ if (srcStart >= srcEnd) return out;
61
+
62
+ const signed = isSigned<valueof<T>>();
63
+ while (true) {
64
+ const tokenStart = srcStart;
65
+ while (srcStart < srcEnd) {
66
+ const c = load<u16>(srcStart);
67
+ if (c == COMMA || isSpace(c)) break;
68
+ srcStart += 2;
69
+ }
70
+ if (srcStart == tokenStart)
71
+ throw new Error("Invalid JSON array: missing value");
72
+ validateJSONInteger(tokenStart, srcStart, signed);
73
+ out.push(atoi<valueof<T>>(tokenStart, srcStart));
74
+
75
+ while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
76
+ if (srcStart >= srcEnd) break;
77
+ if (load<u16>(srcStart) != COMMA)
78
+ throw new Error("Invalid JSON array: expected ',' or ']'");
79
+ srcStart += 2;
80
+ while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
81
+ if (srcStart >= srcEnd)
82
+ throw new Error("Invalid JSON array: trailing comma");
83
+ }
84
+
85
+ return out;
86
+ }
@@ -0,0 +1,47 @@
1
+ import {
2
+ BRACE_LEFT,
3
+ BRACE_RIGHT,
4
+ BRACKET_LEFT,
5
+ BRACKET_RIGHT,
6
+ } from "../../../custom/chars";
7
+ import { JSON } from "../../..";
8
+ import { isSpace } from "util/string";
9
+
10
+ export function deserializeMapArray<T extends Map<any, any>[]>(
11
+ srcStart: usize,
12
+ srcEnd: usize,
13
+ dst: usize,
14
+ ): T {
15
+ const out = changetype<nonnull<T>>(
16
+ dst || changetype<usize>(instantiate<T>()),
17
+ );
18
+ let lastIndex: usize = 0;
19
+ let depth: u32 = 0;
20
+
21
+ while (srcEnd > srcStart && isSpace(load<u16>(srcEnd - 2))) srcEnd -= 2;
22
+
23
+ if (srcStart - srcEnd == 0)
24
+ throw new Error("Input string had zero length or was all whitespace");
25
+
26
+ if (load<u16>(srcStart) != BRACKET_LEFT)
27
+ throw new Error(
28
+ "Expected '[' at start of object at position " +
29
+ (srcEnd - srcStart).toString(),
30
+ );
31
+ if (load<u16>(srcEnd - 2) != BRACKET_RIGHT)
32
+ throw new Error(
33
+ "Expected ']' at end of object at position " +
34
+ (srcEnd - srcStart).toString(),
35
+ );
36
+
37
+ 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)));
43
+ }
44
+ srcStart += 2;
45
+ }
46
+ return out;
47
+ }
@@ -0,0 +1,47 @@
1
+ import {
2
+ BRACE_LEFT,
3
+ BRACE_RIGHT,
4
+ BRACKET_LEFT,
5
+ BRACKET_RIGHT,
6
+ } from "../../../custom/chars";
7
+ import { JSON } from "../../..";
8
+ import { isSpace } from "util/string";
9
+
10
+ export function deserializeObjectArray<T extends unknown[]>(
11
+ srcStart: usize,
12
+ srcEnd: usize,
13
+ dst: usize,
14
+ ): T {
15
+ const out = changetype<nonnull<T>>(
16
+ dst || changetype<usize>(instantiate<T>()),
17
+ );
18
+ let lastIndex: usize = 0;
19
+ let depth: u32 = 0;
20
+
21
+ while (srcEnd > srcStart && isSpace(load<u16>(srcEnd - 2))) srcEnd -= 2;
22
+
23
+ if (srcStart - srcEnd == 0)
24
+ throw new Error("Input string had zero length or was all whitespace");
25
+
26
+ if (load<u16>(srcStart) != BRACKET_LEFT)
27
+ throw new Error(
28
+ "Expected '[' at start of object at position " +
29
+ (srcEnd - srcStart).toString(),
30
+ );
31
+ if (load<u16>(srcEnd - 2) != BRACKET_RIGHT)
32
+ throw new Error(
33
+ "Expected ']' at end of object at position " +
34
+ (srcEnd - srcStart).toString(),
35
+ );
36
+
37
+ 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)));
43
+ }
44
+ srcStart += 2;
45
+ }
46
+ return out;
47
+ }
@@ -1,11 +1,28 @@
1
1
  import { isSpace, isUnescapedQuote, scanStringEnd } from "../../../util";
2
- import { COMMA, BRACKET_RIGHT, QUOTE, BRACE_LEFT, BRACE_RIGHT, BRACKET_LEFT, BACK_SLASH, CHAR_T, CHAR_F, CHAR_N } from "../../../custom/chars";
2
+ import {
3
+ COMMA,
4
+ BRACKET_RIGHT,
5
+ QUOTE,
6
+ BRACE_LEFT,
7
+ BRACE_RIGHT,
8
+ BRACKET_LEFT,
9
+ BACK_SLASH,
10
+ CHAR_T,
11
+ CHAR_F,
12
+ CHAR_N,
13
+ } from "../../../custom/chars";
3
14
  import { JSON } from "../../..";
4
15
  import { ptrToStr } from "../../../util/ptrToStr";
5
16
 
6
- export function deserializeRawArray(srcStart: usize, srcEnd: usize, dst: usize): JSON.Raw[] {
17
+ export function deserializeRawArray(
18
+ srcStart: usize,
19
+ srcEnd: usize,
20
+ dst: usize,
21
+ ): JSON.Raw[] {
7
22
  // console.log("data: " + ptrToStr(srcStart, srcEnd));
8
- const out = changetype<JSON.Raw[]>(dst || changetype<usize>(instantiate<JSON.Raw[]>()));
23
+ const out = changetype<JSON.Raw[]>(
24
+ dst || changetype<usize>(instantiate<JSON.Raw[]>()),
25
+ );
9
26
  let lastIndex: usize = 0;
10
27
  let depth = 0;
11
28
  srcStart += 2;
@@ -19,7 +36,8 @@ export function deserializeRawArray(srcStart: usize, srcEnd: usize, dst: usize):
19
36
  } else if (code == QUOTE) {
20
37
  lastIndex = srcStart;
21
38
  srcStart = scanStringEnd(srcStart, srcEnd);
22
- if (srcStart >= srcEnd) throw new Error("Unterminated string in JSON array");
39
+ if (srcStart >= srcEnd)
40
+ throw new Error("Unterminated string in JSON array");
23
41
  out.push(JSON.Raw.from(ptrToStr(lastIndex, srcStart + 2)));
24
42
  srcStart += 2;
25
43
  } else if (code - 48 <= 9 || code == 45) {
@@ -43,7 +61,8 @@ export function deserializeRawArray(srcStart: usize, srcEnd: usize, dst: usize):
43
61
  const code = load<u16>(srcStart);
44
62
  if (code == QUOTE) {
45
63
  srcStart = scanStringEnd(srcStart, srcEnd);
46
- if (srcStart >= srcEnd) throw new Error("Unterminated string in JSON array");
64
+ if (srcStart >= srcEnd)
65
+ throw new Error("Unterminated string in JSON array");
47
66
  } else if (code == BRACE_RIGHT) {
48
67
  if (--depth == 0) {
49
68
  // console.log("Value (object): " + ptrToStr(lastIndex, srcStart + 2));
@@ -62,7 +81,8 @@ export function deserializeRawArray(srcStart: usize, srcEnd: usize, dst: usize):
62
81
  const code = load<u16>(srcStart);
63
82
  if (code == QUOTE) {
64
83
  srcStart = scanStringEnd(srcStart, srcEnd);
65
- if (srcStart >= srcEnd) throw new Error("Unterminated string in JSON array");
84
+ if (srcStart >= srcEnd)
85
+ throw new Error("Unterminated string in JSON array");
66
86
  } else if (code == BRACKET_RIGHT) {
67
87
  if (--depth == 0) {
68
88
  // console.log("Value (array): " + ptrToStr(lastIndex, srcStart + 2));
@@ -92,7 +112,14 @@ export function deserializeRawArray(srcStart: usize, srcEnd: usize, dst: usize):
92
112
  srcStart += 10;
93
113
  }
94
114
  } else {
95
- throw new Error("Unexpected character in JSON object '" + String.fromCharCode(code) + "' at position " + (srcEnd - srcStart).toString() + " " + ptrToStr(lastIndex, srcStart + 10));
115
+ throw new Error(
116
+ "Unexpected character in JSON object '" +
117
+ String.fromCharCode(code) +
118
+ "' at position " +
119
+ (srcEnd - srcStart).toString() +
120
+ " " +
121
+ ptrToStr(lastIndex, srcStart + 10),
122
+ );
96
123
  }
97
124
  }
98
125
  return out;
@@ -0,0 +1,69 @@
1
+ import { JSON } from "../../..";
2
+ import {
3
+ COMMA,
4
+ BRACKET_LEFT,
5
+ BRACKET_RIGHT,
6
+ NULL_WORD_U64,
7
+ QUOTE,
8
+ } from "../../../custom/chars";
9
+ import { isSpace, scanStringEnd } from "../../../util";
10
+
11
+ /**
12
+ * Strict string-array deserializer (`string[]` / `(string | null)[]`).
13
+ *
14
+ * Enforces RFC 8259 array structure: `[`-framed, single-comma separated, no
15
+ * leading / trailing / doubled commas, and each element must be a quoted string
16
+ * (or the literal `null` for a nullable element type). Element contents are
17
+ * validated by `deserializeString_NAIVE` (via `JSON.__deserialize`). Throws on
18
+ * any deviation.
19
+ */
20
+ export function deserializeStringArray_NAIVE(
21
+ srcStart: usize,
22
+ srcEnd: usize,
23
+ dst: usize,
24
+ ): string[] {
25
+ const out = changetype<string[]>(
26
+ dst || changetype<usize>(instantiate<string[]>()),
27
+ );
28
+ out.length = 0; // dst may arrive pre-sized; re-parse from empty via push
29
+
30
+ while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
31
+ while (srcEnd > srcStart && isSpace(load<u16>(srcEnd - 2))) srcEnd -= 2;
32
+ if (srcStart >= srcEnd || load<u16>(srcStart) != BRACKET_LEFT)
33
+ throw new Error("Invalid JSON array: expected '['");
34
+ if (load<u16>(srcEnd - 2) != BRACKET_RIGHT)
35
+ throw new Error("Invalid JSON array: expected ']'");
36
+ srcStart += 2; // past '['
37
+ srcEnd -= 2; // before ']'
38
+
39
+ while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
40
+ if (srcStart >= srcEnd) return out;
41
+
42
+ while (true) {
43
+ const code = load<u16>(srcStart);
44
+ if (code == QUOTE) {
45
+ const closing = scanStringEnd(srcStart, srcEnd);
46
+ if (closing >= srcEnd)
47
+ throw new Error("Invalid JSON array: unterminated string");
48
+ out.push(JSON.__deserialize<string>(srcStart, closing + 2));
49
+ srcStart = closing + 2;
50
+ } else if (srcStart + 8 <= srcEnd && load<u64>(srcStart) == NULL_WORD_U64) {
51
+ // `(string | null)[]` element
52
+ out.push(changetype<string>(0));
53
+ srcStart += 8;
54
+ } else {
55
+ throw new Error("Invalid JSON array: expected string");
56
+ }
57
+
58
+ while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
59
+ if (srcStart >= srcEnd) break;
60
+ if (load<u16>(srcStart) != COMMA)
61
+ throw new Error("Invalid JSON array: expected ',' or ']'");
62
+ srcStart += 2;
63
+ while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
64
+ if (srcStart >= srcEnd)
65
+ throw new Error("Invalid JSON array: trailing comma");
66
+ }
67
+
68
+ return out;
69
+ }
@@ -0,0 +1,47 @@
1
+ import {
2
+ BRACE_LEFT,
3
+ BRACE_RIGHT,
4
+ BRACKET_LEFT,
5
+ BRACKET_RIGHT,
6
+ } from "../../../custom/chars";
7
+ import { JSON } from "../../..";
8
+ import { isSpace } from "util/string";
9
+
10
+ export function deserializeStructArray<T extends unknown[]>(
11
+ srcStart: usize,
12
+ srcEnd: usize,
13
+ dst: usize,
14
+ ): T {
15
+ const out = changetype<nonnull<T>>(
16
+ dst || changetype<usize>(instantiate<T>()),
17
+ );
18
+ let lastIndex: usize = 0;
19
+ let depth: u32 = 0;
20
+
21
+ while (srcEnd > srcStart && isSpace(load<u16>(srcEnd - 2))) srcEnd -= 2;
22
+
23
+ if (srcStart - srcEnd == 0)
24
+ throw new Error("Input string had zero length or was all whitespace");
25
+
26
+ if (load<u16>(srcStart) != BRACKET_LEFT)
27
+ throw new Error(
28
+ "Expected '[' at start of object at position " +
29
+ (srcEnd - srcStart).toString(),
30
+ );
31
+ if (load<u16>(srcEnd - 2) != BRACKET_RIGHT)
32
+ throw new Error(
33
+ "Expected ']' at end of object at position " +
34
+ (srcEnd - srcStart).toString(),
35
+ );
36
+
37
+ 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)));
43
+ }
44
+ srcStart += 2;
45
+ }
46
+ return out;
47
+ }
@@ -2,30 +2,32 @@ import { JSON } from "../..";
2
2
  import { deserializeArbitraryArray } from "./array/arbitrary";
3
3
  import { deserializeArrayArray } from "./array/array";
4
4
  import { deserializeBooleanArray } from "./array/bool";
5
- import { deserializeFloatArray } from "./array/float";
5
+ import { deserializeFloatArray_NAIVE } from "./array/float";
6
6
  import { deserializeGenericArray } from "./array/generic";
7
- import { deserializeIntegerArray } from "./array/integer";
7
+ import { deserializeIntegerArray_NAIVE } from "./array/integer";
8
8
  import { deserializeMapArray } from "./array/map";
9
9
  import { deserializeStructArray } from "./array/struct";
10
- import { deserializeStringArray } from "./array/string";
10
+ import { deserializeStringArray_NAIVE } from "./array/string";
11
11
  import { deserializeObjectArray } from "./array/object";
12
12
  import { deserializeBoxArray } from "./array/box";
13
13
  import { deserializeRawArray } from "./array/raw";
14
- export { deserializeArrayField, deserializeArrayField as deserializeArrayField_SWAR } from "../swar/array";
15
-
16
14
  // @ts-ignore: Decorator valid here
17
- export function deserializeArray<T extends unknown[]>(srcStart: usize, srcEnd: usize, dst: usize): T {
15
+ export function deserializeArray<T extends unknown[]>(
16
+ srcStart: usize,
17
+ srcEnd: usize,
18
+ dst: usize,
19
+ ): T {
18
20
  if (isString<valueof<T>>()) {
19
- return <T>deserializeStringArray(srcStart, srcEnd, dst);
21
+ return <T>deserializeStringArray_NAIVE(srcStart, srcEnd, dst);
20
22
  } else if (isBoolean<valueof<T>>()) {
21
23
  // @ts-ignore
22
24
  return deserializeBooleanArray<T>(srcStart, srcEnd, dst);
23
25
  } else if (isInteger<valueof<T>>()) {
24
26
  // @ts-ignore
25
- return deserializeIntegerArray<T>(srcStart, srcEnd, dst);
27
+ return deserializeIntegerArray_NAIVE<T>(srcStart, srcEnd, dst);
26
28
  } else if (isFloat<valueof<T>>()) {
27
29
  // @ts-ignore
28
- return deserializeFloatArray<T>(srcStart, srcEnd, dst);
30
+ return deserializeFloatArray_NAIVE<T>(srcStart, srcEnd, dst);
29
31
  } else if (isArray<valueof<T>>()) {
30
32
  // @ts-ignore: type
31
33
  return deserializeArrayArray<T>(srcStart, srcEnd, dst);
@@ -56,7 +58,10 @@ export function deserializeArray<T extends unknown[]>(srcStart: usize, srcEnd: u
56
58
  } else if (isDefined(type.__DESERIALIZE_CUSTOM)) {
57
59
  return deserializeStructArray<T>(srcStart, srcEnd, dst);
58
60
  // @ts-ignore: defined by transform
59
- } else if (isDefined(type.__DESERIALIZE_SLOW) || isDefined(type.__DESERIALIZE_FAST)) {
61
+ } else if (
62
+ isDefined(type.__DESERIALIZE_SLOW) ||
63
+ isDefined(type.__DESERIALIZE_FAST)
64
+ ) {
60
65
  return deserializeStructArray<T>(srcStart, srcEnd, dst);
61
66
  }
62
67
  throw new Error("Could not parse array of type " + nameof<T>() + "!");
@@ -1,7 +1,11 @@
1
1
  // @ts-ignore: inline
2
- @inline export function deserializeBoolean(srcStart: usize, srcEnd: usize): boolean {
2
+ @inline export function deserializeBoolean(
3
+ srcStart: usize,
4
+ srcEnd: usize,
5
+ ): boolean {
3
6
  const block = load<u64>(srcStart);
4
7
  if (block == 28429475166421108) return true;
5
- else if (block == 32370086184550502 && load<u16>(srcStart, 8) == 101) return false;
8
+ else if (block == 32370086184550502 && load<u16>(srcStart, 8) == 101)
9
+ return false;
6
10
  return false; //throw new Error(`Expected to find boolean, but found "${data.slice(0, 100)}" instead!`);
7
11
  }