json-as 1.3.1 → 1.3.3
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 +9 -26
- package/README.md +43 -19
- package/assembly/deserialize/index/arbitrary.ts +1 -1
- package/assembly/deserialize/index/array.ts +6 -1
- package/assembly/deserialize/index/float.ts +1 -1
- package/assembly/deserialize/index/integer.ts +1 -1
- package/assembly/deserialize/index/unsigned.ts +1 -1
- package/assembly/deserialize/simd/string.ts +17 -13
- package/assembly/deserialize/simple/arbitrary.ts +1 -1
- package/assembly/deserialize/simple/array/generic.ts +42 -0
- package/assembly/deserialize/simple/array.ts +8 -1
- package/assembly/deserialize/{float.ts → simple/float.ts} +22 -2
- package/assembly/deserialize/{integer.ts → simple/integer.ts} +3 -2
- package/assembly/deserialize/simple/map.ts +62 -12
- package/assembly/deserialize/simple/object.ts +1 -1
- package/assembly/deserialize/simple/set.ts +119 -134
- package/assembly/deserialize/simple/staticarray.ts +13 -1
- package/assembly/deserialize/simple/string.ts +15 -10
- package/assembly/deserialize/simple/struct.ts +9 -157
- package/assembly/deserialize/simple/typedarray.ts +1 -1
- package/assembly/deserialize/{unsigned.ts → simple/unsigned.ts} +3 -2
- package/assembly/deserialize/swar/array/array.ts +42 -7
- package/assembly/deserialize/swar/array/bool.ts +6 -2
- package/assembly/deserialize/swar/array/float.ts +7 -3
- package/assembly/deserialize/swar/array/generic.ts +41 -0
- package/assembly/deserialize/swar/array/integer.ts +8 -4
- package/assembly/deserialize/swar/array/object.ts +21 -4
- package/assembly/deserialize/swar/array/shared.ts +19 -4
- package/assembly/deserialize/swar/array/string.ts +6 -2
- package/assembly/deserialize/swar/array/struct.ts +21 -4
- package/assembly/deserialize/swar/array.ts +57 -2
- package/assembly/deserialize/swar/string.ts +248 -372
- package/assembly/index.d.ts +1 -0
- package/assembly/index.ts +77 -19
- package/assembly/serialize/index/arbitrary.ts +3 -3
- package/assembly/serialize/index/float.ts +1 -1
- package/assembly/serialize/index/object.ts +1 -5
- package/assembly/serialize/simd/string.ts +4 -5
- package/assembly/serialize/simple/arbitrary.ts +3 -3
- package/assembly/serialize/simple/array.ts +18 -6
- package/assembly/serialize/simple/float.ts +20 -4
- package/assembly/serialize/simple/map.ts +10 -27
- package/assembly/serialize/simple/object.ts +1 -5
- package/assembly/serialize/simple/set.ts +3 -4
- package/assembly/serialize/simple/staticarray.ts +4 -3
- package/assembly/serialize/simple/typedarray.ts +9 -7
- package/assembly/serialize/swar/string.ts +0 -1
- package/assembly/tsconfig.json +1 -0
- package/assembly/util/dragonbox-cache.ts +4 -0
- package/assembly/util/dragonbox.ts +624 -0
- package/lib/as-bs.ts +35 -24
- package/package.json +26 -18
- package/transform/lib/index.d.ts.map +1 -1
- package/transform/lib/index.js +508 -148
- package/transform/lib/index.js.map +1 -1
|
@@ -1,39 +1,66 @@
|
|
|
1
1
|
import { JSON } from "../..";
|
|
2
|
-
import {
|
|
3
|
-
import { isSpace, atoi,
|
|
2
|
+
import { BRACKET_LEFT, BRACKET_RIGHT, BRACE_LEFT, BRACE_RIGHT, CHAR_F, CHAR_T, COMMA, QUOTE } from "../../custom/chars";
|
|
3
|
+
import { isSpace, atoi, scanStringEnd } from "../../util";
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
// @ts-expect-error: Decorator valid here
|
|
6
|
+
@inline function scanSetElementEnd(srcStart: usize, srcEnd: usize): usize {
|
|
7
|
+
const first = load<u16>(srcStart);
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
if (first == QUOTE) {
|
|
10
|
+
const end = scanStringEnd(srcStart, srcEnd);
|
|
11
|
+
return end < srcEnd ? end + 2 : 0;
|
|
12
|
+
}
|
|
10
13
|
|
|
11
|
-
if (
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
if (first == BRACE_LEFT || first == BRACKET_LEFT) {
|
|
15
|
+
let depth: i32 = 1;
|
|
16
|
+
let ptr = srcStart + 2;
|
|
17
|
+
|
|
18
|
+
while (ptr < srcEnd) {
|
|
19
|
+
const code = load<u16>(ptr);
|
|
20
|
+
if (code == QUOTE) {
|
|
21
|
+
ptr = scanStringEnd(ptr, srcEnd);
|
|
22
|
+
if (ptr >= srcEnd) return 0;
|
|
23
|
+
} else if (code == BRACE_LEFT || code == BRACKET_LEFT) {
|
|
24
|
+
depth++;
|
|
25
|
+
} else if (code == BRACE_RIGHT || code == BRACKET_RIGHT) {
|
|
26
|
+
if (--depth == 0) return ptr + 2;
|
|
27
|
+
}
|
|
28
|
+
ptr += 2;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return 0;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
let ptr = srcStart;
|
|
35
|
+
while (ptr < srcEnd) {
|
|
36
|
+
const code = load<u16>(ptr);
|
|
37
|
+
if (code == COMMA || code == BRACKET_RIGHT) return ptr;
|
|
38
|
+
ptr += 2;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return 0;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function deserializeSetDirect<T extends Set<any>>(srcStart: usize, srcEnd: usize, out: nonnull<T>, allowWhitespace: bool = false): usize {
|
|
45
|
+
if (srcStart >= srcEnd || load<u16>(srcStart) != BRACKET_LEFT) throw new Error("Expected '[' at start of set");
|
|
14
46
|
|
|
15
47
|
srcStart += 2;
|
|
48
|
+
if (allowWhitespace) while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
|
|
49
|
+
if (srcStart >= srcEnd) throw new Error("Unterminated set");
|
|
50
|
+
if (load<u16>(srcStart) == BRACKET_RIGHT) return srcStart + 2;
|
|
16
51
|
|
|
17
|
-
while (srcStart < srcEnd
|
|
18
|
-
|
|
19
|
-
|
|
52
|
+
while (srcStart < srcEnd) {
|
|
53
|
+
if (allowWhitespace) while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
|
|
54
|
+
const code = load<u16>(srcStart);
|
|
20
55
|
|
|
21
56
|
// @ts-ignore: type
|
|
22
57
|
if (isString<indexof<T>>()) {
|
|
23
|
-
if (code
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
// @ts-ignore: type
|
|
30
|
-
out.add(JSON.__deserialize<indexof<T>>(lastIndex, srcStart + 2));
|
|
31
|
-
srcStart += 2;
|
|
32
|
-
break;
|
|
33
|
-
}
|
|
34
|
-
srcStart += 2;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
58
|
+
if (code != QUOTE) break;
|
|
59
|
+
const end = scanStringEnd(srcStart, srcEnd);
|
|
60
|
+
if (end >= srcEnd) break;
|
|
61
|
+
// @ts-ignore: type
|
|
62
|
+
out.add(JSON.__deserialize<indexof<T>>(srcStart, end + 2));
|
|
63
|
+
srcStart = end + 2;
|
|
37
64
|
// @ts-ignore: type
|
|
38
65
|
} else if (isBoolean<indexof<T>>()) {
|
|
39
66
|
if (code == CHAR_T) {
|
|
@@ -44,126 +71,84 @@ export function deserializeSet<T extends Set<any>>(srcStart: usize, srcEnd: usiz
|
|
|
44
71
|
// @ts-ignore: type
|
|
45
72
|
out.add(<indexof<T>>false);
|
|
46
73
|
srcStart += 10;
|
|
74
|
+
} else {
|
|
75
|
+
break;
|
|
47
76
|
}
|
|
48
77
|
// @ts-ignore: type
|
|
49
78
|
} else if (isInteger<indexof<T>>()) {
|
|
50
|
-
if (code - 48
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
// @ts-ignore: type
|
|
57
|
-
out.add(atoi<indexof<T>>(lastIndex, srcStart));
|
|
58
|
-
break;
|
|
59
|
-
}
|
|
60
|
-
srcStart += 2;
|
|
61
|
-
}
|
|
79
|
+
if (code - 48 > 9 && code != 45) break;
|
|
80
|
+
let ptr = srcStart + 2;
|
|
81
|
+
while (ptr < srcEnd) {
|
|
82
|
+
const next = load<u16>(ptr);
|
|
83
|
+
if (next == COMMA || next == BRACKET_RIGHT || (allowWhitespace && isSpace(next))) break;
|
|
84
|
+
ptr += 2;
|
|
62
85
|
}
|
|
63
86
|
// @ts-ignore: type
|
|
87
|
+
out.add(atoi<indexof<T>>(srcStart, ptr));
|
|
88
|
+
srcStart = ptr;
|
|
89
|
+
// @ts-ignore: type
|
|
64
90
|
} else if (isFloat<indexof<T>>()) {
|
|
65
|
-
if (code - 48
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
// @ts-ignore: type
|
|
72
|
-
out.add(JSON.__deserialize<indexof<T>>(lastIndex, srcStart));
|
|
73
|
-
break;
|
|
74
|
-
}
|
|
75
|
-
srcStart += 2;
|
|
76
|
-
}
|
|
91
|
+
if (code - 48 > 9 && code != 45) break;
|
|
92
|
+
let ptr = srcStart + 2;
|
|
93
|
+
while (ptr < srcEnd) {
|
|
94
|
+
const next = load<u16>(ptr);
|
|
95
|
+
if (next == COMMA || next == BRACKET_RIGHT || (allowWhitespace && isSpace(next))) break;
|
|
96
|
+
ptr += 2;
|
|
77
97
|
}
|
|
78
98
|
// @ts-ignore: type
|
|
99
|
+
out.add(JSON.__deserialize<indexof<T>>(srcStart, ptr));
|
|
100
|
+
srcStart = ptr;
|
|
101
|
+
// @ts-ignore: type
|
|
79
102
|
} else if (isManaged<indexof<T>>() || isReference<indexof<T>>()) {
|
|
103
|
+
const end = scanSetElementEnd(srcStart, srcEnd);
|
|
104
|
+
if (!end) break;
|
|
80
105
|
// @ts-ignore: type
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
srcStart += 2;
|
|
95
|
-
// @ts-ignore: type
|
|
96
|
-
out.add(JSON.__deserialize<indexof<T>>(lastIndex, srcStart));
|
|
97
|
-
break;
|
|
98
|
-
}
|
|
99
|
-
} else if (c == BRACE_LEFT) {
|
|
100
|
-
depth++;
|
|
101
|
-
}
|
|
102
|
-
srcStart += 2;
|
|
103
|
-
}
|
|
104
|
-
} else if (code == BRACKET_LEFT) {
|
|
105
|
-
// Nested array/set
|
|
106
|
-
const lastIndex = srcStart;
|
|
107
|
-
let depth: u32 = 1;
|
|
108
|
-
srcStart += 2;
|
|
109
|
-
while (srcStart < srcEnd) {
|
|
110
|
-
const c = load<u16>(srcStart);
|
|
111
|
-
if (c == BRACKET_RIGHT) {
|
|
112
|
-
if (--depth == 0) {
|
|
113
|
-
srcStart += 2;
|
|
114
|
-
// @ts-ignore: type
|
|
115
|
-
out.add(JSON.__deserialize<indexof<T>>(lastIndex, srcStart));
|
|
116
|
-
break;
|
|
117
|
-
}
|
|
118
|
-
} else if (c == BRACKET_LEFT) {
|
|
119
|
-
depth++;
|
|
120
|
-
}
|
|
121
|
-
srcStart += 2;
|
|
122
|
-
}
|
|
123
|
-
} else if (type instanceof JSON.Raw) {
|
|
124
|
-
// Handle JSON.Raw
|
|
125
|
-
if (code == QUOTE) {
|
|
126
|
-
const lastIndex = srcStart;
|
|
127
|
-
srcStart += 2;
|
|
128
|
-
while (srcStart < srcEnd) {
|
|
129
|
-
const c = load<u16>(srcStart);
|
|
130
|
-
if (c == QUOTE && isUnescapedQuote(srcStart)) {
|
|
131
|
-
// @ts-ignore: type
|
|
132
|
-
out.add(JSON.__deserialize<indexof<T>>(lastIndex, srcStart + 2));
|
|
133
|
-
srcStart += 2;
|
|
134
|
-
break;
|
|
135
|
-
}
|
|
136
|
-
srcStart += 2;
|
|
137
|
-
}
|
|
138
|
-
} else if (code - 48 <= 9 || code == 45) {
|
|
139
|
-
const lastIndex = srcStart;
|
|
140
|
-
srcStart += 2;
|
|
141
|
-
while (srcStart < srcEnd) {
|
|
142
|
-
const c = load<u16>(srcStart);
|
|
143
|
-
if (c == COMMA || c == BRACKET_RIGHT || isSpace(c)) {
|
|
144
|
-
// @ts-ignore: type
|
|
145
|
-
out.add(JSON.__deserialize<indexof<T>>(lastIndex, srcStart));
|
|
146
|
-
break;
|
|
147
|
-
}
|
|
148
|
-
srcStart += 2;
|
|
149
|
-
}
|
|
150
|
-
} else if (code == CHAR_T) {
|
|
151
|
-
// @ts-ignore: type
|
|
152
|
-
out.add(JSON.__deserialize<indexof<T>>(srcStart, srcStart + 8));
|
|
153
|
-
srcStart += 8;
|
|
154
|
-
} else if (code == CHAR_F) {
|
|
155
|
-
// @ts-ignore: type
|
|
156
|
-
out.add(JSON.__deserialize<indexof<T>>(srcStart, srcStart + 10));
|
|
157
|
-
srcStart += 10;
|
|
158
|
-
} else if (code == CHAR_N) {
|
|
159
|
-
// @ts-ignore: type
|
|
160
|
-
out.add(JSON.__deserialize<indexof<T>>(srcStart, srcStart + 8));
|
|
161
|
-
srcStart += 8;
|
|
162
|
-
}
|
|
163
|
-
}
|
|
106
|
+
out.add(JSON.__deserialize<indexof<T>>(srcStart, end));
|
|
107
|
+
srcStart = end;
|
|
108
|
+
} else {
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (allowWhitespace) while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
|
|
113
|
+
if (srcStart >= srcEnd) break;
|
|
114
|
+
const next = load<u16>(srcStart);
|
|
115
|
+
if (next == COMMA) {
|
|
116
|
+
srcStart += 2;
|
|
117
|
+
if (allowWhitespace) while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
|
|
118
|
+
continue;
|
|
164
119
|
}
|
|
165
|
-
srcStart
|
|
120
|
+
if (next == BRACKET_RIGHT) return srcStart + 2;
|
|
121
|
+
break;
|
|
166
122
|
}
|
|
167
123
|
|
|
124
|
+
throw new Error("Failed to parse JSON!");
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function deserializeSet<T extends Set<any>>(srcStart: usize, srcEnd: usize, dst: usize): T {
|
|
128
|
+
const out = changetype<nonnull<T>>(dst || changetype<usize>(instantiate<T>()));
|
|
129
|
+
out.clear();
|
|
130
|
+
|
|
131
|
+
while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
|
|
132
|
+
while (srcEnd > srcStart && isSpace(load<u16>(srcEnd - 2))) srcEnd -= 2;
|
|
133
|
+
|
|
134
|
+
if (srcStart >= srcEnd) throw new Error("Input string had zero length or was all whitespace");
|
|
135
|
+
const end = deserializeSetDirect<T>(srcStart, srcEnd, out, true);
|
|
136
|
+
if (end != srcEnd) throw new Error("Expected ']' at end of set");
|
|
168
137
|
return out;
|
|
169
138
|
}
|
|
139
|
+
|
|
140
|
+
// @ts-expect-error: Decorator valid here
|
|
141
|
+
@inline export function deserializeSetInto<T extends Set<any>>(srcStart: usize, srcEnd: usize, out: T): usize {
|
|
142
|
+
changetype<nonnull<T>>(out).clear();
|
|
143
|
+
return deserializeSetDirect<T>(srcStart, srcEnd, changetype<nonnull<T>>(out));
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// @ts-expect-error: Decorator valid here
|
|
147
|
+
@inline export function deserializeSetField<T extends Set<any>>(srcStart: usize, srcEnd: usize, dstObj: usize, dstOffset: usize = 0): usize {
|
|
148
|
+
let out = load<T>(dstObj, dstOffset);
|
|
149
|
+
if (!changetype<usize>(out)) {
|
|
150
|
+
out = changetype<T>(instantiate<T>());
|
|
151
|
+
store<T>(dstObj, out, dstOffset);
|
|
152
|
+
}
|
|
153
|
+
return deserializeSetInto<T>(srcStart, srcEnd, out);
|
|
154
|
+
}
|
|
@@ -15,6 +15,7 @@ import { deserializeStaticArrayBoolean } from "./staticarray/bool";
|
|
|
15
15
|
import { deserializeStaticArrayFloat } from "./staticarray/float";
|
|
16
16
|
import { deserializeStaticArrayInteger } from "./staticarray/integer";
|
|
17
17
|
import { deserializeStaticArrayString } from "./staticarray/string";
|
|
18
|
+
import { scanValueEnd } from "../swar/array/shared";
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
@inline function materializeStaticArray<T extends StaticArray<any>>(src: valueof<T>[], dst: usize): T {
|
|
@@ -63,10 +64,21 @@ export function deserializeStaticArray<T extends StaticArray<any>>(srcStart: usi
|
|
|
63
64
|
} else if (isDefined(type.__DESERIALIZE_CUSTOM)) {
|
|
64
65
|
return materializeStaticArray<T>(deserializeStructArray<valueof<T>[]>(srcStart, srcEnd, 0), dst);
|
|
65
66
|
// @ts-ignore: supplied by transform
|
|
66
|
-
} else if (isDefined(type.
|
|
67
|
+
} else if (isDefined(type.__DESERIALIZE_SLOW) || isDefined(type.__DESERIALIZE_FAST)) {
|
|
67
68
|
return materializeStaticArray<T>(deserializeStructArray<valueof<T>[]>(srcStart, srcEnd, 0), dst);
|
|
68
69
|
}
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
throw new Error("Could not parse static array of type " + nameof<T>() + "!");
|
|
72
73
|
}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@inline export function deserializeStaticArrayField<T extends StaticArray<any>>(srcStart: usize, srcEnd: usize, dstObj: usize, dstOffset: usize = 0): usize {
|
|
77
|
+
const valueEnd = scanValueEnd(srcStart, srcEnd);
|
|
78
|
+
if (!valueEnd) throw new Error("Failed to parse JSON!");
|
|
79
|
+
|
|
80
|
+
const fieldPtr = dstObj + dstOffset;
|
|
81
|
+
const out = deserializeStaticArray<T>(srcStart, valueEnd, load<usize>(fieldPtr));
|
|
82
|
+
store<T>(fieldPtr, out);
|
|
83
|
+
return valueEnd;
|
|
84
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { OBJECT, TOTAL_OVERHEAD } from "rt/common";
|
|
2
|
+
import { __heap_base } from "memory";
|
|
2
3
|
import { bs } from "../../../lib/as-bs";
|
|
3
4
|
import { BACK_SLASH, QUOTE } from "../../custom/chars";
|
|
4
5
|
import { DESERIALIZE_ESCAPE_TABLE, ESCAPE_HEX_TABLE } from "../../globals/tables";
|
|
@@ -13,11 +14,13 @@ import { hex4_to_u16_swar } from "../../util/swar";
|
|
|
13
14
|
|
|
14
15
|
const current = load<usize>(dstFieldPtr);
|
|
15
16
|
let stringPtr: usize;
|
|
16
|
-
if (current
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
if (current >= __heap_base) {
|
|
18
|
+
if (changetype<OBJECT>(current - TOTAL_OVERHEAD).rtSize == byteLength) {
|
|
19
|
+
stringPtr = current;
|
|
20
|
+
} else {
|
|
21
|
+
stringPtr = __renew(current, byteLength);
|
|
22
|
+
store<usize>(dstFieldPtr, stringPtr);
|
|
23
|
+
}
|
|
21
24
|
} else {
|
|
22
25
|
stringPtr = __new(byteLength, idof<string>());
|
|
23
26
|
store<usize>(dstFieldPtr, stringPtr);
|
|
@@ -65,7 +68,8 @@ import { hex4_to_u16_swar } from "../../util/swar";
|
|
|
65
68
|
}
|
|
66
69
|
|
|
67
70
|
// @ts-ignore: inline
|
|
68
|
-
@inline export function deserializeStringField<T extends string | null>(srcStart: usize, srcEnd: usize,
|
|
71
|
+
@inline export function deserializeStringField<T extends string | null>(srcStart: usize, srcEnd: usize, dstObj: usize, dstOffset: usize = 0): usize {
|
|
72
|
+
const dstFieldPtr = dstObj + dstOffset;
|
|
69
73
|
if (srcStart + 2 > srcEnd || load<u16>(srcStart) != QUOTE) abort("Expected leading quote");
|
|
70
74
|
|
|
71
75
|
const payloadStart = srcStart + 2;
|
|
@@ -82,18 +86,19 @@ import { hex4_to_u16_swar } from "../../util/swar";
|
|
|
82
86
|
continue;
|
|
83
87
|
}
|
|
84
88
|
|
|
85
|
-
|
|
89
|
+
bs.offset = bs.buffer;
|
|
86
90
|
bs.ensureSize(u32(srcEnd - payloadStart));
|
|
87
91
|
const prefixLen = <u32>(srcStart - payloadStart);
|
|
88
92
|
if (prefixLen != 0) {
|
|
89
|
-
memory.copy(bs.
|
|
93
|
+
memory.copy(bs.buffer, payloadStart, prefixLen);
|
|
90
94
|
bs.offset += prefixLen;
|
|
91
95
|
}
|
|
92
96
|
|
|
93
97
|
while (srcStart < srcEnd) {
|
|
94
98
|
const block = load<u16>(srcStart);
|
|
95
99
|
if (block == QUOTE) {
|
|
96
|
-
bs.
|
|
100
|
+
writeStringToField(dstFieldPtr, bs.buffer, <u32>(bs.offset - bs.buffer));
|
|
101
|
+
bs.offset = bs.buffer;
|
|
97
102
|
return srcStart + 2;
|
|
98
103
|
}
|
|
99
104
|
|
|
@@ -118,7 +123,7 @@ import { hex4_to_u16_swar } from "../../util/swar";
|
|
|
118
123
|
bs.offset += 2;
|
|
119
124
|
}
|
|
120
125
|
|
|
121
|
-
bs.offset = bs.buffer
|
|
126
|
+
bs.offset = bs.buffer;
|
|
122
127
|
break;
|
|
123
128
|
}
|
|
124
129
|
|
|
@@ -1,165 +1,17 @@
|
|
|
1
|
-
import { BACK_SLASH, COMMA, CHAR_F, BRACE_LEFT, BRACKET_LEFT, CHAR_N, QUOTE, BRACE_RIGHT, BRACKET_RIGHT, CHAR_T, COLON } from "../../custom/chars";
|
|
2
|
-
import { isSpace, isUnescapedQuote, scanStringEnd } from "../../util";
|
|
3
|
-
|
|
4
1
|
export function deserializeStruct<T>(srcStart: usize, srcEnd: usize, dst: usize): T {
|
|
5
2
|
const out = changetype<nonnull<T>>(dst || __new(offsetof<T>(), idof<T>()));
|
|
6
3
|
|
|
7
4
|
// @ts-ignore: supplied by transform
|
|
8
5
|
if (isDefined(out.__INITIALIZE)) out.__INITIALIZE();
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
if (srcStart - srcEnd == 0) throw new Error("Input string had zero length or was all whitespace");
|
|
20
|
-
if (load<u16>(srcStart) != BRACE_LEFT) throw new Error("Expected '{' at start of object at position " + (srcEnd - srcStart).toString());
|
|
21
|
-
if (load<u16>(srcEnd - 2) != BRACE_RIGHT) throw new Error("Expected '}' at end of object at position " + (srcEnd - srcStart).toString());
|
|
22
|
-
|
|
23
|
-
srcStart += 2;
|
|
24
|
-
while (srcStart < srcEnd) {
|
|
25
|
-
let code = load<u16>(srcStart); // while (isSpace(code)) code = load<u16>(srcStart += 2);
|
|
26
|
-
if (keyStart == 0) {
|
|
27
|
-
if (code == QUOTE && isUnescapedQuote(srcStart)) {
|
|
28
|
-
if (isKey) {
|
|
29
|
-
keyStart = lastIndex;
|
|
30
|
-
keyEnd = srcStart;
|
|
31
|
-
// console.log("Key: " + ptrToStr(lastIndex, srcStart));
|
|
32
|
-
// console.log("Next: " + String.fromCharCode(load<u16>(srcStart + 2)));
|
|
33
|
-
while (isSpace((code = load<u16>((srcStart += 2))))) {}
|
|
34
|
-
if (code !== COLON) throw new Error("Expected ':' after key at position " + (srcEnd - srcStart).toString());
|
|
35
|
-
isKey = false;
|
|
36
|
-
} else {
|
|
37
|
-
// console.log("Got key start");
|
|
38
|
-
isKey = true; // i don't like this
|
|
39
|
-
lastIndex = srcStart + 2;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
// isKey = !isKey;
|
|
43
|
-
srcStart += 2;
|
|
44
|
-
} else {
|
|
45
|
-
if (code == QUOTE) {
|
|
46
|
-
lastIndex = srcStart;
|
|
47
|
-
srcStart = scanStringEnd(srcStart, srcEnd);
|
|
48
|
-
if (srcStart >= srcEnd) throw new Error("Unterminated string in JSON object");
|
|
49
|
-
// @ts-ignore: exists
|
|
50
|
-
out.__DESERIALIZE(keyStart, keyEnd, lastIndex, srcStart + 2, changetype<usize>(out));
|
|
51
|
-
srcStart += 2;
|
|
52
|
-
keyStart = 0;
|
|
53
|
-
continue;
|
|
54
|
-
} else if (code - 48 <= 9 || code == 45) {
|
|
55
|
-
lastIndex = srcStart;
|
|
56
|
-
srcStart += 2;
|
|
57
|
-
while (srcStart < srcEnd) {
|
|
58
|
-
const code = load<u16>(srcStart);
|
|
59
|
-
if (code == COMMA || code == BRACE_RIGHT || isSpace(code)) {
|
|
60
|
-
// console.log("Value (number): " + ptrToStr(lastIndex, srcStart));
|
|
61
|
-
// @ts-ignore: exists
|
|
62
|
-
out.__DESERIALIZE(keyStart, keyEnd, lastIndex, srcStart, changetype<usize>(out));
|
|
63
|
-
// while (isSpace(load<u16>((srcStart += 2)))) {
|
|
64
|
-
// /* empty */
|
|
65
|
-
// }
|
|
66
|
-
srcStart += 2;
|
|
67
|
-
// console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
|
|
68
|
-
keyStart = 0;
|
|
69
|
-
break;
|
|
70
|
-
}
|
|
71
|
-
srcStart += 2;
|
|
72
|
-
}
|
|
73
|
-
} else if (code == BRACE_LEFT) {
|
|
74
|
-
lastIndex = srcStart;
|
|
75
|
-
depth++;
|
|
76
|
-
srcStart += 2;
|
|
77
|
-
while (srcStart < srcEnd) {
|
|
78
|
-
const code = load<u16>(srcStart);
|
|
79
|
-
if (code == QUOTE) {
|
|
80
|
-
srcStart = scanStringEnd(srcStart, srcEnd);
|
|
81
|
-
if (srcStart >= srcEnd) throw new Error("Unterminated string in JSON object");
|
|
82
|
-
} else if (code == BRACE_RIGHT) {
|
|
83
|
-
if (--depth == 0) {
|
|
84
|
-
// console.log("Value (object): " + ptrToStr(lastIndex, srcStart + 2));
|
|
85
|
-
// @ts-ignore: exists
|
|
86
|
-
out.__DESERIALIZE(keyStart, keyEnd, lastIndex, (srcStart += 2), changetype<usize>(out));
|
|
87
|
-
// console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
|
|
88
|
-
keyStart = 0;
|
|
89
|
-
// while (isSpace(load<u16>(srcStart))) {
|
|
90
|
-
// /* empty */
|
|
91
|
-
// }
|
|
92
|
-
break;
|
|
93
|
-
}
|
|
94
|
-
} else if (code == BRACE_LEFT) depth++;
|
|
95
|
-
srcStart += 2;
|
|
96
|
-
}
|
|
97
|
-
} else if (code == BRACKET_LEFT) {
|
|
98
|
-
lastIndex = srcStart;
|
|
99
|
-
depth++;
|
|
100
|
-
srcStart += 2;
|
|
101
|
-
while (srcStart < srcEnd) {
|
|
102
|
-
const code = load<u16>(srcStart);
|
|
103
|
-
if (code == QUOTE) {
|
|
104
|
-
srcStart = scanStringEnd(srcStart, srcEnd);
|
|
105
|
-
if (srcStart >= srcEnd) throw new Error("Unterminated string in JSON object");
|
|
106
|
-
} else if (code == BRACKET_RIGHT) {
|
|
107
|
-
if (--depth == 0) {
|
|
108
|
-
// console.log("Value (array): " + ptrToStr(lastIndex, srcStart + 2));
|
|
109
|
-
// @ts-ignore: exists
|
|
110
|
-
out.__DESERIALIZE(keyStart, keyEnd, lastIndex, (srcStart += 2), changetype<usize>(out));
|
|
111
|
-
// console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
|
|
112
|
-
keyStart = 0;
|
|
113
|
-
// while (isSpace(load<u16>((srcStart += 2)))) {
|
|
114
|
-
// /* empty */
|
|
115
|
-
// }
|
|
116
|
-
break;
|
|
117
|
-
}
|
|
118
|
-
} else if (code == BRACKET_LEFT) depth++;
|
|
119
|
-
srcStart += 2;
|
|
120
|
-
}
|
|
121
|
-
} else if (code == CHAR_T) {
|
|
122
|
-
if (load<u64>(srcStart) == 28429475166421108) {
|
|
123
|
-
// console.log("Value (bool): " + ptrToStr(srcStart, srcStart + 8));
|
|
124
|
-
// @ts-ignore: exists
|
|
125
|
-
out.__DESERIALIZE(keyStart, keyEnd, srcStart, (srcStart += 8), changetype<usize>(out));
|
|
126
|
-
// while (isSpace(load<u16>((srcStart += 2)))) {
|
|
127
|
-
// /* empty */
|
|
128
|
-
// }
|
|
129
|
-
srcStart += 2;
|
|
130
|
-
// console.log("Next: " + String.fromCharCode(load<u16>(srcStart)) + " " + (srcStart < srcEnd).toString());
|
|
131
|
-
keyStart = 0;
|
|
132
|
-
}
|
|
133
|
-
} else if (code == CHAR_F) {
|
|
134
|
-
if (load<u64>(srcStart, 2) == 28429466576093281) {
|
|
135
|
-
// console.log("Value (bool): " + ptrToStr(srcStart, srcStart + 10));
|
|
136
|
-
// @ts-ignore: exists
|
|
137
|
-
out.__DESERIALIZE(keyStart, keyEnd, srcStart, (srcStart += 10), changetype<usize>(out));
|
|
138
|
-
// while (isSpace(load<u16>((srcStart += 2)))) {
|
|
139
|
-
// /* empty */
|
|
140
|
-
// }
|
|
141
|
-
srcStart += 2;
|
|
142
|
-
// console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
|
|
143
|
-
keyStart = 0;
|
|
144
|
-
}
|
|
145
|
-
} else if (code == CHAR_N) {
|
|
146
|
-
if (load<u64>(srcStart) == 30399761348886638) {
|
|
147
|
-
// console.log("Value (null): " + ptrToStr(srcStart, srcStart + 8));
|
|
148
|
-
// @ts-ignore: exists
|
|
149
|
-
out.__DESERIALIZE(keyStart, keyEnd, srcStart, (srcStart += 8), changetype<usize>(out));
|
|
150
|
-
// while (isSpace(load<u16>((srcStart += 2)))) {
|
|
151
|
-
/* empty */
|
|
152
|
-
// }
|
|
153
|
-
srcStart += 2;
|
|
154
|
-
// console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
|
|
155
|
-
keyStart = 0;
|
|
156
|
-
}
|
|
157
|
-
} else if (isSpace(code)) {
|
|
158
|
-
srcStart += 2;
|
|
159
|
-
} else {
|
|
160
|
-
throw new Error("Unexpected character in JSON object '" + String.fromCharCode(code) + "' at position " + (srcEnd - srcStart).toString());
|
|
161
|
-
}
|
|
162
|
-
}
|
|
6
|
+
// @ts-ignore: supplied by transform
|
|
7
|
+
if (isDefined(out.__DESERIALIZE_FAST)) {
|
|
8
|
+
// @ts-ignore: supplied by transform
|
|
9
|
+
out.__DESERIALIZE_FAST(srcStart, srcEnd, out);
|
|
10
|
+
} else if (isDefined(out.__DESERIALIZE_SLOW)) {
|
|
11
|
+
// @ts-ignore: supplied by transform
|
|
12
|
+
out.__DESERIALIZE_SLOW(srcStart, srcEnd, out);
|
|
13
|
+
} else {
|
|
14
|
+
throw new Error("Missing __DESERIALIZE_FAST/__DESERIALIZE_SLOW");
|
|
163
15
|
}
|
|
164
16
|
return out;
|
|
165
17
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { atoi } from "
|
|
1
|
+
import { atoi } from "../../util/atoi";
|
|
2
2
|
|
|
3
3
|
// @ts-ignore: inline
|
|
4
4
|
@inline export function deserializeUnsigned<T>(srcStart: usize, srcEnd: usize): T {
|
|
@@ -6,7 +6,8 @@ import { atoi } from "../util/atoi";
|
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
// @ts-ignore: inline
|
|
9
|
-
@inline export function deserializeUnsignedField<T extends number>(srcStart: usize, srcEnd: usize,
|
|
9
|
+
@inline export function deserializeUnsignedField<T extends number>(srcStart: usize, srcEnd: usize, dstObj: usize, dstOffset: usize = 0): usize {
|
|
10
|
+
const fieldPtr = dstObj + dstOffset;
|
|
10
11
|
let digit = <u32>load<u16>(srcStart) - 48;
|
|
11
12
|
if (digit > 9) unreachable();
|
|
12
13
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import { JSON } from "../../..";
|
|
1
2
|
import { BRACKET_LEFT, BRACKET_RIGHT, COMMA } from "../../../custom/chars";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
3
|
+
import { deserializeFloatArrayInto } from "./float";
|
|
4
|
+
import { ensureArrayField, scanValueEnd } from "./shared";
|
|
4
5
|
|
|
5
6
|
|
|
6
|
-
@inline export function
|
|
7
|
-
const out = ensureArrayField<T>(fieldPtr);
|
|
7
|
+
@inline export function deserializeArrayArrayInto<T extends unknown[][]>(srcStart: usize, srcEnd: usize, out: T): usize {
|
|
8
8
|
let index = 0;
|
|
9
9
|
|
|
10
10
|
do {
|
|
@@ -17,9 +17,39 @@ import { ensureArrayElementSlot, ensureArrayField } from "./shared";
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
while (srcStart < srcEnd) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
if (isFloat<valueof<valueof<T>>>()) {
|
|
21
|
+
let value: valueof<T>;
|
|
22
|
+
if (index < out.length) {
|
|
23
|
+
value = unchecked(out[index]);
|
|
24
|
+
} else {
|
|
25
|
+
value = changetype<valueof<T>>(instantiate<valueof<T>>());
|
|
26
|
+
out.push(value);
|
|
27
|
+
}
|
|
28
|
+
srcStart = deserializeFloatArrayInto<valueof<T>>(srcStart, srcEnd, value);
|
|
29
|
+
if (!srcStart || srcStart >= srcEnd) break;
|
|
30
|
+
} else if (isArray<valueof<valueof<T>>>()) {
|
|
31
|
+
let value: valueof<T>;
|
|
32
|
+
if (index < out.length) {
|
|
33
|
+
value = unchecked(out[index]);
|
|
34
|
+
} else {
|
|
35
|
+
value = changetype<valueof<T>>(instantiate<valueof<T>>());
|
|
36
|
+
out.push(value);
|
|
37
|
+
}
|
|
38
|
+
srcStart = deserializeArrayArrayInto<valueof<T>>(srcStart, srcEnd, value);
|
|
39
|
+
if (!srcStart || srcStart >= srcEnd) break;
|
|
40
|
+
} else {
|
|
41
|
+
const valueEnd = scanValueEnd(srcStart, srcEnd);
|
|
42
|
+
if (!valueEnd || valueEnd <= srcStart) break;
|
|
43
|
+
|
|
44
|
+
let valuePtr: usize = 0;
|
|
45
|
+
if (index < out.length) {
|
|
46
|
+
valuePtr = changetype<usize>(unchecked(out[index]));
|
|
47
|
+
}
|
|
48
|
+
const value = JSON.__deserialize<valueof<T>>(srcStart, valueEnd, valuePtr);
|
|
49
|
+
if (index < out.length) unchecked((out[index] = value));
|
|
50
|
+
else out.push(value);
|
|
51
|
+
srcStart = valueEnd;
|
|
52
|
+
}
|
|
23
53
|
|
|
24
54
|
const code = load<u16>(srcStart);
|
|
25
55
|
if (code == COMMA) {
|
|
@@ -37,3 +67,8 @@ import { ensureArrayElementSlot, ensureArrayField } from "./shared";
|
|
|
37
67
|
|
|
38
68
|
throw new Error("Failed to parse JSON!");
|
|
39
69
|
}
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@inline export function deserializeArrayArrayField<T extends unknown[][]>(srcStart: usize, srcEnd: usize, fieldPtr: usize): usize {
|
|
73
|
+
return deserializeArrayArrayInto<T>(srcStart, srcEnd, ensureArrayField<T>(fieldPtr));
|
|
74
|
+
}
|