json-as 1.3.9 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/README.md +49 -1
- package/assembly/deserialize/index/arbitrary.ts +2 -2
- package/assembly/deserialize/naive/array/arbitrary.ts +3 -136
- package/assembly/deserialize/naive/array/array.ts +30 -1
- package/assembly/deserialize/naive/array/integer.ts +1 -6
- package/assembly/deserialize/naive/array/map.ts +10 -14
- package/assembly/deserialize/naive/array/object.ts +10 -14
- package/assembly/deserialize/naive/float.ts +2 -4
- package/assembly/deserialize/naive/integer.ts +1 -2
- package/assembly/deserialize/naive/map.ts +40 -202
- package/assembly/deserialize/naive/object.ts +153 -174
- package/assembly/deserialize/naive/set.ts +1 -2
- package/assembly/deserialize/naive/staticarray.ts +1 -2
- package/assembly/deserialize/naive/string.ts +65 -18
- package/assembly/deserialize/naive/typedarray.ts +1 -2
- package/assembly/deserialize/naive/unsigned.ts +1 -2
- package/assembly/deserialize/simd/array/integer.ts +3 -6
- package/assembly/deserialize/simd/float.ts +2 -7
- package/assembly/deserialize/simd/integer.ts +4 -8
- package/assembly/deserialize/simd/string.ts +16 -21
- package/assembly/deserialize/swar/array/array.ts +1 -2
- package/assembly/deserialize/swar/array/bool.ts +1 -2
- package/assembly/deserialize/swar/array/float.ts +2 -3
- package/assembly/deserialize/swar/array/generic.ts +1 -2
- package/assembly/deserialize/swar/array/integer.ts +6 -11
- package/assembly/deserialize/swar/array/object.ts +1 -2
- package/assembly/deserialize/swar/array/shared.ts +3 -8
- package/assembly/deserialize/swar/array/string.ts +1 -2
- package/assembly/deserialize/swar/array/struct.ts +1 -1
- package/assembly/deserialize/swar/float.ts +3 -8
- package/assembly/deserialize/swar/integer.ts +4 -8
- package/assembly/deserialize/swar/string.ts +29 -41
- package/assembly/index.d.ts +248 -15
- package/assembly/index.ts +468 -146
- package/assembly/serialize/index/object.ts +18 -15
- package/assembly/serialize/naive/string.ts +9 -2
- package/assembly/serialize/swar/string.ts +1 -2
- package/assembly/util/atoi.ts +1 -2
- package/assembly/util/dragonbox.ts +0 -8
- package/assembly/util/itoa-fast.ts +3 -6
- package/assembly/util/parsefloat-fast.ts +1 -2
- package/assembly/util/scanValueEnd.ts +1 -2
- package/assembly/util/scanValueEndSimd.ts +160 -0
- package/assembly/util/scanValueEndSwar.ts +142 -0
- package/assembly/util/scientific.ts +3 -6
- package/assembly/util/simd-int.ts +4 -8
- package/assembly/util/snp.ts +1 -5
- package/assembly/util/stringScan.ts +2 -4
- package/assembly/util/swar-int.ts +3 -6
- package/lib/as-bs.ts +37 -0
- package/package.json +14 -4
- package/transform/lib/builder.d.ts +0 -1
- package/transform/lib/builder.js +0 -1
- package/transform/lib/index.d.ts +0 -1
- package/transform/lib/index.js +535 -288
- package/transform/lib/linkers/alias.d.ts +0 -1
- package/transform/lib/linkers/alias.js +0 -1
- package/transform/lib/linkers/custom.d.ts +0 -1
- package/transform/lib/linkers/custom.js +0 -1
- package/transform/lib/linkers/imports.d.ts +0 -1
- package/transform/lib/linkers/imports.js +0 -1
- package/transform/lib/types.d.ts +3 -2
- package/transform/lib/types.js +2 -1
- package/transform/lib/util.d.ts +0 -1
- package/transform/lib/util.js +0 -1
- package/transform/lib/visitor.d.ts +0 -1
- package/transform/lib/visitor.js +0 -1
- package/transform/lib/builder.d.ts.map +0 -1
- package/transform/lib/builder.js.map +0 -1
- package/transform/lib/index.d.ts.map +0 -1
- package/transform/lib/index.js.map +0 -1
- package/transform/lib/linkers/alias.d.ts.map +0 -1
- package/transform/lib/linkers/alias.js.map +0 -1
- package/transform/lib/linkers/custom.d.ts.map +0 -1
- package/transform/lib/linkers/custom.js.map +0 -1
- package/transform/lib/linkers/imports.d.ts.map +0 -1
- package/transform/lib/linkers/imports.js.map +0 -1
- package/transform/lib/types.d.ts.map +0 -1
- package/transform/lib/types.js.map +0 -1
- package/transform/lib/util.d.ts.map +0 -1
- package/transform/lib/util.js.map +0 -1
- package/transform/lib/visitor.d.ts.map +0 -1
- package/transform/lib/visitor.js.map +0 -1
package/transform/lib/index.js
CHANGED
|
@@ -301,10 +301,124 @@ export class JSONTransform extends Visitor {
|
|
|
301
301
|
return;
|
|
302
302
|
if (!this.schemas.has(source.internalPath))
|
|
303
303
|
this.schemas.set(source.internalPath, []);
|
|
304
|
+
const lazyInner = new Map();
|
|
305
|
+
const lazyMode = classLazyMode(node);
|
|
306
|
+
const hasCustomSerde = node.members.some((m) => m.kind === NodeKind.MethodDeclaration &&
|
|
307
|
+
(m.decorators?.some((d) => {
|
|
308
|
+
const t = d.name.text.toLowerCase();
|
|
309
|
+
return t === "serializer" || t === "deserializer";
|
|
310
|
+
}) ??
|
|
311
|
+
false));
|
|
312
|
+
let __hasLazy = false;
|
|
313
|
+
for (let i = node.members.length - 1; i >= 0; i--) {
|
|
314
|
+
const fd = node.members[i];
|
|
315
|
+
if (fd.kind !== NodeKind.FieldDeclaration ||
|
|
316
|
+
fd.is(32) ||
|
|
317
|
+
fd.is(512) ||
|
|
318
|
+
fd.is(1024) ||
|
|
319
|
+
!fd.type)
|
|
320
|
+
continue;
|
|
321
|
+
const written = toString(fd.type).trim();
|
|
322
|
+
const decos = fd.decorators;
|
|
323
|
+
const hasDeco = (name) => decos?.some((d) => d.name.text === name) ??
|
|
324
|
+
false;
|
|
325
|
+
let inner = lazyWrapperInner(fd.type);
|
|
326
|
+
if (inner === null) {
|
|
327
|
+
if (hasDeco("lazy")) {
|
|
328
|
+
inner = written;
|
|
329
|
+
}
|
|
330
|
+
else if (lazyMode !== "none" &&
|
|
331
|
+
!hasDeco("eager") &&
|
|
332
|
+
!hasDeco("omit")) {
|
|
333
|
+
if (lazyMode === "all")
|
|
334
|
+
inner = written;
|
|
335
|
+
else if (lazyAutoCost(this.resolveType(written, source), source, this.parser) >= LAZY_AUTO_THRESHOLD)
|
|
336
|
+
inner = written;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
if (inner === null)
|
|
340
|
+
continue;
|
|
341
|
+
if (hasCustomSerde)
|
|
342
|
+
throwError("Lazy fields (@lazy / JSON.Lazy<T> / @json({ lazy })) are not supported " +
|
|
343
|
+
"on a class with a custom @serializer/@deserializer — the custom methods " +
|
|
344
|
+
"bypass the generated (de)serializer, so the deferred slot is never filled. " +
|
|
345
|
+
"Remove the lazy marker or the custom (de)serializer.", fd.range);
|
|
346
|
+
const fname = fd.name.text;
|
|
347
|
+
const key = JSON.stringify(fname);
|
|
348
|
+
const T = inner;
|
|
349
|
+
const baseT = stripNull(T);
|
|
350
|
+
const storesScalar = isPrimitive(baseT) || isEnum(baseT, source, this.parser);
|
|
351
|
+
const valueType = storesScalar || baseT != T ? T : `${T} | null`;
|
|
352
|
+
const valueDefault = isBoolean(baseT)
|
|
353
|
+
? "false"
|
|
354
|
+
: storesScalar
|
|
355
|
+
? "0"
|
|
356
|
+
: "null";
|
|
357
|
+
const fdInit = fd.initializer;
|
|
358
|
+
const fieldDefault = fdInit ? toString(fdInit) : null;
|
|
359
|
+
__hasLazy = true;
|
|
360
|
+
const omitIfDeco = decos?.find((d) => d.name.text === "omitif");
|
|
361
|
+
lazyInner.set("__" + fname + "_lz", {
|
|
362
|
+
inner: T,
|
|
363
|
+
valueType,
|
|
364
|
+
omitNull: hasDeco("omitnull"),
|
|
365
|
+
omitIf: omitIfDeco?.args?.[0] ?? null,
|
|
366
|
+
});
|
|
367
|
+
const packScalar = baseT === "i8" ||
|
|
368
|
+
baseT === "u8" ||
|
|
369
|
+
baseT === "i16" ||
|
|
370
|
+
baseT === "u16" ||
|
|
371
|
+
baseT === "i32" ||
|
|
372
|
+
baseT === "u32" ||
|
|
373
|
+
baseT === "bool" ||
|
|
374
|
+
baseT === "boolean" ||
|
|
375
|
+
baseT === "f32";
|
|
376
|
+
const encVal = (v) => baseT === "f32"
|
|
377
|
+
? `(<u64>reinterpret<u32>(${v}))`
|
|
378
|
+
: `(<u64><u32>(${v}))`;
|
|
379
|
+
const decSlot = (lz) => baseT === "f32"
|
|
380
|
+
? `reinterpret<f32>(<u32>(${lz}))`
|
|
381
|
+
: `(<${T}>(<u32>(${lz})))`;
|
|
382
|
+
const lowered = (packScalar
|
|
383
|
+
? [
|
|
384
|
+
`@alias(${key}) private __${fname}_lz: u64 = ${fieldDefault != null
|
|
385
|
+
? `(((<u64>0xffffffff) << 32) | ${encVal(`<${T}>(${fieldDefault})`)})`
|
|
386
|
+
: "0"};`,
|
|
387
|
+
`get ${fname}(): ${T} {\n` +
|
|
388
|
+
` const __lz = this.__${fname}_lz;\n` +
|
|
389
|
+
` if ((__lz >>> 32) == 0xffffffff) return ${decSlot("__lz")};\n` +
|
|
390
|
+
` if (__lz != 0) {\n` +
|
|
391
|
+
` const __v = JSON.__deserialize<${T}>(<usize>(__lz >>> 32), <usize>(<u32>__lz));\n` +
|
|
392
|
+
` this.__${fname}_lz = ((<u64>0xffffffff) << 32) | ${encVal("__v")};\n` +
|
|
393
|
+
` return __v;\n` +
|
|
394
|
+
` }\n` +
|
|
395
|
+
` return ${valueDefault};\n}`,
|
|
396
|
+
`set ${fname}(value: ${T}) {\n` +
|
|
397
|
+
` this.__${fname}_lz = ((<u64>0xffffffff) << 32) | ${encVal("value")};\n}`,
|
|
398
|
+
]
|
|
399
|
+
: [
|
|
400
|
+
`@alias(${key}) private __${fname}_lz: u64 = ${fieldDefault != null ? "u64.MAX_VALUE" : "0"};`,
|
|
401
|
+
`private __${fname}_val: ${valueType} = ${fieldDefault ?? valueDefault};`,
|
|
402
|
+
`get ${fname}(): ${T} {\n` +
|
|
403
|
+
` const __lz = this.__${fname}_lz;\n` +
|
|
404
|
+
` if (__lz != 0 && __lz != u64.MAX_VALUE) {\n` +
|
|
405
|
+
` this.__${fname}_val = JSON.__deserialize<${T}>(<usize>(__lz >>> 32), <usize>(<u32>__lz));\n` +
|
|
406
|
+
` this.__${fname}_lz = u64.MAX_VALUE;\n` +
|
|
407
|
+
` }\n` +
|
|
408
|
+
` return this.__${fname}_val as ${T};\n}`,
|
|
409
|
+
`set ${fname}(value: ${T}) {\n` +
|
|
410
|
+
` this.__${fname}_val = value;\n` +
|
|
411
|
+
` this.__${fname}_lz = u64.MAX_VALUE;\n}`,
|
|
412
|
+
]).map((src) => SimpleParser.parseClassMember(src, node));
|
|
413
|
+
node.members.splice(i, 1, ...lowered);
|
|
414
|
+
}
|
|
415
|
+
if (__hasLazy) {
|
|
416
|
+
node.members.push(SimpleParser.parseClassMember(`private __src: string = "";`, node), SimpleParser.parseClassMember(`__SET_SRC(s: string): void { this.__src = s; }`, node));
|
|
417
|
+
}
|
|
304
418
|
const members = [
|
|
305
419
|
...node.members.filter((v) => v.kind === NodeKind.FieldDeclaration &&
|
|
306
420
|
!v.is(32) &&
|
|
307
|
-
!v.is(512) &&
|
|
421
|
+
(!v.is(512) || lazyInner.has(v.name.text)) &&
|
|
308
422
|
!v.is(1024) &&
|
|
309
423
|
!v.decorators?.some((decorator) => decorator.name.text === "omit")),
|
|
310
424
|
];
|
|
@@ -549,8 +663,7 @@ export class JSONTransform extends Visitor {
|
|
|
549
663
|
this.schemas.get(source.internalPath).push(schema);
|
|
550
664
|
this.schema = schema;
|
|
551
665
|
this.visitedClasses.add(fullClassPath);
|
|
552
|
-
const
|
|
553
|
-
const requestedFastPath = USE_FAST_PATH && codegenMode !== JSONMode.NAIVE;
|
|
666
|
+
const requestedFastPath = USE_FAST_PATH;
|
|
554
667
|
let SERIALIZE = "__SERIALIZE(ptr: usize): void {\n";
|
|
555
668
|
let INITIALIZE = "@inline __INITIALIZE(): this {\n";
|
|
556
669
|
let DESERIALIZE = "__DESERIALIZE_SLOW<__JSON_T>(srcStart: usize, srcEnd: usize, out: __JSON_T): usize {\n";
|
|
@@ -663,9 +776,7 @@ export class JSONTransform extends Visitor {
|
|
|
663
776
|
DESERIALIZE_CUSTOM +=
|
|
664
777
|
" @inline __DESERIALIZE_CUSTOM(data: string): this {\n";
|
|
665
778
|
DESERIALIZE_CUSTOM +=
|
|
666
|
-
" return
|
|
667
|
-
deserializer.name.text +
|
|
668
|
-
"(data));\n";
|
|
779
|
+
" return this." + deserializer.name.text + "(data);\n";
|
|
669
780
|
DESERIALIZE_CUSTOM += " }\n";
|
|
670
781
|
}
|
|
671
782
|
if (!members.length && !deserializers.length && !serializers.length) {
|
|
@@ -689,6 +800,19 @@ export class JSONTransform extends Visitor {
|
|
|
689
800
|
mem.node = member;
|
|
690
801
|
mem.byteSize = estimatedSerializedByteSize(mem.type, source, this.parser);
|
|
691
802
|
mem.custom = schema.deps.some((dep) => dep?.name == stripNull(type) && dep.custom);
|
|
803
|
+
const lzInner = lazyInner.get(name.text);
|
|
804
|
+
if (lzInner !== undefined) {
|
|
805
|
+
mem.flags.set(PropertyFlags.Lazy, null);
|
|
806
|
+
mem.lazyInner = lzInner.inner;
|
|
807
|
+
if (lzInner.omitNull) {
|
|
808
|
+
mem.flags.set(PropertyFlags.OmitNull, null);
|
|
809
|
+
this.schema.static = false;
|
|
810
|
+
}
|
|
811
|
+
if (lzInner.omitIf) {
|
|
812
|
+
mem.flags.set(PropertyFlags.OmitIf, lzInner.omitIf);
|
|
813
|
+
this.schema.static = false;
|
|
814
|
+
}
|
|
815
|
+
}
|
|
692
816
|
this.schema.byteSize += mem.byteSize;
|
|
693
817
|
if (member.decorators) {
|
|
694
818
|
for (const decorator of member.decorators) {
|
|
@@ -738,6 +862,7 @@ export class JSONTransform extends Visitor {
|
|
|
738
862
|
const hasOmitIfMembers = this.schema.members.some((v) => v.flags.has(PropertyFlags.OmitIf));
|
|
739
863
|
const hasOmitNullMembers = this.schema.members.some((v) => v.flags.has(PropertyFlags.OmitNull));
|
|
740
864
|
const hasOptionalMembers = hasOmitIfMembers || hasOmitNullMembers;
|
|
865
|
+
const hasLazyMembers = this.schema.members.some((v) => v.flags.has(PropertyFlags.Lazy));
|
|
741
866
|
const supportsFastOptionalPath = requestedFastPath && hasOptionalMembers;
|
|
742
867
|
const hasTypeParams = !!node.typeParameters && node.typeParameters.length > 0;
|
|
743
868
|
const useFastPath = requestedFastPath &&
|
|
@@ -748,6 +873,9 @@ export class JSONTransform extends Visitor {
|
|
|
748
873
|
if (this.schema.members.some((v) => v.flags.has(PropertyFlags.OmitNull))) {
|
|
749
874
|
SERIALIZE += indent + "let block: usize = 0;\n";
|
|
750
875
|
}
|
|
876
|
+
if (hasOptionalMembers) {
|
|
877
|
+
SERIALIZE += indent + "let wrote = false;\n";
|
|
878
|
+
}
|
|
751
879
|
this.schema.byteSize += 2;
|
|
752
880
|
SERIALIZE += indent + "store<u16>(bs.offset, 123, 0); // {\n";
|
|
753
881
|
SERIALIZE += indent + "bs.offset += 2;\n";
|
|
@@ -755,11 +883,64 @@ export class JSONTransform extends Visitor {
|
|
|
755
883
|
const isPure = this.schema.static;
|
|
756
884
|
let isRegular = isPure;
|
|
757
885
|
let isFirst = true;
|
|
886
|
+
const serValue = (member, realName) => {
|
|
887
|
+
if (!member.flags.has(PropertyFlags.Lazy))
|
|
888
|
+
return getSerializeCall(member.type, realName);
|
|
889
|
+
const T = member.lazyInner;
|
|
890
|
+
const baseName = realName.slice(0, -3);
|
|
891
|
+
const baseT = stripNull(T);
|
|
892
|
+
const packScalar = baseT === "i8" ||
|
|
893
|
+
baseT === "u8" ||
|
|
894
|
+
baseT === "i16" ||
|
|
895
|
+
baseT === "u16" ||
|
|
896
|
+
baseT === "i32" ||
|
|
897
|
+
baseT === "u32" ||
|
|
898
|
+
baseT === "bool" ||
|
|
899
|
+
baseT === "boolean" ||
|
|
900
|
+
baseT === "f32";
|
|
901
|
+
if (packScalar) {
|
|
902
|
+
const dec = baseT === "f32"
|
|
903
|
+
? `reinterpret<f32>(<u32>(__s))`
|
|
904
|
+
: `(<${T}>(<u32>(__s)))`;
|
|
905
|
+
const def = baseT === "bool" || baseT === "boolean" ? "false" : "0";
|
|
906
|
+
return (`{\n` +
|
|
907
|
+
` const __s = this.${realName};\n` +
|
|
908
|
+
` if ((__s >>> 32) == 0xffffffff) {\n` +
|
|
909
|
+
` JSON.__serialize<${T}>(${dec});\n` +
|
|
910
|
+
` } else if (__s != 0) {\n` +
|
|
911
|
+
` const __hi = <usize>(__s >>> 32);\n` +
|
|
912
|
+
` const __len = (<usize>(<u32>__s)) - __hi;\n` +
|
|
913
|
+
` bs.ensureSize(<u32>__len);\n` +
|
|
914
|
+
` memory.copy(bs.offset, __hi, __len);\n` +
|
|
915
|
+
` bs.offset += __len;\n` +
|
|
916
|
+
` } else {\n` +
|
|
917
|
+
` JSON.__serialize<${T}>(${def});\n` +
|
|
918
|
+
` }\n` +
|
|
919
|
+
`}\n`);
|
|
920
|
+
}
|
|
921
|
+
return (`{\n` +
|
|
922
|
+
` const __s = this.${realName};\n` +
|
|
923
|
+
` if (__s == u64.MAX_VALUE) {\n` +
|
|
924
|
+
` JSON.__serialize<${T}>(this.${baseName}_val as ${T});\n` +
|
|
925
|
+
` } else if (__s != 0) {\n` +
|
|
926
|
+
` const __hi = <usize>(__s >>> 32);\n` +
|
|
927
|
+
` const __len = (<usize>(<u32>__s)) - __hi;\n` +
|
|
928
|
+
` bs.ensureSize(<u32>__len);\n` +
|
|
929
|
+
` memory.copy(bs.offset, __hi, __len);\n` +
|
|
930
|
+
` bs.offset += __len;\n` +
|
|
931
|
+
` } else {\n` +
|
|
932
|
+
(isPrimitive(baseT)
|
|
933
|
+
? ` JSON.__serialize<${T}>(0);\n`
|
|
934
|
+
: ` bs.ensureSize(8);\n` +
|
|
935
|
+
` store<u64>(bs.offset, 0x006c006c0075006e);\n` +
|
|
936
|
+
` bs.offset += 8;\n`) +
|
|
937
|
+
` }\n` +
|
|
938
|
+
`}\n`);
|
|
939
|
+
};
|
|
758
940
|
for (let i = 0; i < this.schema.members.length; i++) {
|
|
759
941
|
const member = this.schema.members[i];
|
|
760
942
|
const aliasName = JSON.stringify(member.alias || member.name);
|
|
761
943
|
const realName = member.name;
|
|
762
|
-
const isLast = i == this.schema.members.length - 1;
|
|
763
944
|
if (member.value) {
|
|
764
945
|
if (member.value != "null" &&
|
|
765
946
|
member.value != "0" &&
|
|
@@ -801,40 +982,69 @@ export class JSONTransform extends Visitor {
|
|
|
801
982
|
if (isRegular && isPure) {
|
|
802
983
|
const keyPart = (isFirst ? "{" : ",") + aliasName + ":";
|
|
803
984
|
this.schema.byteSize += keyPart.length << 1;
|
|
985
|
+
if (hasLazyMembers)
|
|
986
|
+
SERIALIZE += indent + `bs.ensureSize(${keyPart.length << 1});\n`;
|
|
804
987
|
SERIALIZE += this.getStores(keyPart, SIMD_ENABLED)
|
|
805
988
|
.map((v) => indent + v + "\n")
|
|
806
989
|
.join("");
|
|
807
|
-
SERIALIZE += indent +
|
|
990
|
+
SERIALIZE += indent + serValue(member, realName);
|
|
808
991
|
if (isFirst)
|
|
809
992
|
isFirst = false;
|
|
810
993
|
}
|
|
811
994
|
else if (isRegular && !isPure) {
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
995
|
+
if (isFirst && hasOptionalMembers) {
|
|
996
|
+
const keyPart = aliasName + ":";
|
|
997
|
+
this.schema.byteSize += 2 + (keyPart.length << 1);
|
|
998
|
+
SERIALIZE +=
|
|
999
|
+
indent +
|
|
1000
|
+
"if (wrote) { store<u16>(bs.offset, 44, 0); bs.offset += 2; } // ,\n";
|
|
1001
|
+
if (hasLazyMembers)
|
|
1002
|
+
SERIALIZE += indent + `bs.ensureSize(${keyPart.length << 1});\n`;
|
|
1003
|
+
SERIALIZE += this.getStores(keyPart, SIMD_ENABLED)
|
|
1004
|
+
.map((v) => indent + v + "\n")
|
|
1005
|
+
.join("");
|
|
1006
|
+
SERIALIZE += indent + serValue(member, realName);
|
|
1007
|
+
}
|
|
1008
|
+
else {
|
|
1009
|
+
const keyPart = (isFirst ? "" : ",") + aliasName + ":";
|
|
1010
|
+
this.schema.byteSize += keyPart.length << 1;
|
|
1011
|
+
if (hasLazyMembers)
|
|
1012
|
+
SERIALIZE += indent + `bs.ensureSize(${keyPart.length << 1});\n`;
|
|
1013
|
+
SERIALIZE += this.getStores(keyPart, SIMD_ENABLED)
|
|
1014
|
+
.map((v) => indent + v + "\n")
|
|
1015
|
+
.join("");
|
|
1016
|
+
SERIALIZE += indent + serValue(member, realName);
|
|
1017
|
+
}
|
|
818
1018
|
if (isFirst)
|
|
819
1019
|
isFirst = false;
|
|
820
1020
|
}
|
|
821
1021
|
else {
|
|
822
1022
|
if (member.flags.has(PropertyFlags.OmitNull)) {
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
1023
|
+
let omitNullCond;
|
|
1024
|
+
if (member.flags.has(PropertyFlags.Lazy)) {
|
|
1025
|
+
const base = realName.slice(0, -3);
|
|
1026
|
+
omitNullCond =
|
|
1027
|
+
`!JSON.__lazyIsNull(` +
|
|
1028
|
+
`load<usize>(ptr, offsetof<this>(${JSON.stringify(base + "_val")})), ` +
|
|
1029
|
+
`load<u64>(ptr, offsetof<this>(${JSON.stringify(realName)})))`;
|
|
1030
|
+
}
|
|
1031
|
+
else {
|
|
1032
|
+
omitNullCond = `(block = load<usize>(ptr, offsetof<this>(${JSON.stringify(realName)}))) !== 0`;
|
|
1033
|
+
}
|
|
1034
|
+
SERIALIZE += indent + `if (${omitNullCond}) {\n`;
|
|
826
1035
|
indentInc();
|
|
827
1036
|
const keyPart = aliasName + ":";
|
|
828
|
-
this.schema.byteSize += keyPart.length << 1;
|
|
1037
|
+
this.schema.byteSize += 2 + (keyPart.length << 1);
|
|
1038
|
+
SERIALIZE +=
|
|
1039
|
+
indent +
|
|
1040
|
+
"if (wrote) { store<u16>(bs.offset, 44, 0); bs.offset += 2; } // ,\n";
|
|
1041
|
+
if (hasLazyMembers)
|
|
1042
|
+
SERIALIZE += indent + `bs.ensureSize(${keyPart.length << 1});\n`;
|
|
829
1043
|
SERIALIZE += this.getStores(keyPart, SIMD_ENABLED)
|
|
830
1044
|
.map((v) => indent + v + "\n")
|
|
831
1045
|
.join("");
|
|
832
|
-
SERIALIZE += indent +
|
|
833
|
-
|
|
834
|
-
this.schema.byteSize += 2;
|
|
835
|
-
SERIALIZE += indent + `store<u16>(bs.offset, 44, 0); // ,\n`;
|
|
836
|
-
SERIALIZE += indent + `bs.offset += 2;\n`;
|
|
837
|
-
}
|
|
1046
|
+
SERIALIZE += indent + serValue(member, realName);
|
|
1047
|
+
SERIALIZE += indent + "wrote = true;\n";
|
|
838
1048
|
indentDec();
|
|
839
1049
|
this.schema.byteSize += 2;
|
|
840
1050
|
SERIALIZE += indent + `}\n`;
|
|
@@ -860,15 +1070,15 @@ export class JSONTransform extends Visitor {
|
|
|
860
1070
|
SERIALIZE += indent + `if (!(${rendered})) {\n`;
|
|
861
1071
|
}
|
|
862
1072
|
indentInc();
|
|
1073
|
+
this.schema.byteSize += 2;
|
|
1074
|
+
SERIALIZE +=
|
|
1075
|
+
indent +
|
|
1076
|
+
"if (wrote) { store<u16>(bs.offset, 44, 0); bs.offset += 2; } // ,\n";
|
|
863
1077
|
SERIALIZE += this.getStores(aliasName + ":", SIMD_ENABLED)
|
|
864
1078
|
.map((v) => indent + v + "\n")
|
|
865
1079
|
.join("");
|
|
866
|
-
SERIALIZE += indent +
|
|
867
|
-
|
|
868
|
-
this.schema.byteSize += 2;
|
|
869
|
-
SERIALIZE += indent + `store<u16>(bs.offset, 44, 0); // ,\n`;
|
|
870
|
-
SERIALIZE += indent + `bs.offset += 2;\n`;
|
|
871
|
-
}
|
|
1080
|
+
SERIALIZE += indent + serValue(member, realName);
|
|
1081
|
+
SERIALIZE += indent + "wrote = true;\n";
|
|
872
1082
|
indentDec();
|
|
873
1083
|
SERIALIZE += indent + `}\n`;
|
|
874
1084
|
}
|
|
@@ -912,6 +1122,23 @@ export class JSONTransform extends Visitor {
|
|
|
912
1122
|
sortedMembers.object.push(member);
|
|
913
1123
|
}
|
|
914
1124
|
}
|
|
1125
|
+
const lazyMembers = this.schema.members.filter((member) => member.flags.has(PropertyFlags.Lazy));
|
|
1126
|
+
const withLazyMembers = (members) => {
|
|
1127
|
+
if (!lazyMembers.length)
|
|
1128
|
+
return members;
|
|
1129
|
+
const out = members.slice();
|
|
1130
|
+
for (const member of lazyMembers) {
|
|
1131
|
+
if (!out.includes(member))
|
|
1132
|
+
out.push(member);
|
|
1133
|
+
}
|
|
1134
|
+
return out;
|
|
1135
|
+
};
|
|
1136
|
+
const slowStringMembers = withLazyMembers(sortedMembers.string);
|
|
1137
|
+
const slowNumberMembers = withLazyMembers(sortedMembers.number);
|
|
1138
|
+
const slowObjectMembers = withLazyMembers(sortedMembers.object);
|
|
1139
|
+
const slowArrayMembers = withLazyMembers(sortedMembers.array);
|
|
1140
|
+
const slowBooleanMembers = withLazyMembers(sortedMembers.boolean);
|
|
1141
|
+
const slowNullMembers = withLazyMembers(sortedMembers.null);
|
|
915
1142
|
const getComparisions = (data, ptr, operator) => {
|
|
916
1143
|
const dataBytes = data.length << 1;
|
|
917
1144
|
let offset = 0;
|
|
@@ -952,6 +1179,17 @@ export class JSONTransform extends Visitor {
|
|
|
952
1179
|
const resolvedSchema = this.getSchema(resolvedType);
|
|
953
1180
|
const fieldOffset = `offsetof<this>(${JSON.stringify(member.name)})`;
|
|
954
1181
|
const valuePtr = keyOffset ? `${srcPtr} + ${keyOffset}` : srcPtr;
|
|
1182
|
+
if (member.flags.has(PropertyFlags.Lazy)) {
|
|
1183
|
+
const lazyInner = member.lazyInner;
|
|
1184
|
+
out.push("{");
|
|
1185
|
+
out.push(` const valueStart = JSON.Util.skipWhitespace(${valuePtr}, srcEnd);`);
|
|
1186
|
+
out.push(` const valueEnd = JSON.Util.scanValueEnd<${lazyInner}>(valueStart, srcEnd);`);
|
|
1187
|
+
out.push(" if (!valueEnd) break;");
|
|
1188
|
+
out.push(` store<u64>(${outPtr}, ((<u64>valueStart) << 32) | (<u64>(<u32>valueEnd)), ${fieldOffset});`);
|
|
1189
|
+
out.push(` ${srcPtr} = valueEnd;`);
|
|
1190
|
+
out.push("}");
|
|
1191
|
+
return out;
|
|
1192
|
+
}
|
|
955
1193
|
if (INTEGER_TYPES.includes(resolvedType)) {
|
|
956
1194
|
const helper = SIGNED_INTEGER_TYPES.includes(resolvedType)
|
|
957
1195
|
? "__deserializeIntegerField"
|
|
@@ -1121,7 +1359,7 @@ export class JSONTransform extends Visitor {
|
|
|
1121
1359
|
out.push(` store<${resolvedType}>(${outPtr}, value, ${fieldOffset});`);
|
|
1122
1360
|
out.push(" }");
|
|
1123
1361
|
out.push(` const valueStart = ${valuePtr};`);
|
|
1124
|
-
out.push(` const valueEnd = JSON.Util.scanValueEnd(valueStart, srcEnd);`);
|
|
1362
|
+
out.push(` const valueEnd = JSON.Util.scanValueEnd<${resolvedType}>(valueStart, srcEnd);`);
|
|
1125
1363
|
out.push(" if (!valueEnd) break;");
|
|
1126
1364
|
if (fastPath) {
|
|
1127
1365
|
out.push(` ${srcPtr} = changetype<nonnull<${resolvedType}>>(value).__DESERIALIZE_FAST<${resolvedType}>(valueStart, valueEnd, value);`);
|
|
@@ -1273,6 +1511,50 @@ export class JSONTransform extends Visitor {
|
|
|
1273
1511
|
return out;
|
|
1274
1512
|
};
|
|
1275
1513
|
indent = " ";
|
|
1514
|
+
const FAST_CHUNK_SIZE = 32;
|
|
1515
|
+
const fastChunkMethods = [];
|
|
1516
|
+
let fastChunkId = 0;
|
|
1517
|
+
const chunkFastBlocks = (blocks, tag, callIndent) => {
|
|
1518
|
+
if (blocks.length <= FAST_CHUNK_SIZE)
|
|
1519
|
+
return blocks.join("");
|
|
1520
|
+
let calls = "";
|
|
1521
|
+
for (let c = 0; c < blocks.length; c += FAST_CHUNK_SIZE) {
|
|
1522
|
+
const name = `__DESERIALIZE_FAST_${tag}_${fastChunkId++}`;
|
|
1523
|
+
const body = blocks
|
|
1524
|
+
.slice(c, c + FAST_CHUNK_SIZE)
|
|
1525
|
+
.join("")
|
|
1526
|
+
.replace(/\bbreak;/g, "return 0;");
|
|
1527
|
+
fastChunkMethods.push(`${name}(srcStart: usize, srcEnd: usize, dst: usize): usize {\n${body}\n return srcStart;\n}`);
|
|
1528
|
+
calls +=
|
|
1529
|
+
`${callIndent}srcStart = this.${name}(srcStart, srcEnd, dst);\n` +
|
|
1530
|
+
`${callIndent}if (srcStart == 0) break;\n`;
|
|
1531
|
+
}
|
|
1532
|
+
return calls;
|
|
1533
|
+
};
|
|
1534
|
+
const chunkFastBlocksOptional = (blocks, tag, callIndent, needsKp) => {
|
|
1535
|
+
if (blocks.length <= FAST_CHUNK_SIZE)
|
|
1536
|
+
return blocks.join("");
|
|
1537
|
+
let calls = "";
|
|
1538
|
+
for (let c = 0; c < blocks.length; c += FAST_CHUNK_SIZE) {
|
|
1539
|
+
const name = `__DESERIALIZE_FAST_${tag}_${fastChunkId++}`;
|
|
1540
|
+
const body = blocks
|
|
1541
|
+
.slice(c, c + FAST_CHUNK_SIZE)
|
|
1542
|
+
.join("")
|
|
1543
|
+
.replace(/\bbreak;/g, "return 0;");
|
|
1544
|
+
fastChunkMethods.push(`${name}(srcStart: usize, srcEnd: usize, dst: usize, seenAny: bool): u64 {\n` +
|
|
1545
|
+
(needsKp ? " let kp: usize = 0;\n" : "") +
|
|
1546
|
+
`${body}\n` +
|
|
1547
|
+
` return (<u64>srcStart) | ((<u64>(seenAny ? 1 : 0)) << 32);\n}`);
|
|
1548
|
+
calls +=
|
|
1549
|
+
`${callIndent}{\n` +
|
|
1550
|
+
`${callIndent} const __r = this.${name}(srcStart, srcEnd, dst, seenAny);\n` +
|
|
1551
|
+
`${callIndent} if (__r == 0) break;\n` +
|
|
1552
|
+
`${callIndent} srcStart = <usize>(<u32>__r);\n` +
|
|
1553
|
+
`${callIndent} seenAny = (<u32>(__r >>> 32)) != 0;\n` +
|
|
1554
|
+
`${callIndent}}\n`;
|
|
1555
|
+
}
|
|
1556
|
+
return calls;
|
|
1557
|
+
};
|
|
1276
1558
|
DESERIALIZE_FAST += indent + "const start = srcStart;\n";
|
|
1277
1559
|
DESERIALIZE_FAST += indent + "const dst = changetype<usize>(out);\n";
|
|
1278
1560
|
DESERIALIZE_FAST += indent + "do {\n";
|
|
@@ -1282,6 +1564,7 @@ export class JSONTransform extends Visitor {
|
|
|
1282
1564
|
indent + "if (load<u16>(srcStart) !== 0x7b) break; // {\n";
|
|
1283
1565
|
DESERIALIZE_FAST += indent + "srcStart += 2;\n";
|
|
1284
1566
|
DESERIALIZE_FAST += indent + "let seenAny = false;\n\n";
|
|
1567
|
+
const t1opt = [];
|
|
1285
1568
|
for (let i = 0; i < this.schema.members.length; i++) {
|
|
1286
1569
|
const member = this.schema.members[i];
|
|
1287
1570
|
const key = JSON.stringify(member.alias || member.name);
|
|
@@ -1298,89 +1581,92 @@ export class JSONTransform extends Visitor {
|
|
|
1298
1581
|
const isOptional = member.flags.has(PropertyFlags.OmitNull) ||
|
|
1299
1582
|
member.flags.has(PropertyFlags.OmitIf);
|
|
1300
1583
|
if (!deserializerFirst.length || !deserializerNext.length) {
|
|
1301
|
-
|
|
1584
|
+
t1opt.push(indent + "break;\n\n");
|
|
1302
1585
|
continue;
|
|
1303
1586
|
}
|
|
1304
|
-
|
|
1587
|
+
let blk = indent + "if (!seenAny) {\n";
|
|
1305
1588
|
indent += " ";
|
|
1306
|
-
|
|
1589
|
+
blk +=
|
|
1307
1590
|
indent +
|
|
1308
1591
|
`if ( // ${firstKeySection}\n${(indent += " ")}${getComparisions(firstKeySection, "srcStart", "!=").join("\n" + indent + "|| ")}\n${(indent = indent.slice(0, -2))}) {\n`;
|
|
1309
1592
|
indent += " ";
|
|
1310
1593
|
if (isOptional) {
|
|
1311
|
-
|
|
1594
|
+
blk += indent + "// optional @omitnull field omitted\n";
|
|
1312
1595
|
}
|
|
1313
1596
|
else {
|
|
1314
|
-
|
|
1597
|
+
blk += indent + "break;\n";
|
|
1315
1598
|
}
|
|
1316
1599
|
indent = indent.slice(0, -2);
|
|
1317
|
-
|
|
1600
|
+
blk += indent + "} else {\n";
|
|
1318
1601
|
indent += " ";
|
|
1319
1602
|
if (!inlineStringValue)
|
|
1320
|
-
|
|
1321
|
-
|
|
1603
|
+
blk += indent + `srcStart += ${firstKeyOffset};\n`;
|
|
1604
|
+
blk +=
|
|
1322
1605
|
indent +
|
|
1323
1606
|
`if (JSON.Util.isSpace(load<u16>(${inlineStringValue ? `srcStart + ${firstKeyOffset}` : "srcStart"}))) break;\n`;
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
DESERIALIZE_FAST += indent + "seenAny = true;\n";
|
|
1607
|
+
blk += indent + deserializerFirst.join("\n" + indent) + "\n";
|
|
1608
|
+
blk += indent + "seenAny = true;\n";
|
|
1327
1609
|
indent = indent.slice(0, -2);
|
|
1328
|
-
|
|
1610
|
+
blk += indent + "}\n";
|
|
1329
1611
|
indent = indent.slice(0, -2);
|
|
1330
|
-
|
|
1612
|
+
blk += indent + "} else {\n";
|
|
1331
1613
|
indent += " ";
|
|
1332
|
-
|
|
1614
|
+
blk +=
|
|
1333
1615
|
indent +
|
|
1334
1616
|
`if ( // ${nextKeySection}\n${(indent += " ")}${getComparisions(nextKeySection, "srcStart", "!=").join("\n" + indent + "|| ")}\n${(indent = indent.slice(0, -2))}) {\n`;
|
|
1335
1617
|
indent += " ";
|
|
1336
1618
|
if (isOptional) {
|
|
1337
|
-
|
|
1619
|
+
blk += indent + "// optional @omitnull field omitted\n";
|
|
1338
1620
|
}
|
|
1339
1621
|
else {
|
|
1340
|
-
|
|
1622
|
+
blk += indent + "break;\n";
|
|
1341
1623
|
}
|
|
1342
1624
|
indent = indent.slice(0, -2);
|
|
1343
|
-
|
|
1625
|
+
blk += indent + "} else {\n";
|
|
1344
1626
|
indent += " ";
|
|
1345
1627
|
if (!inlineStringValue)
|
|
1346
|
-
|
|
1347
|
-
|
|
1628
|
+
blk += indent + `srcStart += ${nextKeyOffset};\n`;
|
|
1629
|
+
blk +=
|
|
1348
1630
|
indent +
|
|
1349
1631
|
`if (JSON.Util.isSpace(load<u16>(${inlineStringValue ? `srcStart + ${nextKeyOffset}` : "srcStart"}))) break;\n`;
|
|
1350
|
-
|
|
1351
|
-
indent + deserializerNext.join("\n" + indent) + "\n";
|
|
1632
|
+
blk += indent + deserializerNext.join("\n" + indent) + "\n";
|
|
1352
1633
|
indent = indent.slice(0, -2);
|
|
1353
|
-
|
|
1634
|
+
blk += indent + "}\n";
|
|
1354
1635
|
indent = indent.slice(0, -2);
|
|
1355
|
-
|
|
1636
|
+
blk += indent + "}\n\n";
|
|
1637
|
+
t1opt.push(blk);
|
|
1356
1638
|
}
|
|
1639
|
+
DESERIALIZE_FAST += chunkFastBlocksOptional(t1opt, "T1O", indent, false);
|
|
1357
1640
|
}
|
|
1358
1641
|
else {
|
|
1642
|
+
const t1blocks = [];
|
|
1359
1643
|
for (let i = 0; i < this.schema.members.length; i++) {
|
|
1360
1644
|
const member = this.schema.members[i];
|
|
1361
1645
|
const key = JSON.stringify(member.alias || member.name);
|
|
1362
1646
|
if (key.length <= 2)
|
|
1363
1647
|
throw new Error("Key cannot be empty!");
|
|
1364
1648
|
const keySection = (i == 0 ? "{" : ",") + key + ":";
|
|
1365
|
-
|
|
1366
|
-
indent +
|
|
1367
|
-
`if ( // ${keySection}\n${(indent += " ")}${getComparisions(keySection, "srcStart", "!=").join("\n" + indent + "|| ")}\n${(indent = indent.slice(0, -2))}) break;\n`;
|
|
1649
|
+
let blk = indent +
|
|
1650
|
+
`if ( // ${keySection}\n${(indent += " ")}${getComparisions(keySection, "srcStart", "!=").join("\n" + indent + "|| ")}\n${(indent = indent.slice(0, -2))}) break;\n`;
|
|
1368
1651
|
const keyOffset = keySection.length << 1;
|
|
1369
1652
|
const resolvedType = stripNull(member.type);
|
|
1370
1653
|
const inlineStringValue = ["string", "String"].includes(resolvedType);
|
|
1371
1654
|
if (!inlineStringValue) {
|
|
1372
|
-
|
|
1655
|
+
blk += indent + `srcStart += ${keyOffset};\n\n`;
|
|
1373
1656
|
}
|
|
1374
1657
|
const deserializer = getDeserializer(member.type, "srcStart", "dst", member, inlineStringValue ? keyOffset : 0, true);
|
|
1375
1658
|
if (!deserializer.length) {
|
|
1376
|
-
|
|
1659
|
+
blk += indent + "break;\n\n";
|
|
1660
|
+
t1blocks.push(blk);
|
|
1377
1661
|
continue;
|
|
1378
1662
|
}
|
|
1379
|
-
|
|
1663
|
+
blk +=
|
|
1380
1664
|
indent +
|
|
1381
1665
|
`if (JSON.Util.isSpace(load<u16>(${inlineStringValue ? `srcStart + ${keyOffset}` : "srcStart"}))) break;\n`;
|
|
1382
|
-
|
|
1666
|
+
blk += indent + deserializer.join("\n" + indent) + "\n\n";
|
|
1667
|
+
t1blocks.push(blk);
|
|
1383
1668
|
}
|
|
1669
|
+
DESERIALIZE_FAST += chunkFastBlocks(t1blocks, "T1", indent);
|
|
1384
1670
|
}
|
|
1385
1671
|
DESERIALIZE_FAST +=
|
|
1386
1672
|
indent + "if (load<u16>(srcStart) !== 0x7d) break; // }\n";
|
|
@@ -1399,31 +1685,32 @@ export class JSONTransform extends Visitor {
|
|
|
1399
1685
|
DESERIALIZE_FAST += skip;
|
|
1400
1686
|
DESERIALIZE_FAST += i2 + "if (load<u16>(srcStart) != 0x7b) break; // {\n";
|
|
1401
1687
|
DESERIALIZE_FAST += i2 + "srcStart += 2;\n";
|
|
1688
|
+
const t2blocks = [];
|
|
1402
1689
|
for (let i = 0; i < this.schema.members.length; i++) {
|
|
1403
1690
|
const member = this.schema.members[i];
|
|
1404
1691
|
const key = JSON.stringify(member.alias || member.name);
|
|
1405
1692
|
const keyBytes = key.length << 1;
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1693
|
+
let blk = "\n";
|
|
1694
|
+
blk += skip;
|
|
1695
|
+
blk +=
|
|
1409
1696
|
i2 +
|
|
1410
1697
|
`if ( // ${key}\n${i2} ` +
|
|
1411
1698
|
getComparisions(key, "srcStart", "!=").join("\n" + i2 + " || ") +
|
|
1412
1699
|
`\n${i2}) break;\n`;
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
DESERIALIZE_FAST += i2 + tier2Desers[i].join("\n" + i2) + "\n";
|
|
1700
|
+
blk += i2 + `srcStart += ${keyBytes};\n`;
|
|
1701
|
+
blk += skip;
|
|
1702
|
+
blk += i2 + "if (load<u16>(srcStart) != 0x3a) break; // :\n";
|
|
1703
|
+
blk += i2 + "srcStart += 2;\n";
|
|
1704
|
+
blk += skip;
|
|
1705
|
+
blk += i2 + tier2Desers[i].join("\n" + i2) + "\n";
|
|
1420
1706
|
if (i < this.schema.members.length - 1) {
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
DESERIALIZE_FAST += i2 + "srcStart += 2;\n";
|
|
1707
|
+
blk += skip;
|
|
1708
|
+
blk += i2 + "if (load<u16>(srcStart) != 0x2c) break; // ,\n";
|
|
1709
|
+
blk += i2 + "srcStart += 2;\n";
|
|
1425
1710
|
}
|
|
1711
|
+
t2blocks.push(blk);
|
|
1426
1712
|
}
|
|
1713
|
+
DESERIALIZE_FAST += chunkFastBlocks(t2blocks, "T2", i2);
|
|
1427
1714
|
DESERIALIZE_FAST += "\n";
|
|
1428
1715
|
DESERIALIZE_FAST += skip;
|
|
1429
1716
|
DESERIALIZE_FAST += i2 + "if (load<u16>(srcStart) != 0x7d) break; // }\n";
|
|
@@ -1445,33 +1732,34 @@ export class JSONTransform extends Visitor {
|
|
|
1445
1732
|
DESERIALIZE_FAST += i2 + "let kp: usize = 0;\n";
|
|
1446
1733
|
if (multi)
|
|
1447
1734
|
DESERIALIZE_FAST += i2 + "let seenAny = false;\n";
|
|
1735
|
+
const t2opt = [];
|
|
1448
1736
|
for (let i = 0; i < this.schema.members.length; i++) {
|
|
1449
1737
|
const member = this.schema.members[i];
|
|
1450
1738
|
const key = JSON.stringify(member.alias || member.name);
|
|
1451
1739
|
const keyBytes = key.length << 1;
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
i2 + "kp = JSON.Util.skipWhitespace(srcStart, srcEnd);\n";
|
|
1740
|
+
let blk = "\n";
|
|
1741
|
+
blk += i2 + "kp = JSON.Util.skipWhitespace(srcStart, srcEnd);\n";
|
|
1455
1742
|
if (multi && i > 0) {
|
|
1456
|
-
|
|
1743
|
+
blk +=
|
|
1457
1744
|
i2 +
|
|
1458
1745
|
"if (seenAny && load<u16>(kp) == 0x2c) kp = JSON.Util.skipWhitespace(kp + 2, srcEnd);\n";
|
|
1459
1746
|
}
|
|
1460
|
-
|
|
1747
|
+
blk +=
|
|
1461
1748
|
i2 +
|
|
1462
1749
|
`if ( // ${key}\n${i2} ` +
|
|
1463
1750
|
getComparisions(key, "kp", "==").join("\n" + i2 + " && ") +
|
|
1464
1751
|
`\n${i2}) {\n`;
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
DESERIALIZE_FAST += i3 + tier2Desers[i].join("\n" + i3) + "\n";
|
|
1752
|
+
blk += i3 + `kp += ${keyBytes};\n`;
|
|
1753
|
+
blk += i3 + "kp = JSON.Util.skipWhitespace(kp, srcEnd);\n";
|
|
1754
|
+
blk += i3 + "if (load<u16>(kp) != 0x3a) break; // :\n";
|
|
1755
|
+
blk += i3 + "srcStart = JSON.Util.skipWhitespace(kp + 2, srcEnd);\n";
|
|
1756
|
+
blk += i3 + tier2Desers[i].join("\n" + i3) + "\n";
|
|
1471
1757
|
if (multi)
|
|
1472
|
-
|
|
1473
|
-
|
|
1758
|
+
blk += i3 + "seenAny = true;\n";
|
|
1759
|
+
blk += i2 + "}\n";
|
|
1760
|
+
t2opt.push(blk);
|
|
1474
1761
|
}
|
|
1762
|
+
DESERIALIZE_FAST += chunkFastBlocksOptional(t2opt, "T2O", i2, true);
|
|
1475
1763
|
DESERIALIZE_FAST += "\n";
|
|
1476
1764
|
DESERIALIZE_FAST +=
|
|
1477
1765
|
i2 + "srcStart = JSON.Util.skipWhitespace(srcStart, srcEnd);\n";
|
|
@@ -1498,7 +1786,7 @@ export class JSONTransform extends Visitor {
|
|
|
1498
1786
|
DESERIALIZE += indent + " let keyStart: usize = 0;\n";
|
|
1499
1787
|
DESERIALIZE += indent + " let keyEnd: usize = 0;\n";
|
|
1500
1788
|
DESERIALIZE += indent + " let isKey = false;\n";
|
|
1501
|
-
if (!STRICT ||
|
|
1789
|
+
if (!STRICT || slowObjectMembers.length || slowArrayMembers.length)
|
|
1502
1790
|
DESERIALIZE += indent + " let depth: i32 = 0;\n";
|
|
1503
1791
|
DESERIALIZE += indent + " let lastIndex: usize = 0;\n\n";
|
|
1504
1792
|
DESERIALIZE +=
|
|
@@ -1643,8 +1931,37 @@ export class JSONTransform extends Visitor {
|
|
|
1643
1931
|
DESERIALIZE += toMemCDecl(Math.max(...members.map((m) => (m.alias || m.name).length << 1)), " ");
|
|
1644
1932
|
}
|
|
1645
1933
|
};
|
|
1934
|
+
const getLazyRangeStore = (member, valueStart, valueEnd, prefix) => {
|
|
1935
|
+
return (prefix +
|
|
1936
|
+
`store<u64>(changetype<usize>(out), ((<u64>${valueStart}) << 32) | (<u64>(<u32>${valueEnd})), offsetof<this>(${JSON.stringify(member.name)}));\n`);
|
|
1937
|
+
};
|
|
1938
|
+
const getSlowValueStore = (member, valueStart, valueEnd, prefix) => {
|
|
1939
|
+
if (member.flags.has(PropertyFlags.Lazy))
|
|
1940
|
+
return getLazyRangeStore(member, valueStart, valueEnd, prefix);
|
|
1941
|
+
return (prefix +
|
|
1942
|
+
`store<${member.type}>(changetype<usize>(out), JSON.__deserialize<${member.type}>(${valueStart}, ${valueEnd}), offsetof<this>(${JSON.stringify(member.name)}));\n`);
|
|
1943
|
+
};
|
|
1944
|
+
const getSlowBooleanStore = (member, value, valueStart, valueEnd, prefix) => {
|
|
1945
|
+
if (member.flags.has(PropertyFlags.Lazy))
|
|
1946
|
+
return getLazyRangeStore(member, valueStart, valueEnd, prefix);
|
|
1947
|
+
if (member.type.startsWith("JSON.Box<bool") ||
|
|
1948
|
+
member.type.startsWith("JSON.Box<boolean") ||
|
|
1949
|
+
member.type.startsWith("Box<bool") ||
|
|
1950
|
+
member.type.startsWith("Box<boolean")) {
|
|
1951
|
+
return (prefix +
|
|
1952
|
+
`store<${member.type}>(changetype<usize>(out), changetype<${member.type}>(JSON.Box.from<bool>(${value})), offsetof<this>(${JSON.stringify(member.name)}));\n`);
|
|
1953
|
+
}
|
|
1954
|
+
return (prefix +
|
|
1955
|
+
`store<boolean>(changetype<usize>(out), ${value}, offsetof<this>(${JSON.stringify(member.name)}));\n`);
|
|
1956
|
+
};
|
|
1957
|
+
const getSlowNullStore = (member, valueStart, valueEnd, prefix) => {
|
|
1958
|
+
if (member.flags.has(PropertyFlags.Lazy))
|
|
1959
|
+
return getLazyRangeStore(member, valueStart, valueEnd, prefix);
|
|
1960
|
+
return (prefix +
|
|
1961
|
+
`store<usize>(changetype<usize>(out), 0, offsetof<this>(${JSON.stringify(member.name)}));\n`);
|
|
1962
|
+
};
|
|
1646
1963
|
let mbElse = " ";
|
|
1647
|
-
if (!STRICT ||
|
|
1964
|
+
if (!STRICT || slowStringMembers.length) {
|
|
1648
1965
|
DESERIALIZE += mbElse + "if (code == 34) {\n";
|
|
1649
1966
|
DESERIALIZE += " lastIndex = srcStart;\n";
|
|
1650
1967
|
DESERIALIZE += " srcStart += 2;\n";
|
|
@@ -1657,7 +1974,7 @@ export class JSONTransform extends Visitor {
|
|
|
1657
1974
|
' console.log("Value (string, ' +
|
|
1658
1975
|
++id +
|
|
1659
1976
|
'): " + JSON.Util.ptrToStr(lastIndex, srcStart + 2));';
|
|
1660
|
-
generateGroups(
|
|
1977
|
+
generateGroups(slowStringMembers, (group) => {
|
|
1661
1978
|
generateConsts(group);
|
|
1662
1979
|
const first = group[0];
|
|
1663
1980
|
const fName = first.alias || first.name;
|
|
@@ -1669,15 +1986,7 @@ export class JSONTransform extends Visitor {
|
|
|
1669
1986
|
") { // " +
|
|
1670
1987
|
fName +
|
|
1671
1988
|
"\n";
|
|
1672
|
-
DESERIALIZE +=
|
|
1673
|
-
indent +
|
|
1674
|
-
" store<" +
|
|
1675
|
-
first.type +
|
|
1676
|
-
">(changetype<usize>(out), JSON.__deserialize<" +
|
|
1677
|
-
first.type +
|
|
1678
|
-
">(lastIndex, srcStart + 2), offsetof<this>(" +
|
|
1679
|
-
JSON.stringify(first.name) +
|
|
1680
|
-
"));\n";
|
|
1989
|
+
DESERIALIZE += getSlowValueStore(first, "lastIndex", "srcStart + 2", indent + " ");
|
|
1681
1990
|
DESERIALIZE += indent + " srcStart += 4;\n";
|
|
1682
1991
|
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
1683
1992
|
DESERIALIZE += indent + " break;\n";
|
|
@@ -1693,15 +2002,7 @@ export class JSONTransform extends Visitor {
|
|
|
1693
2002
|
") { // " +
|
|
1694
2003
|
memName +
|
|
1695
2004
|
"\n";
|
|
1696
|
-
DESERIALIZE +=
|
|
1697
|
-
indent +
|
|
1698
|
-
" store<" +
|
|
1699
|
-
mem.type +
|
|
1700
|
-
">(changetype<usize>(out), JSON.__deserialize<" +
|
|
1701
|
-
mem.type +
|
|
1702
|
-
">(lastIndex, srcStart + 2), offsetof<this>(" +
|
|
1703
|
-
JSON.stringify(mem.name) +
|
|
1704
|
-
"));\n";
|
|
2005
|
+
DESERIALIZE += getSlowValueStore(mem, "lastIndex", "srcStart + 2", indent + " ");
|
|
1705
2006
|
DESERIALIZE += indent + " srcStart += 4;\n";
|
|
1706
2007
|
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
1707
2008
|
DESERIALIZE += indent + " break;\n";
|
|
@@ -1728,7 +2029,7 @@ export class JSONTransform extends Visitor {
|
|
|
1728
2029
|
DESERIALIZE += " }\n";
|
|
1729
2030
|
mbElse = " else ";
|
|
1730
2031
|
}
|
|
1731
|
-
if (!STRICT ||
|
|
2032
|
+
if (!STRICT || slowNumberMembers.length) {
|
|
1732
2033
|
DESERIALIZE += mbElse + "if (code - 48 <= 9 || code == 45) {\n";
|
|
1733
2034
|
DESERIALIZE += " lastIndex = srcStart;\n";
|
|
1734
2035
|
DESERIALIZE += " srcStart += 2;\n";
|
|
@@ -1741,7 +2042,7 @@ export class JSONTransform extends Visitor {
|
|
|
1741
2042
|
' console.log("Value (number, ' +
|
|
1742
2043
|
++id +
|
|
1743
2044
|
'): " + JSON.Util.ptrToStr(lastIndex, srcStart));';
|
|
1744
|
-
generateGroups(
|
|
2045
|
+
generateGroups(slowNumberMembers, (group) => {
|
|
1745
2046
|
generateConsts(group);
|
|
1746
2047
|
const first = group[0];
|
|
1747
2048
|
const fName = first.alias || first.name;
|
|
@@ -1759,15 +2060,7 @@ export class JSONTransform extends Visitor {
|
|
|
1759
2060
|
") { // " +
|
|
1760
2061
|
fName +
|
|
1761
2062
|
"\n";
|
|
1762
|
-
DESERIALIZE +=
|
|
1763
|
-
indent +
|
|
1764
|
-
" store<" +
|
|
1765
|
-
first.type +
|
|
1766
|
-
">(changetype<usize>(out), JSON.__deserialize<" +
|
|
1767
|
-
first.type +
|
|
1768
|
-
">(lastIndex, srcStart), offsetof<this>(" +
|
|
1769
|
-
JSON.stringify(first.name) +
|
|
1770
|
-
"));\n";
|
|
2063
|
+
DESERIALIZE += getSlowValueStore(first, "lastIndex", "srcStart", indent + " ");
|
|
1771
2064
|
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
1772
2065
|
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
1773
2066
|
DESERIALIZE += indent + " break;\n";
|
|
@@ -1789,15 +2082,7 @@ export class JSONTransform extends Visitor {
|
|
|
1789
2082
|
") { // " +
|
|
1790
2083
|
memName +
|
|
1791
2084
|
"\n";
|
|
1792
|
-
DESERIALIZE +=
|
|
1793
|
-
indent +
|
|
1794
|
-
" store<" +
|
|
1795
|
-
mem.type +
|
|
1796
|
-
">(changetype<usize>(out), JSON.__deserialize<" +
|
|
1797
|
-
mem.type +
|
|
1798
|
-
">(lastIndex, srcStart), offsetof<this>(" +
|
|
1799
|
-
JSON.stringify(mem.name) +
|
|
1800
|
-
"));\n";
|
|
2085
|
+
DESERIALIZE += getSlowValueStore(mem, "lastIndex", "srcStart", indent + " ");
|
|
1801
2086
|
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
1802
2087
|
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
1803
2088
|
DESERIALIZE += indent + " break;\n";
|
|
@@ -1824,7 +2109,7 @@ export class JSONTransform extends Visitor {
|
|
|
1824
2109
|
DESERIALIZE += " }";
|
|
1825
2110
|
mbElse = " else ";
|
|
1826
2111
|
}
|
|
1827
|
-
if (!STRICT ||
|
|
2112
|
+
if (!STRICT || slowObjectMembers.length) {
|
|
1828
2113
|
DESERIALIZE += mbElse + "if (code == 123) {\n";
|
|
1829
2114
|
DESERIALIZE += " lastIndex = srcStart;\n";
|
|
1830
2115
|
DESERIALIZE += " depth++;\n";
|
|
@@ -1844,7 +2129,7 @@ export class JSONTransform extends Visitor {
|
|
|
1844
2129
|
++id +
|
|
1845
2130
|
'): " + JSON.Util.ptrToStr(lastIndex, srcStart));';
|
|
1846
2131
|
indent = " ";
|
|
1847
|
-
generateGroups(
|
|
2132
|
+
generateGroups(slowObjectMembers, (group) => {
|
|
1848
2133
|
generateConsts(group);
|
|
1849
2134
|
const first = group[0];
|
|
1850
2135
|
const fName = first.alias || first.name;
|
|
@@ -1855,15 +2140,7 @@ export class JSONTransform extends Visitor {
|
|
|
1855
2140
|
") { // " +
|
|
1856
2141
|
fName +
|
|
1857
2142
|
"\n";
|
|
1858
|
-
DESERIALIZE +=
|
|
1859
|
-
indent +
|
|
1860
|
-
" store<" +
|
|
1861
|
-
first.type +
|
|
1862
|
-
">(changetype<usize>(out), JSON.__deserialize<" +
|
|
1863
|
-
first.type +
|
|
1864
|
-
">(lastIndex, srcStart), offsetof<this>(" +
|
|
1865
|
-
JSON.stringify(first.name) +
|
|
1866
|
-
"));\n";
|
|
2143
|
+
DESERIALIZE += getSlowValueStore(first, "lastIndex", "srcStart", indent + " ");
|
|
1867
2144
|
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
1868
2145
|
DESERIALIZE += indent + " break;\n";
|
|
1869
2146
|
DESERIALIZE += indent + " }";
|
|
@@ -1877,15 +2154,7 @@ export class JSONTransform extends Visitor {
|
|
|
1877
2154
|
") { // " +
|
|
1878
2155
|
memName +
|
|
1879
2156
|
"\n";
|
|
1880
|
-
DESERIALIZE +=
|
|
1881
|
-
indent +
|
|
1882
|
-
" store<" +
|
|
1883
|
-
mem.type +
|
|
1884
|
-
">(changetype<usize>(out), JSON.__deserialize<" +
|
|
1885
|
-
mem.type +
|
|
1886
|
-
">(lastIndex, srcStart), offsetof<this>(" +
|
|
1887
|
-
JSON.stringify(mem.name) +
|
|
1888
|
-
"));\n";
|
|
2157
|
+
DESERIALIZE += getSlowValueStore(mem, "lastIndex", "srcStart", indent + " ");
|
|
1889
2158
|
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
1890
2159
|
DESERIALIZE += indent + " break;\n";
|
|
1891
2160
|
DESERIALIZE += indent + " }";
|
|
@@ -1912,7 +2181,7 @@ export class JSONTransform extends Visitor {
|
|
|
1912
2181
|
DESERIALIZE += " }";
|
|
1913
2182
|
mbElse = " else ";
|
|
1914
2183
|
}
|
|
1915
|
-
if (!STRICT ||
|
|
2184
|
+
if (!STRICT || slowArrayMembers.length) {
|
|
1916
2185
|
DESERIALIZE += mbElse + "if (code == 91) {\n";
|
|
1917
2186
|
DESERIALIZE += " lastIndex = srcStart;\n";
|
|
1918
2187
|
DESERIALIZE += " depth++;\n";
|
|
@@ -1932,7 +2201,7 @@ export class JSONTransform extends Visitor {
|
|
|
1932
2201
|
++id +
|
|
1933
2202
|
'): " + JSON.Util.ptrToStr(lastIndex, srcStart));';
|
|
1934
2203
|
indent = " ";
|
|
1935
|
-
generateGroups(
|
|
2204
|
+
generateGroups(slowArrayMembers, (group) => {
|
|
1936
2205
|
generateConsts(group);
|
|
1937
2206
|
const first = group[0];
|
|
1938
2207
|
const fName = first.alias || first.name;
|
|
@@ -1944,15 +2213,7 @@ export class JSONTransform extends Visitor {
|
|
|
1944
2213
|
") { // " +
|
|
1945
2214
|
fName +
|
|
1946
2215
|
"\n";
|
|
1947
|
-
DESERIALIZE +=
|
|
1948
|
-
indent +
|
|
1949
|
-
" store<" +
|
|
1950
|
-
first.type +
|
|
1951
|
-
">(changetype<usize>(out), JSON.__deserialize<" +
|
|
1952
|
-
first.type +
|
|
1953
|
-
">(lastIndex, srcStart), offsetof<this>(" +
|
|
1954
|
-
JSON.stringify(first.name) +
|
|
1955
|
-
"));\n";
|
|
2216
|
+
DESERIALIZE += getSlowValueStore(first, "lastIndex", "srcStart", indent + " ");
|
|
1956
2217
|
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
1957
2218
|
DESERIALIZE += indent + " break;\n";
|
|
1958
2219
|
DESERIALIZE += indent + " }";
|
|
@@ -1967,15 +2228,7 @@ export class JSONTransform extends Visitor {
|
|
|
1967
2228
|
") { // " +
|
|
1968
2229
|
memName +
|
|
1969
2230
|
"\n";
|
|
1970
|
-
DESERIALIZE +=
|
|
1971
|
-
indent +
|
|
1972
|
-
" store<" +
|
|
1973
|
-
mem.type +
|
|
1974
|
-
">(changetype<usize>(out), JSON.__deserialize<" +
|
|
1975
|
-
mem.type +
|
|
1976
|
-
">(lastIndex, srcStart), offsetof<this>(" +
|
|
1977
|
-
JSON.stringify(mem.name) +
|
|
1978
|
-
"));\n";
|
|
2231
|
+
DESERIALIZE += getSlowValueStore(mem, "lastIndex", "srcStart", indent + " ");
|
|
1979
2232
|
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
1980
2233
|
DESERIALIZE += indent + " break;\n";
|
|
1981
2234
|
DESERIALIZE += indent + " }";
|
|
@@ -2002,7 +2255,7 @@ export class JSONTransform extends Visitor {
|
|
|
2002
2255
|
DESERIALIZE += " }";
|
|
2003
2256
|
mbElse = " else ";
|
|
2004
2257
|
}
|
|
2005
|
-
if (!STRICT ||
|
|
2258
|
+
if (!STRICT || slowBooleanMembers.length) {
|
|
2006
2259
|
DESERIALIZE += mbElse + "if (code == 116) {\n";
|
|
2007
2260
|
DESERIALIZE +=
|
|
2008
2261
|
" if (load<u64>(srcStart) == 28429475166421108) {\n";
|
|
@@ -2012,7 +2265,7 @@ export class JSONTransform extends Visitor {
|
|
|
2012
2265
|
' console.log("Value (bool, ' +
|
|
2013
2266
|
++id +
|
|
2014
2267
|
'): " + JSON.Util.ptrToStr(lastIndex, srcStart - 8));';
|
|
2015
|
-
generateGroups(
|
|
2268
|
+
generateGroups(slowBooleanMembers, (group) => {
|
|
2016
2269
|
generateConsts(group);
|
|
2017
2270
|
const first = group[0];
|
|
2018
2271
|
const fName = first.alias || first.name;
|
|
@@ -2024,27 +2277,7 @@ export class JSONTransform extends Visitor {
|
|
|
2024
2277
|
") { // " +
|
|
2025
2278
|
fName +
|
|
2026
2279
|
"\n";
|
|
2027
|
-
|
|
2028
|
-
first.type.startsWith("JSON.Box<boolean") ||
|
|
2029
|
-
first.type.startsWith("Box<bool") ||
|
|
2030
|
-
first.type.startsWith("Box<boolean")) {
|
|
2031
|
-
DESERIALIZE +=
|
|
2032
|
-
indent +
|
|
2033
|
-
" store<" +
|
|
2034
|
-
first.type +
|
|
2035
|
-
">(changetype<usize>(out), changetype<" +
|
|
2036
|
-
first.type +
|
|
2037
|
-
">(JSON.Box.from<bool>(true)), offsetof<this>(" +
|
|
2038
|
-
JSON.stringify(first.name) +
|
|
2039
|
-
"));\n";
|
|
2040
|
-
}
|
|
2041
|
-
else {
|
|
2042
|
-
DESERIALIZE +=
|
|
2043
|
-
indent +
|
|
2044
|
-
" store<boolean>(changetype<usize>(out), true, offsetof<this>(" +
|
|
2045
|
-
JSON.stringify(first.name) +
|
|
2046
|
-
"));\n";
|
|
2047
|
-
}
|
|
2280
|
+
DESERIALIZE += getSlowBooleanStore(first, "true", "srcStart - 8", "srcStart", indent + " ");
|
|
2048
2281
|
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
2049
2282
|
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
2050
2283
|
DESERIALIZE += indent + " break;\n";
|
|
@@ -2060,27 +2293,7 @@ export class JSONTransform extends Visitor {
|
|
|
2060
2293
|
") { // " +
|
|
2061
2294
|
memName +
|
|
2062
2295
|
"\n";
|
|
2063
|
-
|
|
2064
|
-
mem.type.startsWith("JSON.Box<boolean") ||
|
|
2065
|
-
mem.type.startsWith("Box<bool") ||
|
|
2066
|
-
mem.type.startsWith("Box<boolean")) {
|
|
2067
|
-
DESERIALIZE +=
|
|
2068
|
-
indent +
|
|
2069
|
-
" store<" +
|
|
2070
|
-
mem.type +
|
|
2071
|
-
">(changetype<usize>(out), changetype<" +
|
|
2072
|
-
mem.type +
|
|
2073
|
-
">(JSON.Box.from<bool>(true)), offsetof<this>(" +
|
|
2074
|
-
JSON.stringify(mem.name) +
|
|
2075
|
-
"));\n";
|
|
2076
|
-
}
|
|
2077
|
-
else {
|
|
2078
|
-
DESERIALIZE +=
|
|
2079
|
-
indent +
|
|
2080
|
-
" store<boolean>(changetype<usize>(out), true, offsetof<this>(" +
|
|
2081
|
-
JSON.stringify(mem.name) +
|
|
2082
|
-
"));\n";
|
|
2083
|
-
}
|
|
2296
|
+
DESERIALIZE += getSlowBooleanStore(mem, "true", "srcStart - 8", "srcStart", indent + " ");
|
|
2084
2297
|
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
2085
2298
|
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
2086
2299
|
DESERIALIZE += indent + " break;\n";
|
|
@@ -2116,7 +2329,7 @@ export class JSONTransform extends Visitor {
|
|
|
2116
2329
|
' console.log("Value (bool, ' +
|
|
2117
2330
|
++id +
|
|
2118
2331
|
'): " + JSON.Util.ptrToStr(lastIndex, srcStart - 10));';
|
|
2119
|
-
generateGroups(
|
|
2332
|
+
generateGroups(slowBooleanMembers, (group) => {
|
|
2120
2333
|
generateConsts(group);
|
|
2121
2334
|
const first = group[0];
|
|
2122
2335
|
const fName = first.alias || first.name;
|
|
@@ -2128,27 +2341,7 @@ export class JSONTransform extends Visitor {
|
|
|
2128
2341
|
") { // " +
|
|
2129
2342
|
fName +
|
|
2130
2343
|
"\n";
|
|
2131
|
-
|
|
2132
|
-
first.type.startsWith("JSON.Box<boolean") ||
|
|
2133
|
-
first.type.startsWith("Box<bool") ||
|
|
2134
|
-
first.type.startsWith("Box<boolean")) {
|
|
2135
|
-
DESERIALIZE +=
|
|
2136
|
-
indent +
|
|
2137
|
-
" store<" +
|
|
2138
|
-
first.type +
|
|
2139
|
-
">(changetype<usize>(out), changetype<" +
|
|
2140
|
-
first.type +
|
|
2141
|
-
">(JSON.Box.from<bool>(false)), offsetof<this>(" +
|
|
2142
|
-
JSON.stringify(first.name) +
|
|
2143
|
-
"));\n";
|
|
2144
|
-
}
|
|
2145
|
-
else {
|
|
2146
|
-
DESERIALIZE +=
|
|
2147
|
-
indent +
|
|
2148
|
-
" store<boolean>(changetype<usize>(out), false, offsetof<this>(" +
|
|
2149
|
-
JSON.stringify(first.name) +
|
|
2150
|
-
"));\n";
|
|
2151
|
-
}
|
|
2344
|
+
DESERIALIZE += getSlowBooleanStore(first, "false", "srcStart - 10", "srcStart", indent + " ");
|
|
2152
2345
|
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
2153
2346
|
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
2154
2347
|
DESERIALIZE += indent + " break;\n";
|
|
@@ -2164,27 +2357,7 @@ export class JSONTransform extends Visitor {
|
|
|
2164
2357
|
") { // " +
|
|
2165
2358
|
memName +
|
|
2166
2359
|
"\n";
|
|
2167
|
-
|
|
2168
|
-
mem.type.startsWith("JSON.Box<boolean") ||
|
|
2169
|
-
mem.type.startsWith("Box<bool") ||
|
|
2170
|
-
mem.type.startsWith("Box<boolean")) {
|
|
2171
|
-
DESERIALIZE +=
|
|
2172
|
-
indent +
|
|
2173
|
-
" store<" +
|
|
2174
|
-
mem.type +
|
|
2175
|
-
">(changetype<usize>(out), changetype<" +
|
|
2176
|
-
mem.type +
|
|
2177
|
-
">(JSON.Box.from<bool>(false)), offsetof<this>(" +
|
|
2178
|
-
JSON.stringify(mem.name) +
|
|
2179
|
-
"));\n";
|
|
2180
|
-
}
|
|
2181
|
-
else {
|
|
2182
|
-
DESERIALIZE +=
|
|
2183
|
-
indent +
|
|
2184
|
-
" store<boolean>(changetype<usize>(out), false, offsetof<this>(" +
|
|
2185
|
-
JSON.stringify(mem.name) +
|
|
2186
|
-
"));\n";
|
|
2187
|
-
}
|
|
2360
|
+
DESERIALIZE += getSlowBooleanStore(mem, "false", "srcStart - 10", "srcStart", indent + " ");
|
|
2188
2361
|
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
2189
2362
|
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
2190
2363
|
DESERIALIZE += indent + " break;\n";
|
|
@@ -2209,7 +2382,7 @@ export class JSONTransform extends Visitor {
|
|
|
2209
2382
|
DESERIALIZE += "\n }";
|
|
2210
2383
|
mbElse = " else ";
|
|
2211
2384
|
}
|
|
2212
|
-
if (!STRICT ||
|
|
2385
|
+
if (!STRICT || slowNullMembers.length) {
|
|
2213
2386
|
DESERIALIZE += mbElse + "if (code == 110) {\n";
|
|
2214
2387
|
DESERIALIZE +=
|
|
2215
2388
|
" if (load<u64>(srcStart) == 30399761348886638) {\n";
|
|
@@ -2219,7 +2392,7 @@ export class JSONTransform extends Visitor {
|
|
|
2219
2392
|
' console.log("Value (null, ' +
|
|
2220
2393
|
++id +
|
|
2221
2394
|
'): " + JSON.Util.ptrToStr(lastIndex, srcStart - 8));';
|
|
2222
|
-
generateGroups(
|
|
2395
|
+
generateGroups(slowNullMembers, (group) => {
|
|
2223
2396
|
generateConsts(group);
|
|
2224
2397
|
const first = group[0];
|
|
2225
2398
|
const fName = first.alias || first.name;
|
|
@@ -2231,11 +2404,7 @@ export class JSONTransform extends Visitor {
|
|
|
2231
2404
|
") { // " +
|
|
2232
2405
|
fName +
|
|
2233
2406
|
"\n";
|
|
2234
|
-
DESERIALIZE +=
|
|
2235
|
-
indent +
|
|
2236
|
-
" store<usize>(changetype<usize>(out), 0, offsetof<this>(" +
|
|
2237
|
-
JSON.stringify(first.name) +
|
|
2238
|
-
"));\n";
|
|
2407
|
+
DESERIALIZE += getSlowNullStore(first, "srcStart - 8", "srcStart", indent + " ");
|
|
2239
2408
|
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
2240
2409
|
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
2241
2410
|
DESERIALIZE += indent + " break;\n";
|
|
@@ -2251,11 +2420,7 @@ export class JSONTransform extends Visitor {
|
|
|
2251
2420
|
") { // " +
|
|
2252
2421
|
memName +
|
|
2253
2422
|
"\n";
|
|
2254
|
-
DESERIALIZE +=
|
|
2255
|
-
indent +
|
|
2256
|
-
" store<usize>(changetype<usize>(out), 0, offsetof<this>(" +
|
|
2257
|
-
JSON.stringify(mem.name) +
|
|
2258
|
-
"));\n";
|
|
2423
|
+
DESERIALIZE += getSlowNullStore(mem, "srcStart - 8", "srcStart", indent + " ");
|
|
2259
2424
|
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
2260
2425
|
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
2261
2426
|
DESERIALIZE += indent + " break;\n";
|
|
@@ -2308,6 +2473,11 @@ export class JSONTransform extends Visitor {
|
|
|
2308
2473
|
console.log(INITIALIZE);
|
|
2309
2474
|
console.log(DESERIALIZE_CUSTOM || DESERIALIZE);
|
|
2310
2475
|
}
|
|
2476
|
+
const WIDE_STRUCT_FIELD_LIMIT = 32;
|
|
2477
|
+
if (this.schema.members.length > WIDE_STRUCT_FIELD_LIMIT) {
|
|
2478
|
+
INITIALIZE = INITIALIZE.replace(/^@inline /, "");
|
|
2479
|
+
DESERIALIZE_FAST = DESERIALIZE_FAST.replace(/^@inline /, "");
|
|
2480
|
+
}
|
|
2311
2481
|
const SERIALIZE_METHOD = SimpleParser.parseClassMember(SERIALIZE_CUSTOM || SERIALIZE, node);
|
|
2312
2482
|
const INITIALIZE_METHOD = SimpleParser.parseClassMember(INITIALIZE, node);
|
|
2313
2483
|
const DESERIALIZE_CUSTOM_METHOD = DESERIALIZE_CUSTOM
|
|
@@ -2334,6 +2504,13 @@ export class JSONTransform extends Visitor {
|
|
|
2334
2504
|
DESERIALIZE_FAST_METHOD &&
|
|
2335
2505
|
!node.members.find((v) => v.name.text == "__DESERIALIZE_FAST"))
|
|
2336
2506
|
node.members.push(DESERIALIZE_FAST_METHOD);
|
|
2507
|
+
if (useFastPath && !DESERIALIZE_CUSTOM) {
|
|
2508
|
+
for (const chunk of fastChunkMethods) {
|
|
2509
|
+
const chunkMethod = SimpleParser.parseClassMember(chunk, node);
|
|
2510
|
+
if (!node.members.find((v) => v.name.text == chunkMethod.name.text))
|
|
2511
|
+
node.members.push(chunkMethod);
|
|
2512
|
+
}
|
|
2513
|
+
}
|
|
2337
2514
|
super.visitClassDeclaration(node);
|
|
2338
2515
|
}
|
|
2339
2516
|
getSchema(name) {
|
|
@@ -2552,25 +2729,6 @@ var JSONMode;
|
|
|
2552
2729
|
JSONMode[JSONMode["NAIVE"] = 2] = "NAIVE";
|
|
2553
2730
|
})(JSONMode || (JSONMode = {}));
|
|
2554
2731
|
let MODE = JSONMode.SWAR;
|
|
2555
|
-
function getCodegenMode(program) {
|
|
2556
|
-
let mode = program.options.hasFeature(16)
|
|
2557
|
-
? JSONMode.SIMD
|
|
2558
|
-
: JSONMode.SWAR;
|
|
2559
|
-
if (process.env["JSON_MODE"]) {
|
|
2560
|
-
switch (process.env["JSON_MODE"].toLowerCase().trim()) {
|
|
2561
|
-
case "simd":
|
|
2562
|
-
mode = JSONMode.SIMD;
|
|
2563
|
-
break;
|
|
2564
|
-
case "swar":
|
|
2565
|
-
mode = JSONMode.SWAR;
|
|
2566
|
-
break;
|
|
2567
|
-
case "naive":
|
|
2568
|
-
mode = JSONMode.NAIVE;
|
|
2569
|
-
break;
|
|
2570
|
-
}
|
|
2571
|
-
}
|
|
2572
|
-
return mode;
|
|
2573
|
-
}
|
|
2574
2732
|
export default class Transformer extends Transform {
|
|
2575
2733
|
afterInitialize(program) {
|
|
2576
2734
|
if (program.options.hasFeature(16))
|
|
@@ -2648,6 +2806,12 @@ export default class Transformer extends Transform {
|
|
|
2648
2806
|
writeFileSync(path.join(process.cwd(), this.baseDir, removeExtension(source.normalizedPath) + ".tmp.ts"), toString(source));
|
|
2649
2807
|
}
|
|
2650
2808
|
}
|
|
2809
|
+
for (const source of parser.sources) {
|
|
2810
|
+
const p = source.internalPath;
|
|
2811
|
+
if (p === "assembly/index" || p.endsWith("/json-as/assembly/index")) {
|
|
2812
|
+
source.sourceKind = 2;
|
|
2813
|
+
}
|
|
2814
|
+
}
|
|
2651
2815
|
}
|
|
2652
2816
|
}
|
|
2653
2817
|
function sortMembers(members) {
|
|
@@ -2808,6 +2972,90 @@ function sizeof(type) {
|
|
|
2808
2972
|
else
|
|
2809
2973
|
return 0;
|
|
2810
2974
|
}
|
|
2975
|
+
function classLazyMode(node) {
|
|
2976
|
+
const dec = node.decorators?.find((d) => {
|
|
2977
|
+
const n = d.name.text;
|
|
2978
|
+
return n === "json" || n === "serializable";
|
|
2979
|
+
});
|
|
2980
|
+
if (!dec || !dec.args || dec.args.length === 0)
|
|
2981
|
+
return "none";
|
|
2982
|
+
const arg = dec.args[0];
|
|
2983
|
+
if (arg.kind !== NodeKind.Literal ||
|
|
2984
|
+
arg.literalKind !== 6)
|
|
2985
|
+
return "none";
|
|
2986
|
+
const obj = arg;
|
|
2987
|
+
for (let i = 0; i < obj.names.length; i++) {
|
|
2988
|
+
if (obj.names[i].text !== "lazy")
|
|
2989
|
+
continue;
|
|
2990
|
+
const v = obj.values[i];
|
|
2991
|
+
if (v.kind === NodeKind.Literal &&
|
|
2992
|
+
v.literalKind === 2) {
|
|
2993
|
+
const s = v.value;
|
|
2994
|
+
if (s === "none" || s === "auto" || s === "all")
|
|
2995
|
+
return s;
|
|
2996
|
+
}
|
|
2997
|
+
throwError(`@json lazy must be "none", "auto", or "all"`, v.range);
|
|
2998
|
+
}
|
|
2999
|
+
return "none";
|
|
3000
|
+
}
|
|
3001
|
+
const LAZY_AUTO_THRESHOLD = 10;
|
|
3002
|
+
function lazyTypeCost(type, source, parser) {
|
|
3003
|
+
const base = stripNull(type);
|
|
3004
|
+
if (isPrimitive(base) || isBoolean(base) || isEnum(base, source, parser))
|
|
3005
|
+
return 1;
|
|
3006
|
+
if (base === "Date")
|
|
3007
|
+
return 4;
|
|
3008
|
+
if (isString(base))
|
|
3009
|
+
return 10;
|
|
3010
|
+
if (base === "JSON.Value" ||
|
|
3011
|
+
base === "Value" ||
|
|
3012
|
+
base === "JSON.Obj" ||
|
|
3013
|
+
base === "Obj" ||
|
|
3014
|
+
base === "JSON.Raw" ||
|
|
3015
|
+
base === "Raw")
|
|
3016
|
+
return 15;
|
|
3017
|
+
return 20;
|
|
3018
|
+
}
|
|
3019
|
+
function lazyAutoCost(type, source, parser) {
|
|
3020
|
+
const direct = lazyTypeCost(type, source, parser);
|
|
3021
|
+
if (direct < 20)
|
|
3022
|
+
return direct;
|
|
3023
|
+
const decl = source.getClass(stripNull(type));
|
|
3024
|
+
if (!decl)
|
|
3025
|
+
return 20;
|
|
3026
|
+
let sum = 0;
|
|
3027
|
+
for (let i = 0; i < decl.members.length; i++) {
|
|
3028
|
+
const m = decl.members[i];
|
|
3029
|
+
if (m.kind !== NodeKind.FieldDeclaration)
|
|
3030
|
+
continue;
|
|
3031
|
+
const fd = m;
|
|
3032
|
+
if (fd.is(32) ||
|
|
3033
|
+
fd.is(512) ||
|
|
3034
|
+
fd.is(1024) ||
|
|
3035
|
+
!fd.type)
|
|
3036
|
+
continue;
|
|
3037
|
+
sum += lazyTypeCost(toString(fd.type), source, parser);
|
|
3038
|
+
if (sum >= LAZY_AUTO_THRESHOLD)
|
|
3039
|
+
return sum;
|
|
3040
|
+
}
|
|
3041
|
+
return sum;
|
|
3042
|
+
}
|
|
3043
|
+
function lazyWrapperInner(typeNode) {
|
|
3044
|
+
if (!typeNode || typeNode.kind !== NodeKind.NamedType)
|
|
3045
|
+
return null;
|
|
3046
|
+
const named = typeNode;
|
|
3047
|
+
let seg = named.name;
|
|
3048
|
+
while (seg.next)
|
|
3049
|
+
seg = seg.next;
|
|
3050
|
+
if (seg.identifier.text !== "Lazy")
|
|
3051
|
+
return null;
|
|
3052
|
+
if (!named.typeArguments || named.typeArguments.length !== 1)
|
|
3053
|
+
return null;
|
|
3054
|
+
let inner = toString(named.typeArguments[0]).trim();
|
|
3055
|
+
if (named.isNullable && !inner.endsWith("null"))
|
|
3056
|
+
inner += " | null";
|
|
3057
|
+
return inner;
|
|
3058
|
+
}
|
|
2811
3059
|
function estimatedSerializedByteSize(type, source, parser) {
|
|
2812
3060
|
const trimmed = type.trim();
|
|
2813
3061
|
const baseType = stripNull(trimmed);
|
|
@@ -2905,4 +3153,3 @@ function getComparison(data) {
|
|
|
2905
3153
|
}
|
|
2906
3154
|
}
|
|
2907
3155
|
}
|
|
2908
|
-
//# sourceMappingURL=index.js.map
|