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.
- package/CHANGELOG.md +45 -0
- package/README.md +1 -1
- package/assembly/deserialize/helpers/uint.ts +4 -1
- package/assembly/deserialize/index/arbitrary.ts +7 -3
- package/assembly/deserialize/index/array.ts +42 -17
- package/assembly/deserialize/index/bool.ts +1 -1
- package/assembly/deserialize/index/date.ts +1 -1
- package/assembly/deserialize/index/float.ts +40 -1
- package/assembly/deserialize/index/integer.ts +68 -1
- package/assembly/deserialize/index/map.ts +1 -1
- package/assembly/deserialize/index/object.ts +1 -1
- package/assembly/deserialize/index/raw.ts +1 -1
- package/assembly/deserialize/index/set.ts +1 -1
- package/assembly/deserialize/index/staticarray.ts +4 -1
- package/assembly/deserialize/index/string.ts +32 -4
- package/assembly/deserialize/index/struct.ts +1 -1
- package/assembly/deserialize/index/typedarray.ts +30 -10
- package/assembly/deserialize/index/unsigned.ts +78 -1
- package/assembly/deserialize/index.ts +1 -0
- package/assembly/deserialize/{simple → naive}/array/arbitrary.ts +24 -5
- package/assembly/deserialize/{simple → naive}/array/array.ts +8 -2
- package/assembly/deserialize/naive/array/bool.ts +68 -0
- package/assembly/deserialize/{simple → naive}/array/box.ts +8 -2
- package/assembly/deserialize/naive/array/float.ts +63 -0
- package/assembly/deserialize/{simple → naive}/array/generic.ts +14 -7
- package/assembly/deserialize/naive/array/integer.ts +86 -0
- package/assembly/deserialize/naive/array/map.ts +47 -0
- package/assembly/deserialize/naive/array/object.ts +47 -0
- package/assembly/deserialize/{simple → naive}/array/raw.ts +34 -7
- package/assembly/deserialize/naive/array/string.ts +69 -0
- package/assembly/deserialize/naive/array/struct.ts +47 -0
- package/assembly/deserialize/{simple → naive}/array.ts +15 -10
- package/assembly/deserialize/{simple → naive}/bool.ts +6 -2
- package/assembly/deserialize/naive/float.ts +135 -0
- package/assembly/deserialize/{simple → naive}/integer.ts +10 -2
- package/assembly/deserialize/{simple → naive}/map.ts +106 -27
- package/assembly/deserialize/{simple → naive}/object.ts +65 -19
- package/assembly/deserialize/{simple → naive}/raw.ts +4 -1
- package/assembly/deserialize/{simple → naive}/set.ts +49 -19
- package/assembly/deserialize/{simple → naive}/staticarray/array.ts +1 -1
- package/assembly/deserialize/{simple → naive}/staticarray/bool.ts +1 -1
- package/assembly/deserialize/{simple → naive}/staticarray/float.ts +1 -1
- package/assembly/deserialize/{simple → naive}/staticarray/integer.ts +1 -1
- package/assembly/deserialize/{simple → naive}/staticarray/string.ts +11 -3
- package/assembly/deserialize/{simple → naive}/staticarray/struct.ts +1 -2
- package/assembly/deserialize/{simple → naive}/staticarray.ts +68 -18
- package/assembly/deserialize/naive/string.ts +199 -0
- package/assembly/deserialize/{simple → naive}/struct.ts +5 -1
- package/assembly/deserialize/{simple → naive}/typedarray.ts +17 -4
- package/assembly/deserialize/{simple → naive}/unsigned.ts +10 -15
- package/assembly/deserialize/simd/array/integer.ts +339 -62
- package/assembly/deserialize/simd/float.ts +303 -0
- package/assembly/deserialize/simd/integer.ts +233 -0
- package/assembly/deserialize/simd/string.ts +266 -107
- package/assembly/deserialize/swar/array/arbitrary.ts +11 -3
- package/assembly/deserialize/swar/array/array.ts +40 -9
- package/assembly/deserialize/swar/array/bool.ts +28 -5
- package/assembly/deserialize/swar/array/box.ts +11 -3
- package/assembly/deserialize/swar/array/float.ts +295 -7
- package/assembly/deserialize/swar/array/generic.ts +28 -7
- package/assembly/deserialize/swar/array/integer.ts +363 -112
- package/assembly/deserialize/swar/array/map.ts +11 -3
- package/assembly/deserialize/swar/array/object.ts +37 -25
- package/assembly/deserialize/swar/array/raw.ts +11 -3
- package/assembly/deserialize/swar/array/shared.ts +63 -14
- package/assembly/deserialize/swar/array/string.ts +140 -7
- package/assembly/deserialize/swar/array/struct.ts +66 -12
- package/assembly/deserialize/swar/array.ts +12 -51
- package/assembly/deserialize/swar/float.ts +304 -0
- package/assembly/deserialize/swar/integer.ts +246 -0
- package/assembly/deserialize/swar/string.ts +213 -294
- package/assembly/deserialize/swar/typedarray.ts +224 -0
- package/assembly/index.d.ts +3 -1
- package/assembly/index.ts +402 -261
- package/assembly/serialize/index/array.ts +1 -1
- package/assembly/serialize/index/bool.ts +1 -1
- package/assembly/serialize/index/date.ts +1 -1
- package/assembly/serialize/index/float.ts +5 -1
- package/assembly/serialize/index/integer.ts +1 -1
- package/assembly/serialize/index/map.ts +1 -1
- package/assembly/serialize/index/raw.ts +1 -1
- package/assembly/serialize/index/set.ts +1 -1
- package/assembly/serialize/index/staticarray.ts +1 -1
- package/assembly/serialize/index/string.ts +1 -1
- package/assembly/serialize/index/struct.ts +1 -1
- package/assembly/serialize/index/typedarray.ts +21 -12
- package/assembly/serialize/index.ts +1 -0
- package/assembly/serialize/naive/array.ts +351 -0
- package/assembly/serialize/{simple → naive}/float.ts +4 -1
- package/assembly/serialize/naive/integer.ts +19 -0
- package/assembly/serialize/{simple → naive}/map.ts +6 -2
- package/assembly/serialize/{simple → naive}/raw.ts +5 -1
- package/assembly/serialize/{simple → naive}/set.ts +6 -1
- package/assembly/serialize/{simple → naive}/staticarray.ts +6 -1
- package/assembly/serialize/{simple → naive}/string.ts +1 -2
- package/assembly/serialize/{simple → naive}/typedarray.ts +10 -3
- package/assembly/serialize/simd/string.ts +6 -2
- package/assembly/serialize/swar/string.ts +15 -141
- 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 +53 -17
- package/assembly/util/itoa-fast.ts +241 -0
- package/assembly/util/masks.ts +18 -1
- package/assembly/util/parsefloat-fast.ts +167 -0
- package/assembly/util/scanValueEnd.ts +78 -0
- package/assembly/util/scientific.ts +132 -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 +27 -6
- package/package.json +15 -11
- 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 +5 -0
- package/transform/lib/index.d.ts.map +1 -1
- package/transform/lib/index.js +1046 -340
- 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
- package/assembly/deserialize/simple/arbitrary.ts +0 -23
- package/assembly/deserialize/simple/array/bool.ts +0 -17
- package/assembly/deserialize/simple/array/float.ts +0 -28
- package/assembly/deserialize/simple/array/integer.ts +0 -27
- package/assembly/deserialize/simple/array/map.ts +0 -28
- package/assembly/deserialize/simple/array/object.ts +0 -28
- package/assembly/deserialize/simple/array/string.ts +0 -23
- package/assembly/deserialize/simple/array/struct.ts +0 -28
- package/assembly/deserialize/simple/float.ts +0 -201
- package/assembly/deserialize/simple/string.ts +0 -132
- package/assembly/serialize/simple/arbitrary.ts +0 -79
- package/assembly/serialize/simple/array.ts +0 -86
- package/assembly/serialize/simple/integer.ts +0 -20
- package/assembly/serialize/simple/object.ts +0 -42
- /package/assembly/deserialize/{simple → naive}/date.ts +0 -0
- /package/assembly/serialize/{simple → naive}/bool.ts +0 -0
- /package/assembly/serialize/{simple → naive}/date.ts +0 -0
- /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>[]>(
|
|
6
|
-
|
|
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 "
|
|
5
|
-
|
|
6
|
-
export function deserializeGenericArray<T extends unknown[]>(
|
|
7
|
-
|
|
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)
|
|
14
|
-
|
|
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 {
|
|
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(
|
|
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[]>(
|
|
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)
|
|
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)
|
|
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)
|
|
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(
|
|
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 {
|
|
5
|
+
import { deserializeFloatArray_NAIVE } from "./array/float";
|
|
6
6
|
import { deserializeGenericArray } from "./array/generic";
|
|
7
|
-
import {
|
|
7
|
+
import { deserializeIntegerArray_NAIVE } from "./array/integer";
|
|
8
8
|
import { deserializeMapArray } from "./array/map";
|
|
9
9
|
import { deserializeStructArray } from "./array/struct";
|
|
10
|
-
import {
|
|
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[]>(
|
|
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>
|
|
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
|
|
27
|
+
return deserializeIntegerArray_NAIVE<T>(srcStart, srcEnd, dst);
|
|
26
28
|
} else if (isFloat<valueof<T>>()) {
|
|
27
29
|
// @ts-ignore
|
|
28
|
-
return
|
|
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 (
|
|
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(
|
|
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)
|
|
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
|
}
|