json-as 1.3.9 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +60 -19
- package/README.md +120 -21
- package/assembly/custom/chars.ts +39 -78
- package/assembly/deserialize/index/arbitrary.ts +28 -10
- package/assembly/deserialize/index/float.ts +2 -4
- package/assembly/deserialize/index/integer.ts +2 -4
- package/assembly/deserialize/index/object.ts +6 -1
- package/assembly/deserialize/index/string.ts +2 -7
- package/assembly/deserialize/index/unsigned.ts +2 -4
- package/assembly/deserialize/naive/array/arbitrary.ts +3 -136
- package/assembly/deserialize/naive/array/array.ts +30 -1
- package/assembly/deserialize/naive/array/integer.ts +2 -7
- package/assembly/deserialize/naive/array/map.ts +10 -14
- package/assembly/deserialize/naive/array/object.ts +10 -14
- package/assembly/deserialize/naive/array/struct.ts +19 -1
- package/assembly/deserialize/naive/bool.ts +1 -5
- package/assembly/deserialize/naive/date.ts +1 -2
- package/assembly/deserialize/naive/float.ts +4 -11
- package/assembly/deserialize/naive/integer.ts +2 -4
- package/assembly/deserialize/naive/map.ts +42 -205
- package/assembly/deserialize/naive/object.ts +291 -174
- package/assembly/deserialize/naive/raw.ts +1 -5
- package/assembly/deserialize/naive/set.ts +3 -6
- package/assembly/deserialize/naive/staticarray.ts +2 -4
- package/assembly/deserialize/naive/string.ts +68 -24
- package/assembly/deserialize/naive/typedarray.ts +1 -2
- package/assembly/deserialize/naive/unsigned.ts +2 -4
- package/assembly/deserialize/simd/array/integer.ts +5 -13
- package/assembly/deserialize/simd/float.ts +5 -12
- package/assembly/deserialize/simd/integer.ts +6 -15
- package/assembly/deserialize/simd/string.ts +21 -43
- package/assembly/deserialize/swar/array/arbitrary.ts +1 -2
- package/assembly/deserialize/swar/array/array.ts +2 -4
- package/assembly/deserialize/swar/array/bool.ts +2 -4
- package/assembly/deserialize/swar/array/box.ts +1 -2
- package/assembly/deserialize/swar/array/float.ts +8 -21
- package/assembly/deserialize/swar/array/generic.ts +2 -4
- package/assembly/deserialize/swar/array/integer.ts +13 -27
- package/assembly/deserialize/swar/array/map.ts +1 -2
- package/assembly/deserialize/swar/array/object.ts +2 -4
- package/assembly/deserialize/swar/array/raw.ts +1 -2
- package/assembly/deserialize/swar/array/shared.ts +9 -21
- package/assembly/deserialize/swar/array/string.ts +4 -10
- package/assembly/deserialize/swar/array/struct.ts +3 -9
- package/assembly/deserialize/swar/array.ts +1 -3
- package/assembly/deserialize/swar/float.ts +7 -17
- package/assembly/deserialize/swar/integer.ts +6 -15
- package/assembly/deserialize/swar/string.ts +40 -54
- package/assembly/deserialize/swar/typedarray.ts +4 -4
- package/assembly/index.d.ts +259 -21
- package/assembly/index.ts +1704 -266
- package/assembly/serialize/index/arbitrary.ts +70 -4
- package/assembly/serialize/index/jsonarray.ts +51 -0
- package/assembly/serialize/index/object.ts +39 -14
- package/assembly/serialize/index/string.ts +1 -2
- package/assembly/serialize/index/typedarray.ts +1 -2
- package/assembly/serialize/index.ts +1 -0
- package/assembly/serialize/naive/array.ts +23 -34
- package/assembly/serialize/naive/bool.ts +0 -1
- package/assembly/serialize/naive/float.ts +16 -25
- package/assembly/serialize/naive/integer.ts +1 -5
- package/assembly/serialize/naive/raw.ts +1 -2
- package/assembly/serialize/naive/set.ts +0 -4
- package/assembly/serialize/naive/staticarray.ts +0 -5
- package/assembly/serialize/naive/string.ts +11 -7
- package/assembly/serialize/naive/typedarray.ts +0 -6
- package/assembly/serialize/simd/string.ts +1 -3
- package/assembly/serialize/swar/string.ts +2 -4
- package/assembly/util/atoi-fast.ts +4 -14
- package/assembly/util/atoi.ts +1 -2
- package/assembly/util/bytes.ts +1 -2
- package/assembly/util/idofd.ts +1 -2
- package/assembly/util/isSpace.ts +1 -2
- package/assembly/util/itoa-fast.ts +9 -15
- package/assembly/util/nextPowerOf2.ts +1 -2
- package/assembly/util/parsefloat-fast.ts +4 -7
- package/assembly/util/ptrToStr.ts +1 -2
- package/assembly/util/scanValueEnd.ts +1 -2
- package/assembly/util/scanValueEndSimd.ts +198 -0
- package/assembly/util/scanValueEndSwar.ts +184 -0
- package/assembly/util/scientific.ts +8 -14
- package/assembly/util/simd-int.ts +4 -8
- package/assembly/util/snp.ts +2 -7
- package/assembly/util/stringScan.ts +2 -4
- package/assembly/util/swar-int.ts +8 -16
- package/assembly/util/swar.ts +2 -4
- package/lib/as-bs.ts +57 -42
- package/package.json +27 -10
- package/transform/lib/builder.d.ts +0 -1
- package/transform/lib/builder.js +0 -1
- package/transform/lib/index.d.ts +0 -1
- package/transform/lib/index.js +617 -326
- package/transform/lib/linkers/alias.d.ts +0 -1
- package/transform/lib/linkers/alias.js +0 -1
- package/transform/lib/linkers/custom.d.ts +0 -1
- package/transform/lib/linkers/custom.js +0 -1
- package/transform/lib/linkers/imports.d.ts +0 -1
- package/transform/lib/linkers/imports.js +0 -1
- package/transform/lib/types.d.ts +4 -2
- package/transform/lib/types.js +5 -1
- package/transform/lib/util.d.ts +0 -1
- package/transform/lib/util.js +0 -1
- package/transform/lib/visitor.d.ts +0 -1
- package/transform/lib/visitor.js +0 -1
- package/assembly/util/dragonbox-cache.ts +0 -445
- package/assembly/util/dragonbox.ts +0 -660
- package/transform/lib/builder.d.ts.map +0 -1
- package/transform/lib/builder.js.map +0 -1
- package/transform/lib/index.d.ts.map +0 -1
- package/transform/lib/index.js.map +0 -1
- package/transform/lib/linkers/alias.d.ts.map +0 -1
- package/transform/lib/linkers/alias.js.map +0 -1
- package/transform/lib/linkers/custom.d.ts.map +0 -1
- package/transform/lib/linkers/custom.js.map +0 -1
- package/transform/lib/linkers/imports.d.ts.map +0 -1
- package/transform/lib/linkers/imports.js.map +0 -1
- package/transform/lib/types.d.ts.map +0 -1
- package/transform/lib/types.js.map +0 -1
- package/transform/lib/util.d.ts.map +0 -1
- package/transform/lib/util.js.map +0 -1
- package/transform/lib/visitor.d.ts.map +0 -1
- package/transform/lib/visitor.js.map +0 -1
|
@@ -41,11 +41,7 @@ import { hex4_to_u16_swar } from "../../util/swar";
|
|
|
41
41
|
* @param dst buffer to write to
|
|
42
42
|
* @returns number of bytes written
|
|
43
43
|
*/
|
|
44
|
-
|
|
45
|
-
@inline function copyStringFromSource(
|
|
46
|
-
srcStart: usize,
|
|
47
|
-
byteLength: usize,
|
|
48
|
-
): string {
|
|
44
|
+
function copyStringFromSource(srcStart: usize, byteLength: usize): string {
|
|
49
45
|
if (byteLength == 0) return changetype<string>("");
|
|
50
46
|
const out = __new(byteLength, idof<string>());
|
|
51
47
|
memory.copy(out, srcStart, byteLength);
|
|
@@ -61,8 +57,7 @@ import { hex4_to_u16_swar } from "../../util/swar";
|
|
|
61
57
|
// NOTE: vs the prior overflow scanner this is faster on dense and sparse
|
|
62
58
|
// escaping but ~20% slower on sustained moderate-density escaping (escape
|
|
63
59
|
// every ~20 chars), where multi-escape-per-block had an edge.
|
|
64
|
-
|
|
65
|
-
@inline function deserializeEscapedString_SWAR(
|
|
60
|
+
function deserializeEscapedString_SWAR(
|
|
66
61
|
payloadStart: usize,
|
|
67
62
|
escapeStart: usize,
|
|
68
63
|
srcEnd: usize,
|
|
@@ -80,20 +75,20 @@ import { hex4_to_u16_swar } from "../../util/swar";
|
|
|
80
75
|
|
|
81
76
|
while (srcStart <= srcEnd8) {
|
|
82
77
|
const block = load<u64>(srcStart);
|
|
83
|
-
let mask =
|
|
78
|
+
let mask = backslash_mask_unsafe(block);
|
|
84
79
|
if (mask == 0) {
|
|
85
80
|
store<u64>(bs.offset, block);
|
|
86
81
|
bs.offset += 8;
|
|
87
82
|
srcStart += 8;
|
|
88
83
|
if (
|
|
89
84
|
srcStart <= srcEnd8 &&
|
|
90
|
-
|
|
85
|
+
backslash_mask_unsafe(load<u64>(srcStart)) == 0
|
|
91
86
|
) {
|
|
92
87
|
const runStart = srcStart;
|
|
93
88
|
srcStart += 8;
|
|
94
89
|
while (
|
|
95
90
|
srcStart <= srcEnd8 &&
|
|
96
|
-
|
|
91
|
+
backslash_mask_unsafe(load<u64>(srcStart)) == 0
|
|
97
92
|
) {
|
|
98
93
|
srcStart += 8;
|
|
99
94
|
}
|
|
@@ -162,8 +157,8 @@ export function deserializeString_SWAR(srcStart: usize, srcEnd: usize): string {
|
|
|
162
157
|
const srcEnd16Fast = srcEnd - 16;
|
|
163
158
|
|
|
164
159
|
while (srcStart < srcEnd16Fast) {
|
|
165
|
-
const m0 =
|
|
166
|
-
const m1 =
|
|
160
|
+
const m0 = backslash_mask_unsafe(load<u64>(srcStart));
|
|
161
|
+
const m1 = backslash_mask_unsafe(load<u64>(srcStart, 8));
|
|
167
162
|
if ((m0 | m1) != 0) break;
|
|
168
163
|
srcStart += 16;
|
|
169
164
|
}
|
|
@@ -183,7 +178,7 @@ export function deserializeString_SWAR(srcStart: usize, srcEnd: usize): string {
|
|
|
183
178
|
|
|
184
179
|
while (srcStart < srcEnd8) {
|
|
185
180
|
const block = load<u64>(srcStart);
|
|
186
|
-
let mask =
|
|
181
|
+
let mask = backslash_mask_unsafe(block);
|
|
187
182
|
|
|
188
183
|
if (mask === 0) {
|
|
189
184
|
srcStart += 8;
|
|
@@ -199,9 +194,7 @@ export function deserializeString_SWAR(srcStart: usize, srcEnd: usize): string {
|
|
|
199
194
|
// Detect false positive (code unit where low byte is 0x5C)
|
|
200
195
|
if ((header & 0xffff) !== 0x5c) continue;
|
|
201
196
|
|
|
202
|
-
return
|
|
203
|
-
deserializeEscapedString_SWAR(payloadStart, srcIdx, srcEnd),
|
|
204
|
-
);
|
|
197
|
+
return deserializeEscapedString_SWAR(payloadStart, srcIdx, srcEnd);
|
|
205
198
|
} while (mask !== 0);
|
|
206
199
|
|
|
207
200
|
srcStart += 8;
|
|
@@ -209,9 +202,7 @@ export function deserializeString_SWAR(srcStart: usize, srcEnd: usize): string {
|
|
|
209
202
|
|
|
210
203
|
while (srcStart < srcEnd) {
|
|
211
204
|
if (load<u16>(srcStart) == BACK_SLASH) {
|
|
212
|
-
return
|
|
213
|
-
deserializeEscapedString_SWAR(payloadStart, srcStart, srcEnd),
|
|
214
|
-
);
|
|
205
|
+
return deserializeEscapedString_SWAR(payloadStart, srcStart, srcEnd);
|
|
215
206
|
}
|
|
216
207
|
srcStart += 2;
|
|
217
208
|
}
|
|
@@ -220,8 +211,7 @@ export function deserializeString_SWAR(srcStart: usize, srcEnd: usize): string {
|
|
|
220
211
|
}
|
|
221
212
|
|
|
222
213
|
// Writes into the destination field, reusing or resizing the backing string.
|
|
223
|
-
|
|
224
|
-
@inline function writeStringToField(
|
|
214
|
+
function writeStringToField(
|
|
225
215
|
dstFieldPtr: usize,
|
|
226
216
|
srcStart: usize,
|
|
227
217
|
byteLength: u32,
|
|
@@ -251,15 +241,14 @@ export function deserializeString_SWAR(srcStart: usize, srcEnd: usize): string {
|
|
|
251
241
|
// the next unread src pointer.
|
|
252
242
|
//
|
|
253
243
|
// HYBRID strategy (validated against the prior run-copy scanner across escape
|
|
254
|
-
// densities
|
|
244
|
+
// densities - see __benches__/custom/swar-string-deser-hybrid-h2h: +17–70%):
|
|
255
245
|
// * Escape-bearing block: one optimistic whole-block u64 store copies the
|
|
256
246
|
// plain prefix for free, then the (scalar-confirmed) escape is decoded.
|
|
257
247
|
// * Clean block: stream the first one, then if the clean run continues switch
|
|
258
248
|
// to one bulk memory.copy for the remainder.
|
|
259
249
|
// SWAR masks carry high-byte false positives, so each hit is confirmed
|
|
260
250
|
// scalarly before acting.
|
|
261
|
-
|
|
262
|
-
@inline function deserializeEscapedStringField_SWAR(
|
|
251
|
+
function deserializeEscapedStringField_SWAR(
|
|
263
252
|
payloadStart: usize,
|
|
264
253
|
escapeStart: usize,
|
|
265
254
|
srcEnd: usize,
|
|
@@ -278,20 +267,20 @@ export function deserializeString_SWAR(srcStart: usize, srcEnd: usize): string {
|
|
|
278
267
|
|
|
279
268
|
while (srcStart <= srcEnd8) {
|
|
280
269
|
const block = load<u64>(srcStart);
|
|
281
|
-
let mask =
|
|
270
|
+
let mask = backslash_or_quote_mask(block);
|
|
282
271
|
if (mask == 0) {
|
|
283
272
|
store<u64>(bs.offset, block);
|
|
284
273
|
bs.offset += 8;
|
|
285
274
|
srcStart += 8;
|
|
286
275
|
if (
|
|
287
276
|
srcStart <= srcEnd8 &&
|
|
288
|
-
|
|
277
|
+
backslash_or_quote_mask(load<u64>(srcStart)) == 0
|
|
289
278
|
) {
|
|
290
279
|
const runStart = srcStart;
|
|
291
280
|
srcStart += 8;
|
|
292
281
|
while (
|
|
293
282
|
srcStart <= srcEnd8 &&
|
|
294
|
-
|
|
283
|
+
backslash_or_quote_mask(load<u64>(srcStart)) == 0
|
|
295
284
|
) {
|
|
296
285
|
srcStart += 8;
|
|
297
286
|
}
|
|
@@ -371,8 +360,7 @@ export function deserializeString_SWAR(srcStart: usize, srcEnd: usize): string {
|
|
|
371
360
|
return srcStart;
|
|
372
361
|
}
|
|
373
362
|
|
|
374
|
-
|
|
375
|
-
@inline function deserializeEscapedStringContinuation_SWAR_MergedTuned(
|
|
363
|
+
function deserializeEscapedStringContinuation_SWAR_MergedTuned(
|
|
376
364
|
lastPtr: usize,
|
|
377
365
|
srcStart: usize,
|
|
378
366
|
srcEnd: usize,
|
|
@@ -382,7 +370,7 @@ export function deserializeString_SWAR(srcStart: usize, srcEnd: usize): string {
|
|
|
382
370
|
|
|
383
371
|
while (srcStart <= srcEnd8) {
|
|
384
372
|
const blockStart = srcStart;
|
|
385
|
-
let mask =
|
|
373
|
+
let mask = backslash_or_quote_mask(load<u64>(srcStart));
|
|
386
374
|
if (mask === 0) {
|
|
387
375
|
srcStart += 8;
|
|
388
376
|
continue;
|
|
@@ -491,16 +479,21 @@ export function deserializeStringField_SWAR<T extends string | null>(
|
|
|
491
479
|
if (srcEnd >= 16) {
|
|
492
480
|
const srcEnd16 = srcEnd - 16;
|
|
493
481
|
while (srcStart <= srcEnd16) {
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
482
|
+
// Test the first word before loading the second: short values and keys
|
|
483
|
+
// close (or escape) within the first 8 bytes, so this skips the second
|
|
484
|
+
// load on the common case while still skipping 16 bytes when both clean.
|
|
485
|
+
if (backslash_or_quote_mask(load<u64>(srcStart)) != 0) break;
|
|
486
|
+
if (backslash_or_quote_mask(load<u64>(srcStart, 8)) != 0) {
|
|
487
|
+
srcStart += 8;
|
|
488
|
+
break;
|
|
489
|
+
}
|
|
497
490
|
srcStart += 16;
|
|
498
491
|
}
|
|
499
492
|
}
|
|
500
493
|
|
|
501
494
|
const srcEnd8 = srcEnd - 8;
|
|
502
495
|
while (srcStart <= srcEnd8) {
|
|
503
|
-
let mask =
|
|
496
|
+
let mask = backslash_or_quote_mask(load<u64>(srcStart));
|
|
504
497
|
if (mask === 0) {
|
|
505
498
|
srcStart += 8;
|
|
506
499
|
continue;
|
|
@@ -520,13 +513,11 @@ export function deserializeStringField_SWAR<T extends string | null>(
|
|
|
520
513
|
return srcIdx + 2;
|
|
521
514
|
}
|
|
522
515
|
if (char != BACK_SLASH) continue;
|
|
523
|
-
return
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
dstFieldPtr,
|
|
529
|
-
),
|
|
516
|
+
return deserializeEscapedStringField_SWAR(
|
|
517
|
+
payloadStart,
|
|
518
|
+
srcIdx,
|
|
519
|
+
srcEnd,
|
|
520
|
+
dstFieldPtr,
|
|
530
521
|
);
|
|
531
522
|
} while (mask !== 0);
|
|
532
523
|
|
|
@@ -544,13 +535,11 @@ export function deserializeStringField_SWAR<T extends string | null>(
|
|
|
544
535
|
return srcStart + 2;
|
|
545
536
|
}
|
|
546
537
|
if (char == BACK_SLASH) {
|
|
547
|
-
return
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
dstFieldPtr,
|
|
553
|
-
),
|
|
538
|
+
return deserializeEscapedStringField_SWAR(
|
|
539
|
+
payloadStart,
|
|
540
|
+
srcStart,
|
|
541
|
+
srcEnd,
|
|
542
|
+
dstFieldPtr,
|
|
554
543
|
);
|
|
555
544
|
}
|
|
556
545
|
srcStart += 2;
|
|
@@ -567,8 +556,7 @@ export function deserializeStringField_SWAR<T extends string | null>(
|
|
|
567
556
|
* so callers must confirm the hit scalarly.
|
|
568
557
|
* Each matching lane sets itself to 0x80.
|
|
569
558
|
*/
|
|
570
|
-
|
|
571
|
-
@inline function backslash_or_quote_mask(block: u64): u64 {
|
|
559
|
+
function backslash_or_quote_mask(block: u64): u64 {
|
|
572
560
|
const b = block ^ 0x005c_005c_005c_005c;
|
|
573
561
|
const q = block ^ 0x0022_0022_0022_0022;
|
|
574
562
|
return (
|
|
@@ -587,8 +575,7 @@ export function deserializeStringField_SWAR<T extends string | null>(
|
|
|
587
575
|
*
|
|
588
576
|
* Each matching lane sets itself to 0x80.
|
|
589
577
|
*/
|
|
590
|
-
|
|
591
|
-
@inline function backslash_mask(block: u64): u64 {
|
|
578
|
+
function backslash_mask(block: u64): u64 {
|
|
592
579
|
const b = block ^ 0x005c_005c_005c_005c;
|
|
593
580
|
const backslash_mask =
|
|
594
581
|
(b - 0x0001_0001_0001_0001) & ~b & 0x0080_0080_0080_0080;
|
|
@@ -609,8 +596,7 @@ export function deserializeStringField_SWAR<T extends string | null>(
|
|
|
609
596
|
* WARNING: The low byte of a code unit *may* be a backslash, thus triggering false positives!
|
|
610
597
|
* This is useful for a hot path where it is possible to detect the false positive scalarly.
|
|
611
598
|
*/
|
|
612
|
-
|
|
613
|
-
@inline function backslash_mask_unsafe(block: u64): u64 {
|
|
599
|
+
function backslash_mask_unsafe(block: u64): u64 {
|
|
614
600
|
const b = block ^ 0x005c_005c_005c_005c;
|
|
615
601
|
const backslash_mask =
|
|
616
602
|
(b - 0x0001_0001_0001_0001) & ~b & 0x0080_0080_0080_0080;
|
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
//
|
|
7
7
|
// - **No count pass.** TypedArrays have a fixed length at construction,
|
|
8
8
|
// so the natural approach is to count first then allocate. We tried
|
|
9
|
-
// that with a SWAR comma counter
|
|
9
|
+
// that with a SWAR comma counter - it cut the per-element cost but
|
|
10
10
|
// kept us ~30% below the top-level `f64[]` path because the count
|
|
11
11
|
// scan still touched the whole input twice. Instead we allocate
|
|
12
|
-
// worst-case (`(srcEnd - srcStart) >> 2 + 1` elements
|
|
12
|
+
// worst-case (`(srcEnd - srcStart) >> 2 + 1` elements - each
|
|
13
13
|
// element needs >= "D," = 2 UTF-16 chars = 4 bytes) and `__renew`
|
|
14
14
|
// the underlying buffer down to the exact byte count after parsing.
|
|
15
15
|
// The over-allocation peaks at ~2-3× the final size for typical
|
|
@@ -46,7 +46,7 @@ import {
|
|
|
46
46
|
* Worst-case element count: each element occupies >= 1 digit + 1
|
|
47
47
|
* delimiter = 2 UTF-16 chars = 4 bytes. So `(srcEnd - srcStart) >> 2`
|
|
48
48
|
* upper-bounds the count. Allocating to worst-case lets us skip a
|
|
49
|
-
* full count pass over the input
|
|
49
|
+
* full count pass over the input - at the cost of an over-allocated
|
|
50
50
|
* underlying buffer that we trim via `__renew` once we know the
|
|
51
51
|
* actual element count.
|
|
52
52
|
*
|
|
@@ -125,7 +125,7 @@ export function deserializeTypedArray_SWAR<T extends ArrayLike<number>>(
|
|
|
125
125
|
// directly: `__renew` the buffer to the actual byte length and
|
|
126
126
|
// update the view's `byteLength` and `dataStart`. AS's TypedArray
|
|
127
127
|
// structure has `buffer`, `dataStart` (= buffer), `byteLength`
|
|
128
|
-
// (capacity in bytes) in that order
|
|
128
|
+
// (capacity in bytes) in that order - same layout as ArrayBufferView.
|
|
129
129
|
const actualCount = i32(<usize>(writePtr - dataStart) / elementSize);
|
|
130
130
|
if (actualCount != maxElements) {
|
|
131
131
|
const actualBytes = <usize>actualCount * elementSize;
|
package/assembly/index.d.ts
CHANGED
|
@@ -1,57 +1,295 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Options for the {@link json} class decorator: `@json({ ... })`.
|
|
3
3
|
*/
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
declare class JSONConfig {
|
|
5
|
+
/**
|
|
6
|
+
* Class-level lazy (on-demand) parsing mode. A lazy field stores its raw JSON
|
|
7
|
+
* slice at parse time and only parses it into the field's type on first
|
|
8
|
+
* access; untouched fields pass their original bytes straight through on
|
|
9
|
+
* serialize.
|
|
10
|
+
*
|
|
11
|
+
* - `"none"` *(default)* - every field is parsed eagerly, up-front.
|
|
12
|
+
* - `"auto"` - the transform defers fields whose estimated parse cost is high
|
|
13
|
+
* (nested structs, arrays, maps, long strings) and keeps cheap fields
|
|
14
|
+
* (primitives, enums, `Date`) eager. Use `@eager` to force a field back to
|
|
15
|
+
* eager, or `@lazy` to force one on.
|
|
16
|
+
* - `"all"` - every field is deferred. Best for proxy / filter / forward
|
|
17
|
+
* workloads over large payloads; note it generates a getter and a serialize
|
|
18
|
+
* branch per field, so module size grows with very wide schemas.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* @json({ lazy: "auto" })
|
|
23
|
+
* class Repo {
|
|
24
|
+
* name: string = ""; // cheap -> stays eager
|
|
25
|
+
* owner: Owner = new Owner; // costly -> deferred
|
|
26
|
+
* @eager id: i32 = 0; // opt back out
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
lazy?: "none" | "auto" | "all";
|
|
31
|
+
}
|
|
6
32
|
|
|
7
33
|
/**
|
|
8
|
-
*
|
|
34
|
+
* Marks a class as serializable, generating the (de)serialization methods the
|
|
35
|
+
* runtime needs. Required on every type passed to `JSON.parse` / `JSON.stringify`
|
|
36
|
+
* (including nested types).
|
|
37
|
+
*
|
|
38
|
+
* @param config - Optional {@link JSONConfig} (currently `{ lazy }`).
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```ts
|
|
42
|
+
* @json
|
|
43
|
+
* class Vec3 {
|
|
44
|
+
* x: f64 = 0;
|
|
45
|
+
* y: f64 = 0;
|
|
46
|
+
* z: f64 = 0;
|
|
47
|
+
* }
|
|
48
|
+
*
|
|
49
|
+
* JSON.stringify(new Vec3()); // '{"x":0.0,"y":0.0,"z":0.0}'
|
|
50
|
+
* JSON.parse<Vec3>('{"x":1,"y":2,"z":3}');
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
declare function json(config?: JSONConfig): Function;
|
|
54
|
+
// @ts-expect-error: type
|
|
55
|
+
declare function json(..._): void;
|
|
56
|
+
/**
|
|
57
|
+
* Alias for {@link json}. `@serializable` and `@json` are interchangeable.
|
|
9
58
|
*/
|
|
10
59
|
// @ts-ignore: type
|
|
11
60
|
declare function serializable(..._): void;
|
|
12
61
|
|
|
13
62
|
/**
|
|
14
|
-
*
|
|
63
|
+
* Field decorator that overrides the JSON key used for a property, decoupling
|
|
64
|
+
* the wire name from the AssemblyScript field name.
|
|
65
|
+
*
|
|
66
|
+
* @param newName - The key to emit and read for this field.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```ts
|
|
70
|
+
* @json
|
|
71
|
+
* class User {
|
|
72
|
+
* @alias("user_id") userId: i32 = 0; // <-> {"user_id": 0}
|
|
73
|
+
* }
|
|
74
|
+
* ```
|
|
15
75
|
*/
|
|
16
76
|
declare function alias(newName: string): Function;
|
|
17
77
|
|
|
18
78
|
/**
|
|
19
|
-
*
|
|
79
|
+
* Field decorator that excludes a property from JSON entirely: it is never
|
|
80
|
+
* serialized and is ignored during parsing.
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```ts
|
|
84
|
+
* @json
|
|
85
|
+
* class Session {
|
|
86
|
+
* token: string = "";
|
|
87
|
+
* @omit secret: string = ""; // never (de)serialized
|
|
88
|
+
* }
|
|
89
|
+
* ```
|
|
20
90
|
*/
|
|
21
91
|
// @ts-ignore: type
|
|
22
92
|
declare function omit(..._): void;
|
|
23
93
|
|
|
24
94
|
/**
|
|
25
|
-
*
|
|
95
|
+
* Field decorator that omits a property from the output when a predicate holds.
|
|
96
|
+
* The field is still parsed normally; the condition only affects serialization.
|
|
97
|
+
*
|
|
98
|
+
* @param condition - A predicate that receives the **instance** and returns
|
|
99
|
+
* `true` to omit the field - `(self: T) => boolean` - or a string expression
|
|
100
|
+
* evaluated in the instance's scope (reference fields via `this`).
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```ts
|
|
104
|
+
* @json
|
|
105
|
+
* class Player {
|
|
106
|
+
* age: i32 = 0;
|
|
107
|
+
* @omitif((self: Player) => self.age < 18) email: string = ""; // arrow form
|
|
108
|
+
* @omitif("this.age < 18") phone: string = ""; // string form
|
|
109
|
+
* }
|
|
110
|
+
* ```
|
|
26
111
|
*/
|
|
27
|
-
declare function omitif(
|
|
28
|
-
condition: string | ((value: any) => boolean),
|
|
29
|
-
): Function;
|
|
112
|
+
declare function omitif(condition: string | ((self: any) => boolean)): Function;
|
|
30
113
|
|
|
31
114
|
/**
|
|
32
|
-
*
|
|
115
|
+
* Field decorator that omits a property from the output when its value is
|
|
116
|
+
* `null`. Shorthand for the common nullable case; the field is still parsed.
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```ts
|
|
120
|
+
* @json
|
|
121
|
+
* class Profile {
|
|
122
|
+
* @omitnull bio: string | null = null; // key absent when null
|
|
123
|
+
* }
|
|
124
|
+
* ```
|
|
33
125
|
*/
|
|
34
126
|
// @ts-ignore: type
|
|
35
|
-
declare function omitnull(..._):
|
|
127
|
+
declare function omitnull(..._): void;
|
|
36
128
|
|
|
37
129
|
/**
|
|
38
|
-
*
|
|
130
|
+
* Field decorator that marks a property as optional for deserialization: the
|
|
131
|
+
* key may be absent from (or appear anywhere in) the input, and the field keeps
|
|
132
|
+
* its default. Unlike `@omitnull`/`@omitif` it does NOT omit the field on
|
|
133
|
+
* serialize and has no nullability requirement - it only opts the field into
|
|
134
|
+
* the order-tolerant fast path.
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```ts
|
|
138
|
+
* @json
|
|
139
|
+
* class Tweet {
|
|
140
|
+
* @optional retweeted_status: Retweet | null = null; // key may be absent
|
|
141
|
+
* }
|
|
142
|
+
* ```
|
|
39
143
|
*/
|
|
40
144
|
// @ts-ignore: type
|
|
41
|
-
declare function
|
|
145
|
+
declare function optional(..._): void;
|
|
42
146
|
|
|
43
147
|
/**
|
|
44
|
-
*
|
|
148
|
+
* Field decorator that defers parsing of a property until it is first read
|
|
149
|
+
* (on-demand / lazy parsing). The raw JSON slice is stored at parse time and
|
|
150
|
+
* materialized into the field's type on first access, then cached; an untouched
|
|
151
|
+
* field round-trips by copying its original bytes - never re-parsed or
|
|
152
|
+
* re-serialized.
|
|
153
|
+
*
|
|
154
|
+
* Equivalent to the `JSON.Lazy<T>` type-wrapper form. Pays off for fields you
|
|
155
|
+
* usually skip or forward; reading a deferred field is a one-time cost.
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* ```ts
|
|
159
|
+
* @json
|
|
160
|
+
* class Repo {
|
|
161
|
+
* name: string = ""; // eager
|
|
162
|
+
* @lazy owner: Owner = new Owner; // parsed only when `repo.owner` is read
|
|
163
|
+
* }
|
|
164
|
+
* ```
|
|
45
165
|
*/
|
|
46
166
|
// @ts-ignore: type
|
|
47
|
-
declare function
|
|
167
|
+
declare function lazy(..._): void;
|
|
48
168
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
169
|
+
/**
|
|
170
|
+
* Field decorator that forces a property to be parsed eagerly, opting it out of
|
|
171
|
+
* class-level lazy deferral (`@json({ lazy: "auto" | "all" })`). No effect on a
|
|
172
|
+
* class that is not lazy.
|
|
173
|
+
*
|
|
174
|
+
* @example
|
|
175
|
+
* ```ts
|
|
176
|
+
* @json({ lazy: "all" })
|
|
177
|
+
* class Event {
|
|
178
|
+
* @eager id: i32 = 0; // always parsed up-front
|
|
179
|
+
* payload: Payload = new Payload; // deferred
|
|
180
|
+
* }
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
183
|
+
// @ts-ignore: type
|
|
184
|
+
declare function eager(..._): void;
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Method decorator marking a member as the class's custom serializer, replacing
|
|
188
|
+
* the generated serialization. The method receives the instance and must return
|
|
189
|
+
* a **valid JSON string**. Pair with {@link deserializer}.
|
|
190
|
+
*
|
|
191
|
+
* @param shape - Optional JSON value shape the output conforms to - one of
|
|
192
|
+
* `"any"` (default), `"string"`, `"number"`, `"object"`, `"array"`,
|
|
193
|
+
* `"boolean"`, or `"null"`.
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* ```ts
|
|
197
|
+
* @json
|
|
198
|
+
* class Point {
|
|
199
|
+
* x: f64 = 0;
|
|
200
|
+
* y: f64 = 0;
|
|
201
|
+
* constructor(x: f64, y: f64) {
|
|
202
|
+
* this.x = x;
|
|
203
|
+
* this.y = y;
|
|
204
|
+
* }
|
|
205
|
+
*
|
|
206
|
+
* // Serialize a Point to a single JSON string.
|
|
207
|
+
* @serializer("string")
|
|
208
|
+
* serializer(self: Point): string {
|
|
209
|
+
* return JSON.stringify(`${self.x},${self.y}`);
|
|
210
|
+
* }
|
|
211
|
+
*
|
|
212
|
+
* // ...and back. Always return a fresh instance.
|
|
213
|
+
* @deserializer("string")
|
|
214
|
+
* deserializer(data: string): Point {
|
|
215
|
+
* const raw = JSON.parse<string>(data);
|
|
216
|
+
* const c = raw.indexOf(",");
|
|
217
|
+
* return new Point(f64.parse(raw.slice(0, c)), f64.parse(raw.slice(c + 1)));
|
|
218
|
+
* }
|
|
219
|
+
* }
|
|
220
|
+
*
|
|
221
|
+
* JSON.stringify(new Point(3.5, -9.2)); // '"3.5,-9.2"'
|
|
222
|
+
* JSON.parse<Point>('"3.5,-9.2"'); // Point { x: 3.5, y: -9.2 }
|
|
223
|
+
* ```
|
|
224
|
+
*/
|
|
225
|
+
// @ts-ignore: type
|
|
226
|
+
declare function serializer(
|
|
227
|
+
shape?: "any" | "string" | "number" | "object" | "array" | "boolean" | "null",
|
|
228
|
+
): any;
|
|
54
229
|
|
|
230
|
+
/**
|
|
231
|
+
* Method decorator marking a member as the class's custom deserializer,
|
|
232
|
+
* replacing the generated deserialization. The method receives the raw JSON
|
|
233
|
+
* string and must return a **new** instance - never assume an existing
|
|
234
|
+
* destination is reused. Pair with {@link serializer} (see it for a full,
|
|
235
|
+
* round-tripping example).
|
|
236
|
+
*
|
|
237
|
+
* @param shape - Optional JSON value shape the input conforms to - one of
|
|
238
|
+
* `"any"` (default), `"string"`, `"number"`, `"object"`, `"array"`,
|
|
239
|
+
* `"boolean"`, or `"null"`.
|
|
240
|
+
*
|
|
241
|
+
* @example
|
|
242
|
+
* ```ts
|
|
243
|
+
* @deserializer("string")
|
|
244
|
+
* deserializer(data: string): Point {
|
|
245
|
+
* const raw = JSON.parse<string>(data); // unwrap the JSON string
|
|
246
|
+
* const c = raw.indexOf(",");
|
|
247
|
+
* return new Point(f64.parse(raw.slice(0, c)), f64.parse(raw.slice(c + 1)));
|
|
248
|
+
* }
|
|
249
|
+
* ```
|
|
250
|
+
*/
|
|
251
|
+
// @ts-ignore: type
|
|
252
|
+
declare function deserializer(
|
|
253
|
+
shape?: "any" | "string" | "number" | "object" | "array" | "boolean" | "null",
|
|
254
|
+
): any;
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* The active {@link JSONMode}, injected by the transform from the `JSON_MODE`
|
|
258
|
+
* build-time environment variable (default `SWAR`). Set it on the `asc`
|
|
259
|
+
* command/build env; `SIMD` additionally requires `--enable simd`.
|
|
260
|
+
*
|
|
261
|
+
* @example
|
|
262
|
+
* ```sh
|
|
263
|
+
* JSON_MODE=SIMD asc app.ts --transform json-as/transform --enable simd
|
|
264
|
+
* JSON_MODE=SWAR asc app.ts --transform json-as/transform # default
|
|
265
|
+
* JSON_MODE=NAIVE asc app.ts --transform json-as/transform
|
|
266
|
+
* ```
|
|
267
|
+
*/
|
|
55
268
|
declare const JSON_MODE: JSONMode;
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Whether the string cache is enabled (default off). Injected from the
|
|
272
|
+
* `JSON_CACHE` build-time environment variable. When on, repeated strings are
|
|
273
|
+
* reused to speed up string-heavy serialization.
|
|
274
|
+
*
|
|
275
|
+
* @example
|
|
276
|
+
* ```sh
|
|
277
|
+
* JSON_CACHE=true asc app.ts --transform json-as/transform # default size
|
|
278
|
+
* JSON_CACHE=512kb asc app.ts --transform json-as/transform # enable + size
|
|
279
|
+
* JSON_CACHE=false asc app.ts --transform json-as/transform # off (default)
|
|
280
|
+
* ```
|
|
281
|
+
*/
|
|
56
282
|
declare const JSON_CACHE: bool;
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* The string-cache size in bytes when {@link JSON_CACHE} is enabled. Both this
|
|
286
|
+
* and {@link JSON_CACHE} are derived from the single `JSON_CACHE` build-time
|
|
287
|
+
* environment variable, which accepts raw bytes (`JSON_CACHE=1048576`), bit
|
|
288
|
+
* units (`512kb`, `2mb`, `1gb`), or byte units (`64KB`, `2MB`, `1GB`).
|
|
289
|
+
*
|
|
290
|
+
* @example
|
|
291
|
+
* ```sh
|
|
292
|
+
* JSON_CACHE=1mb asc app.ts --transform json-as/transform # JSON_CACHE_SIZE == 1048576
|
|
293
|
+
* ```
|
|
294
|
+
*/
|
|
57
295
|
declare const JSON_CACHE_SIZE: usize;
|