json-as 1.3.6 → 1.3.7

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 (106) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/assembly/deserialize/helpers/uint.ts +4 -1
  3. package/assembly/deserialize/index/arbitrary.ts +5 -1
  4. package/assembly/deserialize/index/array.ts +13 -3
  5. package/assembly/deserialize/index/integer.ts +68 -1
  6. package/assembly/deserialize/index/string.ts +4 -1
  7. package/assembly/deserialize/index/typedarray.ts +13 -3
  8. package/assembly/deserialize/index/unsigned.ts +78 -1
  9. package/assembly/deserialize/simd/array/integer.ts +327 -50
  10. package/assembly/deserialize/simd/integer.ts +233 -0
  11. package/assembly/deserialize/simd/string.ts +45 -11
  12. package/assembly/deserialize/simple/arbitrary.ts +11 -4
  13. package/assembly/deserialize/simple/array/arbitrary.ts +24 -5
  14. package/assembly/deserialize/simple/array/array.ts +8 -2
  15. package/assembly/deserialize/simple/array/bool.ts +38 -7
  16. package/assembly/deserialize/simple/array/box.ts +8 -2
  17. package/assembly/deserialize/simple/array/float.ts +36 -9
  18. package/assembly/deserialize/simple/array/generic.ts +12 -4
  19. package/assembly/deserialize/simple/array/integer.ts +8 -2
  20. package/assembly/deserialize/simple/array/map.ts +26 -6
  21. package/assembly/deserialize/simple/array/object.ts +26 -6
  22. package/assembly/deserialize/simple/array/raw.ts +34 -7
  23. package/assembly/deserialize/simple/array/string.ts +8 -2
  24. package/assembly/deserialize/simple/array/struct.ts +26 -6
  25. package/assembly/deserialize/simple/array.ts +13 -3
  26. package/assembly/deserialize/simple/bool.ts +6 -2
  27. package/assembly/deserialize/simple/float.ts +6 -1
  28. package/assembly/deserialize/simple/integer.ts +10 -2
  29. package/assembly/deserialize/simple/map.ts +95 -22
  30. package/assembly/deserialize/simple/object.ts +63 -14
  31. package/assembly/deserialize/simple/raw.ts +4 -1
  32. package/assembly/deserialize/simple/set.ts +59 -14
  33. package/assembly/deserialize/simple/staticarray/string.ts +11 -3
  34. package/assembly/deserialize/simple/staticarray.ts +64 -14
  35. package/assembly/deserialize/simple/string.ts +5 -92
  36. package/assembly/deserialize/simple/struct.ts +5 -1
  37. package/assembly/deserialize/simple/typedarray.ts +16 -3
  38. package/assembly/deserialize/simple/unsigned.ts +10 -15
  39. package/assembly/deserialize/swar/array/arbitrary.ts +5 -1
  40. package/assembly/deserialize/swar/array/array.ts +30 -6
  41. package/assembly/deserialize/swar/array/bool.ts +22 -4
  42. package/assembly/deserialize/swar/array/box.ts +5 -1
  43. package/assembly/deserialize/swar/array/float.ts +15 -3
  44. package/assembly/deserialize/swar/array/generic.ts +24 -7
  45. package/assembly/deserialize/swar/array/integer.ts +328 -84
  46. package/assembly/deserialize/swar/array/map.ts +5 -1
  47. package/assembly/deserialize/swar/array/object.ts +27 -7
  48. package/assembly/deserialize/swar/array/raw.ts +5 -1
  49. package/assembly/deserialize/swar/array/shared.ts +36 -11
  50. package/assembly/deserialize/swar/array/string.ts +20 -4
  51. package/assembly/deserialize/swar/array/struct.ts +27 -7
  52. package/assembly/deserialize/swar/array.ts +19 -4
  53. package/assembly/deserialize/swar/integer.ts +246 -0
  54. package/assembly/deserialize/swar/string.ts +98 -194
  55. package/assembly/index.d.ts +3 -1
  56. package/assembly/index.ts +312 -81
  57. package/assembly/serialize/index/float.ts +5 -1
  58. package/assembly/serialize/index/typedarray.ts +25 -7
  59. package/assembly/serialize/simd/string.ts +6 -2
  60. package/assembly/serialize/simple/array.ts +179 -1
  61. package/assembly/serialize/simple/float.ts +4 -1
  62. package/assembly/serialize/simple/integer.ts +8 -9
  63. package/assembly/serialize/simple/map.ts +6 -2
  64. package/assembly/serialize/simple/raw.ts +5 -1
  65. package/assembly/serialize/simple/set.ts +6 -1
  66. package/assembly/serialize/simple/staticarray.ts +6 -1
  67. package/assembly/serialize/simple/string.ts +0 -1
  68. package/assembly/serialize/simple/typedarray.ts +10 -3
  69. package/assembly/serialize/swar/string.ts +18 -5
  70. package/assembly/util/atoi-fast.ts +81 -0
  71. package/assembly/util/concat.ts +5 -1
  72. package/assembly/util/dragonbox-cache.ts +443 -2
  73. package/assembly/util/dragonbox.ts +43 -14
  74. package/assembly/util/itoa-fast.ts +230 -0
  75. package/assembly/util/masks.ts +18 -1
  76. package/assembly/util/parsefloat-fast.ts +167 -0
  77. package/assembly/util/simd-int.ts +191 -0
  78. package/assembly/util/snp.ts +4 -1
  79. package/assembly/util/swar-int.ts +248 -0
  80. package/assembly/util/swar.ts +13 -3
  81. package/lib/as-bs.ts +13 -5
  82. package/package.json +5 -2
  83. package/transform/lib/builder.d.ts.map +1 -1
  84. package/transform/lib/builder.js +13 -5
  85. package/transform/lib/builder.js.map +1 -1
  86. package/transform/lib/index.d.ts +1 -0
  87. package/transform/lib/index.d.ts.map +1 -1
  88. package/transform/lib/index.js +1030 -241
  89. package/transform/lib/index.js.map +1 -1
  90. package/transform/lib/linkers/alias.d.ts.map +1 -1
  91. package/transform/lib/linkers/alias.js.map +1 -1
  92. package/transform/lib/linkers/custom.d.ts.map +1 -1
  93. package/transform/lib/linkers/custom.js +3 -2
  94. package/transform/lib/linkers/custom.js.map +1 -1
  95. package/transform/lib/linkers/imports.d.ts.map +1 -1
  96. package/transform/lib/linkers/imports.js.map +1 -1
  97. package/transform/lib/types.d.ts.map +1 -1
  98. package/transform/lib/types.js +54 -16
  99. package/transform/lib/types.js.map +1 -1
  100. package/transform/lib/util.d.ts.map +1 -1
  101. package/transform/lib/util.js +1 -1
  102. package/transform/lib/util.js.map +1 -1
  103. package/transform/lib/visitor.d.ts.map +1 -1
  104. package/transform/lib/visitor.js +2 -1
  105. package/transform/lib/visitor.js.map +1 -1
  106. package/assembly/custom/util.ts +0 -310
@@ -1,7 +1,17 @@
1
- import { BACK_SLASH, BRACE_LEFT, BRACE_RIGHT, BRACKET_LEFT, BRACKET_RIGHT, COMMA, QUOTE } from "../../../custom/chars";
2
-
3
-
4
- @inline export function ensureArrayField<T extends Array<any>>(fieldPtr: usize): T {
1
+ import {
2
+ BACK_SLASH,
3
+ BRACE_LEFT,
4
+ BRACE_RIGHT,
5
+ BRACKET_LEFT,
6
+ BRACKET_RIGHT,
7
+ COMMA,
8
+ QUOTE,
9
+ } from "../../../custom/chars";
10
+
11
+
12
+ @inline export function ensureArrayField<T extends Array<any>>(
13
+ fieldPtr: usize,
14
+ ): T {
5
15
  let out = load<T>(fieldPtr);
6
16
  if (!changetype<usize>(out)) {
7
17
  out = changetype<T>(instantiate<T>());
@@ -11,7 +21,10 @@ import { BACK_SLASH, BRACE_LEFT, BRACE_RIGHT, BRACKET_LEFT, BRACKET_RIGHT, COMMA
11
21
  }
12
22
 
13
23
 
14
- @inline export function ensureArrayFieldAt<T extends Array<any>>(dstObj: usize, dstOffset: usize): T {
24
+ @inline export function ensureArrayFieldAt<T extends Array<any>>(
25
+ dstObj: usize,
26
+ dstOffset: usize,
27
+ ): T {
15
28
  let out = load<T>(dstObj, dstOffset);
16
29
  if (!changetype<usize>(out)) {
17
30
  out = changetype<T>(instantiate<T>());
@@ -24,25 +37,35 @@ import { BACK_SLASH, BRACE_LEFT, BRACE_RIGHT, BRACKET_LEFT, BRACKET_RIGHT, COMMA
24
37
  @inline function backslashOrQuoteMask(block: u64): u64 {
25
38
  const b = block ^ 0x005c_005c_005c_005c;
26
39
  const q = block ^ 0x0022_0022_0022_0022;
27
- return (((q - 0x0001_0001_0001_0001) & ~q) | ((b - 0x0001_0001_0001_0001) & ~b)) & 0x0080_0080_0080_0080;
40
+ return (
41
+ (((q - 0x0001_0001_0001_0001) & ~q) | ((b - 0x0001_0001_0001_0001) & ~b)) &
42
+ 0x0080_0080_0080_0080
43
+ );
28
44
  }
29
45
 
30
46
 
31
- @inline export function ensureArrayElementSlot<T extends Array<any>>(out: T, index: i32): usize {
47
+ @inline export function ensureArrayElementSlot<T extends Array<any>>(
48
+ out: T,
49
+ index: i32,
50
+ ): usize {
32
51
  const nextLength = index + 1;
33
52
  if (out.length < nextLength) {
34
53
  out.length = nextLength;
35
54
  const slot = out.dataStart + <usize>index * sizeof<valueof<T>>();
36
55
  // Reference arrays can allocate recursively before the caller stores the new element.
37
56
  // Zero the newly exposed slot immediately so incremental GC never observes a garbage pointer.
38
- if (isManaged<valueof<T>>() || isReference<valueof<T>>()) store<usize>(slot, 0);
57
+ if (isManaged<valueof<T>>() || isReference<valueof<T>>())
58
+ store<usize>(slot, 0);
39
59
  return slot;
40
60
  }
41
61
  return out.dataStart + <usize>index * sizeof<valueof<T>>();
42
62
  }
43
63
 
44
64
 
45
- @inline export function scanQuotedValueEnd_SWAR(srcStart: usize, srcEnd: usize): usize {
65
+ @inline export function scanQuotedValueEnd_SWAR(
66
+ srcStart: usize,
67
+ srcEnd: usize,
68
+ ): usize {
46
69
  srcStart += 2;
47
70
  const srcEnd8 = srcEnd >= 8 ? srcEnd - 8 : 0;
48
71
 
@@ -67,7 +90,8 @@ import { BACK_SLASH, BRACE_LEFT, BRACE_RIGHT, BRACKET_LEFT, BRACKET_RIGHT, COMMA
67
90
 
68
91
  while (srcStart < srcEnd) {
69
92
  const char = load<u16>(srcStart);
70
- if (char == QUOTE && load<u16>(srcStart - 2) != BACK_SLASH) return srcStart + 2;
93
+ if (char == QUOTE && load<u16>(srcStart - 2) != BACK_SLASH)
94
+ return srcStart + 2;
71
95
  srcStart += 2;
72
96
  }
73
97
 
@@ -103,7 +127,8 @@ import { BACK_SLASH, BRACE_LEFT, BRACE_RIGHT, BRACKET_LEFT, BRACKET_RIGHT, COMMA
103
127
 
104
128
  while (srcStart < srcEnd) {
105
129
  const code = load<u16>(srcStart);
106
- if (code == COMMA || code == BRACKET_RIGHT || code == BRACE_RIGHT) return srcStart;
130
+ if (code == COMMA || code == BRACKET_RIGHT || code == BRACE_RIGHT)
131
+ return srcStart;
107
132
  srcStart += 2;
108
133
  }
109
134
 
@@ -3,7 +3,11 @@ import { ensureArrayElementSlot, ensureArrayField } from "./shared";
3
3
  import { deserializeStringField_SWAR } from "../string";
4
4
 
5
5
 
6
- @inline export function deserializeStringArrayInto<T extends string[]>(srcStart: usize, srcEnd: usize, out: T): usize {
6
+ @inline export function deserializeStringArrayInto<T extends string[]>(
7
+ srcStart: usize,
8
+ srcEnd: usize,
9
+ out: T,
10
+ ): usize {
7
11
  let index = 0;
8
12
 
9
13
  do {
@@ -17,7 +21,11 @@ import { deserializeStringField_SWAR } from "../string";
17
21
 
18
22
  while (srcStart < srcEnd) {
19
23
  const slot = ensureArrayElementSlot<T>(out, index);
20
- srcStart = deserializeStringField_SWAR<valueof<T>>(srcStart, srcEnd, slot);
24
+ srcStart = deserializeStringField_SWAR<valueof<T>>(
25
+ srcStart,
26
+ srcEnd,
27
+ slot,
28
+ );
21
29
  if (!srcStart || srcStart >= srcEnd) break;
22
30
 
23
31
  const code = load<u16>(srcStart);
@@ -38,6 +46,14 @@ import { deserializeStringField_SWAR } from "../string";
38
46
  }
39
47
 
40
48
 
41
- @inline export function deserializeStringArrayField<T extends string[]>(srcStart: usize, srcEnd: usize, fieldPtr: usize): usize {
42
- return deserializeStringArrayInto<T>(srcStart, srcEnd, ensureArrayField<T>(fieldPtr));
49
+ @inline export function deserializeStringArrayField<T extends string[]>(
50
+ srcStart: usize,
51
+ srcEnd: usize,
52
+ fieldPtr: usize,
53
+ ): usize {
54
+ return deserializeStringArrayInto<T>(
55
+ srcStart,
56
+ srcEnd,
57
+ ensureArrayField<T>(fieldPtr),
58
+ );
43
59
  }
@@ -2,7 +2,11 @@ import { BRACKET_LEFT, BRACKET_RIGHT, COMMA } from "../../../custom/chars";
2
2
  import { ensureArrayElementSlot, ensureArrayField } from "./shared";
3
3
 
4
4
 
5
- @inline export function deserializeStructArrayInto<T extends unknown[]>(srcStart: usize, srcEnd: usize, out: T): usize {
5
+ @inline export function deserializeStructArrayInto<T extends unknown[]>(
6
+ srcStart: usize,
7
+ srcEnd: usize,
8
+ out: T,
9
+ ): usize {
6
10
  let index = 0;
7
11
 
8
12
  do {
@@ -18,7 +22,9 @@ import { ensureArrayElementSlot, ensureArrayField } from "./shared";
18
22
  const slot = ensureArrayElementSlot<T>(out, index);
19
23
  let value = load<valueof<T>>(slot);
20
24
  if (changetype<usize>(value) == 0) {
21
- value = changetype<valueof<T>>(__new(offsetof<nonnull<valueof<T>>>(), idof<nonnull<valueof<T>>>()));
25
+ value = changetype<valueof<T>>(
26
+ __new(offsetof<nonnull<valueof<T>>>(), idof<nonnull<valueof<T>>>()),
27
+ );
22
28
  // @ts-ignore: supplied by transform
23
29
  if (isDefined(changetype<nonnull<valueof<T>>>(value).__INITIALIZE)) {
24
30
  // @ts-ignore: supplied by transform
@@ -29,12 +35,18 @@ import { ensureArrayElementSlot, ensureArrayField } from "./shared";
29
35
 
30
36
  const valueStart = srcStart;
31
37
  // @ts-ignore: supplied by transform
32
- if (isDefined(changetype<nonnull<valueof<T>>>(value).__DESERIALIZE_FAST)) {
38
+ if (
39
+ isDefined(changetype<nonnull<valueof<T>>>(value).__DESERIALIZE_FAST)
40
+ ) {
33
41
  // @ts-ignore: supplied by transform
34
- srcStart = changetype<nonnull<valueof<T>>>(value).__DESERIALIZE_FAST<valueof<T>>(valueStart, srcEnd, value);
42
+ srcStart = changetype<nonnull<valueof<T>>>(value).__DESERIALIZE_FAST<
43
+ valueof<T>
44
+ >(valueStart, srcEnd, value);
35
45
  } else {
36
46
  // @ts-ignore: supplied by transform
37
- srcStart = changetype<nonnull<valueof<T>>>(value).__DESERIALIZE_SLOW<valueof<T>>(valueStart, srcEnd, value);
47
+ srcStart = changetype<nonnull<valueof<T>>>(value).__DESERIALIZE_SLOW<
48
+ valueof<T>
49
+ >(valueStart, srcEnd, value);
38
50
  }
39
51
  if (!srcStart || srcStart >= srcEnd) break;
40
52
 
@@ -56,6 +68,14 @@ import { ensureArrayElementSlot, ensureArrayField } from "./shared";
56
68
  }
57
69
 
58
70
 
59
- @inline export function deserializeStructArrayField<T extends unknown[]>(srcStart: usize, srcEnd: usize, fieldPtr: usize): usize {
60
- return deserializeStructArrayInto<T>(srcStart, srcEnd, ensureArrayField<T>(fieldPtr));
71
+ @inline export function deserializeStructArrayField<T extends unknown[]>(
72
+ srcStart: usize,
73
+ srcEnd: usize,
74
+ fieldPtr: usize,
75
+ ): usize {
76
+ return deserializeStructArrayInto<T>(
77
+ srcStart,
78
+ srcEnd,
79
+ ensureArrayField<T>(fieldPtr),
80
+ );
61
81
  }
@@ -21,7 +21,12 @@ import { deserializeStringArrayInto } from "./array/string";
21
21
  import { deserializeStructArrayInto } from "./array/struct";
22
22
 
23
23
 
24
- @inline export function deserializeArrayField<T extends unknown[]>(srcStart: usize, srcEnd: usize, dstObj: usize, dstOffset: usize = 0): usize {
24
+ @inline export function deserializeArrayField<T extends unknown[]>(
25
+ srcStart: usize,
26
+ srcEnd: usize,
27
+ dstObj: usize,
28
+ dstOffset: usize = 0,
29
+ ): usize {
25
30
  const fieldPtr = dstObj + dstOffset;
26
31
  if (isString<valueof<T>>()) {
27
32
  return deserializeStringArrayField<T>(srcStart, srcEnd, fieldPtr);
@@ -53,7 +58,10 @@ import { deserializeStructArrayInto } from "./array/struct";
53
58
  } else if (isDefined(type.__DESERIALIZE_CUSTOM)) {
54
59
  return deserializeStructArrayField<T>(srcStart, srcEnd, fieldPtr);
55
60
  // @ts-ignore: defined by transform
56
- } else if (isDefined(type.__DESERIALIZE_SLOW) || isDefined(type.__DESERIALIZE_FAST)) {
61
+ } else if (
62
+ isDefined(type.__DESERIALIZE_SLOW) ||
63
+ isDefined(type.__DESERIALIZE_FAST)
64
+ ) {
57
65
  return deserializeStructArrayField<T>(srcStart, srcEnd, fieldPtr);
58
66
  }
59
67
  throw new Error("Could not parse array field of type " + nameof<T>() + "!");
@@ -63,7 +71,11 @@ import { deserializeStructArrayInto } from "./array/struct";
63
71
  }
64
72
 
65
73
 
66
- @inline export function deserializeArrayInto_SWAR<T extends unknown[]>(srcStart: usize, srcEnd: usize, out: T): usize {
74
+ @inline export function deserializeArrayInto_SWAR<T extends unknown[]>(
75
+ srcStart: usize,
76
+ srcEnd: usize,
77
+ out: T,
78
+ ): usize {
67
79
  if (isString<valueof<T>>()) {
68
80
  return deserializeStringArrayInto<T>(srcStart, srcEnd, out);
69
81
  } else if (isBoolean<valueof<T>>()) {
@@ -94,7 +106,10 @@ import { deserializeStructArrayInto } from "./array/struct";
94
106
  } else if (isDefined(type.__DESERIALIZE_CUSTOM)) {
95
107
  return deserializeStructArrayInto<T>(srcStart, srcEnd, out);
96
108
  // @ts-ignore: defined by transform
97
- } else if (isDefined(type.__DESERIALIZE_SLOW) || isDefined(type.__DESERIALIZE_FAST)) {
109
+ } else if (
110
+ isDefined(type.__DESERIALIZE_SLOW) ||
111
+ isDefined(type.__DESERIALIZE_FAST)
112
+ ) {
98
113
  return deserializeStructArrayInto<T>(srcStart, srcEnd, out);
99
114
  }
100
115
  throw new Error("Could not parse array field of type " + nameof<T>() + "!");
@@ -0,0 +1,246 @@
1
+ // SWAR integer deserializers (signed + unsigned) over UTF-16 sources.
2
+ //
3
+ // Consume-to-end paths use the full tiered stride hierarchy:
4
+ //
5
+ // - parse16 (32 bytes / 16 digits): best for long inputs
6
+ // - parse8 (16 bytes / 8 digits)
7
+ // - parse4 ( 8 bytes / 4 digits)
8
+ // - scalar ( 2 bytes / 1 digit )
9
+ //
10
+ // Scan paths use asymmetric tuning based on empirical h2h benches:
11
+ //
12
+ // - Unsigned scan: parse8 + scalar (no parse4). For unsigned inputs the
13
+ // digit run is aligned, so parse8 either succeeds cleanly or terminates
14
+ // early. The intermediate parse4 stride costs more in wasted-validate
15
+ // than it saves in successful work.
16
+ // - Signed scan: parse4 + scalar (no parse8). The leading minus consumes
17
+ // 2 bytes, shifting the digit run into parse8's "terminator-in-load"
18
+ // zone where validate-fail is common. parse4 is a smaller failure unit.
19
+ //
20
+ // parse16 is omitted from scan entirely: a 16-character digit run plus
21
+ // terminator fits in its 32-byte load, so the terminator triggers a wasted
22
+ // validate-fail at the boundary.
23
+
24
+ import {
25
+ parse4Digits_PairMul,
26
+ parse4Digits_PairMul_Unsafe,
27
+ parse8Digits_PairMul,
28
+ parse8Digits_PairMul_Unsafe,
29
+ parse16Digits_SWAR,
30
+ parse16Digits_SWAR_Unsafe,
31
+ } from "../../util/swar-int";
32
+
33
+ const ASCII_MINUS: u16 = 45;
34
+ const ASCII_ZERO: u16 = 48;
35
+
36
+ /**
37
+ * Store a signed value into a typed integer field, truncating to `T`'s width.
38
+ *
39
+ * @param dstPtr Destination pointer (already includes any field offset).
40
+ * @param value The `u64` accumulator, interpreted as a two's-complement
41
+ * signed integer for narrower types.
42
+ */
43
+ // @ts-expect-error: @inline is a valid decorator
44
+ @inline function storeSignedToField<T extends number>(
45
+ dstPtr: usize,
46
+ value: u64,
47
+ ): void {
48
+ if (sizeof<T>() == 1) {
49
+ store<i8>(dstPtr, <i8>value);
50
+ } else if (sizeof<T>() == 2) {
51
+ store<i16>(dstPtr, <i16>value);
52
+ } else if (sizeof<T>() == 4) {
53
+ store<i32>(dstPtr, <i32>value);
54
+ } else {
55
+ store<i64>(dstPtr, <i64>value);
56
+ }
57
+ }
58
+
59
+ /**
60
+ * Store an unsigned value into a typed integer field, truncating to `T`'s
61
+ * width.
62
+ *
63
+ * @param dstPtr Destination pointer (already includes any field offset).
64
+ * @param value The `u64` accumulator.
65
+ */
66
+ // @ts-expect-error: @inline is a valid decorator
67
+ @inline function storeUnsignedToField<T extends number>(
68
+ dstPtr: usize,
69
+ value: u64,
70
+ ): void {
71
+ if (sizeof<T>() == 1) {
72
+ store<u8>(dstPtr, <u8>value);
73
+ } else if (sizeof<T>() == 2) {
74
+ store<u16>(dstPtr, <u16>value);
75
+ } else if (sizeof<T>() == 4) {
76
+ store<u32>(dstPtr, <u32>value);
77
+ } else {
78
+ store<u64>(dstPtr, value);
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Parse a signed integer by consuming the entire `[srcStart, srcEnd)` range
84
+ * as a digit run, with an optional leading `-`.
85
+ *
86
+ * Caller guarantees the range is well-formed (optional minus followed by
87
+ * digits only). Uses the unsafe SWAR kernels with no per-stride validation.
88
+ *
89
+ * @param srcStart Pointer to the first UTF-16 code unit.
90
+ * @param srcEnd Pointer just past the last code unit.
91
+ * @returns The parsed value, two's-complement truncated to `T`.
92
+ */
93
+ // @ts-expect-error: @inline is a valid decorator
94
+ @inline export function deserializeInteger_SWAR<T extends number>(
95
+ srcStart: usize,
96
+ srcEnd: usize,
97
+ ): T {
98
+ let negative = false;
99
+ if (srcStart < srcEnd && load<u16>(srcStart) == ASCII_MINUS) {
100
+ negative = true;
101
+ srcStart += 2;
102
+ }
103
+ let value: u64 = 0;
104
+ while (srcStart + 30 < srcEnd) {
105
+ value =
106
+ value * 10_000_000_000_000_000 + parse16Digits_SWAR_Unsafe(srcStart);
107
+ srcStart += 32;
108
+ }
109
+ while (srcStart + 14 < srcEnd) {
110
+ value =
111
+ value * 100_000_000 +
112
+ parse8Digits_PairMul_Unsafe(load<u64>(srcStart), load<u64>(srcStart, 8));
113
+ srcStart += 16;
114
+ }
115
+ while (srcStart + 6 < srcEnd) {
116
+ value = value * 10_000 + parse4Digits_PairMul_Unsafe(load<u64>(srcStart));
117
+ srcStart += 8;
118
+ }
119
+ while (srcStart < srcEnd) {
120
+ value = value * 10 + (<u32>load<u16>(srcStart) - ASCII_ZERO);
121
+ srcStart += 2;
122
+ }
123
+ return <T>(negative ? 0 - value : value);
124
+ }
125
+
126
+ /**
127
+ * Scan for a signed integer field, stopping at the first non-digit
128
+ * character. Writes the parsed value through `dstObj + dstOffset` and
129
+ * returns the source position immediately after the last digit.
130
+ *
131
+ * Used by struct field deserializers, where the digit run is followed by
132
+ * a `,`, `}`, `]`, whitespace, etc.
133
+ *
134
+ * @param srcStart Pointer to the first UTF-16 code unit.
135
+ * @param srcEnd Pointer just past the last code unit.
136
+ * @param dstObj Destination object pointer.
137
+ * @param dstOffset Byte offset of the field within `dstObj`.
138
+ * @returns The source position immediately after the last digit consumed.
139
+ */
140
+ // @ts-expect-error: @inline is a valid decorator
141
+ @inline export function deserializeIntegerField_SWAR<T extends number>(
142
+ srcStart: usize,
143
+ srcEnd: usize,
144
+ dstObj: usize,
145
+ dstOffset: usize = 0,
146
+ ): usize {
147
+ let negative = false;
148
+ if (srcStart < srcEnd && load<u16>(srcStart) == ASCII_MINUS) {
149
+ negative = true;
150
+ srcStart += 2;
151
+ }
152
+ let value: u64 = 0;
153
+ // Signed scan uses parse4 + scalar only (see file header).
154
+ while (srcStart + 6 < srcEnd) {
155
+ const parsed = parse4Digits_PairMul(load<u64>(srcStart));
156
+ if (parsed == U32.MAX_VALUE) break;
157
+ value = value * 10_000 + parsed;
158
+ srcStart += 8;
159
+ }
160
+ while (srcStart < srcEnd) {
161
+ const digit = <u32>load<u16>(srcStart) - ASCII_ZERO;
162
+ if (digit > 9) break;
163
+ value = value * 10 + digit;
164
+ srcStart += 2;
165
+ }
166
+ storeSignedToField<T>(dstObj + dstOffset, negative ? 0 - value : value);
167
+ return srcStart;
168
+ }
169
+
170
+ /**
171
+ * Parse an unsigned integer by consuming the entire `[srcStart, srcEnd)`
172
+ * range as a digit run.
173
+ *
174
+ * Caller guarantees the range is digits only. Uses the unsafe SWAR kernels
175
+ * with no per-stride validation.
176
+ *
177
+ * @param srcStart Pointer to the first UTF-16 code unit.
178
+ * @param srcEnd Pointer just past the last code unit.
179
+ * @returns The parsed value, truncated to `T`.
180
+ */
181
+ // @ts-expect-error: @inline is a valid decorator
182
+ @inline export function deserializeUnsigned_SWAR<T extends number>(
183
+ srcStart: usize,
184
+ srcEnd: usize,
185
+ ): T {
186
+ let value: u64 = 0;
187
+ while (srcStart + 30 < srcEnd) {
188
+ value =
189
+ value * 10_000_000_000_000_000 + parse16Digits_SWAR_Unsafe(srcStart);
190
+ srcStart += 32;
191
+ }
192
+ while (srcStart + 14 < srcEnd) {
193
+ value =
194
+ value * 100_000_000 +
195
+ parse8Digits_PairMul_Unsafe(load<u64>(srcStart), load<u64>(srcStart, 8));
196
+ srcStart += 16;
197
+ }
198
+ while (srcStart + 6 < srcEnd) {
199
+ value = value * 10_000 + parse4Digits_PairMul_Unsafe(load<u64>(srcStart));
200
+ srcStart += 8;
201
+ }
202
+ while (srcStart < srcEnd) {
203
+ value = value * 10 + (<u32>load<u16>(srcStart) - ASCII_ZERO);
204
+ srcStart += 2;
205
+ }
206
+ return <T>value;
207
+ }
208
+
209
+ /**
210
+ * Scan for an unsigned integer field, stopping at the first non-digit
211
+ * character. Writes the parsed value through `dstObj + dstOffset` and
212
+ * returns the source position immediately after the last digit.
213
+ *
214
+ * @param srcStart Pointer to the first UTF-16 code unit.
215
+ * @param srcEnd Pointer just past the last code unit.
216
+ * @param dstObj Destination object pointer.
217
+ * @param dstOffset Byte offset of the field within `dstObj`.
218
+ * @returns The source position immediately after the last digit consumed.
219
+ */
220
+ // @ts-expect-error: @inline is a valid decorator
221
+ @inline export function deserializeUnsignedField_SWAR<T extends number>(
222
+ srcStart: usize,
223
+ srcEnd: usize,
224
+ dstObj: usize,
225
+ dstOffset: usize = 0,
226
+ ): usize {
227
+ let value: u64 = 0;
228
+ // Unsigned scan uses parse8 + scalar only (see file header).
229
+ while (srcStart + 14 < srcEnd) {
230
+ const parsed = parse8Digits_PairMul(
231
+ load<u64>(srcStart),
232
+ load<u64>(srcStart, 8),
233
+ );
234
+ if (parsed == U32.MAX_VALUE) break;
235
+ value = value * 100_000_000 + parsed;
236
+ srcStart += 16;
237
+ }
238
+ while (srcStart < srcEnd) {
239
+ const digit = <u32>load<u16>(srcStart) - ASCII_ZERO;
240
+ if (digit > 9) break;
241
+ value = value * 10 + digit;
242
+ srcStart += 2;
243
+ }
244
+ storeUnsignedToField<T>(dstObj + dstOffset, value);
245
+ return srcStart;
246
+ }