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