json-as 1.2.6 → 1.3.1
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 +417 -0
- package/README.md +135 -36
- package/assembly/custom/util.ts +24 -70
- package/assembly/deserialize/float.ts +181 -0
- package/assembly/deserialize/helpers/uint.ts +12 -0
- package/assembly/deserialize/index/arbitrary.ts +25 -0
- package/assembly/deserialize/index/array.ts +61 -0
- package/assembly/deserialize/index/bool.ts +1 -0
- package/assembly/deserialize/index/date.ts +1 -0
- package/assembly/deserialize/index/float.ts +1 -0
- package/assembly/deserialize/index/integer.ts +1 -0
- package/assembly/deserialize/index/map.ts +1 -0
- package/assembly/deserialize/index/object.ts +1 -0
- package/assembly/deserialize/index/raw.ts +1 -0
- package/assembly/deserialize/index/set.ts +1 -0
- package/assembly/deserialize/index/staticarray.ts +1 -0
- package/assembly/deserialize/index/string.ts +15 -0
- package/assembly/deserialize/index/struct.ts +1 -0
- package/assembly/deserialize/index/typedarray.ts +15 -0
- package/assembly/deserialize/index/unsigned.ts +1 -0
- package/assembly/deserialize/index.ts +14 -0
- package/assembly/deserialize/integer.ts +42 -0
- package/assembly/deserialize/simd/array/integer.ts +307 -0
- package/assembly/deserialize/simd/string.ts +130 -11
- package/assembly/deserialize/simple/arbitrary.ts +5 -12
- package/assembly/deserialize/simple/array/arbitrary.ts +12 -36
- package/assembly/deserialize/simple/array/array.ts +2 -8
- package/assembly/deserialize/simple/array/bool.ts +2 -8
- package/assembly/deserialize/simple/array/box.ts +2 -8
- package/assembly/deserialize/simple/array/float.ts +2 -8
- package/assembly/deserialize/simple/array/integer.ts +2 -8
- package/assembly/deserialize/simple/array/map.ts +6 -26
- package/assembly/deserialize/simple/array/object.ts +6 -26
- package/assembly/deserialize/simple/array/raw.ts +18 -61
- package/assembly/deserialize/simple/array/string.ts +5 -10
- package/assembly/deserialize/simple/array/struct.ts +6 -26
- package/assembly/deserialize/simple/array.ts +2 -5
- package/assembly/deserialize/simple/bool.ts +2 -6
- package/assembly/deserialize/simple/map.ts +29 -102
- package/assembly/deserialize/simple/object.ts +24 -81
- package/assembly/deserialize/simple/raw.ts +1 -4
- package/assembly/deserialize/simple/set.ts +11 -37
- package/assembly/deserialize/simple/staticarray/array.ts +1 -1
- package/assembly/deserialize/simple/staticarray/bool.ts +1 -1
- package/assembly/deserialize/simple/staticarray/float.ts +1 -1
- package/assembly/deserialize/simple/staticarray/integer.ts +1 -1
- package/assembly/deserialize/simple/staticarray/string.ts +7 -14
- package/assembly/deserialize/simple/staticarray/struct.ts +1 -1
- package/assembly/deserialize/simple/staticarray.ts +57 -21
- package/assembly/deserialize/simple/string.ts +90 -10
- package/assembly/deserialize/simple/struct.ts +25 -121
- package/assembly/deserialize/simple/typedarray.ts +94 -0
- package/assembly/deserialize/swar/array/arbitrary.ts +8 -0
- package/assembly/deserialize/swar/array/array.ts +39 -0
- package/assembly/deserialize/swar/array/bool.ts +47 -0
- package/assembly/deserialize/swar/array/box.ts +8 -0
- package/assembly/deserialize/swar/array/float.ts +39 -0
- package/assembly/deserialize/swar/array/integer.ts +461 -0
- package/assembly/deserialize/swar/array/map.ts +7 -0
- package/assembly/deserialize/swar/array/object.ts +44 -0
- package/assembly/deserialize/swar/array/raw.ts +8 -0
- package/assembly/deserialize/swar/array/shared.ts +96 -0
- package/assembly/deserialize/swar/array/string.ts +39 -0
- package/assembly/deserialize/swar/array/struct.ts +44 -0
- package/assembly/deserialize/swar/array.ts +49 -0
- package/assembly/deserialize/swar/string.ts +648 -15
- package/assembly/deserialize/unsigned.ts +75 -0
- package/assembly/index.d.ts +1 -3
- package/assembly/index.ts +316 -374
- package/assembly/serialize/index/arbitrary.ts +75 -0
- package/assembly/serialize/index/array.ts +1 -0
- package/assembly/serialize/index/bool.ts +1 -0
- package/assembly/serialize/index/date.ts +1 -0
- package/assembly/serialize/index/float.ts +1 -0
- package/assembly/serialize/index/integer.ts +1 -0
- package/assembly/serialize/index/map.ts +1 -0
- package/assembly/serialize/index/object.ts +46 -0
- package/assembly/serialize/index/raw.ts +1 -0
- package/assembly/serialize/index/set.ts +1 -0
- package/assembly/serialize/index/staticarray.ts +1 -0
- package/assembly/serialize/index/string.ts +15 -0
- package/assembly/serialize/index/struct.ts +1 -0
- package/assembly/serialize/index/typedarray.ts +66 -0
- package/assembly/serialize/index.ts +13 -0
- package/assembly/serialize/simd/string.ts +4 -13
- package/assembly/serialize/simple/arbitrary.ts +6 -0
- package/assembly/serialize/simple/raw.ts +1 -5
- package/assembly/serialize/simple/string.ts +3 -11
- package/assembly/serialize/simple/typedarray.ts +63 -0
- package/assembly/serialize/swar/string.ts +6 -21
- package/assembly/util/concat.ts +1 -5
- package/assembly/util/index.ts +1 -0
- package/assembly/util/masks.ts +12 -18
- package/assembly/util/memory.ts +0 -0
- package/assembly/util/snp.ts +1 -4
- package/assembly/util/stringScan.ts +24 -0
- package/assembly/util/swar.ts +50 -6
- package/lib/as-bs.ts +137 -127
- package/package.json +26 -5
- package/transform/lib/builder.d.ts.map +1 -1
- package/transform/lib/builder.js +5 -13
- 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 +672 -757
- 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 +8 -9
- 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 +6 -0
- package/transform/lib/types.d.ts.map +1 -1
- package/transform/lib/types.js +83 -21
- 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 +1 -2
- package/transform/lib/visitor.js.map +1 -1
- package/.prettierrc +0 -3
- package/ARCHITECTURE.md +0 -320
- package/CONTRIBUTING.md +0 -238
- package/TODO +0 -1
- package/assembly/deserialize/simple/float.ts +0 -11
- package/assembly/deserialize/simple/integer.ts +0 -9
- package/assembly/test.ts +0 -30
- package/eslint.config.js +0 -60
- package/lib/tsconfig.json +0 -8
- package/tools/assemblyscript-eslint-local.js +0 -29
- package/tools/assemblyscript-eslint.js +0 -29
- package/transform/tsconfig.json +0 -35
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { bs } from "../../../lib/as-bs";
|
|
2
|
+
import { OBJECT, TOTAL_OVERHEAD } from "rt/common";
|
|
3
|
+
import { BACK_SLASH, QUOTE } from "../../custom/chars";
|
|
2
4
|
import { DESERIALIZE_ESCAPE_TABLE } from "../../globals/tables";
|
|
3
5
|
import { hex4_to_u16_swar } from "../../util/swar";
|
|
4
6
|
|
|
@@ -38,12 +40,26 @@ import { hex4_to_u16_swar } from "../../util/swar";
|
|
|
38
40
|
* @param dst buffer to write to
|
|
39
41
|
* @returns number of bytes written
|
|
40
42
|
*/
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
// @ts-expect-error: @inline is a valid decorator
|
|
44
|
+
@inline function copyStringFromSource(srcStart: usize, byteLength: usize): string {
|
|
45
|
+
if (byteLength == 0) return changetype<string>("");
|
|
46
|
+
const out = __new(byteLength, idof<string>());
|
|
47
|
+
memory.copy(out, srcStart, byteLength);
|
|
48
|
+
return changetype<string>(out);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// @ts-expect-error: @inline is a valid decorator
|
|
52
|
+
@inline function deserializeEscapedString_SWAR(payloadStart: usize, escapeStart: usize, srcEnd: usize): string {
|
|
45
53
|
const srcEnd8 = srcEnd - 8;
|
|
46
|
-
|
|
54
|
+
const prefixLen = <u32>(escapeStart - payloadStart);
|
|
55
|
+
const outStart = bs.offset - bs.buffer;
|
|
56
|
+
bs.ensureSize(<u32>(srcEnd - payloadStart));
|
|
57
|
+
if (prefixLen != 0) {
|
|
58
|
+
memory.copy(bs.offset, payloadStart, prefixLen);
|
|
59
|
+
bs.offset += prefixLen;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
let srcStart = escapeStart;
|
|
47
63
|
|
|
48
64
|
while (srcStart < srcEnd8) {
|
|
49
65
|
const block = load<u64>(srcStart);
|
|
@@ -124,9 +140,632 @@ export function deserializeString_SWAR(srcStart: usize, srcEnd: usize): string {
|
|
|
124
140
|
|
|
125
141
|
bs.offset += 2;
|
|
126
142
|
}
|
|
127
|
-
return bs.
|
|
143
|
+
return bs.sliceOut<string>(outStart);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export function deserializeString_SWAR(srcStart: usize, srcEnd: usize): string {
|
|
147
|
+
// Strip quotes
|
|
148
|
+
srcStart += 2;
|
|
149
|
+
srcEnd -= 2;
|
|
150
|
+
const payloadStart = srcStart;
|
|
151
|
+
const srcEnd8 = srcEnd - 8;
|
|
152
|
+
|
|
153
|
+
while (srcStart < srcEnd8) {
|
|
154
|
+
const block = load<u64>(srcStart);
|
|
155
|
+
let mask = inline.always(backslash_mask_unsafe(block));
|
|
156
|
+
|
|
157
|
+
if (mask === 0) {
|
|
158
|
+
srcStart += 8;
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
do {
|
|
163
|
+
const laneIdx = usize(ctz(mask) >> 3);
|
|
164
|
+
mask &= mask - 1;
|
|
165
|
+
const srcIdx = srcStart + laneIdx;
|
|
166
|
+
const header = load<u32>(srcIdx);
|
|
167
|
+
|
|
168
|
+
// Detect false positive (code unit where low byte is 0x5C)
|
|
169
|
+
if ((header & 0xffff) !== 0x5c) continue;
|
|
170
|
+
|
|
171
|
+
return inline.always(deserializeEscapedString_SWAR(payloadStart, srcIdx, srcEnd));
|
|
172
|
+
} while (mask !== 0);
|
|
173
|
+
|
|
174
|
+
srcStart += 8;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
while (srcStart < srcEnd) {
|
|
178
|
+
if (load<u16>(srcStart) == BACK_SLASH) {
|
|
179
|
+
return inline.always(deserializeEscapedString_SWAR(payloadStart, srcStart, srcEnd));
|
|
180
|
+
}
|
|
181
|
+
srcStart += 2;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return copyStringFromSource(payloadStart, srcEnd - payloadStart);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// /**
|
|
188
|
+
// * Deserializes a quoted JSON string into a reused/renewed destination string buffer.
|
|
189
|
+
// * @param srcStart pointer to opening quote
|
|
190
|
+
// * @param srcEnd pointer to closing quote
|
|
191
|
+
// * @param outPtr existing destination string pointer (or 0)
|
|
192
|
+
// * @returns next unread source pointer
|
|
193
|
+
// */
|
|
194
|
+
// export function deserializeString_SWAR_TO(srcStart: usize, srcEnd: usize, outPtr: usize): usize {
|
|
195
|
+
// srcStart += 2;
|
|
196
|
+
// let dst = outPtr;
|
|
197
|
+
// const srcEnd8 = srcEnd - 8;
|
|
198
|
+
// const byteSize = srcEnd - srcStart;
|
|
199
|
+
// if (!dst) {
|
|
200
|
+
// dst = __new(byteSize, idof<string>());
|
|
201
|
+
// } else if (changetype<OBJECT>(dst - TOTAL_OVERHEAD).rtSize < <u32>byteSize) {
|
|
202
|
+
// dst = __renew(dst, byteSize);
|
|
203
|
+
// }
|
|
204
|
+
// let offset = dst;
|
|
205
|
+
|
|
206
|
+
// while (srcStart < srcEnd8) {
|
|
207
|
+
// const block = load<u64>(srcStart);
|
|
208
|
+
// store<u64>(offset, block);
|
|
209
|
+
|
|
210
|
+
// let mask = inline.always(backslash_mask_unsafe(block));
|
|
211
|
+
|
|
212
|
+
// if (mask === 0) {
|
|
213
|
+
// srcStart += 8;
|
|
214
|
+
// offset += 8;
|
|
215
|
+
// continue;
|
|
216
|
+
// }
|
|
217
|
+
|
|
218
|
+
// do {
|
|
219
|
+
// const laneIdx = usize(ctz(mask) >> 3); // 0 2 4 6
|
|
220
|
+
// mask &= mask - 1;
|
|
221
|
+
// const srcIdx = srcStart + laneIdx;
|
|
222
|
+
// const dstIdx = offset + laneIdx;
|
|
223
|
+
// const header = load<u32>(srcIdx);
|
|
224
|
+
// const code = <u16>(header >> 16);
|
|
225
|
+
|
|
226
|
+
// if ((header & 0xffff) !== 0x5c) continue;
|
|
227
|
+
|
|
228
|
+
// if (code !== 0x75) {
|
|
229
|
+
// const escaped = load<u16>(DESERIALIZE_ESCAPE_TABLE + code);
|
|
230
|
+
// mask &= mask - usize(escaped === 0x5c);
|
|
231
|
+
// store<u16>(dstIdx, escaped);
|
|
232
|
+
// const copyStart = srcIdx + 4;
|
|
233
|
+
// if (copyStart < srcEnd) {
|
|
234
|
+
// const copyBytes = min<usize>(4, srcEnd - copyStart);
|
|
235
|
+
// memory.copy(dstIdx + 2, copyStart, copyBytes);
|
|
236
|
+
// }
|
|
237
|
+
|
|
238
|
+
// const l6 = usize(laneIdx === 6);
|
|
239
|
+
// offset -= (1 - l6) << 1;
|
|
240
|
+
// srcStart += l6 << 1;
|
|
241
|
+
// continue;
|
|
242
|
+
// }
|
|
243
|
+
|
|
244
|
+
// const block = load<u64>(srcIdx, 4); // XXXX
|
|
245
|
+
// const escaped = hex4_to_u16_swar(block);
|
|
246
|
+
// store<u16>(dstIdx, escaped);
|
|
247
|
+
// srcStart += 4 + laneIdx;
|
|
248
|
+
// offset -= 6 - laneIdx;
|
|
249
|
+
// } while (mask !== 0);
|
|
250
|
+
|
|
251
|
+
// offset += 8;
|
|
252
|
+
// srcStart += 8;
|
|
253
|
+
// }
|
|
254
|
+
|
|
255
|
+
// while (srcStart < srcEnd) {
|
|
256
|
+
// const block = load<u16>(srcStart);
|
|
257
|
+
// store<u16>(offset, block);
|
|
258
|
+
// srcStart += 2;
|
|
259
|
+
|
|
260
|
+
// if (block !== 0x5c) {
|
|
261
|
+
// offset += 2;
|
|
262
|
+
// continue;
|
|
263
|
+
// }
|
|
264
|
+
|
|
265
|
+
// const code = load<u16>(srcStart);
|
|
266
|
+
// if (code !== 0x75) {
|
|
267
|
+
// const block = load<u16>(srcStart);
|
|
268
|
+
// const escape = load<u16>(DESERIALIZE_ESCAPE_TABLE + block);
|
|
269
|
+
// store<u16>(offset, escape);
|
|
270
|
+
// srcStart += 2;
|
|
271
|
+
// } else {
|
|
272
|
+
// const block = load<u64>(srcStart, 2); // XXXX
|
|
273
|
+
// const escaped = hex4_to_u16_swar(block);
|
|
274
|
+
// store<u16>(offset, escaped);
|
|
275
|
+
// srcStart += 10;
|
|
276
|
+
// }
|
|
277
|
+
|
|
278
|
+
// offset += 2;
|
|
279
|
+
// }
|
|
280
|
+
// if (offset - dst != byteSize) {
|
|
281
|
+
// dst = __renew(dst, offset - dst);
|
|
282
|
+
// }
|
|
283
|
+
// return srcEnd + 2;
|
|
284
|
+
// }
|
|
285
|
+
|
|
286
|
+
// Scans a quoted string value, writes into the destination field, and returns next unread src pointer.
|
|
287
|
+
// @ts-expect-error: @inline is a valid decorator
|
|
288
|
+
@inline function writeStringToField(dstFieldPtr: usize, srcStart: usize, byteLength: u32): void {
|
|
289
|
+
if (byteLength == 0) {
|
|
290
|
+
store<usize>(dstFieldPtr, changetype<usize>(""));
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const current = load<usize>(dstFieldPtr);
|
|
295
|
+
let stringPtr: usize;
|
|
296
|
+
if (current != 0 && changetype<OBJECT>(current - TOTAL_OVERHEAD).rtSize == byteLength) {
|
|
297
|
+
stringPtr = current;
|
|
298
|
+
} else if (current != 0 && current != changetype<usize>("")) {
|
|
299
|
+
stringPtr = __renew(current, byteLength);
|
|
300
|
+
store<usize>(dstFieldPtr, stringPtr);
|
|
301
|
+
} else {
|
|
302
|
+
stringPtr = __new(byteLength, idof<string>());
|
|
303
|
+
store<usize>(dstFieldPtr, stringPtr);
|
|
304
|
+
}
|
|
305
|
+
memory.copy(stringPtr, srcStart, byteLength);
|
|
128
306
|
}
|
|
129
307
|
|
|
308
|
+
/*
|
|
309
|
+
export function deserializeStringField_SWAR<T extends string | null>(srcStart: usize, srcEnd: usize, dstFieldPtr: usize): usize {
|
|
310
|
+
if (srcStart + 2 > srcEnd || load<u16>(srcStart) != QUOTE) abort("Expected leading quote");
|
|
311
|
+
|
|
312
|
+
const payloadStart = srcStart + 2;
|
|
313
|
+
const srcEnd8 = srcEnd >= 8 ? srcEnd - 8 : 0;
|
|
314
|
+
srcStart = payloadStart;
|
|
315
|
+
|
|
316
|
+
while (srcStart <= srcEnd8) {
|
|
317
|
+
let mask = inline.always(backslash_or_quote_mask(load<u64>(srcStart)));
|
|
318
|
+
|
|
319
|
+
if (mask === 0) {
|
|
320
|
+
srcStart += 8;
|
|
321
|
+
continue;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
do {
|
|
325
|
+
const laneIdx = usize(ctz(mask) >> 3);
|
|
326
|
+
mask &= ~(0xffff << (laneIdx << 3));
|
|
327
|
+
// since we clear the entire byte, we can guarentee that any discovered lane where char == QUOTE is unescaped and a terminator.
|
|
328
|
+
const srcIdx = srcStart + laneIdx;
|
|
329
|
+
const char = load<u16>(srcIdx);
|
|
330
|
+
|
|
331
|
+
if (char == QUOTE) {
|
|
332
|
+
writeStringToField(dstFieldPtr, payloadStart, <u32>(srcIdx - payloadStart));
|
|
333
|
+
return srcIdx + 2;
|
|
334
|
+
}
|
|
335
|
+
if (char != BACK_SLASH) continue;
|
|
336
|
+
|
|
337
|
+
bs.offset = bs.buffer;
|
|
338
|
+
bs.ensureSize(<u32>(srcEnd - payloadStart));
|
|
339
|
+
const prefixLen = <u32>(srcIdx - payloadStart);
|
|
340
|
+
if (prefixLen != 0) {
|
|
341
|
+
memory.copy(bs.buffer, payloadStart, prefixLen);
|
|
342
|
+
bs.offset += prefixLen;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
const chunk = load<u32>(srcIdx);
|
|
346
|
+
const code = <u16>(chunk >> 16);
|
|
347
|
+
|
|
348
|
+
if (code !== 0x75) {
|
|
349
|
+
store<u16>(bs.offset, load<u16>(DESERIALIZE_ESCAPE_TABLE + code));
|
|
350
|
+
bs.offset += 2;
|
|
351
|
+
let lastPtr = srcIdx + 4;
|
|
352
|
+
srcStart = lastPtr;
|
|
353
|
+
while (srcStart <= srcEnd8) {
|
|
354
|
+
const blockStart = srcStart;
|
|
355
|
+
let escapedMask = inline.always(backslash_or_quote_mask(load<u64>(srcStart)));
|
|
356
|
+
if (escapedMask === 0) {
|
|
357
|
+
srcStart += 8;
|
|
358
|
+
continue;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
do {
|
|
362
|
+
const escapedLaneIdx = usize(ctz(escapedMask) >> 3);
|
|
363
|
+
escapedMask &= escapedMask - 1;
|
|
364
|
+
const escapedIdx = srcStart + escapedLaneIdx;
|
|
365
|
+
const escapedChar = load<u16>(escapedIdx);
|
|
366
|
+
|
|
367
|
+
if (escapedChar == QUOTE) {
|
|
368
|
+
const runLen = <u32>(escapedIdx - lastPtr);
|
|
369
|
+
if (runLen != 0) {
|
|
370
|
+
memory.copy(bs.offset, lastPtr, runLen);
|
|
371
|
+
bs.offset += runLen;
|
|
372
|
+
}
|
|
373
|
+
writeStringToField(dstFieldPtr, bs.buffer, <u32>(bs.offset - bs.buffer));
|
|
374
|
+
bs.offset = bs.buffer;
|
|
375
|
+
return escapedIdx + 2;
|
|
376
|
+
}
|
|
377
|
+
if (escapedChar != BACK_SLASH) continue;
|
|
378
|
+
|
|
379
|
+
const runLen = <u32>(escapedIdx - lastPtr);
|
|
380
|
+
if (runLen != 0) {
|
|
381
|
+
memory.copy(bs.offset, lastPtr, runLen);
|
|
382
|
+
bs.offset += runLen;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
const escapedChunk = load<u32>(escapedIdx);
|
|
386
|
+
const escapedCode = <u16>(escapedChunk >> 16);
|
|
387
|
+
if (escapedCode !== 0x75) {
|
|
388
|
+
store<u16>(bs.offset, load<u16>(DESERIALIZE_ESCAPE_TABLE + escapedCode));
|
|
389
|
+
bs.offset += 2;
|
|
390
|
+
lastPtr = escapedIdx + 4;
|
|
391
|
+
} else {
|
|
392
|
+
store<u16>(bs.offset, hex4_to_u16_swar(load<u64>(escapedIdx, 4)));
|
|
393
|
+
bs.offset += 2;
|
|
394
|
+
lastPtr = escapedIdx + 12;
|
|
395
|
+
}
|
|
396
|
+
srcStart = lastPtr;
|
|
397
|
+
break;
|
|
398
|
+
} while (escapedMask !== 0);
|
|
399
|
+
|
|
400
|
+
if (srcStart == blockStart) srcStart += 8;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
while (srcStart < srcEnd) {
|
|
404
|
+
const tailChar = load<u16>(srcStart);
|
|
405
|
+
if (tailChar == QUOTE) {
|
|
406
|
+
const runLen = <u32>(srcStart - lastPtr);
|
|
407
|
+
if (runLen != 0) {
|
|
408
|
+
memory.copy(bs.offset, lastPtr, runLen);
|
|
409
|
+
bs.offset += runLen;
|
|
410
|
+
}
|
|
411
|
+
writeStringToField(dstFieldPtr, bs.buffer, <u32>(bs.offset - bs.buffer));
|
|
412
|
+
bs.offset = bs.buffer;
|
|
413
|
+
return srcStart + 2;
|
|
414
|
+
}
|
|
415
|
+
if (tailChar != BACK_SLASH) {
|
|
416
|
+
srcStart += 2;
|
|
417
|
+
continue;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
const runLen = <u32>(srcStart - lastPtr);
|
|
421
|
+
if (runLen != 0) {
|
|
422
|
+
memory.copy(bs.offset, lastPtr, runLen);
|
|
423
|
+
bs.offset += runLen;
|
|
424
|
+
}
|
|
425
|
+
const tailCode = load<u16>(srcStart, 2);
|
|
426
|
+
if (tailCode !== 0x75) {
|
|
427
|
+
store<u16>(bs.offset, load<u16>(DESERIALIZE_ESCAPE_TABLE + tailCode));
|
|
428
|
+
bs.offset += 2;
|
|
429
|
+
srcStart += 4;
|
|
430
|
+
} else {
|
|
431
|
+
store<u16>(bs.offset, hex4_to_u16_swar(load<u64>(srcStart, 4)));
|
|
432
|
+
bs.offset += 2;
|
|
433
|
+
srcStart += 12;
|
|
434
|
+
}
|
|
435
|
+
lastPtr = srcStart;
|
|
436
|
+
}
|
|
437
|
+
bs.offset = bs.buffer;
|
|
438
|
+
return srcStart;
|
|
439
|
+
} else {
|
|
440
|
+
store<u16>(bs.offset, hex4_to_u16_swar(load<u64>(srcIdx, 4)));
|
|
441
|
+
bs.offset += 2;
|
|
442
|
+
let lastPtr = srcIdx + 12;
|
|
443
|
+
srcStart = lastPtr;
|
|
444
|
+
while (srcStart <= srcEnd8) {
|
|
445
|
+
const blockStart = srcStart;
|
|
446
|
+
let escapedMask = inline.always(backslash_or_quote_mask(load<u64>(srcStart)));
|
|
447
|
+
if (escapedMask === 0) {
|
|
448
|
+
srcStart += 8;
|
|
449
|
+
continue;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
do {
|
|
453
|
+
const escapedLaneIdx = usize(ctz(escapedMask) >> 3);
|
|
454
|
+
escapedMask &= escapedMask - 1;
|
|
455
|
+
const escapedIdx = srcStart + escapedLaneIdx;
|
|
456
|
+
const escapedChar = load<u16>(escapedIdx);
|
|
457
|
+
|
|
458
|
+
if (escapedChar == QUOTE) {
|
|
459
|
+
const runLen = <u32>(escapedIdx - lastPtr);
|
|
460
|
+
if (runLen != 0) {
|
|
461
|
+
memory.copy(bs.offset, lastPtr, runLen);
|
|
462
|
+
bs.offset += runLen;
|
|
463
|
+
}
|
|
464
|
+
writeStringToField(dstFieldPtr, bs.buffer, <u32>(bs.offset - bs.buffer));
|
|
465
|
+
bs.offset = bs.buffer;
|
|
466
|
+
return escapedIdx + 2;
|
|
467
|
+
}
|
|
468
|
+
if (escapedChar != BACK_SLASH) continue;
|
|
469
|
+
|
|
470
|
+
const runLen = <u32>(escapedIdx - lastPtr);
|
|
471
|
+
if (runLen != 0) {
|
|
472
|
+
memory.copy(bs.offset, lastPtr, runLen);
|
|
473
|
+
bs.offset += runLen;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
const escapedChunk = load<u32>(escapedIdx);
|
|
477
|
+
const escapedCode = <u16>(escapedChunk >> 16);
|
|
478
|
+
if (escapedCode !== 0x75) {
|
|
479
|
+
store<u16>(bs.offset, load<u16>(DESERIALIZE_ESCAPE_TABLE + escapedCode));
|
|
480
|
+
bs.offset += 2;
|
|
481
|
+
lastPtr = escapedIdx + 4;
|
|
482
|
+
} else {
|
|
483
|
+
store<u16>(bs.offset, hex4_to_u16_swar(load<u64>(escapedIdx, 4)));
|
|
484
|
+
bs.offset += 2;
|
|
485
|
+
lastPtr = escapedIdx + 12;
|
|
486
|
+
}
|
|
487
|
+
srcStart = lastPtr;
|
|
488
|
+
break;
|
|
489
|
+
} while (escapedMask !== 0);
|
|
490
|
+
|
|
491
|
+
if (srcStart == blockStart) srcStart += 8;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
while (srcStart < srcEnd) {
|
|
495
|
+
const tailChar = load<u16>(srcStart);
|
|
496
|
+
if (tailChar == QUOTE) {
|
|
497
|
+
const runLen = <u32>(srcStart - lastPtr);
|
|
498
|
+
if (runLen != 0) {
|
|
499
|
+
memory.copy(bs.offset, lastPtr, runLen);
|
|
500
|
+
bs.offset += runLen;
|
|
501
|
+
}
|
|
502
|
+
writeStringToField(dstFieldPtr, bs.buffer, <u32>(bs.offset - bs.buffer));
|
|
503
|
+
bs.offset = bs.buffer;
|
|
504
|
+
return srcStart + 2;
|
|
505
|
+
}
|
|
506
|
+
if (tailChar != BACK_SLASH) {
|
|
507
|
+
srcStart += 2;
|
|
508
|
+
continue;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
const runLen = <u32>(srcStart - lastPtr);
|
|
512
|
+
if (runLen != 0) {
|
|
513
|
+
memory.copy(bs.offset, lastPtr, runLen);
|
|
514
|
+
bs.offset += runLen;
|
|
515
|
+
}
|
|
516
|
+
const tailCode = load<u16>(srcStart, 2);
|
|
517
|
+
if (tailCode !== 0x75) {
|
|
518
|
+
store<u16>(bs.offset, load<u16>(DESERIALIZE_ESCAPE_TABLE + tailCode));
|
|
519
|
+
bs.offset += 2;
|
|
520
|
+
srcStart += 4;
|
|
521
|
+
} else {
|
|
522
|
+
store<u16>(bs.offset, hex4_to_u16_swar(load<u64>(srcStart, 4)));
|
|
523
|
+
bs.offset += 2;
|
|
524
|
+
srcStart += 12;
|
|
525
|
+
}
|
|
526
|
+
lastPtr = srcStart;
|
|
527
|
+
}
|
|
528
|
+
bs.offset = bs.buffer;
|
|
529
|
+
return srcStart;
|
|
530
|
+
}
|
|
531
|
+
} while (mask !== 0);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
while (srcStart < srcEnd) {
|
|
535
|
+
const char = load<u16>(srcStart);
|
|
536
|
+
if (char == QUOTE) {
|
|
537
|
+
writeStringToField(dstFieldPtr, payloadStart, <u32>(srcStart - payloadStart));
|
|
538
|
+
return srcStart + 2;
|
|
539
|
+
}
|
|
540
|
+
if (char == BACK_SLASH) {
|
|
541
|
+
bs.offset = bs.buffer;
|
|
542
|
+
bs.ensureSize(<u32>(srcEnd - payloadStart));
|
|
543
|
+
const prefixLen = <u32>(srcStart - payloadStart);
|
|
544
|
+
if (prefixLen != 0) {
|
|
545
|
+
memory.copy(bs.buffer, payloadStart, prefixLen);
|
|
546
|
+
bs.offset += prefixLen;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
let lastPtr = srcStart;
|
|
550
|
+
const code = load<u16>(srcStart, 2);
|
|
551
|
+
if (code !== 0x75) {
|
|
552
|
+
store<u16>(bs.offset, load<u16>(DESERIALIZE_ESCAPE_TABLE + code));
|
|
553
|
+
bs.offset += 2;
|
|
554
|
+
srcStart += 4;
|
|
555
|
+
} else {
|
|
556
|
+
store<u16>(bs.offset, hex4_to_u16_swar(load<u64>(srcStart, 4)));
|
|
557
|
+
bs.offset += 2;
|
|
558
|
+
srcStart += 12;
|
|
559
|
+
}
|
|
560
|
+
lastPtr = srcStart;
|
|
561
|
+
|
|
562
|
+
while (srcStart < srcEnd) {
|
|
563
|
+
const tailChar = load<u16>(srcStart);
|
|
564
|
+
if (tailChar == QUOTE) {
|
|
565
|
+
const runLen = <u32>(srcStart - lastPtr);
|
|
566
|
+
if (runLen != 0) {
|
|
567
|
+
memory.copy(bs.offset, lastPtr, runLen);
|
|
568
|
+
bs.offset += runLen;
|
|
569
|
+
}
|
|
570
|
+
writeStringToField(dstFieldPtr, bs.buffer, <u32>(bs.offset - bs.buffer));
|
|
571
|
+
bs.offset = bs.buffer;
|
|
572
|
+
return srcStart + 2;
|
|
573
|
+
}
|
|
574
|
+
if (tailChar != BACK_SLASH) {
|
|
575
|
+
srcStart += 2;
|
|
576
|
+
continue;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
const runLen = <u32>(srcStart - lastPtr);
|
|
580
|
+
if (runLen != 0) {
|
|
581
|
+
memory.copy(bs.offset, lastPtr, runLen);
|
|
582
|
+
bs.offset += runLen;
|
|
583
|
+
}
|
|
584
|
+
const tailCode = load<u16>(srcStart, 2);
|
|
585
|
+
if (tailCode !== 0x75) {
|
|
586
|
+
store<u16>(bs.offset, load<u16>(DESERIALIZE_ESCAPE_TABLE + tailCode));
|
|
587
|
+
bs.offset += 2;
|
|
588
|
+
srcStart += 4;
|
|
589
|
+
} else {
|
|
590
|
+
store<u16>(bs.offset, hex4_to_u16_swar(load<u64>(srcStart, 4)));
|
|
591
|
+
bs.offset += 2;
|
|
592
|
+
srcStart += 12;
|
|
593
|
+
}
|
|
594
|
+
lastPtr = srcStart;
|
|
595
|
+
}
|
|
596
|
+
bs.offset = bs.buffer;
|
|
597
|
+
return srcStart;
|
|
598
|
+
}
|
|
599
|
+
srcStart += 2;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
return srcStart;
|
|
603
|
+
}
|
|
604
|
+
*/
|
|
605
|
+
|
|
606
|
+
// @ts-expect-error: @inline is a valid decorator
|
|
607
|
+
@inline function deserializeEscapedStringScan_SWAR(payloadStart: usize, escapeStart: usize, srcEnd: usize, dstFieldPtr: usize): usize {
|
|
608
|
+
const prefixLen = <u32>(escapeStart - payloadStart);
|
|
609
|
+
const srcEnd8 = srcEnd >= 8 ? srcEnd - 8 : 0;
|
|
610
|
+
const outStart = bs.offset - bs.buffer;
|
|
611
|
+
bs.ensureSize(<u32>(srcEnd - payloadStart));
|
|
612
|
+
if (prefixLen != 0) {
|
|
613
|
+
memory.copy(bs.offset, payloadStart, prefixLen);
|
|
614
|
+
bs.offset += prefixLen;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
let lastPtr = escapeStart;
|
|
618
|
+
let srcStart = escapeStart;
|
|
619
|
+
|
|
620
|
+
while (srcStart <= srcEnd8) {
|
|
621
|
+
const blockStart = srcStart;
|
|
622
|
+
let mask = inline.always(backslash_or_quote_mask(load<u64>(srcStart)));
|
|
623
|
+
if (mask === 0) {
|
|
624
|
+
srcStart += 8;
|
|
625
|
+
continue;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
do {
|
|
629
|
+
const laneIdx = usize(ctz(mask) >> 3);
|
|
630
|
+
mask &= mask - 1;
|
|
631
|
+
const srcIdx = srcStart + laneIdx;
|
|
632
|
+
const char = load<u16>(srcIdx);
|
|
633
|
+
if (char == QUOTE) {
|
|
634
|
+
const runLen = <u32>(srcIdx - lastPtr);
|
|
635
|
+
if (runLen != 0) {
|
|
636
|
+
memory.copy(bs.offset, lastPtr, runLen);
|
|
637
|
+
bs.offset += runLen;
|
|
638
|
+
}
|
|
639
|
+
bs.toField(outStart, dstFieldPtr);
|
|
640
|
+
return srcIdx + 2;
|
|
641
|
+
}
|
|
642
|
+
if (char != BACK_SLASH) continue;
|
|
643
|
+
|
|
644
|
+
const runLen = <u32>(srcIdx - lastPtr);
|
|
645
|
+
if (runLen != 0) {
|
|
646
|
+
memory.copy(bs.offset, lastPtr, runLen);
|
|
647
|
+
bs.offset += runLen;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
const chunk = load<u32>(srcIdx);
|
|
651
|
+
const code = <u16>(chunk >> 16);
|
|
652
|
+
if (code !== 0x75) {
|
|
653
|
+
store<u16>(bs.offset, load<u16>(DESERIALIZE_ESCAPE_TABLE + code));
|
|
654
|
+
bs.offset += 2;
|
|
655
|
+
lastPtr = srcIdx + 4;
|
|
656
|
+
} else {
|
|
657
|
+
store<u16>(bs.offset, hex4_to_u16_swar(load<u64>(srcIdx, 4)));
|
|
658
|
+
bs.offset += 2;
|
|
659
|
+
lastPtr = srcIdx + 12;
|
|
660
|
+
}
|
|
661
|
+
srcStart = lastPtr;
|
|
662
|
+
break;
|
|
663
|
+
} while (mask !== 0);
|
|
664
|
+
if (srcStart == blockStart) srcStart += 8;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
while (srcStart < srcEnd) {
|
|
668
|
+
const char = load<u16>(srcStart);
|
|
669
|
+
if (char == QUOTE) {
|
|
670
|
+
const runLen = <u32>(srcStart - lastPtr);
|
|
671
|
+
if (runLen != 0) {
|
|
672
|
+
memory.copy(bs.offset, lastPtr, runLen);
|
|
673
|
+
bs.offset += runLen;
|
|
674
|
+
}
|
|
675
|
+
bs.toField(outStart, dstFieldPtr);
|
|
676
|
+
return srcStart + 2;
|
|
677
|
+
}
|
|
678
|
+
if (char != BACK_SLASH) {
|
|
679
|
+
srcStart += 2;
|
|
680
|
+
continue;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
const runLen = <u32>(srcStart - lastPtr);
|
|
684
|
+
if (runLen != 0) {
|
|
685
|
+
memory.copy(bs.offset, lastPtr, runLen);
|
|
686
|
+
bs.offset += runLen;
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
const code = load<u16>(srcStart, 2);
|
|
690
|
+
if (code !== 0x75) {
|
|
691
|
+
store<u16>(bs.offset, load<u16>(DESERIALIZE_ESCAPE_TABLE + code));
|
|
692
|
+
bs.offset += 2;
|
|
693
|
+
srcStart += 4;
|
|
694
|
+
} else {
|
|
695
|
+
store<u16>(bs.offset, hex4_to_u16_swar(load<u64>(srcStart, 4)));
|
|
696
|
+
bs.offset += 2;
|
|
697
|
+
srcStart += 12;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
lastPtr = srcStart;
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
bs.offset = bs.buffer + outStart;
|
|
704
|
+
abort("Unterminated string literal");
|
|
705
|
+
return srcStart;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
// Scans a quoted string value, writes into the destination field, and returns next unread src pointer.
|
|
709
|
+
export function deserializeStringField_SWAR<T extends string | null>(srcStart: usize, srcEnd: usize, dstFieldPtr: usize): usize {
|
|
710
|
+
if (srcStart + 2 > srcEnd || load<u16>(srcStart) != QUOTE) abort("Expected leading quote");
|
|
711
|
+
|
|
712
|
+
const payloadStart = srcStart + 2;
|
|
713
|
+
const srcEnd8 = srcEnd >= 8 ? srcEnd - 8 : 0;
|
|
714
|
+
srcStart = payloadStart;
|
|
715
|
+
|
|
716
|
+
while (srcStart <= srcEnd8) {
|
|
717
|
+
let mask = inline.always(backslash_or_quote_mask(load<u64>(srcStart)));
|
|
718
|
+
if (mask === 0) {
|
|
719
|
+
srcStart += 8;
|
|
720
|
+
continue;
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
do {
|
|
724
|
+
const laneIdx = usize(ctz(mask) >> 3);
|
|
725
|
+
mask &= mask - 1;
|
|
726
|
+
const srcIdx = srcStart + laneIdx;
|
|
727
|
+
const char = load<u16>(srcIdx);
|
|
728
|
+
if (char == QUOTE) {
|
|
729
|
+
writeStringToField(dstFieldPtr, payloadStart, <u32>(srcIdx - payloadStart));
|
|
730
|
+
return srcIdx + 2;
|
|
731
|
+
}
|
|
732
|
+
if (char != BACK_SLASH) continue;
|
|
733
|
+
|
|
734
|
+
return deserializeEscapedStringScan_SWAR(payloadStart, srcIdx, srcEnd, dstFieldPtr);
|
|
735
|
+
} while (mask !== 0);
|
|
736
|
+
|
|
737
|
+
srcStart += 8;
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
while (srcStart < srcEnd) {
|
|
741
|
+
const char = load<u16>(srcStart);
|
|
742
|
+
if (char == QUOTE) {
|
|
743
|
+
writeStringToField(dstFieldPtr, payloadStart, <u32>(srcStart - payloadStart));
|
|
744
|
+
return srcStart + 2;
|
|
745
|
+
}
|
|
746
|
+
if (char == BACK_SLASH) {
|
|
747
|
+
return deserializeEscapedStringScan_SWAR(payloadStart, srcStart, srcEnd, dstFieldPtr);
|
|
748
|
+
}
|
|
749
|
+
srcStart += 2;
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
abort("Unterminated string literal");
|
|
753
|
+
return srcStart;
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
/**
|
|
757
|
+
* Computes a per-byte mask identifying ASCII backslash or quote bytes.
|
|
758
|
+
*
|
|
759
|
+
* WARNING: Matches in the high byte of a UTF-16 code unit are not filtered,
|
|
760
|
+
* so callers must confirm the hit scalarly.
|
|
761
|
+
* Each matching lane sets itself to 0x80.
|
|
762
|
+
*/
|
|
763
|
+
// @ts-expect-error: @inline is a valid decorator
|
|
764
|
+
@inline function backslash_or_quote_mask(block: u64): u64 {
|
|
765
|
+
const b = block ^ 0x005c_005c_005c_005c;
|
|
766
|
+
const q = block ^ 0x0022_0022_0022_0022;
|
|
767
|
+
return (((q - 0x0001_0001_0001_0001) & ~q) | ((b - 0x0001_0001_0001_0001) & ~b)) & 0x0080_0080_0080_0080;
|
|
768
|
+
}
|
|
130
769
|
/**
|
|
131
770
|
* Computes a per-lane mask identifying UTF-16 code units whose **low byte**
|
|
132
771
|
* is the ASCII backslash (`'\\'`, 0x5C).
|
|
@@ -141,13 +780,8 @@ export function deserializeString_SWAR(srcStart: usize, srcEnd: usize): string {
|
|
|
141
780
|
// @ts-expect-error: @inline is a valid decorator
|
|
142
781
|
@inline function backslash_mask(block: u64): u64 {
|
|
143
782
|
const b = block ^ 0x005c_005c_005c_005c;
|
|
144
|
-
const backslash_mask =
|
|
145
|
-
|
|
146
|
-
const high_byte_mask =
|
|
147
|
-
~(
|
|
148
|
-
((block - 0x0100_0100_0100_0100) & ~block & 0x8000_8000_8000_8000) ^
|
|
149
|
-
0x8000_8000_8000_8000
|
|
150
|
-
) >> 8;
|
|
783
|
+
const backslash_mask = (b - 0x0001_0001_0001_0001) & ~b & 0x0080_0080_0080_0080;
|
|
784
|
+
const high_byte_mask = ~(((block - 0x0100_0100_0100_0100) & ~block & 0x8000_8000_8000_8000) ^ 0x8000_8000_8000_8000) >> 8;
|
|
151
785
|
return backslash_mask & high_byte_mask;
|
|
152
786
|
}
|
|
153
787
|
|
|
@@ -163,7 +797,6 @@ export function deserializeString_SWAR(srcStart: usize, srcEnd: usize): string {
|
|
|
163
797
|
// @ts-expect-error: @inline is a valid decorator
|
|
164
798
|
@inline function backslash_mask_unsafe(block: u64): u64 {
|
|
165
799
|
const b = block ^ 0x005c_005c_005c_005c;
|
|
166
|
-
const backslash_mask =
|
|
167
|
-
(b - 0x0001_0001_0001_0001) & ~b & 0x0080_0080_0080_0080;
|
|
800
|
+
const backslash_mask = (b - 0x0001_0001_0001_0001) & ~b & 0x0080_0080_0080_0080;
|
|
168
801
|
return backslash_mask;
|
|
169
802
|
}
|