json-as 1.3.6 → 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 +13 -0
- 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 +8 -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 +18 -5
- 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 +5 -2
- 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,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 "../simple/typedarray";
|
|
7
|
+
import {
|
|
8
|
+
serializeArrayBufferUnsafe,
|
|
9
|
+
serializeTypedArray,
|
|
10
|
+
} from "../simple/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) {
|
|
@@ -62,5 +77,8 @@ import { serializeArrayBufferUnsafe, serializeTypedArray } from "../simple/typed
|
|
|
62
77
|
|
|
63
78
|
@inline export function serializeArrayBuffer(data: ArrayBuffer): void {
|
|
64
79
|
const dataStart = changetype<usize>(data);
|
|
65
|
-
serializeArrayBufferUnsafe(
|
|
80
|
+
serializeArrayBufferUnsafe(
|
|
81
|
+
dataStart,
|
|
82
|
+
changetype<OBJECT>(dataStart - TOTAL_OVERHEAD).rtSize,
|
|
83
|
+
);
|
|
66
84
|
}
|
|
@@ -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);
|
|
@@ -53,7 +53,180 @@ function serializeArrayElement<T>(value: T): void {
|
|
|
53
53
|
JSON.__serialize<T>(value);
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
// Specialized fast paths
|
|
58
|
+
// ---------------------------------------------------------------------------
|
|
59
|
+
//
|
|
60
|
+
// `bool[]` and `u8[]` / `i8[]` serializers fold the element write and the
|
|
61
|
+
// trailing comma into a single per-element store. The outer dispatcher
|
|
62
|
+
// emits `[` once, the loop emits `VALUE,` once per element, and the closing
|
|
63
|
+
// `]` overwrites the trailing comma. This eliminates the separate
|
|
64
|
+
// comma-store + advance per element that the generic `serializeArray` does.
|
|
65
|
+
|
|
66
|
+
// `"true,"` packed UTF-16: `t,r,u,e,,` lanes 0..4 = bytes 0..9.
|
|
67
|
+
@inline const TRUE_COMMA_LO: u64 = 0x0065_0075_0072_0074;
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@inline const TRUE_COMMA_HI: u16 = 0x002c;
|
|
71
|
+
// `"false,"` packed UTF-16: `f,a,l,s,e,,` lanes 0..5 = bytes 0..11.
|
|
72
|
+
@inline const FALSE_COMMA_LO: u64 = 0x0073_006c_0061_0066;
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@inline const FALSE_COMMA_HI: u32 = 0x002c_0065;
|
|
76
|
+
|
|
77
|
+
function serializeBoolArrayFast(src: bool[]): void {
|
|
78
|
+
const len = src.length;
|
|
79
|
+
// Worst case: every element is `"false,"` = 12 bytes; plus 4 for `[]`.
|
|
80
|
+
bs.proposeSize(4 + <u32>len * 12);
|
|
81
|
+
store<u16>(bs.offset, BRACKET_LEFT);
|
|
82
|
+
bs.offset += 2;
|
|
83
|
+
if (len == 0) {
|
|
84
|
+
store<u16>(bs.offset, BRACKET_RIGHT);
|
|
85
|
+
bs.offset += 2;
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const dataStart = src.dataStart;
|
|
90
|
+
for (let i: i32 = 0; i < len; i++) {
|
|
91
|
+
if (load<bool>(dataStart + <usize>i)) {
|
|
92
|
+
store<u64>(bs.offset, TRUE_COMMA_LO);
|
|
93
|
+
store<u16>(bs.offset, TRUE_COMMA_HI, 8);
|
|
94
|
+
bs.offset += 10;
|
|
95
|
+
} else {
|
|
96
|
+
store<u64>(bs.offset, FALSE_COMMA_LO);
|
|
97
|
+
store<u32>(bs.offset, FALSE_COMMA_HI, 8);
|
|
98
|
+
bs.offset += 12;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// Overwrite the final trailing comma with `]`.
|
|
102
|
+
store<u16>(bs.offset - 2, BRACKET_RIGHT);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// 256-entry table mapping `u8` value -> UTF-16 chars of `"DDD,"` packed in a
|
|
106
|
+
// u64. Unused lanes hold garbage that the next element's store overwrites.
|
|
107
|
+
const U8_SERIALIZE_LUT: usize = memory.data(2048); // 256 * sizeof<u64>
|
|
108
|
+
// 256-entry table mapping `u8` value -> byte count of the packed encoding.
|
|
109
|
+
const U8_SERIALIZE_LEN_LUT: usize = memory.data(256);
|
|
110
|
+
let _u8LutInited: bool = false;
|
|
111
|
+
|
|
112
|
+
function initU8Lut(): void {
|
|
113
|
+
for (let i: i32 = 0; i < 256; i++) {
|
|
114
|
+
let chars: u64;
|
|
115
|
+
let bytes: u8;
|
|
116
|
+
if (i < 10) {
|
|
117
|
+
chars = u64(0x30 + i) | (u64(0x2c) << 16);
|
|
118
|
+
bytes = 4;
|
|
119
|
+
} else if (i < 100) {
|
|
120
|
+
const d0 = i / 10;
|
|
121
|
+
const d1 = i % 10;
|
|
122
|
+
chars = u64(0x30 + d0) | (u64(0x30 + d1) << 16) | (u64(0x2c) << 32);
|
|
123
|
+
bytes = 6;
|
|
124
|
+
} else {
|
|
125
|
+
const d0 = i / 100;
|
|
126
|
+
const d1 = (i / 10) % 10;
|
|
127
|
+
const d2 = i % 10;
|
|
128
|
+
chars =
|
|
129
|
+
u64(0x30 + d0) |
|
|
130
|
+
(u64(0x30 + d1) << 16) |
|
|
131
|
+
(u64(0x30 + d2) << 32) |
|
|
132
|
+
(u64(0x2c) << 48);
|
|
133
|
+
bytes = 8;
|
|
134
|
+
}
|
|
135
|
+
store<u64>(U8_SERIALIZE_LUT + ((<usize>i) << 3), chars);
|
|
136
|
+
store<u8>(U8_SERIALIZE_LEN_LUT + <usize>i, bytes);
|
|
137
|
+
}
|
|
138
|
+
_u8LutInited = true;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
@inline function ensureU8Lut(): void {
|
|
143
|
+
if (!_u8LutInited) initU8Lut();
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function serializeU8ArrayFast(src: u8[]): void {
|
|
147
|
+
const len = src.length;
|
|
148
|
+
// Worst case: every element is 3 digits + comma = 8 bytes; plus 4 for `[]`.
|
|
149
|
+
bs.proposeSize(4 + <u32>len * 8);
|
|
150
|
+
store<u16>(bs.offset, BRACKET_LEFT);
|
|
151
|
+
bs.offset += 2;
|
|
152
|
+
if (len == 0) {
|
|
153
|
+
store<u16>(bs.offset, BRACKET_RIGHT);
|
|
154
|
+
bs.offset += 2;
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
ensureU8Lut();
|
|
158
|
+
|
|
159
|
+
const dataStart = src.dataStart;
|
|
160
|
+
for (let i: i32 = 0; i < len; i++) {
|
|
161
|
+
const v = <usize>load<u8>(dataStart + <usize>i);
|
|
162
|
+
const chars = load<u64>(U8_SERIALIZE_LUT + (v << 3));
|
|
163
|
+
const byteCount = <usize>load<u8>(U8_SERIALIZE_LEN_LUT + v);
|
|
164
|
+
store<u64>(bs.offset, chars);
|
|
165
|
+
bs.offset += byteCount;
|
|
166
|
+
}
|
|
167
|
+
store<u16>(bs.offset - 2, BRACKET_RIGHT);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function serializeI8ArrayFast(src: i8[]): void {
|
|
171
|
+
const len = src.length;
|
|
172
|
+
// Worst case: every element is `-DDD,` = 5 chars = 10 bytes; plus 4 for `[]`.
|
|
173
|
+
bs.proposeSize(4 + <u32>len * 10);
|
|
174
|
+
store<u16>(bs.offset, BRACKET_LEFT);
|
|
175
|
+
bs.offset += 2;
|
|
176
|
+
if (len == 0) {
|
|
177
|
+
store<u16>(bs.offset, BRACKET_RIGHT);
|
|
178
|
+
bs.offset += 2;
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
ensureU8Lut();
|
|
182
|
+
|
|
183
|
+
const dataStart = src.dataStart;
|
|
184
|
+
for (let i: i32 = 0; i < len; i++) {
|
|
185
|
+
let signed = load<i8>(dataStart + <usize>i);
|
|
186
|
+
let absVal: u32;
|
|
187
|
+
if (signed < 0) {
|
|
188
|
+
store<u16>(bs.offset, 0x2d); // '-'
|
|
189
|
+
bs.offset += 2;
|
|
190
|
+
absVal = <u32>-(<i32>signed);
|
|
191
|
+
} else {
|
|
192
|
+
absVal = <u32>signed;
|
|
193
|
+
}
|
|
194
|
+
const chars = load<u64>(U8_SERIALIZE_LUT + ((<usize>absVal) << 3));
|
|
195
|
+
const byteCount = <usize>load<u8>(U8_SERIALIZE_LEN_LUT + <usize>absVal);
|
|
196
|
+
store<u64>(bs.offset, chars);
|
|
197
|
+
bs.offset += byteCount;
|
|
198
|
+
}
|
|
199
|
+
store<u16>(bs.offset - 2, BRACKET_RIGHT);
|
|
200
|
+
}
|
|
201
|
+
|
|
56
202
|
export function serializeArray<T extends any[]>(src: T): void {
|
|
203
|
+
// Specialized fast paths fold the per-element comma into the element write,
|
|
204
|
+
// saving one `store<u16>` + advance per iteration. AS folds the type checks
|
|
205
|
+
// at compile time so the non-matching branches don't ship.
|
|
206
|
+
if (isBoolean<valueof<T>>()) {
|
|
207
|
+
// @ts-expect-error: T is bool[]
|
|
208
|
+
serializeBoolArrayFast(changetype<bool[]>(src));
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
if (
|
|
212
|
+
isInteger<valueof<T>>() &&
|
|
213
|
+
!isSigned<valueof<T>>() &&
|
|
214
|
+
sizeof<valueof<T>>() == 1
|
|
215
|
+
) {
|
|
216
|
+
// @ts-expect-error: T is u8[]
|
|
217
|
+
serializeU8ArrayFast(changetype<u8[]>(src));
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
if (
|
|
221
|
+
isInteger<valueof<T>>() &&
|
|
222
|
+
isSigned<valueof<T>>() &&
|
|
223
|
+
sizeof<valueof<T>>() == 1
|
|
224
|
+
) {
|
|
225
|
+
// @ts-expect-error: T is i8[]
|
|
226
|
+
serializeI8ArrayFast(changetype<i8[]>(src));
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
|
|
57
230
|
const len = src.length;
|
|
58
231
|
const end = len - 1;
|
|
59
232
|
let i = 0;
|
|
@@ -63,7 +236,12 @@ export function serializeArray<T extends any[]>(src: T): void {
|
|
|
63
236
|
bs.offset += 4;
|
|
64
237
|
return;
|
|
65
238
|
}
|
|
66
|
-
if (
|
|
239
|
+
if (
|
|
240
|
+
isBoolean<valueof<T>>() ||
|
|
241
|
+
isInteger<valueof<T>>() ||
|
|
242
|
+
isFloat<valueof<T>>() ||
|
|
243
|
+
isString<valueof<T>>()
|
|
244
|
+
) {
|
|
67
245
|
reservePrimitiveArray<valueof<T>>(len);
|
|
68
246
|
} else {
|
|
69
247
|
bs.proposeSize(4 + <u32>(len - 1) * 2);
|
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
import { bs } from "../../../lib/as-bs";
|
|
2
|
-
import {
|
|
2
|
+
import { ensureItoaPairs, itoaFast } from "../../util/itoa-fast";
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
@inline
|
|
6
6
|
export function serializeIntegerUnsafe<T extends number>(data: T): void {
|
|
7
|
-
|
|
8
|
-
bs.offset
|
|
7
|
+
ensureItoaPairs();
|
|
8
|
+
const charsWritten = itoaFast<T>(bs.offset, data);
|
|
9
|
+
bs.offset += (<usize>charsWritten) << 1;
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
// @ts-ignore: inline
|
|
12
13
|
@inline export function serializeInteger<T extends number>(data: T): void {
|
|
14
|
+
ensureItoaPairs();
|
|
13
15
|
bs.ensureSize(sizeof<T>() << 3);
|
|
14
|
-
const
|
|
15
|
-
bs.growSize(
|
|
16
|
-
bs.offset +=
|
|
16
|
+
const charsWritten = itoaFast<T>(bs.offset, data);
|
|
17
|
+
bs.growSize((<u32>charsWritten) << 1);
|
|
18
|
+
bs.offset += (<usize>charsWritten) << 1;
|
|
17
19
|
}
|
|
18
|
-
|
|
19
|
-
// 32 {"x":,"y":,"z"}
|
|
20
|
-
// 18 3.41.28.3
|
|
@@ -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);
|
|
@@ -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) {
|
|
@@ -25,7 +25,11 @@ export function serializeString_SWAR(src: string): void {
|
|
|
25
25
|
const block = load<u64>(srcStart);
|
|
26
26
|
if ((block & 0xff00_ff00_ff00_ff00) != 0) break;
|
|
27
27
|
const lo = block & 0x00ff_00ff_00ff_00ff;
|
|
28
|
-
const asciiMask =
|
|
28
|
+
const asciiMask =
|
|
29
|
+
((lo - 0x0020_0020_0020_0020) |
|
|
30
|
+
((lo ^ 0x0022_0022_0022_0022) - 0x0001_0001_0001_0001) |
|
|
31
|
+
((lo ^ 0x005c_005c_005c_005c) - 0x0001_0001_0001_0001)) &
|
|
32
|
+
(0x0080_0080_0080_0080 & ~lo);
|
|
29
33
|
if (asciiMask != 0) break;
|
|
30
34
|
store<u64>(dst, block);
|
|
31
35
|
srcStart += 8;
|
|
@@ -35,7 +39,8 @@ export function serializeString_SWAR(src: string): void {
|
|
|
35
39
|
|
|
36
40
|
while (srcStart <= srcEnd - 2) {
|
|
37
41
|
const code = load<u16>(srcStart);
|
|
38
|
-
if (code > 0x7f || code == BACK_SLASH || code == QUOTE || code < 32)
|
|
42
|
+
if (code > 0x7f || code == BACK_SLASH || code == QUOTE || code < 32)
|
|
43
|
+
break;
|
|
39
44
|
store<u16>(dst, code);
|
|
40
45
|
srcStart += 2;
|
|
41
46
|
dst += 2;
|
|
@@ -169,7 +174,9 @@ export function serializeString_SWAR(src: string): void {
|
|
|
169
174
|
bs.offset += 2;
|
|
170
175
|
}
|
|
171
176
|
|
|
172
|
-
export function serializeString_SWAR_ExperimentalTableEscapes(
|
|
177
|
+
export function serializeString_SWAR_ExperimentalTableEscapes(
|
|
178
|
+
src: string,
|
|
179
|
+
): void {
|
|
173
180
|
let srcStart = changetype<usize>(src);
|
|
174
181
|
const srcSize = changetype<OBJECT>(srcStart - TOTAL_OVERHEAD).rtSize;
|
|
175
182
|
const srcEnd = srcStart + srcSize;
|
|
@@ -308,9 +315,15 @@ export function serializeString_SWAR_ExperimentalTableEscapes(src: string): void
|
|
|
308
315
|
// Setting bit 8 of each 16-bit lane (high byte LSB) prevents borrow from a
|
|
309
316
|
// low byte underflow from propagating across lane boundaries into the next lane.
|
|
310
317
|
const loSafe = lo | 0x0100_0100_0100_0100;
|
|
311
|
-
const ascii_mask =
|
|
318
|
+
const ascii_mask =
|
|
319
|
+
((loSafe - 0x0020_0020_0020_0020) |
|
|
320
|
+
((loSafe ^ 0x0022_0022_0022_0022) - 0x0001_0001_0001_0001) |
|
|
321
|
+
((loSafe ^ 0x005c_005c_005c_005c) - 0x0001_0001_0001_0001)) &
|
|
322
|
+
(0x0080_0080_0080_0080 & ~lo);
|
|
312
323
|
if (hi == 0) return ascii_mask;
|
|
313
|
-
const hi_mask =
|
|
324
|
+
const hi_mask =
|
|
325
|
+
((block - 0x0100_0100_0100_0100) & ~block & 0x8000_8000_8000_8000) ^
|
|
326
|
+
0x8000_8000_8000_8000;
|
|
314
327
|
return (ascii_mask & (~hi_mask >> 8)) | hi_mask;
|
|
315
328
|
}
|
|
316
329
|
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// Back-compat shim. The canonical fast SWAR atoi/atou implementations live
|
|
2
|
+
// in `deserialize/swar/integer.ts`, using the full tiered stride hierarchy
|
|
3
|
+
// (parse16 -> parse8 -> parse4 -> scalar). These thin wrappers preserve the
|
|
4
|
+
// original `(srcStart, srcEnd, [dstPtr])` signatures used by existing tests
|
|
5
|
+
// and benches.
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
deserializeInteger_SWAR,
|
|
9
|
+
deserializeIntegerField_SWAR,
|
|
10
|
+
deserializeUnsigned_SWAR,
|
|
11
|
+
deserializeUnsignedField_SWAR,
|
|
12
|
+
} from "../deserialize/swar/integer";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Parse an unsigned integer by consuming the whole range as digits.
|
|
16
|
+
*
|
|
17
|
+
* @param srcStart Pointer to the first UTF-16 code unit.
|
|
18
|
+
* @param srcEnd Pointer just past the last code unit.
|
|
19
|
+
* @returns The parsed value, truncated to `T`.
|
|
20
|
+
*/
|
|
21
|
+
// @ts-expect-error: @inline is a valid decorator
|
|
22
|
+
@inline export function atou<T extends number>(
|
|
23
|
+
srcStart: usize,
|
|
24
|
+
srcEnd: usize,
|
|
25
|
+
): T {
|
|
26
|
+
return deserializeUnsigned_SWAR<T>(srcStart, srcEnd);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Parse a signed integer by consuming the whole range as digits, with an
|
|
31
|
+
* optional leading `-`.
|
|
32
|
+
*
|
|
33
|
+
* @param srcStart Pointer to the first UTF-16 code unit.
|
|
34
|
+
* @param srcEnd Pointer just past the last code unit.
|
|
35
|
+
* @returns The parsed value, truncated to `T`.
|
|
36
|
+
*/
|
|
37
|
+
// @ts-expect-error: @inline is a valid decorator
|
|
38
|
+
@inline export function atoi<T extends number>(
|
|
39
|
+
srcStart: usize,
|
|
40
|
+
srcEnd: usize,
|
|
41
|
+
): T {
|
|
42
|
+
return deserializeInteger_SWAR<T>(srcStart, srcEnd);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Scan an unsigned integer, stopping at the first non-digit. Writes the
|
|
47
|
+
* parsed value through `dstPtr` and returns the source position immediately
|
|
48
|
+
* after the last digit.
|
|
49
|
+
*
|
|
50
|
+
* @param srcStart Pointer to the first UTF-16 code unit.
|
|
51
|
+
* @param srcEnd Pointer just past the last code unit.
|
|
52
|
+
* @param dstPtr Destination pointer for the parsed value.
|
|
53
|
+
* @returns The source position immediately after the last digit consumed.
|
|
54
|
+
*/
|
|
55
|
+
// @ts-expect-error: @inline is a valid decorator
|
|
56
|
+
@inline export function atouScan<T extends number>(
|
|
57
|
+
srcStart: usize,
|
|
58
|
+
srcEnd: usize,
|
|
59
|
+
dstPtr: usize,
|
|
60
|
+
): usize {
|
|
61
|
+
return deserializeUnsignedField_SWAR<T>(srcStart, srcEnd, dstPtr, 0);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Scan a signed integer, stopping at the first non-digit. Handles an
|
|
66
|
+
* optional leading `-`. Writes the parsed value through `dstPtr` and
|
|
67
|
+
* returns the source position immediately after the last digit.
|
|
68
|
+
*
|
|
69
|
+
* @param srcStart Pointer to the first UTF-16 code unit.
|
|
70
|
+
* @param srcEnd Pointer just past the last code unit.
|
|
71
|
+
* @param dstPtr Destination pointer for the parsed value.
|
|
72
|
+
* @returns The source position immediately after the last digit consumed.
|
|
73
|
+
*/
|
|
74
|
+
// @ts-expect-error: @inline is a valid decorator
|
|
75
|
+
@inline export function atoiScan<T extends number>(
|
|
76
|
+
srcStart: usize,
|
|
77
|
+
srcEnd: usize,
|
|
78
|
+
dstPtr: usize,
|
|
79
|
+
): usize {
|
|
80
|
+
return deserializeIntegerField_SWAR<T>(srcStart, srcEnd, dstPtr, 0);
|
|
81
|
+
}
|
package/assembly/util/concat.ts
CHANGED
|
@@ -4,6 +4,10 @@ export function concat(left: string, right: string): string {
|
|
|
4
4
|
const rightSize: usize = bytes(right);
|
|
5
5
|
const jointSize: usize = leftSize + rightSize;
|
|
6
6
|
const jointPtr = __renew(changetype<usize>(left), jointSize);
|
|
7
|
-
memory.copy(
|
|
7
|
+
memory.copy(
|
|
8
|
+
changetype<usize>(left) + leftSize,
|
|
9
|
+
changetype<usize>(right),
|
|
10
|
+
rightSize,
|
|
11
|
+
);
|
|
8
12
|
return changetype<string>(jointPtr);
|
|
9
13
|
}
|