json-as 0.9.28 → 1.0.0-alpha.1
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/.github/workflows/nodejs.yml +0 -3
- package/.prettierrc.json +4 -1
- package/CHANGELOG +13 -0
- package/LICENSE +1 -1
- package/README.md +22 -7
- package/as-test.config.json +1 -1
- package/asconfig.json +2 -2
- package/assembly/__benches__/misc.bench.ts +17 -31
- package/assembly/__tests__/bool.spec.ts +1 -1
- package/assembly/__tests__/simd/string.spec.ts +32 -0
- package/assembly/__tests__/types.ts +17 -0
- package/assembly/custom/chars.ts +2 -2
- package/assembly/custom/memory.ts +25 -0
- package/assembly/custom/types.ts +1 -0
- package/assembly/custom/util.ts +59 -140
- package/assembly/deserialize/simd/string.ts +103 -0
- package/assembly/deserialize/simple/arbitrary.ts +17 -0
- package/assembly/deserialize/simple/array/arbitrary.ts +113 -0
- package/assembly/deserialize/simple/array/array.ts +18 -0
- package/assembly/deserialize/simple/array/bool.ts +17 -0
- package/assembly/deserialize/simple/array/float.ts +28 -0
- package/assembly/deserialize/simple/array/integer.ts +27 -0
- package/assembly/deserialize/simple/array/map.ts +18 -0
- package/assembly/deserialize/simple/array/object.ts +18 -0
- package/assembly/deserialize/simple/array/string.ts +22 -0
- package/assembly/deserialize/simple/array.ts +48 -0
- package/assembly/deserialize/simple/bool.ts +9 -0
- package/assembly/deserialize/simple/date.ts +11 -0
- package/assembly/deserialize/simple/float.ts +10 -0
- package/assembly/deserialize/simple/integer.ts +5 -0
- package/assembly/deserialize/simple/map.ts +154 -0
- package/assembly/deserialize/simple/object.ts +159 -0
- package/assembly/deserialize/simple/string.ts +48 -0
- package/assembly/globals/tables.ts +417 -0
- package/assembly/index.d.ts +9 -13
- package/assembly/index.ts +282 -158
- package/assembly/serialize/simd/string.ts +176 -0
- package/assembly/serialize/simple/arbitrary.ts +36 -0
- package/assembly/serialize/simple/array.ts +32 -0
- package/assembly/serialize/simple/bool.ts +19 -0
- package/assembly/serialize/simple/date.ts +13 -0
- package/assembly/serialize/simple/float.ts +7 -0
- package/assembly/serialize/simple/integer.ts +7 -0
- package/assembly/serialize/simple/map.ts +43 -0
- package/assembly/serialize/simple/object.ts +7 -0
- package/assembly/serialize/simple/string.ts +48 -0
- package/assembly/test.ts +43 -28
- package/assembly/tsconfig.json +2 -91
- package/assembly/types.ts +0 -0
- package/assembly/util/atoi.ts +35 -0
- package/assembly/util/bytes.ts +12 -0
- package/assembly/util/concat.ts +9 -0
- package/assembly/util/getArrayDepth.ts +17 -0
- package/assembly/util/index.ts +5 -0
- package/assembly/util/isSpace.ts +4 -0
- package/assembly/util/nextPowerOf2.ts +4 -0
- package/assembly/util/ptrToStr.ts +7 -0
- package/assembly/util/snp.ts +69 -0
- package/bench.js +5 -5
- package/modules/bs/index.ts +167 -0
- package/modules/tsconfig.json +8 -0
- package/package.json +42 -47
- package/transform/lib/builder.js +1353 -0
- package/transform/lib/builder.js.map +1 -0
- package/transform/lib/index.js +497 -395
- package/transform/lib/index.js.map +1 -1
- package/transform/lib/index.old.js +404 -0
- package/transform/lib/index.old.js.map +1 -0
- package/transform/lib/linker.js +18 -0
- package/transform/lib/linker.js.map +1 -0
- package/transform/lib/types.js +25 -0
- package/transform/lib/types.js.map +1 -0
- package/transform/lib/util.js +47 -0
- package/transform/lib/util.js.map +1 -0
- package/transform/lib/visitor.js +529 -446
- package/transform/lib/visitor.js.map +1 -0
- package/transform/package.json +1 -34
- package/transform/src/builder.ts +1371 -0
- package/transform/src/index.ts +571 -481
- package/transform/src/linker.ts +21 -0
- package/transform/src/types.ts +27 -0
- package/transform/src/util.ts +56 -0
- package/transform/src/visitor.ts +531 -0
- package/transform/tsconfig.json +3 -1
- package/assembly/__benches__/as-tral.d.ts +0 -1
- package/assembly/custom/bs.ts +0 -211
- package/assembly/deserialize/array/array.ts +0 -31
- package/assembly/deserialize/array/bool.ts +0 -19
- package/assembly/deserialize/array/float.ts +0 -24
- package/assembly/deserialize/array/integer.ts +0 -24
- package/assembly/deserialize/array/map.ts +0 -27
- package/assembly/deserialize/array/object.ts +0 -27
- package/assembly/deserialize/array/string.ts +0 -29
- package/assembly/deserialize/array.ts +0 -46
- package/assembly/deserialize/bool.ts +0 -34
- package/assembly/deserialize/date.ts +0 -19
- package/assembly/deserialize/float.ts +0 -21
- package/assembly/deserialize/integer.ts +0 -16
- package/assembly/deserialize/map.ts +0 -189
- package/assembly/deserialize/object.ts +0 -271
- package/assembly/deserialize/string.ts +0 -164
- package/assembly/serialize/array.ts +0 -51
- package/assembly/serialize/bool.ts +0 -10
- package/assembly/serialize/date.ts +0 -4
- package/assembly/serialize/float.ts +0 -4
- package/assembly/serialize/integer.ts +0 -5
- package/assembly/serialize/map.ts +0 -24
- package/assembly/serialize/object.ts +0 -13
- package/assembly/serialize/string.ts +0 -287
- package/logs/test.log.json +0 -1049
package/assembly/custom/util.ts
CHANGED
|
@@ -1,135 +1,60 @@
|
|
|
1
1
|
import { isSpace } from "util/string";
|
|
2
|
-
import { BACK_SLASH,
|
|
2
|
+
import { BACK_SLASH, QUOTE } from "./chars";
|
|
3
3
|
import { Sink } from "./sink";
|
|
4
|
-
import { JSON } from "..";
|
|
5
|
-
|
|
6
|
-
// @ts-ignore: Decorator
|
|
7
|
-
export function isMap<T>(): bool {
|
|
8
|
-
let type = changetype<T>(0);
|
|
9
|
-
return type instanceof Map;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
// @ts-ignore: Decorator
|
|
13
|
-
@inline export function unsafeCharCodeAt(data: string, pos: i32): i32 {
|
|
14
|
-
return load<u16>(changetype<usize>(data) + ((<usize>pos) << 1));
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// @ts-ignore: Decorator
|
|
18
|
-
@inline export function removeWhitespace(data: string): string {
|
|
19
|
-
const result = new Sink();
|
|
20
|
-
let instr = false;
|
|
21
|
-
for (let i = 0; i < data.length; i++) {
|
|
22
|
-
const char = unsafeCharCodeAt(data, i);
|
|
23
|
-
if (instr === false && char === QUOTE) instr = true;
|
|
24
|
-
else if (
|
|
25
|
-
instr === true && char === QUOTE
|
|
26
|
-
&& unsafeCharCodeAt(data, i - 1) !== BACK_SLASH
|
|
27
|
-
) instr = false;
|
|
28
|
-
|
|
29
|
-
if (instr === false) {
|
|
30
|
-
if (!isSpace(char)) result.write(data.charAt(i));
|
|
31
|
-
} else {
|
|
32
|
-
result.write(data.charAt(i));
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
return result.toString();
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// @ts-ignore: Decorator
|
|
39
|
-
@inline export function escapeChar(char: string): string {
|
|
40
|
-
switch (unsafeCharCodeAt(char, 0)) {
|
|
41
|
-
case 0x22:
|
|
42
|
-
return '\\"';
|
|
43
|
-
case 0x5c:
|
|
44
|
-
return "\\\\";
|
|
45
|
-
case 0x08:
|
|
46
|
-
return "\\b";
|
|
47
|
-
case 0x0a:
|
|
48
|
-
return "\\n";
|
|
49
|
-
case 0x0d:
|
|
50
|
-
return "\\r";
|
|
51
|
-
case 0x09:
|
|
52
|
-
return "\\t";
|
|
53
|
-
case 0x0c:
|
|
54
|
-
return "\\f";
|
|
55
|
-
case 0x0b:
|
|
56
|
-
return "\\u000b";
|
|
57
|
-
default:
|
|
58
|
-
return char;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* A terrible function which finds the depth of a certain array.
|
|
64
|
-
* Suffers no overhead besides function calling and a if/else.
|
|
65
|
-
* @returns depth of array
|
|
66
|
-
*/
|
|
67
|
-
|
|
68
|
-
// @ts-ignore: Decorator
|
|
69
|
-
export function getArrayDepth<T extends ArrayLike>(depth: i32 = 1): i32 {
|
|
70
|
-
if (!isArray<T>()) {
|
|
71
|
-
return 0;
|
|
72
|
-
} else if (isArray<valueof<T>>()) {
|
|
73
|
-
depth++;
|
|
74
|
-
return getArrayDepth<valueof<T>>(depth);
|
|
75
|
-
} else {
|
|
76
|
-
return depth;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
4
|
|
|
80
5
|
/** Scientific Notation Integer Parsing - SNIP
|
|
81
6
|
* This is absolutely the fastest algorithm I could think of while adding full support for Scientific Notation
|
|
82
7
|
* Loads 32 bits and retrieves the high/low bits.
|
|
83
8
|
* The reason why we only load 4 bytes at a time is that numbers in the 32-bit range are 7 chars long at most.
|
|
84
9
|
* Using SIMD or 64 bit loads would only work well when parsing large 128+ numbers.
|
|
85
|
-
*
|
|
10
|
+
*
|
|
86
11
|
* Here are some benchmarks
|
|
87
|
-
* Parsing: "12345"
|
|
12
|
+
* Parsing: "12345"
|
|
88
13
|
* Results are spread over 5000ms
|
|
89
|
-
*
|
|
14
|
+
*
|
|
90
15
|
* SNIP: 270M iterations
|
|
91
16
|
* ATOI: 285M iterations
|
|
92
|
-
* ParseInt: 176M iterations
|
|
93
|
-
*
|
|
17
|
+
* ParseInt: 176M iterations
|
|
18
|
+
*
|
|
94
19
|
* @param str - Any number. Can include scientific notation.
|
|
95
|
-
*/
|
|
20
|
+
*/
|
|
96
21
|
// @ts-ignore: Decorator
|
|
97
22
|
@inline export function snip_fast<T extends number>(str: string, len: u32 = 0, offset: u32 = 0): T {
|
|
98
23
|
if (isSigned<T>()) {
|
|
99
24
|
const firstChar: u32 = load<u16>(changetype<usize>(str));
|
|
100
|
-
if (firstChar
|
|
101
|
-
const isNegative = firstChar
|
|
25
|
+
if (firstChar == 48) return 0 as T;
|
|
26
|
+
const isNegative = firstChar == 45; // Check if the number is negative
|
|
102
27
|
let val: T = 0 as T;
|
|
103
28
|
if (len == 0) len = u32(str.length << 1);
|
|
104
29
|
if (isNegative) {
|
|
105
30
|
offset += 2;
|
|
106
31
|
if (len >= 4) {
|
|
107
32
|
// 32-bit route
|
|
108
|
-
for (; offset <
|
|
33
|
+
for (; offset < len - 3; offset += 4) {
|
|
109
34
|
const ch = load<u32>(changetype<usize>(str) + <usize>offset);
|
|
110
|
-
const low = ch &
|
|
35
|
+
const low = ch & 0xffff;
|
|
111
36
|
const high = ch >> 16;
|
|
112
37
|
// 9 is 57. The highest group of two numbers is 114, so if a e or an E is included, this will fire.
|
|
113
38
|
if (low > 57) {
|
|
114
39
|
// The first char (f) is E or e
|
|
115
40
|
// We push the offset up by two and apply the notation.
|
|
116
41
|
if (load<u16>(changetype<usize>(str) + <usize>offset + 2) == 45) {
|
|
117
|
-
return -(val /
|
|
42
|
+
return -(val / 10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1)) as T;
|
|
118
43
|
} else {
|
|
119
44
|
// Inlined this operation instead of using a loop
|
|
120
|
-
return -(val *
|
|
45
|
+
return -(val * 10 ** (__atoi_fast<u32>(str, offset + 2, offset + 4) + 1)) as T;
|
|
121
46
|
}
|
|
122
47
|
} else if (high > 57) {
|
|
123
48
|
// The first char (f) is E or e
|
|
124
49
|
// We push the offset up by two and apply the notation.
|
|
125
50
|
if (load<u16>(changetype<usize>(str) + <usize>offset + 4) == 45) {
|
|
126
|
-
return -(val /
|
|
51
|
+
return -(val / 10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1)) as T;
|
|
127
52
|
} else {
|
|
128
53
|
// Inlined this operation instead of using a loop
|
|
129
|
-
return -(val *
|
|
54
|
+
return -(val * 10 ** (__atoi_fast<u32>(str, offset + 4, offset + 6) + 1)) as T;
|
|
130
55
|
}
|
|
131
56
|
} else {
|
|
132
|
-
val = (val * 100 + (
|
|
57
|
+
val = (val * 100 + (low - 48) * 10 + (high - 48)) as T;
|
|
133
58
|
}
|
|
134
59
|
}
|
|
135
60
|
}
|
|
@@ -141,43 +66,43 @@ export function getArrayDepth<T extends ArrayLike>(depth: i32 = 1): i32 {
|
|
|
141
66
|
// The first char (f) is E or e
|
|
142
67
|
// We push the offset up by two and apply the notation.
|
|
143
68
|
if (load<u16>(changetype<usize>(str) + <usize>offset + 2) == 45) {
|
|
144
|
-
return -(val /
|
|
69
|
+
return -(val / 10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1)) as T;
|
|
145
70
|
} else {
|
|
146
71
|
// Inlined this operation instead of using a loop
|
|
147
|
-
return -(val *
|
|
72
|
+
return -(val * 10 ** (__atoi_fast<u32>(str, offset + 2, offset + 4) + 1)) as T;
|
|
148
73
|
}
|
|
149
74
|
} else {
|
|
150
|
-
val = (val * 10
|
|
75
|
+
val = (val * 10 + (ch - 48)) as T;
|
|
151
76
|
}
|
|
152
77
|
}
|
|
153
78
|
return -val as T;
|
|
154
79
|
} else {
|
|
155
80
|
if (len >= 4) {
|
|
156
81
|
// Duplet 16 bit lane load
|
|
157
|
-
for (; offset <
|
|
82
|
+
for (; offset < len - 3; offset += 4) {
|
|
158
83
|
const ch = load<u32>(changetype<usize>(str) + <usize>offset);
|
|
159
|
-
const low = ch &
|
|
84
|
+
const low = ch & 0xffff;
|
|
160
85
|
const high = ch >> 16;
|
|
161
86
|
// 9 is 57. The highest group of two numbers is 114, so if a e or an E is included, this will fire.
|
|
162
87
|
if (low > 57) {
|
|
163
88
|
// The first char (f) is E or e
|
|
164
89
|
// We push the offset up by two and apply the notation.
|
|
165
90
|
if (load<u16>(changetype<usize>(str) + <usize>offset + 2) == 45) {
|
|
166
|
-
return (val /
|
|
91
|
+
return (val / 10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1)) as T;
|
|
167
92
|
} else {
|
|
168
93
|
// Inlined this operation instead of using a loop
|
|
169
|
-
return (val *
|
|
94
|
+
return (val * 10 ** (__atoi_fast<u32>(str, offset + 2, offset + 4) + 1)) as T;
|
|
170
95
|
}
|
|
171
96
|
} else if (high > 57) {
|
|
172
97
|
if (load<u16>(changetype<usize>(str) + <usize>offset + 4) == 45) {
|
|
173
|
-
return (val /
|
|
98
|
+
return (val / 10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1)) as T;
|
|
174
99
|
} else {
|
|
175
100
|
// Inlined this operation instead of using a loop
|
|
176
|
-
return (val *
|
|
101
|
+
return (val * 10 ** (__atoi_fast<u32>(str, offset + 4, offset + 6) + 1)) as T;
|
|
177
102
|
}
|
|
178
103
|
} else {
|
|
179
104
|
// Optimized with multiplications and shifts.
|
|
180
|
-
val = (val * 100 + (
|
|
105
|
+
val = (val * 100 + (low - 48) * 10 + (high - 48)) as T;
|
|
181
106
|
}
|
|
182
107
|
}
|
|
183
108
|
}
|
|
@@ -188,49 +113,49 @@ export function getArrayDepth<T extends ArrayLike>(depth: i32 = 1): i32 {
|
|
|
188
113
|
// e is 101 and E is 69.
|
|
189
114
|
if (ch > 57) {
|
|
190
115
|
if (load<u16>(changetype<usize>(str) + <usize>offset + 2) == 45) {
|
|
191
|
-
val = (val /
|
|
116
|
+
val = (val / 10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1)) as T;
|
|
192
117
|
} else {
|
|
193
118
|
// Inlined this operation instead of using a loop
|
|
194
|
-
val = (val *
|
|
119
|
+
val = (val * 10 ** (__atoi_fast<u32>(str, offset + 2, offset + 4) + 1)) as T;
|
|
195
120
|
}
|
|
196
121
|
return val as T;
|
|
197
122
|
} else {
|
|
198
|
-
val = (val * 10
|
|
123
|
+
val = (val * 10 + (ch - 48)) as T;
|
|
199
124
|
}
|
|
200
125
|
}
|
|
201
126
|
return val as T;
|
|
202
127
|
}
|
|
203
128
|
} else {
|
|
204
129
|
const firstChar: u32 = load<u16>(changetype<usize>(str));
|
|
205
|
-
if (firstChar
|
|
130
|
+
if (firstChar == 48) return 0 as T;
|
|
206
131
|
let val: T = 0 as T;
|
|
207
132
|
if (len == 0) len = u32(str.length << 1);
|
|
208
133
|
if (len >= 4) {
|
|
209
134
|
// Duplet 16 bit lane load
|
|
210
|
-
for (; offset <
|
|
135
|
+
for (; offset < len - 3; offset += 4) {
|
|
211
136
|
const ch = load<u32>(changetype<usize>(str) + <usize>offset);
|
|
212
|
-
const low = ch &
|
|
137
|
+
const low = ch & 0xffff;
|
|
213
138
|
const high = ch >> 16;
|
|
214
139
|
// 9 is 57. The highest group of two numbers is 114, so if a e or an E is included, this will fire.
|
|
215
140
|
if (low > 57) {
|
|
216
141
|
// The first char (f) is E or e
|
|
217
142
|
// We push the offset up by two and apply the notation.
|
|
218
143
|
if (load<u16>(changetype<usize>(str) + <usize>offset + 2) == 45) {
|
|
219
|
-
return (val /
|
|
144
|
+
return (val / 10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1)) as T;
|
|
220
145
|
} else {
|
|
221
146
|
// Inlined this operation instead of using a loop
|
|
222
|
-
return (val *
|
|
147
|
+
return (val * 10 ** (__atoi_fast<u32>(str, offset + 2, offset + 4) + 1)) as T;
|
|
223
148
|
}
|
|
224
149
|
} else if (high > 57) {
|
|
225
150
|
if (load<u16>(changetype<usize>(str) + <usize>offset + 4) == 45) {
|
|
226
|
-
return (val /
|
|
151
|
+
return (val / 10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1)) as T;
|
|
227
152
|
} else {
|
|
228
153
|
// Inlined this operation instead of using a loop
|
|
229
|
-
return (val *
|
|
154
|
+
return (val * 10 ** (__atoi_fast<u32>(str, offset + 4, offset + 6) + 1)) as T;
|
|
230
155
|
}
|
|
231
156
|
} else {
|
|
232
157
|
// Optimized with multiplications and shifts.
|
|
233
|
-
val = (val * 100 + (
|
|
158
|
+
val = (val * 100 + (low - 48) * 10 + (high - 48)) as T;
|
|
234
159
|
}
|
|
235
160
|
}
|
|
236
161
|
}
|
|
@@ -241,13 +166,13 @@ export function getArrayDepth<T extends ArrayLike>(depth: i32 = 1): i32 {
|
|
|
241
166
|
// e is 101 and E is 69.
|
|
242
167
|
if (ch > 57) {
|
|
243
168
|
if (load<u16>(changetype<usize>(str) + <usize>offset + 2) == 45) {
|
|
244
|
-
return (val /
|
|
169
|
+
return (val / 10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1)) as T;
|
|
245
170
|
} else {
|
|
246
171
|
// Inlined this operation instead of using a loop
|
|
247
|
-
return (val *
|
|
172
|
+
return (val * 10 ** (__atoi_fast<u32>(str, offset + 2, offset + 4) + 1)) as T;
|
|
248
173
|
}
|
|
249
174
|
} else {
|
|
250
|
-
val = (val * 10
|
|
175
|
+
val = (val * 10 + (ch - 48)) as T;
|
|
251
176
|
}
|
|
252
177
|
}
|
|
253
178
|
return val as T;
|
|
@@ -265,21 +190,21 @@ export function getArrayDepth<T extends ArrayLike>(depth: i32 = 1): i32 {
|
|
|
265
190
|
if (!end) end = start + u32(str.length << 1);
|
|
266
191
|
if (isSigned<T>()) {
|
|
267
192
|
// Negative path
|
|
268
|
-
if (load<u16>(changetype<usize>(str) + <usize>start)
|
|
193
|
+
if (load<u16>(changetype<usize>(str) + <usize>start) == 45) {
|
|
269
194
|
start += 2;
|
|
270
195
|
for (; start < end; start += 2) {
|
|
271
|
-
val = (val * 10
|
|
196
|
+
val = (val * 10 + (load<u16>(changetype<usize>(str) + <usize>start) - 48)) as T;
|
|
272
197
|
}
|
|
273
198
|
return -val as T;
|
|
274
199
|
} else {
|
|
275
200
|
for (; start < end; start += 2) {
|
|
276
|
-
val = (
|
|
201
|
+
val = (val * 10 + (load<u16>(changetype<usize>(str) + <usize>start) - 48)) as T;
|
|
277
202
|
}
|
|
278
203
|
return val as T;
|
|
279
204
|
}
|
|
280
205
|
} else {
|
|
281
206
|
for (; start < end; start += 2) {
|
|
282
|
-
val = (
|
|
207
|
+
val = (val * 10 + (load<u16>(changetype<usize>(str) + <usize>start) - 48)) as T;
|
|
283
208
|
}
|
|
284
209
|
return val as T;
|
|
285
210
|
}
|
|
@@ -299,14 +224,14 @@ export function getArrayDepth<T extends ArrayLike>(depth: i32 = 1): i32 {
|
|
|
299
224
|
let val: T = 0;
|
|
300
225
|
let offset = 0;
|
|
301
226
|
let firstChar = load<u16>(changetype<usize>(str) + <usize>offset);
|
|
302
|
-
if (firstChar
|
|
227
|
+
if (firstChar == 45) {
|
|
303
228
|
offset = 2;
|
|
304
229
|
}
|
|
305
230
|
for (; offset < str.length << 1; offset += 2) {
|
|
306
231
|
const char = load<u16>(changetype<usize>(str) + <usize>offset);
|
|
307
|
-
if (char
|
|
232
|
+
if (char == 101 || char == 69) {
|
|
308
233
|
const char = load<u16>(changetype<usize>(str) + <usize>(offset += 2));
|
|
309
|
-
if (char
|
|
234
|
+
if (char == 45) {
|
|
310
235
|
// @ts-ignore
|
|
311
236
|
val /= sciNote<T>(__atoi_fast<T>(str, (offset += 2)));
|
|
312
237
|
// @ts-ignore
|
|
@@ -322,7 +247,7 @@ export function getArrayDepth<T extends ArrayLike>(depth: i32 = 1): i32 {
|
|
|
322
247
|
val = (val << 1) + (val << 3) + (char - 48);
|
|
323
248
|
// We use load because in this case, there is no need to have bounds-checking
|
|
324
249
|
}
|
|
325
|
-
if (firstChar
|
|
250
|
+
if (firstChar == 45) {
|
|
326
251
|
val = -val as T;
|
|
327
252
|
}
|
|
328
253
|
return val;
|
|
@@ -345,17 +270,6 @@ export function getArrayDepth<T extends ArrayLike>(depth: i32 = 1): i32 {
|
|
|
345
270
|
return res;
|
|
346
271
|
}
|
|
347
272
|
|
|
348
|
-
// @ts-ignore
|
|
349
|
-
@inline function equalsSlice(p1_data: string, p1_start: i32, p1_end: i32, p2_data: string, p2_start: i32, p2_end: i32): boolean {
|
|
350
|
-
const p1_len = p1_end - p1_start;
|
|
351
|
-
const p2_len = p2_end - p2_start;
|
|
352
|
-
if (p1_len != p2_len) return false;
|
|
353
|
-
if (p1_len == 2) {
|
|
354
|
-
return load<u16>(changetype<usize>(p1_data) + p1_start) == load<u16>(changetype<usize>(p2_data) + p2_start)
|
|
355
|
-
}
|
|
356
|
-
return memory.compare(changetype<usize>(p1_data) + p1_start, changetype<usize>(p2_data) + p2_start, p1_len) === 0;
|
|
357
|
-
}
|
|
358
|
-
|
|
359
273
|
// @ts-ignore
|
|
360
274
|
@inline export function containsCodePoint(str: string, code: u32, start: i32, end: i32): bool {
|
|
361
275
|
for (let i = start; i <= end; i++) {
|
|
@@ -378,18 +292,23 @@ export function getArrayDepth<T extends ArrayLike>(depth: i32 = 1): i32 {
|
|
|
378
292
|
// @ts-ignore: Decorator
|
|
379
293
|
@inline export function intTo16(int: i32): i32 {
|
|
380
294
|
const high = int >> 4;
|
|
381
|
-
const low = int &
|
|
295
|
+
const low = int & 0x0f;
|
|
382
296
|
if (low < 10) {
|
|
383
297
|
if (high < 10) {
|
|
384
|
-
return ((48 + low) << 16) | 48 + high;
|
|
298
|
+
return ((48 + low) << 16) | (48 + high);
|
|
385
299
|
} else {
|
|
386
|
-
return ((48 + low) << 16) | 87 + high;
|
|
300
|
+
return ((48 + low) << 16) | (87 + high);
|
|
387
301
|
}
|
|
388
302
|
} else {
|
|
389
303
|
if (high < 10) {
|
|
390
|
-
return ((87 + low) << 16) | 48 + high;
|
|
304
|
+
return ((87 + low) << 16) | (48 + high);
|
|
391
305
|
} else {
|
|
392
|
-
return ((87 + low) << 16) | 87 + high;
|
|
306
|
+
return ((87 + low) << 16) | (87 + high);
|
|
393
307
|
}
|
|
394
308
|
}
|
|
395
|
-
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// @ts-ignore: Decorator valid here
|
|
312
|
+
@inline export function nextPowerOf2(n: u32): u32 {
|
|
313
|
+
return 1 << (32 - clz(n - 1));
|
|
314
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { BACK_SLASH } from "../../custom/chars";
|
|
2
|
+
import { DESERIALIZE_ESCAPE_TABLE, ESCAPE_HEX_TABLE } from "../../globals/tables";
|
|
3
|
+
|
|
4
|
+
const SPLAT_92 = i16x8.splat(92); /* \ */
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Deserializes strings back into into their original form using SIMD operations
|
|
8
|
+
* @param src string to deserialize
|
|
9
|
+
* @param dst buffer to write to
|
|
10
|
+
* @returns number of bytes written
|
|
11
|
+
*/
|
|
12
|
+
// todo: optimize and stuff. it works, its not pretty. ideally, i'd like this to be (nearly) branchless
|
|
13
|
+
export function deserializeString_SIMD(src: string, srcStart: usize, srcEnd: usize, dst: usize): usize {
|
|
14
|
+
let src_ptr = srcStart + 2;
|
|
15
|
+
let dst_ptr = changetype<usize>(dst);
|
|
16
|
+
|
|
17
|
+
const src_end = srcEnd - 2;
|
|
18
|
+
const src_end_15 = src_end - 15;
|
|
19
|
+
|
|
20
|
+
while (src_ptr < src_end_15) {
|
|
21
|
+
const block = v128.load(src_ptr);
|
|
22
|
+
v128.store(dst_ptr, block);
|
|
23
|
+
|
|
24
|
+
const backslash_indices = i16x8.eq(block, SPLAT_92);
|
|
25
|
+
let mask = i16x8.bitmask(backslash_indices);
|
|
26
|
+
|
|
27
|
+
while (mask != 0) {
|
|
28
|
+
const lane_index = ctz(mask) << 1;
|
|
29
|
+
const dst_offset = dst_ptr + lane_index;
|
|
30
|
+
const src_offset = src_ptr + lane_index;
|
|
31
|
+
const code = load<u16>(src_offset, 2);
|
|
32
|
+
|
|
33
|
+
mask &= mask - 1;
|
|
34
|
+
if (code == 117 && load<u32>(src_offset, 4) == 3145776) {
|
|
35
|
+
const block = load<u32>(src_offset, 8);
|
|
36
|
+
const codeA = block & 0xffff;
|
|
37
|
+
const codeB = (block >> 16) & 0xffff;
|
|
38
|
+
const escapedA = load<u8>(ESCAPE_HEX_TABLE + codeA);
|
|
39
|
+
const escapedB = load<u8>(ESCAPE_HEX_TABLE + codeB);
|
|
40
|
+
const escaped = (escapedA << 4) + escapedB;
|
|
41
|
+
// console.log("Escaped:");
|
|
42
|
+
// console.log(" a: " + escapedA.toString())
|
|
43
|
+
// console.log(" b: " + escapedB.toString());
|
|
44
|
+
// console.log(" c: " + escaped.toString());
|
|
45
|
+
// console.log(" o: " + (dst_ptr - dst).toString());
|
|
46
|
+
// console.log(" d: " + (dst_offset - dst).toString())
|
|
47
|
+
// console.log(" l: " + (lane_index).toString())
|
|
48
|
+
store<u16>(dst_offset, escaped);
|
|
49
|
+
v128.store(dst_offset, v128.load(src_offset, 4), 2);
|
|
50
|
+
if (lane_index >= 6) {
|
|
51
|
+
const bytes_left = lane_index - 4;
|
|
52
|
+
src_ptr += bytes_left;
|
|
53
|
+
dst_ptr += bytes_left;
|
|
54
|
+
// console.log(" e: " + (bytes_left).toString())
|
|
55
|
+
}
|
|
56
|
+
dst_ptr -= 10;
|
|
57
|
+
} else {
|
|
58
|
+
const escaped = load<u8>(DESERIALIZE_ESCAPE_TABLE + code);
|
|
59
|
+
store<u16>(dst_offset, escaped);
|
|
60
|
+
v128.store(dst_offset, v128.load(src_offset, 4), 2);
|
|
61
|
+
// console.log("Escaped:");
|
|
62
|
+
if (lane_index == 14) {
|
|
63
|
+
src_ptr += 2;
|
|
64
|
+
} else {
|
|
65
|
+
dst_ptr -= 2;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
src_ptr += 16;
|
|
71
|
+
dst_ptr += 16;
|
|
72
|
+
|
|
73
|
+
// console.log("src: " + (src_ptr - changetype<usize>(src)).toString());
|
|
74
|
+
// console.log("dst: " + (dst_ptr - dst).toString());
|
|
75
|
+
}
|
|
76
|
+
while (src_ptr < src_end) {
|
|
77
|
+
let code = load<u16>(src_ptr);
|
|
78
|
+
if (code == BACK_SLASH) {
|
|
79
|
+
code = load<u16>(DESERIALIZE_ESCAPE_TABLE + load<u8>(src_ptr, 2));
|
|
80
|
+
if (code == 117 && load<u32>(src_ptr, 4) == 3145776) {
|
|
81
|
+
const block = load<u32>(src_ptr, 8);
|
|
82
|
+
const codeA = block & 0xffff;
|
|
83
|
+
const codeB = (block >> 16) & 0xffff;
|
|
84
|
+
const escapedA = load<u8>(ESCAPE_HEX_TABLE + codeA);
|
|
85
|
+
const escapedB = load<u8>(ESCAPE_HEX_TABLE + codeB);
|
|
86
|
+
const escaped = (escapedA << 4) + escapedB;
|
|
87
|
+
store<u16>(dst_ptr, escaped);
|
|
88
|
+
dst_ptr += 2;
|
|
89
|
+
src_ptr += 12;
|
|
90
|
+
} else {
|
|
91
|
+
store<u16>(dst_ptr, code);
|
|
92
|
+
dst_ptr += 2;
|
|
93
|
+
src_ptr += 4;
|
|
94
|
+
}
|
|
95
|
+
} else {
|
|
96
|
+
store<u16>(dst_ptr, code);
|
|
97
|
+
dst_ptr += 2;
|
|
98
|
+
src_ptr += 2;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return dst_ptr - dst;
|
|
103
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { JSON } from "../..";
|
|
2
|
+
import { deserializeArray } from "./array";
|
|
3
|
+
import { deserializeBoolean } from "./bool";
|
|
4
|
+
import { deserializeFloat } from "./float";
|
|
5
|
+
import { deserializeObject } from "./object";
|
|
6
|
+
import { deserializeString } from "./string";
|
|
7
|
+
|
|
8
|
+
export function deserializeArbitrary(srcStart: usize, srcEnd: usize, dst: usize): JSON.Value {
|
|
9
|
+
const firstChar = load<u16>(srcStart);
|
|
10
|
+
if (firstChar == 34) return JSON.Value.from(deserializeString(srcStart, srcEnd, dst));
|
|
11
|
+
else if (firstChar == 123) return JSON.Value.from(deserializeObject(srcStart, srcEnd, dst));
|
|
12
|
+
else if (firstChar - 48 <= 9 || firstChar == 45) return JSON.Value.from(deserializeFloat<f64>(srcStart, srcEnd));
|
|
13
|
+
else if (firstChar == 91) {
|
|
14
|
+
return JSON.Value.from(deserializeArray<JSON.Value[]>(srcStart, srcEnd, dst));
|
|
15
|
+
} else if (firstChar == 116 || firstChar == 102) return JSON.Value.from(deserializeBoolean(srcStart, srcEnd));
|
|
16
|
+
return unreachable();
|
|
17
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { BACK_SLASH, BRACE_LEFT, BRACE_RIGHT, BRACKET_LEFT, BRACKET_RIGHT, CHAR_F, CHAR_N, CHAR_T, COMMA, QUOTE } from "../../../custom/chars";
|
|
2
|
+
import { JSON } from "../../../";
|
|
3
|
+
import { isSpace } from "util/string";
|
|
4
|
+
|
|
5
|
+
export function deserializeArbitraryArray<T extends JSON.Value>(srcStart: usize, srcEnd: usize, dst: usize): JSON.Value[] {
|
|
6
|
+
const out = dst ? changetype<T>(dst) : instantiate<T>();
|
|
7
|
+
let lastIndex: usize = 0;
|
|
8
|
+
let depth: u32 = 0;
|
|
9
|
+
while (srcStart < srcEnd) {
|
|
10
|
+
const code = load<u16>(srcStart);
|
|
11
|
+
if (code == QUOTE) {
|
|
12
|
+
lastIndex = srcStart;
|
|
13
|
+
srcStart += 2;
|
|
14
|
+
while (srcStart < srcEnd) {
|
|
15
|
+
const code = load<u16>(srcStart);
|
|
16
|
+
if (code == QUOTE && load<u16>(srcStart - 2) !== BACK_SLASH) {
|
|
17
|
+
while (isSpace(load<u16>((srcStart += 2)))) {
|
|
18
|
+
/* empty */
|
|
19
|
+
}
|
|
20
|
+
// console.log("Value (string): " + ptrToStr(lastIndex, srcStart));
|
|
21
|
+
// @ts-ignore: exists
|
|
22
|
+
out.push(JSON.__deserialize<valueof<T>>(lastIndex, srcStart));
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
srcStart += 2;
|
|
26
|
+
}
|
|
27
|
+
} else if (code - 48 <= 9 || code == 45) {
|
|
28
|
+
lastIndex = srcStart;
|
|
29
|
+
srcStart += 2;
|
|
30
|
+
while (srcStart < srcEnd) {
|
|
31
|
+
const code = load<u16>(srcStart);
|
|
32
|
+
if (code == COMMA || code == BRACE_RIGHT || isSpace(code)) {
|
|
33
|
+
// @ts-ignore: type
|
|
34
|
+
out.push(JSON.__deserialize<valueof<T>>(lastIndex, srcStart));
|
|
35
|
+
// console.log("Value (number): " + ptrToStr(lastIndex, srcStart));
|
|
36
|
+
while (isSpace(load<u16>((srcStart += 2)))) {
|
|
37
|
+
/* empty */
|
|
38
|
+
}
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
srcStart += 2;
|
|
42
|
+
}
|
|
43
|
+
} else if (code == BRACE_LEFT) {
|
|
44
|
+
lastIndex = srcStart;
|
|
45
|
+
depth++;
|
|
46
|
+
srcStart += 2;
|
|
47
|
+
while (srcStart < srcEnd) {
|
|
48
|
+
const code = load<u16>(srcStart);
|
|
49
|
+
if (code == BRACE_RIGHT) {
|
|
50
|
+
if (--depth == 0) {
|
|
51
|
+
// @ts-ignore: type
|
|
52
|
+
out.push(JSON.__deserialize<valueof<T>>(lastIndex, srcStart));
|
|
53
|
+
// console.log("Value (object): " + ptrToStr(lastIndex, srcStart));
|
|
54
|
+
while (isSpace(load<u16>((srcStart += 2)))) {
|
|
55
|
+
/* empty */
|
|
56
|
+
}
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
} else if (code == BRACE_LEFT) depth++;
|
|
60
|
+
srcStart += 2;
|
|
61
|
+
}
|
|
62
|
+
} else if (code == BRACKET_LEFT) {
|
|
63
|
+
lastIndex = srcStart;
|
|
64
|
+
depth++;
|
|
65
|
+
srcStart += 2;
|
|
66
|
+
while (srcStart < srcEnd) {
|
|
67
|
+
const code = load<u16>(srcStart);
|
|
68
|
+
if (code == BRACKET_RIGHT) {
|
|
69
|
+
if (--depth == 0) {
|
|
70
|
+
// @ts-ignore: type
|
|
71
|
+
out.push(JSON.__deserialize<valueof<T>>(lastIndex, srcStart));
|
|
72
|
+
// console.log("Value (array): " + ptrToStr(lastIndex, srcStart));
|
|
73
|
+
while (isSpace(load<u16>((srcStart += 2)))) {
|
|
74
|
+
/* empty */
|
|
75
|
+
}
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
} else if (code == BRACKET_LEFT) depth++;
|
|
79
|
+
srcStart += 2;
|
|
80
|
+
}
|
|
81
|
+
} else if (code == CHAR_T) {
|
|
82
|
+
if (load<u64>(srcStart) == 28429475166421108) {
|
|
83
|
+
// @ts-ignore: type
|
|
84
|
+
out.push(JSON.__deserialize<valueof<T>>(lastIndex, (srcStart += 8)));
|
|
85
|
+
// console.log("Value (bool): " + ptrToStr(srcStart - 8, srcStart));
|
|
86
|
+
while (isSpace(load<u16>((srcStart += 2)))) {
|
|
87
|
+
/* empty */
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
} else if (code == CHAR_F) {
|
|
91
|
+
if (load<u64>(srcStart, 2) == 28429466576093281) {
|
|
92
|
+
// @ts-ignore: type
|
|
93
|
+
out.push(JSON.__deserialize<valueof<T>>(lastIndex, (srcStart += 10)));
|
|
94
|
+
// console.log("Value (bool): " + ptrToStr(srcStart - 10, srcStart));
|
|
95
|
+
while (isSpace(load<u16>((srcStart += 2)))) {
|
|
96
|
+
/* empty */
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
} else if (code == CHAR_N) {
|
|
100
|
+
if (load<u64>(srcStart) == 30399761348886638) {
|
|
101
|
+
// @ts-ignore: type
|
|
102
|
+
out.push(JSON.__deserialize<valueof<T>>(lastIndex, (srcStart += 8)));
|
|
103
|
+
// console.log("Value (null): " + ptrToStr(srcStart - 8, srcStart));
|
|
104
|
+
while (isSpace(load<u16>((srcStart += 2)))) {
|
|
105
|
+
/* empty */
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
srcStart += 2;
|
|
110
|
+
}
|
|
111
|
+
// @ts-ignore: type
|
|
112
|
+
return out;
|
|
113
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { BRACKET_LEFT, BRACKET_RIGHT } from "../../../custom/chars";
|
|
2
|
+
import { JSON } from "../../../";
|
|
3
|
+
|
|
4
|
+
export function deserializeArrayArray<T extends unknown[][]>(srcStart: usize, srcEnd: usize, dst: usize): T {
|
|
5
|
+
const out = dst ? changetype<T>(dst) : instantiate<T>();
|
|
6
|
+
let lastIndex: usize = 0;
|
|
7
|
+
let depth: u32 = 0;
|
|
8
|
+
while (srcStart < srcEnd) {
|
|
9
|
+
const code = load<u16>(srcStart);
|
|
10
|
+
if (code == BRACKET_LEFT && depth++ == 0) {
|
|
11
|
+
lastIndex = srcStart;
|
|
12
|
+
} else if (code == BRACKET_RIGHT && --depth == 0) {
|
|
13
|
+
out.push(JSON.__deserialize<valueof<T>>(lastIndex, srcStart));
|
|
14
|
+
}
|
|
15
|
+
srcStart += 2;
|
|
16
|
+
}
|
|
17
|
+
return out;
|
|
18
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { CHAR_E, CHAR_F, CHAR_T } from "../../../custom/chars";
|
|
2
|
+
|
|
3
|
+
export function deserializeBooleanArray<T extends boolean[]>(srcStart: usize, srcEnd: usize, dst: usize): T {
|
|
4
|
+
const out = dst ? changetype<T>(dst) : instantiate<T>();
|
|
5
|
+
while (srcStart < srcEnd) {
|
|
6
|
+
const code = load<u16>(srcStart);
|
|
7
|
+
if (code == CHAR_T && load<u16>(srcStart, 8) == CHAR_E) {
|
|
8
|
+
out.push(true);
|
|
9
|
+
srcStart += 10;
|
|
10
|
+
} else if (code == CHAR_F && load<u16>(srcStart, 10) == CHAR_E) {
|
|
11
|
+
out.push(false);
|
|
12
|
+
srcStart += 12;
|
|
13
|
+
}
|
|
14
|
+
srcStart += 2;
|
|
15
|
+
}
|
|
16
|
+
return out;
|
|
17
|
+
}
|