json-as 1.3.5 → 1.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -1
- package/assembly/deserialize/helpers/uint.ts +4 -1
- package/assembly/deserialize/index/arbitrary.ts +5 -1
- package/assembly/deserialize/index/array.ts +13 -3
- package/assembly/deserialize/index/integer.ts +68 -1
- package/assembly/deserialize/index/string.ts +4 -1
- package/assembly/deserialize/index/typedarray.ts +13 -3
- package/assembly/deserialize/index/unsigned.ts +78 -1
- package/assembly/deserialize/simd/array/integer.ts +327 -50
- package/assembly/deserialize/simd/integer.ts +233 -0
- package/assembly/deserialize/simd/string.ts +45 -11
- package/assembly/deserialize/simple/arbitrary.ts +11 -4
- package/assembly/deserialize/simple/array/arbitrary.ts +24 -5
- package/assembly/deserialize/simple/array/array.ts +8 -2
- package/assembly/deserialize/simple/array/bool.ts +38 -7
- package/assembly/deserialize/simple/array/box.ts +8 -2
- package/assembly/deserialize/simple/array/float.ts +36 -9
- package/assembly/deserialize/simple/array/generic.ts +12 -4
- package/assembly/deserialize/simple/array/integer.ts +8 -2
- package/assembly/deserialize/simple/array/map.ts +26 -6
- package/assembly/deserialize/simple/array/object.ts +26 -6
- package/assembly/deserialize/simple/array/raw.ts +34 -7
- package/assembly/deserialize/simple/array/string.ts +8 -2
- package/assembly/deserialize/simple/array/struct.ts +26 -6
- package/assembly/deserialize/simple/array.ts +13 -3
- package/assembly/deserialize/simple/bool.ts +6 -2
- package/assembly/deserialize/simple/float.ts +6 -1
- package/assembly/deserialize/simple/integer.ts +10 -2
- package/assembly/deserialize/simple/map.ts +95 -22
- package/assembly/deserialize/simple/object.ts +63 -14
- package/assembly/deserialize/simple/raw.ts +4 -1
- package/assembly/deserialize/simple/set.ts +59 -14
- package/assembly/deserialize/simple/staticarray/string.ts +11 -3
- package/assembly/deserialize/simple/staticarray.ts +64 -14
- package/assembly/deserialize/simple/string.ts +5 -92
- package/assembly/deserialize/simple/struct.ts +5 -1
- package/assembly/deserialize/simple/typedarray.ts +16 -3
- package/assembly/deserialize/simple/unsigned.ts +10 -15
- package/assembly/deserialize/swar/array/arbitrary.ts +5 -1
- package/assembly/deserialize/swar/array/array.ts +30 -6
- package/assembly/deserialize/swar/array/bool.ts +22 -4
- package/assembly/deserialize/swar/array/box.ts +5 -1
- package/assembly/deserialize/swar/array/float.ts +15 -3
- package/assembly/deserialize/swar/array/generic.ts +24 -7
- package/assembly/deserialize/swar/array/integer.ts +328 -84
- package/assembly/deserialize/swar/array/map.ts +5 -1
- package/assembly/deserialize/swar/array/object.ts +27 -7
- package/assembly/deserialize/swar/array/raw.ts +5 -1
- package/assembly/deserialize/swar/array/shared.ts +36 -11
- package/assembly/deserialize/swar/array/string.ts +20 -4
- package/assembly/deserialize/swar/array/struct.ts +27 -7
- package/assembly/deserialize/swar/array.ts +19 -4
- package/assembly/deserialize/swar/integer.ts +246 -0
- package/assembly/deserialize/swar/string.ts +98 -194
- package/assembly/index.d.ts +3 -1
- package/assembly/index.ts +312 -81
- package/assembly/serialize/index/float.ts +5 -1
- package/assembly/serialize/index/typedarray.ts +25 -7
- package/assembly/serialize/simd/string.ts +6 -2
- package/assembly/serialize/simple/array.ts +179 -1
- package/assembly/serialize/simple/float.ts +4 -1
- package/assembly/serialize/simple/integer.ts +9 -9
- package/assembly/serialize/simple/map.ts +6 -2
- package/assembly/serialize/simple/raw.ts +5 -1
- package/assembly/serialize/simple/set.ts +6 -1
- package/assembly/serialize/simple/staticarray.ts +6 -1
- package/assembly/serialize/simple/string.ts +0 -1
- package/assembly/serialize/simple/typedarray.ts +10 -3
- package/assembly/serialize/swar/string.ts +25 -8
- package/assembly/tsconfig.json +1 -21
- package/assembly/util/atoi-fast.ts +81 -0
- package/assembly/util/concat.ts +5 -1
- package/assembly/util/dragonbox-cache.ts +443 -2
- package/assembly/util/dragonbox.ts +43 -14
- package/assembly/util/itoa-fast.ts +230 -0
- package/assembly/util/masks.ts +18 -1
- package/assembly/util/parsefloat-fast.ts +167 -0
- package/assembly/util/simd-int.ts +191 -0
- package/assembly/util/snp.ts +4 -1
- package/assembly/util/swar-int.ts +248 -0
- package/assembly/util/swar.ts +13 -3
- package/lib/as-bs.ts +13 -5
- package/package.json +12 -4
- package/transform/lib/builder.d.ts.map +1 -1
- package/transform/lib/builder.js +13 -5
- package/transform/lib/builder.js.map +1 -1
- package/transform/lib/index.d.ts +1 -0
- package/transform/lib/index.d.ts.map +1 -1
- package/transform/lib/index.js +1030 -241
- package/transform/lib/index.js.map +1 -1
- package/transform/lib/linkers/alias.d.ts.map +1 -1
- package/transform/lib/linkers/alias.js.map +1 -1
- package/transform/lib/linkers/custom.d.ts.map +1 -1
- package/transform/lib/linkers/custom.js +3 -2
- package/transform/lib/linkers/custom.js.map +1 -1
- package/transform/lib/linkers/imports.d.ts.map +1 -1
- package/transform/lib/linkers/imports.js.map +1 -1
- package/transform/lib/types.d.ts.map +1 -1
- package/transform/lib/types.js +54 -16
- package/transform/lib/types.js.map +1 -1
- package/transform/lib/util.d.ts.map +1 -1
- package/transform/lib/util.js +1 -1
- package/transform/lib/util.js.map +1 -1
- package/transform/lib/visitor.d.ts.map +1 -1
- package/transform/lib/visitor.js +2 -1
- package/transform/lib/visitor.js.map +1 -1
- package/assembly/custom/util.ts +0 -310
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { deserializeIntegerField } from "../../
|
|
2
|
-
import { deserializeUnsignedField } from "../../
|
|
1
|
+
import { deserializeIntegerField } from "../../index/integer";
|
|
2
|
+
import { deserializeUnsignedField } from "../../index/unsigned";
|
|
3
|
+
import { deserializeIntegerArray as deserializeIntegerArray_NAIVE } from "../../simple/array/integer";
|
|
3
4
|
import { BRACKET_LEFT, BRACKET_RIGHT, COMMA } from "../../../custom/chars";
|
|
4
5
|
import { isSpace } from "../../../util";
|
|
5
6
|
import { ensureArrayElementSlot, ensureArrayField } from "./shared";
|
|
@@ -10,37 +11,10 @@ const ASCII_RANGE_MASK_4: u64 = 0xfff0fff0fff0fff0;
|
|
|
10
11
|
const ASCII_RANGE_ADD_4: u64 = 0x0006000600060006;
|
|
11
12
|
|
|
12
13
|
|
|
13
|
-
@inline function
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
out.push(<valueof<T>>(<i16>value));
|
|
18
|
-
} else if (sizeof<valueof<T>>() == sizeof<i32>()) {
|
|
19
|
-
out.push(<valueof<T>>(<i32>value));
|
|
20
|
-
} else if (sizeof<valueof<T>>() == sizeof<isize>()) {
|
|
21
|
-
out.push(<valueof<T>>(<isize>value));
|
|
22
|
-
} else {
|
|
23
|
-
out.push(<valueof<T>>value);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
@inline function pushUnsignedInteger<T extends number[]>(out: T, value: u64): void {
|
|
29
|
-
if (sizeof<valueof<T>>() == sizeof<u8>()) {
|
|
30
|
-
out.push(<valueof<T>>(<u8>value));
|
|
31
|
-
} else if (sizeof<valueof<T>>() == sizeof<u16>()) {
|
|
32
|
-
out.push(<valueof<T>>(<u16>value));
|
|
33
|
-
} else if (sizeof<valueof<T>>() == sizeof<u32>()) {
|
|
34
|
-
out.push(<valueof<T>>(<u32>value));
|
|
35
|
-
} else if (sizeof<valueof<T>>() == sizeof<usize>()) {
|
|
36
|
-
out.push(<valueof<T>>(<usize>value));
|
|
37
|
-
} else {
|
|
38
|
-
out.push(<valueof<T>>value);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
@inline function storeSignedInteger<T extends number[]>(slot: usize, value: i64): void {
|
|
14
|
+
@inline function storeSignedInteger<T extends number[]>(
|
|
15
|
+
slot: usize,
|
|
16
|
+
value: i64,
|
|
17
|
+
): void {
|
|
44
18
|
if (sizeof<valueof<T>>() == sizeof<i8>()) {
|
|
45
19
|
store<i8>(slot, <i8>value);
|
|
46
20
|
} else if (sizeof<valueof<T>>() == sizeof<i16>()) {
|
|
@@ -55,7 +29,10 @@ const ASCII_RANGE_ADD_4: u64 = 0x0006000600060006;
|
|
|
55
29
|
}
|
|
56
30
|
|
|
57
31
|
|
|
58
|
-
@inline function storeUnsignedInteger<T extends number[]>(
|
|
32
|
+
@inline function storeUnsignedInteger<T extends number[]>(
|
|
33
|
+
slot: usize,
|
|
34
|
+
value: u64,
|
|
35
|
+
): void {
|
|
59
36
|
if (sizeof<valueof<T>>() == sizeof<u8>()) {
|
|
60
37
|
store<u8>(slot, <u8>value);
|
|
61
38
|
} else if (sizeof<valueof<T>>() == sizeof<u16>()) {
|
|
@@ -72,13 +49,29 @@ const ASCII_RANGE_ADD_4: u64 = 0x0006000600060006;
|
|
|
72
49
|
|
|
73
50
|
@inline function parse4DigitsASCII(block: u64): u32 {
|
|
74
51
|
const digits = (block & ASCII_LANE_MASK_4) - ASCII_ZERO_4;
|
|
75
|
-
if (((digits | (digits + ASCII_RANGE_ADD_4)) & ASCII_RANGE_MASK_4) != 0)
|
|
76
|
-
|
|
77
|
-
|
|
52
|
+
if (((digits | (digits + ASCII_RANGE_ADD_4)) & ASCII_RANGE_MASK_4) != 0)
|
|
53
|
+
return U32.MAX_VALUE;
|
|
54
|
+
|
|
55
|
+
return <u32>(
|
|
56
|
+
(<u32>(digits & 0xffff) * 1000 +
|
|
57
|
+
<u32>((digits >> 16) & 0xffff) * 100 +
|
|
58
|
+
<u32>((digits >> 32) & 0xffff) * 10 +
|
|
59
|
+
<u32>(digits >> 48))
|
|
60
|
+
);
|
|
78
61
|
}
|
|
79
62
|
|
|
80
|
-
|
|
81
|
-
|
|
63
|
+
// The four parse helpers below take a `slot` pointer (`writePtr`) and store
|
|
64
|
+
// the value directly via `store<valueof<T>>(slot, ...)`. The outer dispatcher
|
|
65
|
+
// owns the array's `out.length = maxElements` pre-allocation and the
|
|
66
|
+
// `writePtr` advance, so the per-element `Array.push` capacity check and
|
|
67
|
+
// length write are eliminated for every integer width, not just the u8/i8
|
|
68
|
+
// narrow-lane path.
|
|
69
|
+
|
|
70
|
+
@inline function parseSignedIntegerScalar<T extends number[]>(
|
|
71
|
+
srcStart: usize,
|
|
72
|
+
srcEnd: usize,
|
|
73
|
+
slot: usize,
|
|
74
|
+
): usize {
|
|
82
75
|
let negative = false;
|
|
83
76
|
let code = load<u16>(srcStart);
|
|
84
77
|
if (code == 45) {
|
|
@@ -100,12 +93,16 @@ const ASCII_RANGE_ADD_4: u64 = 0x0006000600060006;
|
|
|
100
93
|
srcStart += 2;
|
|
101
94
|
}
|
|
102
95
|
|
|
103
|
-
|
|
96
|
+
storeSignedInteger<T>(slot, negative ? -(<i64>value) : <i64>value);
|
|
104
97
|
return srcStart;
|
|
105
98
|
}
|
|
106
99
|
|
|
107
100
|
|
|
108
|
-
@inline function parseUnsignedIntegerScalar<T extends number[]>(
|
|
101
|
+
@inline function parseUnsignedIntegerScalar<T extends number[]>(
|
|
102
|
+
srcStart: usize,
|
|
103
|
+
srcEnd: usize,
|
|
104
|
+
slot: usize,
|
|
105
|
+
): usize {
|
|
109
106
|
let digit = <u32>load<u16>(srcStart) - 48;
|
|
110
107
|
if (digit > 9) return 0;
|
|
111
108
|
|
|
@@ -118,12 +115,16 @@ const ASCII_RANGE_ADD_4: u64 = 0x0006000600060006;
|
|
|
118
115
|
srcStart += 2;
|
|
119
116
|
}
|
|
120
117
|
|
|
121
|
-
|
|
118
|
+
storeUnsignedInteger<T>(slot, value);
|
|
122
119
|
return srcStart;
|
|
123
120
|
}
|
|
124
121
|
|
|
125
122
|
|
|
126
|
-
@inline function parseSignedIntegerSWAR<T extends number[]>(
|
|
123
|
+
@inline function parseSignedIntegerSWAR<T extends number[]>(
|
|
124
|
+
srcStart: usize,
|
|
125
|
+
srcEnd: usize,
|
|
126
|
+
slot: usize,
|
|
127
|
+
): usize {
|
|
127
128
|
let negative = false;
|
|
128
129
|
let code = load<u16>(srcStart);
|
|
129
130
|
if (code == 45) {
|
|
@@ -139,11 +140,16 @@ const ASCII_RANGE_ADD_4: u64 = 0x0006000600060006;
|
|
|
139
140
|
let value: u64 = digit;
|
|
140
141
|
srcStart += 2;
|
|
141
142
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
srcStart
|
|
143
|
+
// i8 tops out at 3 digits (-128..127), so the 4-digit kernel can never fire
|
|
144
|
+
// and the failing load + range check just burns cycles. Gate on the lane
|
|
145
|
+
// width so AS folds the loop away at compile time.
|
|
146
|
+
if (sizeof<valueof<T>>() > 1) {
|
|
147
|
+
while (srcStart + 6 < srcEnd) {
|
|
148
|
+
const parsed = parse4DigitsASCII(load<u64>(srcStart));
|
|
149
|
+
if (parsed == U32.MAX_VALUE) break;
|
|
150
|
+
value = value * 10000 + parsed;
|
|
151
|
+
srcStart += 8;
|
|
152
|
+
}
|
|
147
153
|
}
|
|
148
154
|
|
|
149
155
|
while (srcStart < srcEnd) {
|
|
@@ -153,12 +159,40 @@ const ASCII_RANGE_ADD_4: u64 = 0x0006000600060006;
|
|
|
153
159
|
srcStart += 2;
|
|
154
160
|
}
|
|
155
161
|
|
|
156
|
-
|
|
162
|
+
storeSignedInteger<T>(slot, negative ? -(<i64>value) : <i64>value);
|
|
157
163
|
return srcStart;
|
|
158
164
|
}
|
|
159
165
|
|
|
160
166
|
|
|
161
|
-
@inline function parseUnsignedIntegerSWAR<T extends number[]>(
|
|
167
|
+
@inline function parseUnsignedIntegerSWAR<T extends number[]>(
|
|
168
|
+
srcStart: usize,
|
|
169
|
+
srcEnd: usize,
|
|
170
|
+
slot: usize,
|
|
171
|
+
): usize {
|
|
172
|
+
// Narrow-type path mirrors the NAIVE structure: a tight scan loop to find
|
|
173
|
+
// the element terminator, then a fixed-count fold with no per-digit break.
|
|
174
|
+
// TurboFan tends to schedule this better than a single combined
|
|
175
|
+
// scan-and-fold loop because the fold has no data-dependent exit.
|
|
176
|
+
if (sizeof<valueof<T>>() <= 2) {
|
|
177
|
+
const first = <u32>load<u16>(srcStart) - 48;
|
|
178
|
+
if (first > 9) return 0;
|
|
179
|
+
const lastIndex = srcStart;
|
|
180
|
+
srcStart += 2;
|
|
181
|
+
while (srcStart < srcEnd) {
|
|
182
|
+
const c = <u32>load<u16>(srcStart) - 48;
|
|
183
|
+
if (c > 9) break;
|
|
184
|
+
srcStart += 2;
|
|
185
|
+
}
|
|
186
|
+
let value: u64 = 0;
|
|
187
|
+
let p = lastIndex;
|
|
188
|
+
while (p < srcStart) {
|
|
189
|
+
value = value * 10 + (<u32>load<u16>(p) - 48);
|
|
190
|
+
p += 2;
|
|
191
|
+
}
|
|
192
|
+
storeUnsignedInteger<T>(slot, value);
|
|
193
|
+
return srcStart;
|
|
194
|
+
}
|
|
195
|
+
|
|
162
196
|
let digit = <u32>load<u16>(srcStart) - 48;
|
|
163
197
|
if (digit > 9) return 0;
|
|
164
198
|
|
|
@@ -179,12 +213,15 @@ const ASCII_RANGE_ADD_4: u64 = 0x0006000600060006;
|
|
|
179
213
|
srcStart += 2;
|
|
180
214
|
}
|
|
181
215
|
|
|
182
|
-
|
|
216
|
+
storeUnsignedInteger<T>(slot, value);
|
|
183
217
|
return srcStart;
|
|
184
218
|
}
|
|
185
219
|
|
|
186
220
|
|
|
187
|
-
@inline function skipIntegerArrayWhitespace(
|
|
221
|
+
@inline function skipIntegerArrayWhitespace(
|
|
222
|
+
srcStart: usize,
|
|
223
|
+
srcEnd: usize,
|
|
224
|
+
): usize {
|
|
188
225
|
while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) {
|
|
189
226
|
srcStart += 2;
|
|
190
227
|
}
|
|
@@ -192,8 +229,14 @@ const ASCII_RANGE_ADD_4: u64 = 0x0006000600060006;
|
|
|
192
229
|
}
|
|
193
230
|
|
|
194
231
|
// @ts-ignore: Decorator valid here
|
|
195
|
-
export function deserializeIntegerArray_SLOW<T extends number[]>(
|
|
196
|
-
|
|
232
|
+
export function deserializeIntegerArray_SLOW<T extends number[]>(
|
|
233
|
+
srcStart: usize,
|
|
234
|
+
srcEnd: usize,
|
|
235
|
+
dst: usize,
|
|
236
|
+
): T {
|
|
237
|
+
const out = changetype<nonnull<T>>(
|
|
238
|
+
dst || changetype<usize>(instantiate<T>()),
|
|
239
|
+
);
|
|
197
240
|
let index = 0;
|
|
198
241
|
|
|
199
242
|
out.length = 0;
|
|
@@ -231,7 +274,10 @@ export function deserializeIntegerArray_SLOW<T extends number[]>(srcStart: usize
|
|
|
231
274
|
srcStart += 2;
|
|
232
275
|
}
|
|
233
276
|
|
|
234
|
-
storeSignedInteger<T>(
|
|
277
|
+
storeSignedInteger<T>(
|
|
278
|
+
ensureArrayElementSlot<T>(out, index),
|
|
279
|
+
negative ? -(<i64>value) : <i64>value,
|
|
280
|
+
);
|
|
235
281
|
} else {
|
|
236
282
|
let digit = <u32>code - 48;
|
|
237
283
|
if (digit > 9) break;
|
|
@@ -265,8 +311,15 @@ export function deserializeIntegerArray_SLOW<T extends number[]>(srcStart: usize
|
|
|
265
311
|
}
|
|
266
312
|
|
|
267
313
|
|
|
268
|
-
@inline function deserializeIntegerArrayImpl<T extends number[]>(
|
|
269
|
-
|
|
314
|
+
@inline function deserializeIntegerArrayImpl<T extends number[]>(
|
|
315
|
+
srcStart: usize,
|
|
316
|
+
srcEnd: usize,
|
|
317
|
+
dst: usize,
|
|
318
|
+
useSWAR: bool,
|
|
319
|
+
): T {
|
|
320
|
+
const out = changetype<nonnull<T>>(
|
|
321
|
+
dst || changetype<usize>(instantiate<T>()),
|
|
322
|
+
);
|
|
270
323
|
const originalSrcStart = srcStart;
|
|
271
324
|
const reusableLength = out.length;
|
|
272
325
|
|
|
@@ -300,11 +353,13 @@ export function deserializeIntegerArray_SLOW<T extends number[]>(srcStart: usize
|
|
|
300
353
|
let value: u64 = digit;
|
|
301
354
|
srcStart += 2;
|
|
302
355
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
356
|
+
if (sizeof<valueof<T>>() > 1) {
|
|
357
|
+
while (srcStart + 6 < srcEnd) {
|
|
358
|
+
const parsed = parse4DigitsASCII(load<u64>(srcStart));
|
|
359
|
+
if (parsed == U32.MAX_VALUE) break;
|
|
360
|
+
value = value * 10000 + parsed;
|
|
361
|
+
srcStart += 8;
|
|
362
|
+
}
|
|
308
363
|
}
|
|
309
364
|
|
|
310
365
|
while (srcStart < srcEnd) {
|
|
@@ -315,7 +370,10 @@ export function deserializeIntegerArray_SLOW<T extends number[]>(srcStart: usize
|
|
|
315
370
|
}
|
|
316
371
|
|
|
317
372
|
if (index >= reusableLength) break;
|
|
318
|
-
storeSignedInteger<T>(
|
|
373
|
+
storeSignedInteger<T>(
|
|
374
|
+
dataStart + <usize>index * sizeof<valueof<T>>(),
|
|
375
|
+
negative ? -(<i64>value) : <i64>value,
|
|
376
|
+
);
|
|
319
377
|
index++;
|
|
320
378
|
if (srcStart >= srcEnd) break;
|
|
321
379
|
|
|
@@ -338,11 +396,13 @@ export function deserializeIntegerArray_SLOW<T extends number[]>(srcStart: usize
|
|
|
338
396
|
let value: u64 = digit;
|
|
339
397
|
srcStart += 2;
|
|
340
398
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
399
|
+
if (sizeof<valueof<T>>() > 1) {
|
|
400
|
+
while (srcStart + 6 < srcEnd) {
|
|
401
|
+
const parsed = parse4DigitsASCII(load<u64>(srcStart));
|
|
402
|
+
if (parsed == U32.MAX_VALUE) break;
|
|
403
|
+
value = value * 10000 + parsed;
|
|
404
|
+
srcStart += 8;
|
|
405
|
+
}
|
|
346
406
|
}
|
|
347
407
|
|
|
348
408
|
while (srcStart < srcEnd) {
|
|
@@ -353,7 +413,10 @@ export function deserializeIntegerArray_SLOW<T extends number[]>(srcStart: usize
|
|
|
353
413
|
}
|
|
354
414
|
|
|
355
415
|
if (index >= reusableLength) break;
|
|
356
|
-
storeUnsignedInteger<T>(
|
|
416
|
+
storeUnsignedInteger<T>(
|
|
417
|
+
dataStart + <usize>index * sizeof<valueof<T>>(),
|
|
418
|
+
value,
|
|
419
|
+
);
|
|
357
420
|
index++;
|
|
358
421
|
if (srcStart >= srcEnd) break;
|
|
359
422
|
|
|
@@ -374,58 +437,229 @@ export function deserializeIntegerArray_SLOW<T extends number[]>(srcStart: usize
|
|
|
374
437
|
srcStart = originalSrcStart;
|
|
375
438
|
}
|
|
376
439
|
|
|
377
|
-
|
|
440
|
+
// Worst-case sizing: every element is at least 1 digit + 1 delimiter = 2
|
|
441
|
+
// UTF-16 chars = 4 bytes. AS skips zero-fill on `length=` for unmanaged
|
|
442
|
+
// primitive types (every concrete `valueof<T>` here is an integer), so the
|
|
443
|
+
// over-allocation costs only a small amount of trimmed storage at the end.
|
|
444
|
+
// The parse helpers below store through `writePtr` directly, eliminating
|
|
445
|
+
// `Array.push`'s per-element capacity check + length write for every
|
|
446
|
+
// integer width.
|
|
447
|
+
const elementSize = sizeof<valueof<T>>();
|
|
448
|
+
const maxElements = i32((<usize>(srcEnd - srcStart)) >> 2);
|
|
449
|
+
if (maxElements > 0) out.length = maxElements;
|
|
450
|
+
const dataStart = out.dataStart;
|
|
451
|
+
let writePtr = dataStart;
|
|
378
452
|
|
|
379
453
|
do {
|
|
380
454
|
if (srcStart >= srcEnd || load<u16>(srcStart) != BRACKET_LEFT) break;
|
|
381
455
|
srcStart += 2;
|
|
382
456
|
if (srcStart >= srcEnd) break;
|
|
383
|
-
if (load<u16>(srcStart) == BRACKET_RIGHT)
|
|
457
|
+
if (load<u16>(srcStart) == BRACKET_RIGHT) {
|
|
458
|
+
out.length = 0;
|
|
459
|
+
return out;
|
|
460
|
+
}
|
|
384
461
|
|
|
385
462
|
if (isSigned<valueof<T>>()) {
|
|
386
463
|
while (srcStart < srcEnd) {
|
|
387
|
-
|
|
388
|
-
|
|
464
|
+
const next = useSWAR
|
|
465
|
+
? parseSignedIntegerSWAR<T>(srcStart, srcEnd, writePtr)
|
|
466
|
+
: parseSignedIntegerScalar<T>(srcStart, srcEnd, writePtr);
|
|
467
|
+
if (!next) break;
|
|
468
|
+
writePtr += elementSize;
|
|
469
|
+
srcStart = next;
|
|
470
|
+
if (srcStart >= srcEnd) break;
|
|
389
471
|
|
|
390
472
|
const code = load<u16>(srcStart);
|
|
391
473
|
if (code == COMMA) {
|
|
392
474
|
srcStart += 2;
|
|
393
475
|
continue;
|
|
394
476
|
}
|
|
395
|
-
if (code == BRACKET_RIGHT)
|
|
477
|
+
if (code == BRACKET_RIGHT) {
|
|
478
|
+
out.length = i32(<usize>(writePtr - dataStart) / elementSize);
|
|
479
|
+
return out;
|
|
480
|
+
}
|
|
396
481
|
break;
|
|
397
482
|
}
|
|
398
483
|
} else {
|
|
399
484
|
while (srcStart < srcEnd) {
|
|
400
|
-
|
|
401
|
-
|
|
485
|
+
const next = useSWAR
|
|
486
|
+
? parseUnsignedIntegerSWAR<T>(srcStart, srcEnd, writePtr)
|
|
487
|
+
: parseUnsignedIntegerScalar<T>(srcStart, srcEnd, writePtr);
|
|
488
|
+
if (!next) break;
|
|
489
|
+
writePtr += elementSize;
|
|
490
|
+
srcStart = next;
|
|
491
|
+
if (srcStart >= srcEnd) break;
|
|
402
492
|
|
|
403
493
|
const code = load<u16>(srcStart);
|
|
404
494
|
if (code == COMMA) {
|
|
405
495
|
srcStart += 2;
|
|
406
496
|
continue;
|
|
407
497
|
}
|
|
408
|
-
if (code == BRACKET_RIGHT)
|
|
498
|
+
if (code == BRACKET_RIGHT) {
|
|
499
|
+
out.length = i32(<usize>(writePtr - dataStart) / elementSize);
|
|
500
|
+
return out;
|
|
501
|
+
}
|
|
409
502
|
break;
|
|
410
503
|
}
|
|
411
504
|
}
|
|
412
505
|
} while (false);
|
|
413
506
|
|
|
414
|
-
|
|
507
|
+
// Fast path bailed (whitespace, malformed numbers, etc). Hand off to the
|
|
508
|
+
// SLOW path which resets `out.length` to 0 and re-parses from the original
|
|
509
|
+
// input. The pre-allocated buffer is retained, so SLOW's per-element
|
|
510
|
+
// `ensureArrayElementSlot` grows-or-reuses through the existing capacity.
|
|
511
|
+
return deserializeIntegerArray_SLOW<T>(
|
|
512
|
+
originalSrcStart,
|
|
513
|
+
srcEnd,
|
|
514
|
+
changetype<usize>(out),
|
|
515
|
+
);
|
|
415
516
|
}
|
|
416
517
|
|
|
417
518
|
// @ts-ignore: Decorator valid here
|
|
418
|
-
export function deserializeIntegerArray<T extends number[]>(
|
|
519
|
+
export function deserializeIntegerArray<T extends number[]>(
|
|
520
|
+
srcStart: usize,
|
|
521
|
+
srcEnd: usize,
|
|
522
|
+
dst: usize,
|
|
523
|
+
): T {
|
|
419
524
|
return deserializeIntegerArrayImpl<T>(srcStart, srcEnd, dst, false);
|
|
420
525
|
}
|
|
421
526
|
|
|
422
527
|
// @ts-ignore: Decorator valid here
|
|
423
|
-
export function deserializeIntegerArray_SWAR<T extends number[]>(
|
|
528
|
+
export function deserializeIntegerArray_SWAR<T extends number[]>(
|
|
529
|
+
srcStart: usize,
|
|
530
|
+
srcEnd: usize,
|
|
531
|
+
dst: usize,
|
|
532
|
+
): T {
|
|
533
|
+
// u8/i8 elements use a dedicated two-pass SWAR path: a 4-char-stride
|
|
534
|
+
// comma counter pre-sizes the array so the parse pass can drop the
|
|
535
|
+
// per-push capacity check and write through a direct pointer. The
|
|
536
|
+
// wider-lane SWAR kernel never amortizes itself for narrow elements
|
|
537
|
+
// (u8 max 3 digits) so we skip it entirely here.
|
|
538
|
+
if (sizeof<valueof<T>>() <= 1) {
|
|
539
|
+
return deserializeNarrowIntegerArray_SWAR<T>(srcStart, srcEnd, dst);
|
|
540
|
+
}
|
|
424
541
|
return deserializeIntegerArrayImpl<T>(srcStart, srcEnd, dst, true);
|
|
425
542
|
}
|
|
426
543
|
|
|
544
|
+
/**
|
|
545
|
+
* Narrow-lane (u8/i8) integer-array deserializer.
|
|
546
|
+
*
|
|
547
|
+
* Two passes:
|
|
548
|
+
* 1) SWAR comma counter (4 chars per stride, popcnt over the lane mask)
|
|
549
|
+
* sizes the array exactly so the parse pass can use unchecked stores.
|
|
550
|
+
* 2) Walks the input NAIVE-style (skip non-digits, scan to separator,
|
|
551
|
+
* fold digits) but writes through a direct pointer, eliminating
|
|
552
|
+
* `Array.push`'s per-element capacity check and length write.
|
|
553
|
+
*
|
|
554
|
+
* V8 already auto-SIMDs NAIVE's scalar scan loop tighter than a hand-rolled
|
|
555
|
+
* SWAR scan in pass 2, so we keep that pattern there and only pay SWAR cost
|
|
556
|
+
* on the pre-count - which is a tight load-mask-popcnt loop where V8's
|
|
557
|
+
* scalar code can't compete with the explicit 4-lane stride.
|
|
558
|
+
*/
|
|
559
|
+
function deserializeNarrowIntegerArray_SWAR<T extends number[]>(
|
|
560
|
+
srcStart: usize,
|
|
561
|
+
srcEnd: usize,
|
|
562
|
+
dst: usize,
|
|
563
|
+
): T {
|
|
564
|
+
const out = changetype<nonnull<T>>(
|
|
565
|
+
dst || changetype<usize>(instantiate<T>()),
|
|
566
|
+
);
|
|
567
|
+
|
|
568
|
+
// Worst-case sizing: every element is at least 1 digit + 1 delimiter = 2
|
|
569
|
+
// UTF-16 chars = 4 bytes, so the body inside `[...]` can't hold more than
|
|
570
|
+
// `(srcEnd - srcStart) / 4` elements. AS skips zero-fill on `length=` for
|
|
571
|
+
// unmanaged element types, so over-allocation is essentially free here
|
|
572
|
+
// and saves a full SWAR pass over the input.
|
|
573
|
+
const maxElements = i32((<usize>(srcEnd - srcStart)) >> 2);
|
|
574
|
+
if (maxElements > 0) out.length = maxElements;
|
|
575
|
+
const dataStart = out.dataStart;
|
|
576
|
+
const elementSize = sizeof<valueof<T>>();
|
|
577
|
+
let writePtr = dataStart;
|
|
578
|
+
|
|
579
|
+
while (srcStart < srcEnd) {
|
|
580
|
+
// Fast paths: 1-, 2-, or 3-digit unsigned element followed by `,` packs
|
|
581
|
+
// into one u64 load (covers ~100% of the typical 0..255 cycle). Ordered
|
|
582
|
+
// 3 -> 2 -> 1 because 3-digit values dominate any wide-range payload;
|
|
583
|
+
// the 2- and 1-digit branches cover the rest of `out`.
|
|
584
|
+
if (!isSigned<valueof<T>>() && srcStart + 6 < srcEnd) {
|
|
585
|
+
const block = load<u64>(srcStart);
|
|
586
|
+
if (((block >> 48) & 0xffff) == COMMA) {
|
|
587
|
+
const digits = (block & 0x0000_00ff_00ff_00ff) - 0x0000_0030_0030_0030;
|
|
588
|
+
const oor =
|
|
589
|
+
(digits | (digits + 0x0000_0006_0006_0006)) & 0x0000_fff0_fff0_fff0;
|
|
590
|
+
if (oor == 0) {
|
|
591
|
+
const d0 = <u32>(digits & 0xffff);
|
|
592
|
+
const d1 = <u32>((digits >> 16) & 0xffff);
|
|
593
|
+
const d2 = <u32>((digits >> 32) & 0xffff);
|
|
594
|
+
store<valueof<T>>(writePtr, <valueof<T>>(d0 * 100 + d1 * 10 + d2));
|
|
595
|
+
writePtr += elementSize;
|
|
596
|
+
srcStart += 8;
|
|
597
|
+
continue;
|
|
598
|
+
}
|
|
599
|
+
} else if (((block >> 32) & 0xffff) == COMMA) {
|
|
600
|
+
const digits = (block & 0x0000_0000_00ff_00ff) - 0x0000_0000_0030_0030;
|
|
601
|
+
const oor =
|
|
602
|
+
(digits | (digits + 0x0000_0000_0006_0006)) & 0x0000_0000_fff0_fff0;
|
|
603
|
+
if (oor == 0) {
|
|
604
|
+
const d0 = <u32>(digits & 0xffff);
|
|
605
|
+
const d1 = <u32>((digits >> 16) & 0xffff);
|
|
606
|
+
store<valueof<T>>(writePtr, <valueof<T>>(d0 * 10 + d1));
|
|
607
|
+
writePtr += elementSize;
|
|
608
|
+
srcStart += 6;
|
|
609
|
+
continue;
|
|
610
|
+
}
|
|
611
|
+
} else if (((block >> 16) & 0xffff) == COMMA) {
|
|
612
|
+
const d0 = <u32>(block & 0xffff) - 48;
|
|
613
|
+
if (d0 <= 9) {
|
|
614
|
+
store<valueof<T>>(writePtr, <valueof<T>>d0);
|
|
615
|
+
writePtr += elementSize;
|
|
616
|
+
srcStart += 4;
|
|
617
|
+
continue;
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
const code = load<u16>(srcStart);
|
|
622
|
+
if (<u32>code - 48 <= 9 || (isSigned<valueof<T>>() && code == 45)) {
|
|
623
|
+
const lastIndex = srcStart;
|
|
624
|
+
srcStart += 2;
|
|
625
|
+
while (srcStart < srcEnd) {
|
|
626
|
+
const c = load<u16>(srcStart);
|
|
627
|
+
if (c == COMMA || c == BRACKET_RIGHT || isSpace(c)) {
|
|
628
|
+
let value: u64 = 0;
|
|
629
|
+
let p = lastIndex;
|
|
630
|
+
if (isSigned<valueof<T>>() && load<u16>(p) == 45) {
|
|
631
|
+
p += 2;
|
|
632
|
+
while (p < srcStart) {
|
|
633
|
+
value = value * 10 + (<u32>load<u16>(p) - 48);
|
|
634
|
+
p += 2;
|
|
635
|
+
}
|
|
636
|
+
store<valueof<T>>(writePtr, <valueof<T>>-(<i64>value));
|
|
637
|
+
} else {
|
|
638
|
+
while (p < srcStart) {
|
|
639
|
+
value = value * 10 + (<u32>load<u16>(p) - 48);
|
|
640
|
+
p += 2;
|
|
641
|
+
}
|
|
642
|
+
store<valueof<T>>(writePtr, <valueof<T>>value);
|
|
643
|
+
}
|
|
644
|
+
writePtr += elementSize;
|
|
645
|
+
break;
|
|
646
|
+
}
|
|
647
|
+
srcStart += 2;
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
srcStart += 2;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
out.length = i32(<usize>(writePtr - dataStart) / elementSize);
|
|
654
|
+
return out;
|
|
655
|
+
}
|
|
656
|
+
|
|
427
657
|
|
|
428
|
-
@inline export function deserializeIntegerArrayInto<T extends number[]>(
|
|
658
|
+
@inline export function deserializeIntegerArrayInto<T extends number[]>(
|
|
659
|
+
srcStart: usize,
|
|
660
|
+
srcEnd: usize,
|
|
661
|
+
out: T,
|
|
662
|
+
): usize {
|
|
429
663
|
let index = 0;
|
|
430
664
|
|
|
431
665
|
do {
|
|
@@ -439,7 +673,9 @@ export function deserializeIntegerArray_SWAR<T extends number[]>(srcStart: usize
|
|
|
439
673
|
|
|
440
674
|
while (srcStart < srcEnd) {
|
|
441
675
|
const slot = ensureArrayElementSlot<T>(out, index);
|
|
442
|
-
srcStart = isSigned<valueof<T>>()
|
|
676
|
+
srcStart = isSigned<valueof<T>>()
|
|
677
|
+
? deserializeIntegerField<valueof<T>>(srcStart, srcEnd, slot)
|
|
678
|
+
: deserializeUnsignedField<valueof<T>>(srcStart, srcEnd, slot);
|
|
443
679
|
if (!srcStart || srcStart >= srcEnd) break;
|
|
444
680
|
|
|
445
681
|
const code = load<u16>(srcStart);
|
|
@@ -460,6 +696,14 @@ export function deserializeIntegerArray_SWAR<T extends number[]>(srcStart: usize
|
|
|
460
696
|
}
|
|
461
697
|
|
|
462
698
|
|
|
463
|
-
@inline export function deserializeIntegerArrayField<T extends number[]>(
|
|
464
|
-
|
|
699
|
+
@inline export function deserializeIntegerArrayField<T extends number[]>(
|
|
700
|
+
srcStart: usize,
|
|
701
|
+
srcEnd: usize,
|
|
702
|
+
fieldPtr: usize,
|
|
703
|
+
): usize {
|
|
704
|
+
return deserializeIntegerArrayInto<T>(
|
|
705
|
+
srcStart,
|
|
706
|
+
srcEnd,
|
|
707
|
+
ensureArrayField<T>(fieldPtr),
|
|
708
|
+
);
|
|
465
709
|
}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { ensureArrayField } from "./shared";
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
@inline export function deserializeMapArrayField<T extends Map<any, any>[]>(
|
|
4
|
+
@inline export function deserializeMapArrayField<T extends Map<any, any>[]>(
|
|
5
|
+
srcStart: usize,
|
|
6
|
+
srcEnd: usize,
|
|
7
|
+
fieldPtr: usize,
|
|
8
|
+
): usize {
|
|
5
9
|
ensureArrayField<T>(fieldPtr);
|
|
6
10
|
throw new Error("Failed to parse JSON!");
|
|
7
11
|
}
|
|
@@ -2,7 +2,11 @@ import { BRACKET_LEFT, BRACKET_RIGHT, COMMA } from "../../../custom/chars";
|
|
|
2
2
|
import { ensureArrayElementSlot, ensureArrayField } from "./shared";
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
@inline export function deserializeObjectArrayInto<T extends unknown[]>(
|
|
5
|
+
@inline export function deserializeObjectArrayInto<T extends unknown[]>(
|
|
6
|
+
srcStart: usize,
|
|
7
|
+
srcEnd: usize,
|
|
8
|
+
out: T,
|
|
9
|
+
): usize {
|
|
6
10
|
let index = 0;
|
|
7
11
|
|
|
8
12
|
do {
|
|
@@ -18,7 +22,9 @@ import { ensureArrayElementSlot, ensureArrayField } from "./shared";
|
|
|
18
22
|
const slot = ensureArrayElementSlot<T>(out, index);
|
|
19
23
|
let value = load<valueof<T>>(slot);
|
|
20
24
|
if (changetype<usize>(value) == 0) {
|
|
21
|
-
value = changetype<valueof<T>>(
|
|
25
|
+
value = changetype<valueof<T>>(
|
|
26
|
+
__new(offsetof<nonnull<valueof<T>>>(), idof<nonnull<valueof<T>>>()),
|
|
27
|
+
);
|
|
22
28
|
// @ts-ignore: supplied by transform
|
|
23
29
|
if (isDefined(changetype<nonnull<valueof<T>>>(value).__INITIALIZE)) {
|
|
24
30
|
// @ts-ignore: supplied by transform
|
|
@@ -29,12 +35,18 @@ import { ensureArrayElementSlot, ensureArrayField } from "./shared";
|
|
|
29
35
|
|
|
30
36
|
const valueStart = srcStart;
|
|
31
37
|
// @ts-ignore: supplied by transform
|
|
32
|
-
if (
|
|
38
|
+
if (
|
|
39
|
+
isDefined(changetype<nonnull<valueof<T>>>(value).__DESERIALIZE_FAST)
|
|
40
|
+
) {
|
|
33
41
|
// @ts-ignore: supplied by transform
|
|
34
|
-
srcStart = changetype<nonnull<valueof<T>>>(value).__DESERIALIZE_FAST<
|
|
42
|
+
srcStart = changetype<nonnull<valueof<T>>>(value).__DESERIALIZE_FAST<
|
|
43
|
+
valueof<T>
|
|
44
|
+
>(valueStart, srcEnd, value);
|
|
35
45
|
} else {
|
|
36
46
|
// @ts-ignore: supplied by transform
|
|
37
|
-
srcStart = changetype<nonnull<valueof<T>>>(value).__DESERIALIZE_SLOW<
|
|
47
|
+
srcStart = changetype<nonnull<valueof<T>>>(value).__DESERIALIZE_SLOW<
|
|
48
|
+
valueof<T>
|
|
49
|
+
>(valueStart, srcEnd, value);
|
|
38
50
|
}
|
|
39
51
|
if (!srcStart || srcStart >= srcEnd) break;
|
|
40
52
|
|
|
@@ -56,6 +68,14 @@ import { ensureArrayElementSlot, ensureArrayField } from "./shared";
|
|
|
56
68
|
}
|
|
57
69
|
|
|
58
70
|
|
|
59
|
-
@inline export function deserializeObjectArrayField<T extends unknown[]>(
|
|
60
|
-
|
|
71
|
+
@inline export function deserializeObjectArrayField<T extends unknown[]>(
|
|
72
|
+
srcStart: usize,
|
|
73
|
+
srcEnd: usize,
|
|
74
|
+
fieldPtr: usize,
|
|
75
|
+
): usize {
|
|
76
|
+
return deserializeObjectArrayInto<T>(
|
|
77
|
+
srcStart,
|
|
78
|
+
srcEnd,
|
|
79
|
+
ensureArrayField<T>(fieldPtr),
|
|
80
|
+
);
|
|
61
81
|
}
|
|
@@ -2,7 +2,11 @@ import { JSON } from "../../..";
|
|
|
2
2
|
import { ensureArrayField } from "./shared";
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
@inline export function deserializeRawArrayField(
|
|
5
|
+
@inline export function deserializeRawArrayField(
|
|
6
|
+
srcStart: usize,
|
|
7
|
+
srcEnd: usize,
|
|
8
|
+
fieldPtr: usize,
|
|
9
|
+
): usize {
|
|
6
10
|
ensureArrayField<JSON.Raw[]>(fieldPtr);
|
|
7
11
|
throw new Error("Failed to parse JSON!");
|
|
8
12
|
}
|