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.
- package/CHANGELOG.md +13 -0
- package/assembly/deserialize/helpers/uint.ts +4 -1
- package/assembly/deserialize/index/arbitrary.ts +5 -1
- package/assembly/deserialize/index/array.ts +13 -3
- package/assembly/deserialize/index/integer.ts +68 -1
- package/assembly/deserialize/index/string.ts +4 -1
- package/assembly/deserialize/index/typedarray.ts +13 -3
- package/assembly/deserialize/index/unsigned.ts +78 -1
- package/assembly/deserialize/simd/array/integer.ts +327 -50
- package/assembly/deserialize/simd/integer.ts +233 -0
- package/assembly/deserialize/simd/string.ts +45 -11
- package/assembly/deserialize/simple/arbitrary.ts +11 -4
- package/assembly/deserialize/simple/array/arbitrary.ts +24 -5
- package/assembly/deserialize/simple/array/array.ts +8 -2
- package/assembly/deserialize/simple/array/bool.ts +38 -7
- package/assembly/deserialize/simple/array/box.ts +8 -2
- package/assembly/deserialize/simple/array/float.ts +36 -9
- package/assembly/deserialize/simple/array/generic.ts +12 -4
- package/assembly/deserialize/simple/array/integer.ts +8 -2
- package/assembly/deserialize/simple/array/map.ts +26 -6
- package/assembly/deserialize/simple/array/object.ts +26 -6
- package/assembly/deserialize/simple/array/raw.ts +34 -7
- package/assembly/deserialize/simple/array/string.ts +8 -2
- package/assembly/deserialize/simple/array/struct.ts +26 -6
- package/assembly/deserialize/simple/array.ts +13 -3
- package/assembly/deserialize/simple/bool.ts +6 -2
- package/assembly/deserialize/simple/float.ts +6 -1
- package/assembly/deserialize/simple/integer.ts +10 -2
- package/assembly/deserialize/simple/map.ts +95 -22
- package/assembly/deserialize/simple/object.ts +63 -14
- package/assembly/deserialize/simple/raw.ts +4 -1
- package/assembly/deserialize/simple/set.ts +59 -14
- package/assembly/deserialize/simple/staticarray/string.ts +11 -3
- package/assembly/deserialize/simple/staticarray.ts +64 -14
- package/assembly/deserialize/simple/string.ts +5 -92
- package/assembly/deserialize/simple/struct.ts +5 -1
- package/assembly/deserialize/simple/typedarray.ts +16 -3
- package/assembly/deserialize/simple/unsigned.ts +10 -15
- package/assembly/deserialize/swar/array/arbitrary.ts +5 -1
- package/assembly/deserialize/swar/array/array.ts +30 -6
- package/assembly/deserialize/swar/array/bool.ts +22 -4
- package/assembly/deserialize/swar/array/box.ts +5 -1
- package/assembly/deserialize/swar/array/float.ts +15 -3
- package/assembly/deserialize/swar/array/generic.ts +24 -7
- package/assembly/deserialize/swar/array/integer.ts +328 -84
- package/assembly/deserialize/swar/array/map.ts +5 -1
- package/assembly/deserialize/swar/array/object.ts +27 -7
- package/assembly/deserialize/swar/array/raw.ts +5 -1
- package/assembly/deserialize/swar/array/shared.ts +36 -11
- package/assembly/deserialize/swar/array/string.ts +20 -4
- package/assembly/deserialize/swar/array/struct.ts +27 -7
- package/assembly/deserialize/swar/array.ts +19 -4
- package/assembly/deserialize/swar/integer.ts +246 -0
- package/assembly/deserialize/swar/string.ts +98 -194
- package/assembly/index.d.ts +3 -1
- package/assembly/index.ts +312 -81
- package/assembly/serialize/index/float.ts +5 -1
- package/assembly/serialize/index/typedarray.ts +25 -7
- package/assembly/serialize/simd/string.ts +6 -2
- package/assembly/serialize/simple/array.ts +179 -1
- package/assembly/serialize/simple/float.ts +4 -1
- package/assembly/serialize/simple/integer.ts +8 -9
- package/assembly/serialize/simple/map.ts +6 -2
- package/assembly/serialize/simple/raw.ts +5 -1
- package/assembly/serialize/simple/set.ts +6 -1
- package/assembly/serialize/simple/staticarray.ts +6 -1
- package/assembly/serialize/simple/string.ts +0 -1
- package/assembly/serialize/simple/typedarray.ts +10 -3
- package/assembly/serialize/swar/string.ts +18 -5
- package/assembly/util/atoi-fast.ts +81 -0
- package/assembly/util/concat.ts +5 -1
- package/assembly/util/dragonbox-cache.ts +443 -2
- package/assembly/util/dragonbox.ts +43 -14
- package/assembly/util/itoa-fast.ts +230 -0
- package/assembly/util/masks.ts +18 -1
- package/assembly/util/parsefloat-fast.ts +167 -0
- package/assembly/util/simd-int.ts +191 -0
- package/assembly/util/snp.ts +4 -1
- package/assembly/util/swar-int.ts +248 -0
- package/assembly/util/swar.ts +13 -3
- package/lib/as-bs.ts +13 -5
- package/package.json +5 -2
- package/transform/lib/builder.d.ts.map +1 -1
- package/transform/lib/builder.js +13 -5
- package/transform/lib/builder.js.map +1 -1
- package/transform/lib/index.d.ts +1 -0
- package/transform/lib/index.d.ts.map +1 -1
- package/transform/lib/index.js +1030 -241
- package/transform/lib/index.js.map +1 -1
- package/transform/lib/linkers/alias.d.ts.map +1 -1
- package/transform/lib/linkers/alias.js.map +1 -1
- package/transform/lib/linkers/custom.d.ts.map +1 -1
- package/transform/lib/linkers/custom.js +3 -2
- package/transform/lib/linkers/custom.js.map +1 -1
- package/transform/lib/linkers/imports.d.ts.map +1 -1
- package/transform/lib/linkers/imports.js.map +1 -1
- package/transform/lib/types.d.ts.map +1 -1
- package/transform/lib/types.js +54 -16
- package/transform/lib/types.js.map +1 -1
- package/transform/lib/util.d.ts.map +1 -1
- package/transform/lib/util.js +1 -1
- package/transform/lib/util.js.map +1 -1
- package/transform/lib/visitor.d.ts.map +1 -1
- package/transform/lib/visitor.js +2 -1
- package/transform/lib/visitor.js.map +1 -1
- package/assembly/custom/util.ts +0 -310
|
@@ -1,7 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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>>(
|
|
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 (
|
|
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>>(
|
|
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>>())
|
|
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(
|
|
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)
|
|
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)
|
|
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[]>(
|
|
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>>(
|
|
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[]>(
|
|
42
|
-
|
|
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[]>(
|
|
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>>(
|
|
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 (
|
|
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<
|
|
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<
|
|
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[]>(
|
|
60
|
-
|
|
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[]>(
|
|
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 (
|
|
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[]>(
|
|
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 (
|
|
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
|
+
}
|