json-as 1.3.2 → 1.3.4
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 +5 -0
- package/README.md +3 -2
- package/assembly/deserialize/simd/string.ts +20 -0
- package/assembly/deserialize/simple/map.ts +2 -0
- package/assembly/deserialize/simple/staticarray.ts +1 -0
- package/assembly/deserialize/simple/struct.ts +3 -1
- package/assembly/deserialize/swar/array/bool.ts +1 -0
- package/assembly/deserialize/swar/array/generic.ts +2 -1
- package/assembly/deserialize/swar/array/integer.ts +1 -0
- package/assembly/deserialize/swar/array/object.ts +1 -0
- package/assembly/deserialize/swar/array/shared.ts +18 -3
- package/assembly/deserialize/swar/array/string.ts +1 -0
- package/assembly/deserialize/swar/array/struct.ts +1 -0
- package/assembly/deserialize/swar/array.ts +1 -0
- package/assembly/deserialize/swar/string.ts +21 -2
- package/assembly/index.d.ts +1 -0
- package/assembly/index.ts +27 -22
- package/assembly/serialize/simd/string.ts +43 -16
- package/assembly/serialize/simple/array.ts +48 -6
- package/assembly/serialize/simple/bool.ts +12 -0
- package/assembly/serialize/simple/float.ts +16 -0
- package/assembly/serialize/simple/integer.ts +6 -0
- package/assembly/serialize/simple/set.ts +59 -5
- package/assembly/serialize/simple/staticarray.ts +57 -3
- package/assembly/serialize/simple/typedarray.ts +29 -9
- package/assembly/serialize/swar/string.ts +165 -18
- package/assembly/tsconfig.json +2 -2
- package/assembly/util/dragonbox-cache.ts +2 -1320
- package/assembly/util/dragonbox.ts +63 -35
- package/lib/as-bs.ts +26 -18
- package/package.json +11 -10
- package/transform/lib/index.d.ts.map +1 -1
- package/transform/lib/index.js +288 -73
- package/transform/lib/index.js.map +1 -1
|
@@ -1,6 +1,34 @@
|
|
|
1
1
|
import { bs } from "../../../lib/as-bs";
|
|
2
2
|
import { COMMA, BRACKET_RIGHT, BRACKET_LEFT } from "../../custom/chars";
|
|
3
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
|
+
|
|
9
|
+
|
|
10
|
+
@inline
|
|
11
|
+
function maxIntegerBytes<T extends number>(): u32 {
|
|
12
|
+
if (sizeof<T>() == 1) return isSigned<T>() ? 8 : 6;
|
|
13
|
+
if (sizeof<T>() == 2) return isSigned<T>() ? 12 : 10;
|
|
14
|
+
if (sizeof<T>() == 4) return isSigned<T>() ? 22 : 20;
|
|
15
|
+
return isSigned<T>() ? 42 : 40;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@inline
|
|
20
|
+
function reservePrimitiveSet<T>(len: i32): void {
|
|
21
|
+
if (len <= 0) return;
|
|
22
|
+
if (isBoolean<T>()) {
|
|
23
|
+
bs.proposeSize(4 + <u32>len * 12);
|
|
24
|
+
} else if (isInteger<T>()) {
|
|
25
|
+
bs.proposeSize(4 + <u32>len * (maxIntegerBytes<T>() + 2));
|
|
26
|
+
} else if (isFloat<T>()) {
|
|
27
|
+
bs.proposeSize(4 + <u32>len * (sizeof<T>() == 4 ? 34 : 66));
|
|
28
|
+
} else {
|
|
29
|
+
bs.proposeSize(4 + <u32>(len - 1) * 2);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
4
32
|
|
|
5
33
|
export function serializeSet<T extends Set<any>>(src: T): void {
|
|
6
34
|
const srcSize = src.size;
|
|
@@ -10,7 +38,11 @@ export function serializeSet<T extends Set<any>>(src: T): void {
|
|
|
10
38
|
bs.offset += 4;
|
|
11
39
|
return;
|
|
12
40
|
}
|
|
13
|
-
|
|
41
|
+
if (isBoolean<indexof<T>>() || isInteger<indexof<T>>() || isFloat<indexof<T>>() || isString<indexof<T>>()) {
|
|
42
|
+
reservePrimitiveSet<indexof<T>>(srcSize);
|
|
43
|
+
} else {
|
|
44
|
+
bs.proposeSize(4 + <u32>(srcSize - 1) * 2);
|
|
45
|
+
}
|
|
14
46
|
|
|
15
47
|
const values = src.values();
|
|
16
48
|
store<u16>(bs.offset, BRACKET_LEFT);
|
|
@@ -19,15 +51,37 @@ export function serializeSet<T extends Set<any>>(src: T): void {
|
|
|
19
51
|
const end = srcSize - 1;
|
|
20
52
|
for (let i = 0; i < end; i++) {
|
|
21
53
|
const block = unchecked(values[i]);
|
|
22
|
-
|
|
23
|
-
|
|
54
|
+
if (isString<indexof<T>>()) {
|
|
55
|
+
serializeString(block as string);
|
|
56
|
+
} else if (isBoolean<indexof<T>>()) {
|
|
57
|
+
serializeBoolUnsafe(<bool>block);
|
|
58
|
+
} else if (isInteger<indexof<T>>()) {
|
|
59
|
+
serializeIntegerUnsafe<indexof<T>>(block);
|
|
60
|
+
} else if (isFloat<indexof<T>>()) {
|
|
61
|
+
if (sizeof<indexof<T>>() == 4) serializeFloat32Unsafe(<f32>block);
|
|
62
|
+
else serializeFloat64Unsafe(<f64>block);
|
|
63
|
+
} else {
|
|
64
|
+
// @ts-ignore: type
|
|
65
|
+
JSON.__serialize<indexof<T>>(block);
|
|
66
|
+
}
|
|
24
67
|
store<u16>(bs.offset, COMMA);
|
|
25
68
|
bs.offset += 2;
|
|
26
69
|
}
|
|
27
70
|
|
|
28
71
|
const lastBlock = unchecked(values[end]);
|
|
29
|
-
|
|
30
|
-
|
|
72
|
+
if (isString<indexof<T>>()) {
|
|
73
|
+
serializeString(lastBlock as string);
|
|
74
|
+
} else if (isBoolean<indexof<T>>()) {
|
|
75
|
+
serializeBoolUnsafe(<bool>lastBlock);
|
|
76
|
+
} else if (isInteger<indexof<T>>()) {
|
|
77
|
+
serializeIntegerUnsafe<indexof<T>>(lastBlock);
|
|
78
|
+
} else if (isFloat<indexof<T>>()) {
|
|
79
|
+
if (sizeof<indexof<T>>() == 4) serializeFloat32Unsafe(<f32>lastBlock);
|
|
80
|
+
else serializeFloat64Unsafe(<f64>lastBlock);
|
|
81
|
+
} else {
|
|
82
|
+
// @ts-ignore: type
|
|
83
|
+
JSON.__serialize<indexof<T>>(lastBlock);
|
|
84
|
+
}
|
|
31
85
|
store<u16>(bs.offset, BRACKET_RIGHT);
|
|
32
86
|
bs.offset += 2;
|
|
33
87
|
}
|
|
@@ -1,6 +1,34 @@
|
|
|
1
1
|
import { bs } from "../../../lib/as-bs";
|
|
2
2
|
import { COMMA, BRACKET_RIGHT, BRACKET_LEFT } from "../../custom/chars";
|
|
3
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
|
+
|
|
9
|
+
|
|
10
|
+
@inline
|
|
11
|
+
function maxIntegerBytes<T extends number>(): u32 {
|
|
12
|
+
if (sizeof<T>() == 1) return isSigned<T>() ? 8 : 6;
|
|
13
|
+
if (sizeof<T>() == 2) return isSigned<T>() ? 12 : 10;
|
|
14
|
+
if (sizeof<T>() == 4) return isSigned<T>() ? 22 : 20;
|
|
15
|
+
return isSigned<T>() ? 42 : 40;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@inline
|
|
20
|
+
function reservePrimitiveStaticArray<T>(len: i32): void {
|
|
21
|
+
if (len <= 0) return;
|
|
22
|
+
if (isBoolean<T>()) {
|
|
23
|
+
bs.proposeSize(4 + <u32>len * 12);
|
|
24
|
+
} else if (isInteger<T>()) {
|
|
25
|
+
bs.proposeSize(4 + <u32>len * (maxIntegerBytes<T>() + 2));
|
|
26
|
+
} else if (isFloat<T>()) {
|
|
27
|
+
bs.proposeSize(4 + <u32>len * (sizeof<T>() == 4 ? 34 : 66));
|
|
28
|
+
} else {
|
|
29
|
+
bs.proposeSize(4 + <u32>(len - 1) * 2);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
4
32
|
|
|
5
33
|
export function serializeStaticArray<T extends StaticArray<any>>(src: T): void {
|
|
6
34
|
const len = src.length;
|
|
@@ -12,20 +40,46 @@ export function serializeStaticArray<T extends StaticArray<any>>(src: T): void {
|
|
|
12
40
|
bs.offset += 4;
|
|
13
41
|
return;
|
|
14
42
|
}
|
|
15
|
-
|
|
43
|
+
if (isBoolean<valueof<T>>() || isInteger<valueof<T>>() || isFloat<valueof<T>>() || isString<valueof<T>>()) {
|
|
44
|
+
reservePrimitiveStaticArray<valueof<T>>(len);
|
|
45
|
+
} else {
|
|
46
|
+
bs.proposeSize(4 + <u32>(len - 1) * 2);
|
|
47
|
+
}
|
|
16
48
|
|
|
17
49
|
store<u16>(bs.offset, BRACKET_LEFT);
|
|
18
50
|
bs.offset += 2;
|
|
19
51
|
|
|
20
52
|
while (i < end) {
|
|
21
53
|
const block = unchecked(src[i++]);
|
|
22
|
-
|
|
54
|
+
if (isString<valueof<T>>()) {
|
|
55
|
+
serializeString(block as string);
|
|
56
|
+
} else if (isBoolean<valueof<T>>()) {
|
|
57
|
+
serializeBoolUnsafe(<bool>block);
|
|
58
|
+
} else if (isInteger<valueof<T>>()) {
|
|
59
|
+
serializeIntegerUnsafe<valueof<T>>(block);
|
|
60
|
+
} else if (isFloat<valueof<T>>()) {
|
|
61
|
+
if (sizeof<valueof<T>>() == 4) serializeFloat32Unsafe(<f32>block);
|
|
62
|
+
else serializeFloat64Unsafe(<f64>block);
|
|
63
|
+
} else {
|
|
64
|
+
JSON.__serialize<valueof<T>>(block);
|
|
65
|
+
}
|
|
23
66
|
store<u16>(bs.offset, COMMA);
|
|
24
67
|
bs.offset += 2;
|
|
25
68
|
}
|
|
26
69
|
|
|
27
70
|
const lastBlock = unchecked(src[end]);
|
|
28
|
-
|
|
71
|
+
if (isString<valueof<T>>()) {
|
|
72
|
+
serializeString(lastBlock as string);
|
|
73
|
+
} else if (isBoolean<valueof<T>>()) {
|
|
74
|
+
serializeBoolUnsafe(<bool>lastBlock);
|
|
75
|
+
} else if (isInteger<valueof<T>>()) {
|
|
76
|
+
serializeIntegerUnsafe<valueof<T>>(lastBlock);
|
|
77
|
+
} else if (isFloat<valueof<T>>()) {
|
|
78
|
+
if (sizeof<valueof<T>>() == 4) serializeFloat32Unsafe(<f32>lastBlock);
|
|
79
|
+
else serializeFloat64Unsafe(<f64>lastBlock);
|
|
80
|
+
} else {
|
|
81
|
+
JSON.__serialize<valueof<T>>(lastBlock);
|
|
82
|
+
}
|
|
29
83
|
store<u16>(bs.offset, BRACKET_RIGHT);
|
|
30
84
|
bs.offset += 2;
|
|
31
85
|
}
|
|
@@ -1,16 +1,36 @@
|
|
|
1
1
|
import { bs } from "../../../lib/as-bs";
|
|
2
2
|
import { BRACKET_LEFT, BRACKET_RIGHT, COMMA } from "../../custom/chars";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { serializeFloat32Unsafe, serializeFloat64Unsafe } from "./float";
|
|
4
|
+
import { serializeIntegerUnsafe } from "./integer";
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@inline
|
|
8
|
+
function maxIntegerBytes<T extends number>(): u32 {
|
|
9
|
+
if (sizeof<T>() == 1) return isSigned<T>() ? 8 : 6;
|
|
10
|
+
if (sizeof<T>() == 2) return isSigned<T>() ? 12 : 10;
|
|
11
|
+
if (sizeof<T>() == 4) return isSigned<T>() ? 22 : 20;
|
|
12
|
+
return isSigned<T>() ? 42 : 40;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@inline
|
|
17
|
+
function reserveTypedArray<T extends ArrayLike<number>>(len: i32): void {
|
|
18
|
+
if (len <= 0) return;
|
|
19
|
+
if (isFloat<valueof<T>>()) {
|
|
20
|
+
bs.proposeSize(4 + <u32>len * (sizeof<valueof<T>>() == 4 ? 34 : 66));
|
|
21
|
+
} else {
|
|
22
|
+
bs.proposeSize(4 + <u32>len * (maxIntegerBytes<valueof<T>>() + 2));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
5
25
|
|
|
6
26
|
|
|
7
27
|
@inline
|
|
8
28
|
function serializeTypedArrayElement<T extends ArrayLike<number>>(src: T, index: i32): void {
|
|
9
29
|
if (isFloat<valueof<T>>()) {
|
|
10
|
-
if (sizeof<valueof<T>>() == 4)
|
|
11
|
-
else
|
|
30
|
+
if (sizeof<valueof<T>>() == 4) serializeFloat32Unsafe(<f32>unchecked(src[index]));
|
|
31
|
+
else serializeFloat64Unsafe(<f64>unchecked(src[index]));
|
|
12
32
|
} else {
|
|
13
|
-
|
|
33
|
+
serializeIntegerUnsafe<valueof<T>>(unchecked(src[index]));
|
|
14
34
|
}
|
|
15
35
|
}
|
|
16
36
|
|
|
@@ -23,7 +43,7 @@ export function serializeTypedArray<T extends ArrayLike<number>>(src: T): void {
|
|
|
23
43
|
bs.offset += 4;
|
|
24
44
|
return;
|
|
25
45
|
}
|
|
26
|
-
|
|
46
|
+
reserveTypedArray<T>(len);
|
|
27
47
|
|
|
28
48
|
store<u16>(bs.offset, BRACKET_LEFT);
|
|
29
49
|
bs.offset += 2;
|
|
@@ -48,18 +68,18 @@ export function serializeArrayBufferUnsafe(srcStart: usize, byteLength: i32): vo
|
|
|
48
68
|
bs.offset += 4;
|
|
49
69
|
return;
|
|
50
70
|
}
|
|
51
|
-
bs.proposeSize(4 + <u32>
|
|
71
|
+
bs.proposeSize(4 + <u32>byteLength * 8);
|
|
52
72
|
|
|
53
73
|
store<u16>(bs.offset, BRACKET_LEFT);
|
|
54
74
|
bs.offset += 2;
|
|
55
75
|
|
|
56
76
|
for (let i = 0; i < end; i++) {
|
|
57
|
-
|
|
77
|
+
serializeIntegerUnsafe<u8>(load<u8>(srcStart + <usize>i));
|
|
58
78
|
store<u16>(bs.offset, COMMA);
|
|
59
79
|
bs.offset += 2;
|
|
60
80
|
}
|
|
61
81
|
|
|
62
|
-
|
|
82
|
+
serializeIntegerUnsafe<u8>(load<u8>(srcStart + <usize>end));
|
|
63
83
|
store<u16>(bs.offset, BRACKET_RIGHT);
|
|
64
84
|
bs.offset += 2;
|
|
65
85
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { bs
|
|
2
|
-
import { BACK_SLASH } from "../../custom/chars";
|
|
1
|
+
import { bs } from "../../../lib/as-bs";
|
|
2
|
+
import { BACK_SLASH, QUOTE } from "../../custom/chars";
|
|
3
3
|
import { SERIALIZE_ESCAPE_TABLE } from "../../globals/tables";
|
|
4
4
|
import { u16_to_hex4_swar } from "../../util/swar";
|
|
5
5
|
import { OBJECT, TOTAL_OVERHEAD } from "rt/common";
|
|
@@ -11,18 +11,166 @@ import { OBJECT, TOTAL_OVERHEAD } from "rt/common";
|
|
|
11
11
|
|
|
12
12
|
export function serializeString_SWAR(src: string): void {
|
|
13
13
|
let srcStart = changetype<usize>(src);
|
|
14
|
+
const srcInitial = srcStart;
|
|
15
|
+
const srcSize = changetype<OBJECT>(srcStart - TOTAL_OVERHEAD).rtSize;
|
|
16
|
+
const srcEnd = srcStart + srcSize;
|
|
17
|
+
do {
|
|
18
|
+
const srcEnd8Fast = srcEnd - 8;
|
|
19
|
+
bs.proposeSize(srcSize + 4);
|
|
20
|
+
|
|
21
|
+
const dstStart = bs.offset;
|
|
22
|
+
let dst = dstStart + 2;
|
|
23
|
+
|
|
24
|
+
while (srcStart < srcEnd8Fast) {
|
|
25
|
+
const block = load<u64>(srcStart);
|
|
26
|
+
if ((block & 0xff00_ff00_ff00_ff00) != 0) break;
|
|
27
|
+
const lo = block & 0x00ff_00ff_00ff_00ff;
|
|
28
|
+
const asciiMask = ((lo - 0x0020_0020_0020_0020) | ((lo ^ 0x0022_0022_0022_0022) - 0x0001_0001_0001_0001) | ((lo ^ 0x005c_005c_005c_005c) - 0x0001_0001_0001_0001)) & (0x0080_0080_0080_0080 & ~lo);
|
|
29
|
+
if (asciiMask != 0) break;
|
|
30
|
+
store<u64>(dst, block);
|
|
31
|
+
srcStart += 8;
|
|
32
|
+
dst += 8;
|
|
33
|
+
}
|
|
34
|
+
if (srcStart < srcEnd8Fast) break;
|
|
35
|
+
|
|
36
|
+
while (srcStart <= srcEnd - 2) {
|
|
37
|
+
const code = load<u16>(srcStart);
|
|
38
|
+
if (code > 0x7f || code == BACK_SLASH || code == QUOTE || code < 32) break;
|
|
39
|
+
store<u16>(dst, code);
|
|
40
|
+
srcStart += 2;
|
|
41
|
+
dst += 2;
|
|
42
|
+
}
|
|
43
|
+
if (srcStart <= srcEnd - 2) break;
|
|
44
|
+
|
|
45
|
+
store<u16>(dstStart, QUOTE);
|
|
46
|
+
store<u16>(dst, QUOTE);
|
|
47
|
+
bs.offset = dst + 2;
|
|
48
|
+
return;
|
|
49
|
+
} while (false);
|
|
50
|
+
|
|
51
|
+
srcStart = srcInitial;
|
|
52
|
+
const srcEnd8 = srcEnd - 8;
|
|
53
|
+
|
|
54
|
+
bs.proposeSize(srcSize + 4);
|
|
55
|
+
store<u16>(bs.offset, 34); // "
|
|
56
|
+
bs.offset += 2;
|
|
57
|
+
|
|
58
|
+
while (srcStart < srcEnd8) {
|
|
59
|
+
const block = load<u64>(srcStart);
|
|
60
|
+
let mask = detect_escapable_u64_swar_safe(block);
|
|
61
|
+
store<u64>(bs.offset, block);
|
|
62
|
+
|
|
63
|
+
if (mask === 0) {
|
|
64
|
+
srcStart += 8;
|
|
65
|
+
bs.offset += 8;
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
do {
|
|
70
|
+
const laneIdx = usize(ctz(mask) >> 3);
|
|
71
|
+
const srcIdx = srcStart + laneIdx;
|
|
72
|
+
// Even (0 2 4 6) -> Confirmed ASCII Escape
|
|
73
|
+
// Odd (1 3 5 7) -> Possibly a Unicode code unit or surrogate
|
|
74
|
+
if ((laneIdx & 1) === 0) {
|
|
75
|
+
mask &= mask - 1;
|
|
76
|
+
const code = load<u16>(srcIdx);
|
|
77
|
+
const escaped = load<u32>(SERIALIZE_ESCAPE_TABLE + (code << 2));
|
|
78
|
+
|
|
79
|
+
if ((escaped & 0xffff) != BACK_SLASH) {
|
|
80
|
+
bs.growSize(10);
|
|
81
|
+
const dstIdx = bs.offset + laneIdx;
|
|
82
|
+
store<u64>(dstIdx, U00_MARKER);
|
|
83
|
+
store<u32>(dstIdx, escaped, 8);
|
|
84
|
+
store<u64>(dstIdx, load<u64>(srcIdx, 2), 12);
|
|
85
|
+
bs.offset += 10;
|
|
86
|
+
} else {
|
|
87
|
+
bs.growSize(2);
|
|
88
|
+
const dstIdx = bs.offset + laneIdx;
|
|
89
|
+
store<u32>(dstIdx, escaped);
|
|
90
|
+
store<u64>(dstIdx, load<u64>(srcIdx, 2), 4);
|
|
91
|
+
bs.offset += 2;
|
|
92
|
+
}
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
mask &= mask - 1;
|
|
96
|
+
|
|
97
|
+
const code = load<u16>(srcIdx - 1);
|
|
98
|
+
if (code < 0xd800 || code > 0xdfff) continue;
|
|
99
|
+
|
|
100
|
+
if (code <= 0xdbff && srcIdx + 2 < srcEnd) {
|
|
101
|
+
const next = load<u16>(srcIdx, 1);
|
|
102
|
+
if (next >= 0xdc00 && next <= 0xdfff) {
|
|
103
|
+
// paired surrogate
|
|
104
|
+
// mask &= ~(0xFF << ((laneIdx+2) << 3));
|
|
105
|
+
mask &= mask - 1;
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
bs.growSize(10);
|
|
111
|
+
|
|
112
|
+
// unpaired high/low surrogate
|
|
113
|
+
const dstIdx = bs.offset + laneIdx - 1;
|
|
114
|
+
store<u32>(dstIdx, U_MARKER); // \u
|
|
115
|
+
store<u64>(dstIdx, u16_to_hex4_swar(code), 4);
|
|
116
|
+
store<u64>(dstIdx, load<u64>(srcIdx, 1), 12);
|
|
117
|
+
bs.offset += 10;
|
|
118
|
+
} while (mask !== 0);
|
|
119
|
+
|
|
120
|
+
srcStart += 8;
|
|
121
|
+
bs.offset += 8;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
while (srcStart <= srcEnd - 2) {
|
|
125
|
+
const code = load<u16>(srcStart);
|
|
126
|
+
|
|
127
|
+
if (code == BACK_SLASH || code == QUOTE || code < 32) {
|
|
128
|
+
const escaped = load<u32>(SERIALIZE_ESCAPE_TABLE + (code << 2));
|
|
129
|
+
if ((escaped & 0xffff) != BACK_SLASH) {
|
|
130
|
+
bs.growSize(10);
|
|
131
|
+
store<u64>(bs.offset, U00_MARKER);
|
|
132
|
+
store<u32>(bs.offset, escaped, 8);
|
|
133
|
+
bs.offset += 12;
|
|
134
|
+
} else {
|
|
135
|
+
bs.growSize(2);
|
|
136
|
+
store<u32>(bs.offset, escaped);
|
|
137
|
+
bs.offset += 4;
|
|
138
|
+
}
|
|
139
|
+
srcStart += 2;
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (code < 0xd800 || code > 0xdfff) {
|
|
144
|
+
store<u16>(bs.offset, code);
|
|
145
|
+
bs.offset += 2;
|
|
146
|
+
srcStart += 2;
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
14
149
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
150
|
+
if (code <= 0xdbff && srcStart + 2 <= srcEnd - 2) {
|
|
151
|
+
const next = load<u16>(srcStart, 2);
|
|
152
|
+
if (next >= 0xdc00 && next <= 0xdfff) {
|
|
153
|
+
// valid surrogate pair
|
|
154
|
+
store<u16>(bs.offset, code);
|
|
155
|
+
store<u16>(bs.offset + 2, next);
|
|
156
|
+
bs.offset += 4;
|
|
157
|
+
srcStart += 4;
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
23
160
|
}
|
|
161
|
+
|
|
162
|
+
// unpaired high/low surrogate
|
|
163
|
+
write_u_escape(code);
|
|
164
|
+
srcStart += 2;
|
|
165
|
+
continue;
|
|
24
166
|
}
|
|
25
167
|
|
|
168
|
+
store<u16>(bs.offset, 34); // "
|
|
169
|
+
bs.offset += 2;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export function serializeString_SWAR_ExperimentalTableEscapes(src: string): void {
|
|
173
|
+
let srcStart = changetype<usize>(src);
|
|
26
174
|
const srcSize = changetype<OBJECT>(srcStart - TOTAL_OVERHEAD).rtSize;
|
|
27
175
|
const srcEnd = srcStart + srcSize;
|
|
28
176
|
const srcEnd8 = srcEnd - 8;
|
|
@@ -32,10 +180,9 @@ export function serializeString_SWAR(src: string): void {
|
|
|
32
180
|
bs.offset += 2;
|
|
33
181
|
|
|
34
182
|
while (srcStart < srcEnd8) {
|
|
35
|
-
|
|
36
|
-
store<u64>(bs.offset, block);
|
|
37
|
-
|
|
183
|
+
const block = load<u64>(srcStart);
|
|
38
184
|
let mask = detect_escapable_u64_swar_safe(block);
|
|
185
|
+
store<u64>(bs.offset, block);
|
|
39
186
|
|
|
40
187
|
if (mask === 0) {
|
|
41
188
|
srcStart += 8;
|
|
@@ -49,7 +196,7 @@ export function serializeString_SWAR(src: string): void {
|
|
|
49
196
|
// Even (0 2 4 6) -> Confirmed ASCII Escape
|
|
50
197
|
// Odd (1 3 5 7) -> Possibly a Unicode code unit or surrogate
|
|
51
198
|
if ((laneIdx & 1) === 0) {
|
|
52
|
-
mask &=
|
|
199
|
+
mask &= mask - 1;
|
|
53
200
|
const code = load<u16>(srcIdx);
|
|
54
201
|
const escaped = load<u32>(SERIALIZE_ESCAPE_TABLE + (code << 2));
|
|
55
202
|
|
|
@@ -69,7 +216,7 @@ export function serializeString_SWAR(src: string): void {
|
|
|
69
216
|
}
|
|
70
217
|
continue;
|
|
71
218
|
}
|
|
72
|
-
mask &=
|
|
219
|
+
mask &= mask - 1;
|
|
73
220
|
|
|
74
221
|
const code = load<u16>(srcIdx - 1);
|
|
75
222
|
if (code < 0xd800 || code > 0xdfff) continue;
|
|
@@ -101,7 +248,7 @@ export function serializeString_SWAR(src: string): void {
|
|
|
101
248
|
while (srcStart <= srcEnd - 2) {
|
|
102
249
|
const code = load<u16>(srcStart);
|
|
103
250
|
|
|
104
|
-
if (code ==
|
|
251
|
+
if (code == BACK_SLASH || code == QUOTE || code < 32) {
|
|
105
252
|
const escaped = load<u32>(SERIALIZE_ESCAPE_TABLE + (code << 2));
|
|
106
253
|
if ((escaped & 0xffff) != BACK_SLASH) {
|
|
107
254
|
bs.growSize(10);
|
|
@@ -144,8 +291,6 @@ export function serializeString_SWAR(src: string): void {
|
|
|
144
291
|
|
|
145
292
|
store<u16>(bs.offset, 34); // "
|
|
146
293
|
bs.offset += 2;
|
|
147
|
-
|
|
148
|
-
if (isDefined(JSON_CACHE)) sc.insertCached(changetype<usize>(src), srcStart, srcSize);
|
|
149
294
|
}
|
|
150
295
|
|
|
151
296
|
// @ts-expect-error: @inline is a valid decorator
|
|
@@ -158,8 +303,10 @@ export function serializeString_SWAR(src: string): void {
|
|
|
158
303
|
|
|
159
304
|
// @ts-expect-error: @inline is a valid decorator
|
|
160
305
|
@inline export function detect_escapable_u64_swar_safe(block: u64): u64 {
|
|
306
|
+
const hi = block & 0xff00_ff00_ff00_ff00;
|
|
161
307
|
const lo = block & 0x00ff_00ff_00ff_00ff;
|
|
162
308
|
const ascii_mask = ((lo - 0x0020_0020_0020_0020) | ((lo ^ 0x0022_0022_0022_0022) - 0x0001_0001_0001_0001) | ((lo ^ 0x005c_005c_005c_005c) - 0x0001_0001_0001_0001)) & (0x0080_0080_0080_0080 & ~lo);
|
|
309
|
+
if (hi == 0) return ascii_mask;
|
|
163
310
|
const hi_mask = ((block - 0x0100_0100_0100_0100) & ~block & 0x8000_8000_8000_8000) ^ 0x8000_8000_8000_8000;
|
|
164
311
|
return (ascii_mask & (~hi_mask >> 8)) | hi_mask;
|
|
165
312
|
}
|
package/assembly/tsconfig.json
CHANGED