json-as 1.3.6 → 1.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +45 -0
- package/README.md +1 -1
- package/assembly/deserialize/helpers/uint.ts +4 -1
- package/assembly/deserialize/index/arbitrary.ts +7 -3
- package/assembly/deserialize/index/array.ts +42 -17
- package/assembly/deserialize/index/bool.ts +1 -1
- package/assembly/deserialize/index/date.ts +1 -1
- package/assembly/deserialize/index/float.ts +40 -1
- package/assembly/deserialize/index/integer.ts +68 -1
- package/assembly/deserialize/index/map.ts +1 -1
- package/assembly/deserialize/index/object.ts +1 -1
- package/assembly/deserialize/index/raw.ts +1 -1
- package/assembly/deserialize/index/set.ts +1 -1
- package/assembly/deserialize/index/staticarray.ts +4 -1
- package/assembly/deserialize/index/string.ts +32 -4
- package/assembly/deserialize/index/struct.ts +1 -1
- package/assembly/deserialize/index/typedarray.ts +30 -10
- package/assembly/deserialize/index/unsigned.ts +78 -1
- package/assembly/deserialize/index.ts +1 -0
- package/assembly/deserialize/{simple → naive}/array/arbitrary.ts +24 -5
- package/assembly/deserialize/{simple → naive}/array/array.ts +8 -2
- package/assembly/deserialize/naive/array/bool.ts +68 -0
- package/assembly/deserialize/{simple → naive}/array/box.ts +8 -2
- package/assembly/deserialize/naive/array/float.ts +63 -0
- package/assembly/deserialize/{simple → naive}/array/generic.ts +14 -7
- package/assembly/deserialize/naive/array/integer.ts +86 -0
- package/assembly/deserialize/naive/array/map.ts +47 -0
- package/assembly/deserialize/naive/array/object.ts +47 -0
- package/assembly/deserialize/{simple → naive}/array/raw.ts +34 -7
- package/assembly/deserialize/naive/array/string.ts +69 -0
- package/assembly/deserialize/naive/array/struct.ts +47 -0
- package/assembly/deserialize/{simple → naive}/array.ts +15 -10
- package/assembly/deserialize/{simple → naive}/bool.ts +6 -2
- package/assembly/deserialize/naive/float.ts +135 -0
- package/assembly/deserialize/{simple → naive}/integer.ts +10 -2
- package/assembly/deserialize/{simple → naive}/map.ts +106 -27
- package/assembly/deserialize/{simple → naive}/object.ts +65 -19
- package/assembly/deserialize/{simple → naive}/raw.ts +4 -1
- package/assembly/deserialize/{simple → naive}/set.ts +49 -19
- package/assembly/deserialize/{simple → naive}/staticarray/array.ts +1 -1
- package/assembly/deserialize/{simple → naive}/staticarray/bool.ts +1 -1
- package/assembly/deserialize/{simple → naive}/staticarray/float.ts +1 -1
- package/assembly/deserialize/{simple → naive}/staticarray/integer.ts +1 -1
- package/assembly/deserialize/{simple → naive}/staticarray/string.ts +11 -3
- package/assembly/deserialize/{simple → naive}/staticarray/struct.ts +1 -2
- package/assembly/deserialize/{simple → naive}/staticarray.ts +68 -18
- package/assembly/deserialize/naive/string.ts +199 -0
- package/assembly/deserialize/{simple → naive}/struct.ts +5 -1
- package/assembly/deserialize/{simple → naive}/typedarray.ts +17 -4
- package/assembly/deserialize/{simple → naive}/unsigned.ts +10 -15
- package/assembly/deserialize/simd/array/integer.ts +339 -62
- package/assembly/deserialize/simd/float.ts +303 -0
- package/assembly/deserialize/simd/integer.ts +233 -0
- package/assembly/deserialize/simd/string.ts +266 -107
- package/assembly/deserialize/swar/array/arbitrary.ts +11 -3
- package/assembly/deserialize/swar/array/array.ts +40 -9
- package/assembly/deserialize/swar/array/bool.ts +28 -5
- package/assembly/deserialize/swar/array/box.ts +11 -3
- package/assembly/deserialize/swar/array/float.ts +295 -7
- package/assembly/deserialize/swar/array/generic.ts +28 -7
- package/assembly/deserialize/swar/array/integer.ts +363 -112
- package/assembly/deserialize/swar/array/map.ts +11 -3
- package/assembly/deserialize/swar/array/object.ts +37 -25
- package/assembly/deserialize/swar/array/raw.ts +11 -3
- package/assembly/deserialize/swar/array/shared.ts +63 -14
- package/assembly/deserialize/swar/array/string.ts +140 -7
- package/assembly/deserialize/swar/array/struct.ts +66 -12
- package/assembly/deserialize/swar/array.ts +12 -51
- package/assembly/deserialize/swar/float.ts +304 -0
- package/assembly/deserialize/swar/integer.ts +246 -0
- package/assembly/deserialize/swar/string.ts +213 -294
- package/assembly/deserialize/swar/typedarray.ts +224 -0
- package/assembly/index.d.ts +3 -1
- package/assembly/index.ts +402 -261
- package/assembly/serialize/index/array.ts +1 -1
- package/assembly/serialize/index/bool.ts +1 -1
- package/assembly/serialize/index/date.ts +1 -1
- package/assembly/serialize/index/float.ts +5 -1
- package/assembly/serialize/index/integer.ts +1 -1
- package/assembly/serialize/index/map.ts +1 -1
- package/assembly/serialize/index/raw.ts +1 -1
- package/assembly/serialize/index/set.ts +1 -1
- package/assembly/serialize/index/staticarray.ts +1 -1
- package/assembly/serialize/index/string.ts +1 -1
- package/assembly/serialize/index/struct.ts +1 -1
- package/assembly/serialize/index/typedarray.ts +21 -12
- package/assembly/serialize/index.ts +1 -0
- package/assembly/serialize/naive/array.ts +351 -0
- package/assembly/serialize/{simple → naive}/float.ts +4 -1
- package/assembly/serialize/naive/integer.ts +19 -0
- package/assembly/serialize/{simple → naive}/map.ts +6 -2
- package/assembly/serialize/{simple → naive}/raw.ts +5 -1
- package/assembly/serialize/{simple → naive}/set.ts +6 -1
- package/assembly/serialize/{simple → naive}/staticarray.ts +6 -1
- package/assembly/serialize/{simple → naive}/string.ts +1 -2
- package/assembly/serialize/{simple → naive}/typedarray.ts +10 -3
- package/assembly/serialize/simd/string.ts +6 -2
- package/assembly/serialize/swar/string.ts +15 -141
- package/assembly/util/atoi-fast.ts +81 -0
- package/assembly/util/concat.ts +5 -1
- package/assembly/util/dragonbox-cache.ts +443 -2
- package/assembly/util/dragonbox.ts +53 -17
- package/assembly/util/itoa-fast.ts +241 -0
- package/assembly/util/masks.ts +18 -1
- package/assembly/util/parsefloat-fast.ts +167 -0
- package/assembly/util/scanValueEnd.ts +78 -0
- package/assembly/util/scientific.ts +132 -0
- package/assembly/util/simd-int.ts +191 -0
- package/assembly/util/snp.ts +4 -1
- package/assembly/util/swar-int.ts +248 -0
- package/assembly/util/swar.ts +13 -3
- package/lib/as-bs.ts +27 -6
- package/package.json +15 -11
- package/transform/lib/builder.d.ts.map +1 -1
- package/transform/lib/builder.js +13 -5
- package/transform/lib/builder.js.map +1 -1
- package/transform/lib/index.d.ts +5 -0
- package/transform/lib/index.d.ts.map +1 -1
- package/transform/lib/index.js +1046 -340
- package/transform/lib/index.js.map +1 -1
- package/transform/lib/linkers/alias.d.ts.map +1 -1
- package/transform/lib/linkers/alias.js.map +1 -1
- package/transform/lib/linkers/custom.d.ts.map +1 -1
- package/transform/lib/linkers/custom.js +3 -2
- package/transform/lib/linkers/custom.js.map +1 -1
- package/transform/lib/linkers/imports.d.ts.map +1 -1
- package/transform/lib/linkers/imports.js.map +1 -1
- package/transform/lib/types.d.ts.map +1 -1
- package/transform/lib/types.js +54 -16
- package/transform/lib/types.js.map +1 -1
- package/transform/lib/util.d.ts.map +1 -1
- package/transform/lib/util.js +1 -1
- package/transform/lib/util.js.map +1 -1
- package/transform/lib/visitor.d.ts.map +1 -1
- package/transform/lib/visitor.js +2 -1
- package/transform/lib/visitor.js.map +1 -1
- package/assembly/custom/util.ts +0 -310
- package/assembly/deserialize/simple/arbitrary.ts +0 -23
- package/assembly/deserialize/simple/array/bool.ts +0 -17
- package/assembly/deserialize/simple/array/float.ts +0 -28
- package/assembly/deserialize/simple/array/integer.ts +0 -27
- package/assembly/deserialize/simple/array/map.ts +0 -28
- package/assembly/deserialize/simple/array/object.ts +0 -28
- package/assembly/deserialize/simple/array/string.ts +0 -23
- package/assembly/deserialize/simple/array/struct.ts +0 -28
- package/assembly/deserialize/simple/float.ts +0 -201
- package/assembly/deserialize/simple/string.ts +0 -132
- package/assembly/serialize/simple/arbitrary.ts +0 -79
- package/assembly/serialize/simple/array.ts +0 -86
- package/assembly/serialize/simple/integer.ts +0 -20
- package/assembly/serialize/simple/object.ts +0 -42
- /package/assembly/deserialize/{simple → naive}/date.ts +0 -0
- /package/assembly/serialize/{simple → naive}/bool.ts +0 -0
- /package/assembly/serialize/{simple → naive}/date.ts +0 -0
- /package/assembly/serialize/{simple → naive}/struct.ts +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
export { serializeArray } from "../
|
|
1
|
+
export { serializeArray } from "../naive/array";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { serializeBool } from "../
|
|
1
|
+
export { serializeBool } from "../naive/bool";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { serializeDate } from "../
|
|
1
|
+
export { serializeDate } from "../naive/date";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { serializeInteger } from "../
|
|
1
|
+
export { serializeInteger } from "../naive/integer";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { serializeMap } from "../
|
|
1
|
+
export { serializeMap } from "../naive/map";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { serializeRaw } from "../
|
|
1
|
+
export { serializeRaw } from "../naive/raw";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { serializeSet } from "../
|
|
1
|
+
export { serializeSet } from "../naive/set";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { serializeStaticArray } from "../
|
|
1
|
+
export { serializeStaticArray } from "../naive/staticarray";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { JSONMode } from "../..";
|
|
2
|
-
import {
|
|
2
|
+
import { serializeString_NAIVE } from "../naive/string";
|
|
3
3
|
import { serializeString_SIMD } from "../simd/string";
|
|
4
4
|
import { serializeString_SWAR } from "../swar/string";
|
|
5
5
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { serializeStruct } from "../
|
|
1
|
+
export { serializeStruct } from "../naive/struct";
|
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
import { OBJECT, TOTAL_OVERHEAD } from "rt/common";
|
|
2
2
|
import { JSON } from "../..";
|
|
3
|
-
export {
|
|
4
|
-
|
|
3
|
+
export {
|
|
4
|
+
serializeArrayBufferUnsafe,
|
|
5
|
+
serializeTypedArray,
|
|
6
|
+
} from "../naive/typedarray";
|
|
7
|
+
import {
|
|
8
|
+
serializeArrayBufferUnsafe,
|
|
9
|
+
serializeTypedArray,
|
|
10
|
+
} from "../naive/typedarray";
|
|
5
11
|
|
|
6
12
|
|
|
7
13
|
@inline export function serializeDynamic(type: u16, data: usize): void {
|
|
8
14
|
if (type == JSON.Types.ArrayBuffer) {
|
|
9
|
-
serializeArrayBufferUnsafe(
|
|
15
|
+
serializeArrayBufferUnsafe(
|
|
16
|
+
data,
|
|
17
|
+
changetype<OBJECT>(data - TOTAL_OVERHEAD).rtSize,
|
|
18
|
+
);
|
|
10
19
|
} else if (type == JSON.Types.TypedArray) {
|
|
11
20
|
const id = changetype<OBJECT>(data - TOTAL_OVERHEAD).rtId;
|
|
12
21
|
if (id == idof<Int8Array>()) {
|
|
@@ -14,7 +23,9 @@ import { serializeArrayBufferUnsafe, serializeTypedArray } from "../simple/typed
|
|
|
14
23
|
} else if (id == idof<Uint8Array>()) {
|
|
15
24
|
serializeTypedArray<Uint8Array>(changetype<Uint8Array>(data));
|
|
16
25
|
} else if (id == idof<Uint8ClampedArray>()) {
|
|
17
|
-
serializeTypedArray<Uint8ClampedArray>(
|
|
26
|
+
serializeTypedArray<Uint8ClampedArray>(
|
|
27
|
+
changetype<Uint8ClampedArray>(data),
|
|
28
|
+
);
|
|
18
29
|
} else if (id == idof<Int16Array>()) {
|
|
19
30
|
serializeTypedArray<Int16Array>(changetype<Int16Array>(data));
|
|
20
31
|
} else if (id == idof<Uint16Array>()) {
|
|
@@ -35,8 +46,12 @@ import { serializeArrayBufferUnsafe, serializeTypedArray } from "../simple/typed
|
|
|
35
46
|
serializeTypedArray<Int8Array>(changetype<Int8Array>(data));
|
|
36
47
|
} else if (changetype<Uint8Array>(data) instanceof Uint8Array) {
|
|
37
48
|
serializeTypedArray<Uint8Array>(changetype<Uint8Array>(data));
|
|
38
|
-
} else if (
|
|
39
|
-
|
|
49
|
+
} else if (
|
|
50
|
+
changetype<Uint8ClampedArray>(data) instanceof Uint8ClampedArray
|
|
51
|
+
) {
|
|
52
|
+
serializeTypedArray<Uint8ClampedArray>(
|
|
53
|
+
changetype<Uint8ClampedArray>(data),
|
|
54
|
+
);
|
|
40
55
|
} else if (changetype<Int16Array>(data) instanceof Int16Array) {
|
|
41
56
|
serializeTypedArray<Int16Array>(changetype<Int16Array>(data));
|
|
42
57
|
} else if (changetype<Uint16Array>(data) instanceof Uint16Array) {
|
|
@@ -58,9 +73,3 @@ import { serializeArrayBufferUnsafe, serializeTypedArray } from "../simple/typed
|
|
|
58
73
|
}
|
|
59
74
|
}
|
|
60
75
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
@inline export function serializeArrayBuffer(data: ArrayBuffer): void {
|
|
64
|
-
const dataStart = changetype<usize>(data);
|
|
65
|
-
serializeArrayBufferUnsafe(dataStart, changetype<OBJECT>(dataStart - TOTAL_OVERHEAD).rtSize);
|
|
66
|
-
}
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
import { bs } from "../../../lib/as-bs";
|
|
2
|
+
import { COMMA, BRACKET_RIGHT, BRACKET_LEFT } from "../../custom/chars";
|
|
3
|
+
import { JSON } from "../..";
|
|
4
|
+
import { serializeBoolUnsafe } from "./bool";
|
|
5
|
+
import { serializeFloat32Unsafe, serializeFloat64Unsafe } from "./float";
|
|
6
|
+
import { serializeIntegerUnsafe } from "./integer";
|
|
7
|
+
import { serializeString } from "../index/string";
|
|
8
|
+
import {
|
|
9
|
+
dragonbox_f32_buffered,
|
|
10
|
+
dragonbox_f64_buffered,
|
|
11
|
+
} from "../../util/dragonbox";
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@inline
|
|
15
|
+
function maxIntegerBytes<T extends number>(): u32 {
|
|
16
|
+
if (sizeof<T>() == 1) return isSigned<T>() ? 8 : 6;
|
|
17
|
+
if (sizeof<T>() == 2) return isSigned<T>() ? 12 : 10;
|
|
18
|
+
if (sizeof<T>() == 4) return isSigned<T>() ? 22 : 20;
|
|
19
|
+
return isSigned<T>() ? 42 : 40;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@inline
|
|
24
|
+
function reservePrimitiveArray<T>(len: i32): void {
|
|
25
|
+
if (len <= 0) return;
|
|
26
|
+
if (isBoolean<T>()) {
|
|
27
|
+
bs.proposeSize(4 + <u32>len * 12);
|
|
28
|
+
} else if (isInteger<T>()) {
|
|
29
|
+
bs.proposeSize(4 + <u32>len * (maxIntegerBytes<T>() + 2));
|
|
30
|
+
} else if (isFloat<T>()) {
|
|
31
|
+
bs.proposeSize(4 + <u32>len * (sizeof<T>() == 4 ? 34 : 66));
|
|
32
|
+
} else {
|
|
33
|
+
bs.proposeSize(4 + <u32>(len - 1) * 2);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@inline
|
|
39
|
+
function serializeArrayElement<T>(value: T): void {
|
|
40
|
+
if (isString<T>()) {
|
|
41
|
+
serializeString(value as string);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (isBoolean<T>()) {
|
|
45
|
+
serializeBoolUnsafe(<bool>value);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (isInteger<T>()) {
|
|
49
|
+
serializeIntegerUnsafe<T>(value);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (isFloat<T>()) {
|
|
53
|
+
if (sizeof<T>() == 4) serializeFloat32Unsafe(<f32>value);
|
|
54
|
+
else serializeFloat64Unsafe(<f64>value);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (isManaged<T>() || isReference<T>()) {
|
|
58
|
+
// Preserve runtime custom serializers for subclass instances stored in
|
|
59
|
+
// parent-typed arrays before falling back to the static dispatcher.
|
|
60
|
+
// @ts-ignore: transform-defined at runtime when present
|
|
61
|
+
if (isDefined(value.__SERIALIZE_CUSTOM)) {
|
|
62
|
+
// @ts-ignore: transform-defined at runtime when present
|
|
63
|
+
value.__SERIALIZE_CUSTOM();
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
JSON.__serialize<T>(value);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
// Specialized fast paths
|
|
72
|
+
// ---------------------------------------------------------------------------
|
|
73
|
+
//
|
|
74
|
+
// `bool[]` and `u8[]` / `i8[]` serializers fold the element write and the
|
|
75
|
+
// trailing comma into a single per-element store. The outer dispatcher
|
|
76
|
+
// emits `[` once, the loop emits `VALUE,` once per element, and the closing
|
|
77
|
+
// `]` overwrites the trailing comma. This eliminates the separate
|
|
78
|
+
// comma-store + advance per element that the generic `serializeArray` does.
|
|
79
|
+
|
|
80
|
+
// `"true,"` packed UTF-16: `t,r,u,e,,` lanes 0..4 = bytes 0..9.
|
|
81
|
+
@inline const TRUE_COMMA_LO: u64 = 0x0065_0075_0072_0074;
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@inline const TRUE_COMMA_HI: u16 = 0x002c;
|
|
85
|
+
// `"false,"` packed UTF-16: `f,a,l,s,e,,` lanes 0..5 = bytes 0..11.
|
|
86
|
+
@inline const FALSE_COMMA_LO: u64 = 0x0073_006c_0061_0066;
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@inline const FALSE_COMMA_HI: u32 = 0x002c_0065;
|
|
90
|
+
|
|
91
|
+
function serializeBoolArrayFast(src: bool[]): void {
|
|
92
|
+
const len = src.length;
|
|
93
|
+
// Worst case: every element is `"false,"` = 12 bytes; plus 4 for `[]`.
|
|
94
|
+
bs.proposeSize(4 + <u32>len * 12);
|
|
95
|
+
store<u16>(bs.offset, BRACKET_LEFT);
|
|
96
|
+
bs.offset += 2;
|
|
97
|
+
if (len == 0) {
|
|
98
|
+
store<u16>(bs.offset, BRACKET_RIGHT);
|
|
99
|
+
bs.offset += 2;
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const dataStart = src.dataStart;
|
|
104
|
+
for (let i: i32 = 0; i < len; i++) {
|
|
105
|
+
if (load<bool>(dataStart + <usize>i)) {
|
|
106
|
+
store<u64>(bs.offset, TRUE_COMMA_LO);
|
|
107
|
+
store<u16>(bs.offset, TRUE_COMMA_HI, 8);
|
|
108
|
+
bs.offset += 10;
|
|
109
|
+
} else {
|
|
110
|
+
store<u64>(bs.offset, FALSE_COMMA_LO);
|
|
111
|
+
store<u32>(bs.offset, FALSE_COMMA_HI, 8);
|
|
112
|
+
bs.offset += 12;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// Overwrite the final trailing comma with `]`.
|
|
116
|
+
store<u16>(bs.offset - 2, BRACKET_RIGHT);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// 256-entry table mapping `u8` value -> UTF-16 chars of `"DDD,"` packed in a
|
|
120
|
+
// u64. Unused lanes hold garbage that the next element's store overwrites.
|
|
121
|
+
const U8_SERIALIZE_LUT: usize = memory.data(2048); // 256 * sizeof<u64>
|
|
122
|
+
// 256-entry table mapping `u8` value -> byte count of the packed encoding.
|
|
123
|
+
const U8_SERIALIZE_LEN_LUT: usize = memory.data(256);
|
|
124
|
+
let _u8LutInited: bool = false;
|
|
125
|
+
|
|
126
|
+
function initU8Lut(): void {
|
|
127
|
+
for (let i: i32 = 0; i < 256; i++) {
|
|
128
|
+
let chars: u64;
|
|
129
|
+
let bytes: u8;
|
|
130
|
+
if (i < 10) {
|
|
131
|
+
chars = u64(0x30 + i) | (u64(0x2c) << 16);
|
|
132
|
+
bytes = 4;
|
|
133
|
+
} else if (i < 100) {
|
|
134
|
+
const d0 = i / 10;
|
|
135
|
+
const d1 = i % 10;
|
|
136
|
+
chars = u64(0x30 + d0) | (u64(0x30 + d1) << 16) | (u64(0x2c) << 32);
|
|
137
|
+
bytes = 6;
|
|
138
|
+
} else {
|
|
139
|
+
const d0 = i / 100;
|
|
140
|
+
const d1 = (i / 10) % 10;
|
|
141
|
+
const d2 = i % 10;
|
|
142
|
+
chars =
|
|
143
|
+
u64(0x30 + d0) |
|
|
144
|
+
(u64(0x30 + d1) << 16) |
|
|
145
|
+
(u64(0x30 + d2) << 32) |
|
|
146
|
+
(u64(0x2c) << 48);
|
|
147
|
+
bytes = 8;
|
|
148
|
+
}
|
|
149
|
+
store<u64>(U8_SERIALIZE_LUT + ((<usize>i) << 3), chars);
|
|
150
|
+
store<u8>(U8_SERIALIZE_LEN_LUT + <usize>i, bytes);
|
|
151
|
+
}
|
|
152
|
+
_u8LutInited = true;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
@inline function ensureU8Lut(): void {
|
|
157
|
+
if (!_u8LutInited) initU8Lut();
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function serializeU8ArrayFast(src: u8[]): void {
|
|
161
|
+
const len = src.length;
|
|
162
|
+
// Worst case: every element is 3 digits + comma = 8 bytes; plus 4 for `[]`.
|
|
163
|
+
bs.proposeSize(4 + <u32>len * 8);
|
|
164
|
+
store<u16>(bs.offset, BRACKET_LEFT);
|
|
165
|
+
bs.offset += 2;
|
|
166
|
+
if (len == 0) {
|
|
167
|
+
store<u16>(bs.offset, BRACKET_RIGHT);
|
|
168
|
+
bs.offset += 2;
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
ensureU8Lut();
|
|
172
|
+
|
|
173
|
+
const dataStart = src.dataStart;
|
|
174
|
+
for (let i: i32 = 0; i < len; i++) {
|
|
175
|
+
const v = <usize>load<u8>(dataStart + <usize>i);
|
|
176
|
+
const chars = load<u64>(U8_SERIALIZE_LUT + (v << 3));
|
|
177
|
+
const byteCount = <usize>load<u8>(U8_SERIALIZE_LEN_LUT + v);
|
|
178
|
+
store<u64>(bs.offset, chars);
|
|
179
|
+
bs.offset += byteCount;
|
|
180
|
+
}
|
|
181
|
+
store<u16>(bs.offset - 2, BRACKET_RIGHT);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Specialized float-array serializer: dragonbox + trailing comma in a
|
|
185
|
+
// uniform per-iteration body, then overwrite the final comma with `]`. The
|
|
186
|
+
// generic dispatcher splits the loop into "N-1 elements with comma, then
|
|
187
|
+
// last element without, then `]`" — the branch on each `i < end` check
|
|
188
|
+
// stalls the loop's tight bs.offset advance pattern. This variant runs the
|
|
189
|
+
// same number of stores per iteration (dragonbox output + COMMA), but the
|
|
190
|
+
// uniform loop body inlines better and the trailing `]` is a single fixed
|
|
191
|
+
// overwrite outside the loop.
|
|
192
|
+
function serializeF64ArrayFast(src: f64[]): void {
|
|
193
|
+
const len = src.length;
|
|
194
|
+
// Worst case per element: ~24 chars for f64 + comma = 50 bytes.
|
|
195
|
+
// Slight over-reserve (66) matches the existing `reservePrimitiveArray`
|
|
196
|
+
// budget and keeps a safety margin for any NaN/Inf spelling.
|
|
197
|
+
bs.proposeSize(4 + <u32>len * 66);
|
|
198
|
+
store<u16>(bs.offset, BRACKET_LEFT);
|
|
199
|
+
bs.offset += 2;
|
|
200
|
+
if (len == 0) {
|
|
201
|
+
store<u16>(bs.offset, BRACKET_RIGHT);
|
|
202
|
+
bs.offset += 2;
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Hoist `bs.offset` into a local so the loop body has a single
|
|
207
|
+
// monotonically-advancing pointer instead of two reads + two writes back
|
|
208
|
+
// to the global per iteration.
|
|
209
|
+
const dataStart = src.dataStart;
|
|
210
|
+
let offset = bs.offset;
|
|
211
|
+
for (let i: i32 = 0; i < len; i++) {
|
|
212
|
+
const v = load<f64>(dataStart + ((<usize>i) << 3));
|
|
213
|
+
const size = dragonbox_f64_buffered(offset, v) << 1;
|
|
214
|
+
store<u16>(offset + size, COMMA);
|
|
215
|
+
offset += size + 2;
|
|
216
|
+
}
|
|
217
|
+
// Overwrite the final trailing comma with `]`.
|
|
218
|
+
store<u16>(offset - 2, BRACKET_RIGHT);
|
|
219
|
+
bs.offset = offset;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function serializeF32ArrayFast(src: f32[]): void {
|
|
223
|
+
const len = src.length;
|
|
224
|
+
// Worst case for f32 is ~16 chars + comma = ~34 bytes; mirror the budget
|
|
225
|
+
// used by `reservePrimitiveArray`.
|
|
226
|
+
bs.proposeSize(4 + <u32>len * 34);
|
|
227
|
+
store<u16>(bs.offset, BRACKET_LEFT);
|
|
228
|
+
bs.offset += 2;
|
|
229
|
+
if (len == 0) {
|
|
230
|
+
store<u16>(bs.offset, BRACKET_RIGHT);
|
|
231
|
+
bs.offset += 2;
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const dataStart = src.dataStart;
|
|
236
|
+
let offset = bs.offset;
|
|
237
|
+
for (let i: i32 = 0; i < len; i++) {
|
|
238
|
+
const v = load<f32>(dataStart + ((<usize>i) << 2));
|
|
239
|
+
const size = dragonbox_f32_buffered(offset, v) << 1;
|
|
240
|
+
store<u16>(offset + size, COMMA);
|
|
241
|
+
offset += size + 2;
|
|
242
|
+
}
|
|
243
|
+
store<u16>(offset - 2, BRACKET_RIGHT);
|
|
244
|
+
bs.offset = offset;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function serializeI8ArrayFast(src: i8[]): void {
|
|
248
|
+
const len = src.length;
|
|
249
|
+
// Worst case: every element is `-DDD,` = 5 chars = 10 bytes; plus 4 for `[]`.
|
|
250
|
+
bs.proposeSize(4 + <u32>len * 10);
|
|
251
|
+
store<u16>(bs.offset, BRACKET_LEFT);
|
|
252
|
+
bs.offset += 2;
|
|
253
|
+
if (len == 0) {
|
|
254
|
+
store<u16>(bs.offset, BRACKET_RIGHT);
|
|
255
|
+
bs.offset += 2;
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
ensureU8Lut();
|
|
259
|
+
|
|
260
|
+
const dataStart = src.dataStart;
|
|
261
|
+
for (let i: i32 = 0; i < len; i++) {
|
|
262
|
+
let signed = load<i8>(dataStart + <usize>i);
|
|
263
|
+
let absVal: u32;
|
|
264
|
+
if (signed < 0) {
|
|
265
|
+
store<u16>(bs.offset, 0x2d); // '-'
|
|
266
|
+
bs.offset += 2;
|
|
267
|
+
absVal = <u32>-(<i32>signed);
|
|
268
|
+
} else {
|
|
269
|
+
absVal = <u32>signed;
|
|
270
|
+
}
|
|
271
|
+
const chars = load<u64>(U8_SERIALIZE_LUT + ((<usize>absVal) << 3));
|
|
272
|
+
const byteCount = <usize>load<u8>(U8_SERIALIZE_LEN_LUT + <usize>absVal);
|
|
273
|
+
store<u64>(bs.offset, chars);
|
|
274
|
+
bs.offset += byteCount;
|
|
275
|
+
}
|
|
276
|
+
store<u16>(bs.offset - 2, BRACKET_RIGHT);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
export function serializeArray<T extends any[]>(src: T): void {
|
|
280
|
+
// Specialized fast paths fold the per-element comma into the element write,
|
|
281
|
+
// saving one `store<u16>` + advance per iteration. AS folds the type checks
|
|
282
|
+
// at compile time so the non-matching branches don't ship.
|
|
283
|
+
if (isBoolean<valueof<T>>()) {
|
|
284
|
+
// @ts-expect-error: T is bool[]
|
|
285
|
+
serializeBoolArrayFast(changetype<bool[]>(src));
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
if (
|
|
289
|
+
isInteger<valueof<T>>() &&
|
|
290
|
+
!isSigned<valueof<T>>() &&
|
|
291
|
+
sizeof<valueof<T>>() == 1
|
|
292
|
+
) {
|
|
293
|
+
// @ts-expect-error: T is u8[]
|
|
294
|
+
serializeU8ArrayFast(changetype<u8[]>(src));
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
if (
|
|
298
|
+
isInteger<valueof<T>>() &&
|
|
299
|
+
isSigned<valueof<T>>() &&
|
|
300
|
+
sizeof<valueof<T>>() == 1
|
|
301
|
+
) {
|
|
302
|
+
// @ts-expect-error: T is i8[]
|
|
303
|
+
serializeI8ArrayFast(changetype<i8[]>(src));
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
if (isFloat<valueof<T>>() && sizeof<valueof<T>>() == 8) {
|
|
307
|
+
// @ts-expect-error: T is f64[]
|
|
308
|
+
serializeF64ArrayFast(changetype<f64[]>(src));
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
if (isFloat<valueof<T>>() && sizeof<valueof<T>>() == 4) {
|
|
312
|
+
// @ts-expect-error: T is f32[]
|
|
313
|
+
serializeF32ArrayFast(changetype<f32[]>(src));
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
const len = src.length;
|
|
318
|
+
const end = len - 1;
|
|
319
|
+
let i = 0;
|
|
320
|
+
if (end == -1) {
|
|
321
|
+
bs.proposeSize(4);
|
|
322
|
+
store<u32>(bs.offset, 6094939);
|
|
323
|
+
bs.offset += 4;
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
if (
|
|
327
|
+
isBoolean<valueof<T>>() ||
|
|
328
|
+
isInteger<valueof<T>>() ||
|
|
329
|
+
isFloat<valueof<T>>() ||
|
|
330
|
+
isString<valueof<T>>()
|
|
331
|
+
) {
|
|
332
|
+
reservePrimitiveArray<valueof<T>>(len);
|
|
333
|
+
} else {
|
|
334
|
+
bs.proposeSize(4 + <u32>(len - 1) * 2);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
store<u16>(bs.offset, BRACKET_LEFT);
|
|
338
|
+
bs.offset += 2;
|
|
339
|
+
|
|
340
|
+
while (i < end) {
|
|
341
|
+
const block = unchecked(src[i++]);
|
|
342
|
+
serializeArrayElement<valueof<T>>(block);
|
|
343
|
+
store<u16>(bs.offset, COMMA);
|
|
344
|
+
bs.offset += 2;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
const lastBlock = unchecked(src[end]);
|
|
348
|
+
serializeArrayElement<valueof<T>>(lastBlock);
|
|
349
|
+
store<u16>(bs.offset, BRACKET_RIGHT);
|
|
350
|
+
bs.offset += 2;
|
|
351
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { bs } from "../../../lib/as-bs";
|
|
2
|
+
import { ensureItoaPairs, itoaFast } from "../../util/itoa-fast";
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@inline
|
|
6
|
+
export function serializeIntegerUnsafe<T extends number>(data: T): void {
|
|
7
|
+
ensureItoaPairs();
|
|
8
|
+
const charsWritten = itoaFast<T>(bs.offset, data);
|
|
9
|
+
bs.offset += (<usize>charsWritten) << 1;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// @ts-ignore: inline
|
|
13
|
+
@inline export function serializeInteger<T extends number>(data: T): void {
|
|
14
|
+
ensureItoaPairs();
|
|
15
|
+
bs.ensureSize(sizeof<T>() << 3);
|
|
16
|
+
const charsWritten = itoaFast<T>(bs.offset, data);
|
|
17
|
+
bs.growSize((<u32>charsWritten) << 1);
|
|
18
|
+
bs.offset += (<usize>charsWritten) << 1;
|
|
19
|
+
}
|
|
@@ -26,7 +26,9 @@ export function serializeMap<T extends Map<any, any>>(src: T): void {
|
|
|
26
26
|
if (keyIsString) {
|
|
27
27
|
JSON.__serialize(unchecked(keys[i]));
|
|
28
28
|
} else {
|
|
29
|
-
JSON.__serialize<string>(
|
|
29
|
+
JSON.__serialize<string>(
|
|
30
|
+
JSON.internal.stringify<indexof<T>>(unchecked(keys[i])),
|
|
31
|
+
);
|
|
30
32
|
}
|
|
31
33
|
store<u16>(bs.offset, COLON);
|
|
32
34
|
bs.offset += 2;
|
|
@@ -38,7 +40,9 @@ export function serializeMap<T extends Map<any, any>>(src: T): void {
|
|
|
38
40
|
if (keyIsString) {
|
|
39
41
|
JSON.__serialize(unchecked(keys[srcEnd]));
|
|
40
42
|
} else {
|
|
41
|
-
JSON.__serialize<string>(
|
|
43
|
+
JSON.__serialize<string>(
|
|
44
|
+
JSON.internal.stringify<indexof<T>>(unchecked(keys[srcEnd])),
|
|
45
|
+
);
|
|
42
46
|
}
|
|
43
47
|
store<u16>(bs.offset, COLON);
|
|
44
48
|
bs.offset += 2;
|
|
@@ -11,6 +11,10 @@ import { bytes } from "../../util";
|
|
|
11
11
|
@inline export function serializeRaw(data: JSON.Raw): void {
|
|
12
12
|
const dataSize = bytes(data.data);
|
|
13
13
|
bs.proposeSize(dataSize);
|
|
14
|
-
memory.copy(
|
|
14
|
+
memory.copy(
|
|
15
|
+
changetype<usize>(bs.offset),
|
|
16
|
+
changetype<usize>(data.data),
|
|
17
|
+
dataSize,
|
|
18
|
+
);
|
|
15
19
|
bs.offset += dataSize;
|
|
16
20
|
}
|
|
@@ -38,7 +38,12 @@ export function serializeSet<T extends Set<any>>(src: T): void {
|
|
|
38
38
|
bs.offset += 4;
|
|
39
39
|
return;
|
|
40
40
|
}
|
|
41
|
-
if (
|
|
41
|
+
if (
|
|
42
|
+
isBoolean<indexof<T>>() ||
|
|
43
|
+
isInteger<indexof<T>>() ||
|
|
44
|
+
isFloat<indexof<T>>() ||
|
|
45
|
+
isString<indexof<T>>()
|
|
46
|
+
) {
|
|
42
47
|
reservePrimitiveSet<indexof<T>>(srcSize);
|
|
43
48
|
} else {
|
|
44
49
|
bs.proposeSize(4 + <u32>(srcSize - 1) * 2);
|
|
@@ -40,7 +40,12 @@ export function serializeStaticArray<T extends StaticArray<any>>(src: T): void {
|
|
|
40
40
|
bs.offset += 4;
|
|
41
41
|
return;
|
|
42
42
|
}
|
|
43
|
-
if (
|
|
43
|
+
if (
|
|
44
|
+
isBoolean<valueof<T>>() ||
|
|
45
|
+
isInteger<valueof<T>>() ||
|
|
46
|
+
isFloat<valueof<T>>() ||
|
|
47
|
+
isString<valueof<T>>()
|
|
48
|
+
) {
|
|
44
49
|
reservePrimitiveStaticArray<valueof<T>>(len);
|
|
45
50
|
} else {
|
|
46
51
|
bs.proposeSize(4 + <u32>(len - 1) * 2);
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { bs } from "../../../lib/as-bs";
|
|
2
|
-
import { _intTo16 } from "../../custom/util";
|
|
3
2
|
import { bytes } from "../../util/bytes";
|
|
4
3
|
import { BACK_SLASH, QUOTE } from "../../custom/chars";
|
|
5
4
|
import { SERIALIZE_ESCAPE_TABLE } from "../../globals/tables";
|
|
@@ -17,7 +16,7 @@ import { serializeStruct } from "./struct";
|
|
|
17
16
|
* @returns void
|
|
18
17
|
*/
|
|
19
18
|
// @ts-ignore: inline
|
|
20
|
-
@inline export function
|
|
19
|
+
@inline export function serializeString_NAIVE(src: string): void {
|
|
21
20
|
const srcSize = bytes(src);
|
|
22
21
|
bs.proposeSize(srcSize + 4);
|
|
23
22
|
let srcPtr = changetype<usize>(src);
|
|
@@ -25,9 +25,13 @@ function reserveTypedArray<T extends ArrayLike<number>>(len: i32): void {
|
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
@inline
|
|
28
|
-
function serializeTypedArrayElement<T extends ArrayLike<number>>(
|
|
28
|
+
function serializeTypedArrayElement<T extends ArrayLike<number>>(
|
|
29
|
+
src: T,
|
|
30
|
+
index: i32,
|
|
31
|
+
): void {
|
|
29
32
|
if (isFloat<valueof<T>>()) {
|
|
30
|
-
if (sizeof<valueof<T>>() == 4)
|
|
33
|
+
if (sizeof<valueof<T>>() == 4)
|
|
34
|
+
serializeFloat32Unsafe(<f32>unchecked(src[index]));
|
|
31
35
|
else serializeFloat64Unsafe(<f64>unchecked(src[index]));
|
|
32
36
|
} else {
|
|
33
37
|
serializeIntegerUnsafe<valueof<T>>(unchecked(src[index]));
|
|
@@ -59,7 +63,10 @@ export function serializeTypedArray<T extends ArrayLike<number>>(src: T): void {
|
|
|
59
63
|
bs.offset += 2;
|
|
60
64
|
}
|
|
61
65
|
|
|
62
|
-
export function serializeArrayBufferUnsafe(
|
|
66
|
+
export function serializeArrayBufferUnsafe(
|
|
67
|
+
srcStart: usize,
|
|
68
|
+
byteLength: i32,
|
|
69
|
+
): void {
|
|
63
70
|
const end = byteLength - 1;
|
|
64
71
|
|
|
65
72
|
if (end == -1) {
|
|
@@ -39,7 +39,9 @@ export function serializeString_SIMD(src: string): void {
|
|
|
39
39
|
const lt20 = i16x8.lt_u(block, SPLAT_0020);
|
|
40
40
|
const gteD8 = i8x16.gt_u(block, SPLAT_FFD8);
|
|
41
41
|
|
|
42
|
-
const mask = i8x16.bitmask(
|
|
42
|
+
const mask = i8x16.bitmask(
|
|
43
|
+
v128.or(eq22, v128.or(eq5C, v128.or(lt20, gteD8))),
|
|
44
|
+
);
|
|
43
45
|
if (mask != 0) break;
|
|
44
46
|
|
|
45
47
|
store<v128>(dst, block);
|
|
@@ -83,7 +85,9 @@ export function serializeString_SIMD(src: string): void {
|
|
|
83
85
|
// console.log("lt20 : " + mask_to_string_v128(lt20) + " -> " + mask_to_string_v128(SPLAT_0020));
|
|
84
86
|
// console.log("gteD8 : " + mask_to_string_v128(gteD8) + " -> " + mask_to_string_v128(SPLAT_FFD8));
|
|
85
87
|
|
|
86
|
-
let mask = i8x16.bitmask(
|
|
88
|
+
let mask = i8x16.bitmask(
|
|
89
|
+
v128.or(eq22, v128.or(eq5C, v128.or(lt20, gteD8))),
|
|
90
|
+
);
|
|
87
91
|
|
|
88
92
|
if (mask == 0) {
|
|
89
93
|
store<v128>(bs.offset, block);
|