json-as 1.0.8 → 1.1.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 +12 -0
- package/README.md +10 -1
- package/assembly/__benches__/lib/bench.ts +1 -1
- package/assembly/__benches__/vec3.bench.ts +0 -46
- package/assembly/__tests__/custom.spec.ts +4 -3
- package/assembly/__tests__/hierarchy.spec.ts +55 -0
- package/assembly/__tests__/lib/index.ts +1 -0
- package/assembly/deserialize/simple/array/box.ts +36 -36
- package/assembly/deserialize/simple/array.ts +1 -1
- package/assembly/index.ts +23 -30
- package/assembly/test.ts +124 -177
- package/assembly/util/idofd.ts +6 -0
- package/bench/lib/bench.ts +3 -3
- package/bench/runners/assemblyscript.js +17 -19
- package/package.json +1 -1
- package/transform/lib/index.js +383 -120
- package/transform/lib/index.js.map +1 -1
- package/transform/lib/types.js +1 -0
- package/transform/lib/types.js.map +1 -1
- package/transform/src/index.ts +431 -117
- package/transform/src/types.ts +1 -0
package/transform/lib/index.js
CHANGED
|
@@ -7,7 +7,9 @@ import { fileURLToPath } from "url";
|
|
|
7
7
|
import { Property, PropertyFlags, Schema } from "./types.js";
|
|
8
8
|
import { getClasses, getImportedClass } from "./linker.js";
|
|
9
9
|
let indent = " ";
|
|
10
|
+
const DEBUG = process.env["JSON_DEBUG"];
|
|
10
11
|
class JSONTransform extends Visitor {
|
|
12
|
+
static SN = new JSONTransform();
|
|
11
13
|
program;
|
|
12
14
|
baseDir;
|
|
13
15
|
parser;
|
|
@@ -29,7 +31,12 @@ class JSONTransform extends Visitor {
|
|
|
29
31
|
this.schema.node = node;
|
|
30
32
|
this.schema.name = node.name.text;
|
|
31
33
|
this.schemas.push(this.schema);
|
|
32
|
-
|
|
34
|
+
let SERIALIZE = "__SERIALIZE(ptr: usize): void {\n";
|
|
35
|
+
let INITIALIZE = "@inline __INITIALIZE(): this {\n";
|
|
36
|
+
let DESERIALIZE = "__DESERIALIZE<__JSON_T>(srcStart: usize, srcEnd: usize, out: __JSON_T): __JSON_T {\n";
|
|
37
|
+
let DESERIALIZE_CUSTOM = "";
|
|
38
|
+
let SERIALIZE_CUSTOM = "";
|
|
39
|
+
if (DEBUG)
|
|
33
40
|
console.log("Created schema: " + this.schema.name + " in file " + node.range.source.normalizedPath);
|
|
34
41
|
const members = [...node.members.filter((v) => v.kind === 54 && v.flags !== 32 && v.flags !== 512 && v.flags !== 1024 && !v.decorators?.some((decorator) => decorator.name.text === "omit"))];
|
|
35
42
|
const serializers = [...node.members.filter((v) => v.kind === 58 && v.decorators && v.decorators.some((e) => e.name.text.toLowerCase() === "serializer"))];
|
|
@@ -39,6 +46,7 @@ class JSONTransform extends Visitor {
|
|
|
39
46
|
if (deserializers.length > 1)
|
|
40
47
|
throwError("Multiple deserializers detected for class " + node.name.text + " but schemas can only have one deserializer!", deserializers[1].range);
|
|
41
48
|
if (serializers.length) {
|
|
49
|
+
this.schema.custom = true;
|
|
42
50
|
const serializer = serializers[0];
|
|
43
51
|
if (serializer.signature.parameters.length > 1)
|
|
44
52
|
throwError("Found too many parameters in custom serializer for " + this.schema.name + ", but serializers can only accept one parameter of type '" + this.schema.name + "'!", serializer.signature.parameters[1].range);
|
|
@@ -49,20 +57,15 @@ class JSONTransform extends Visitor {
|
|
|
49
57
|
if (!serializer.decorators.some((v) => v.name.text == "inline")) {
|
|
50
58
|
serializer.decorators.push(Node.createDecorator(Node.createIdentifierExpression("inline", serializer.range), null, serializer.range));
|
|
51
59
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
SERIALIZER += " }\n";
|
|
59
|
-
if (process.env["JSON_DEBUG"])
|
|
60
|
-
console.log(SERIALIZER);
|
|
61
|
-
const SERIALIZER_METHOD = SimpleParser.parseClassMember(SERIALIZER, node);
|
|
62
|
-
if (!node.members.find((v) => v.name.text == "__SERIALIZE_CUSTOM"))
|
|
63
|
-
node.members.push(SERIALIZER_METHOD);
|
|
60
|
+
SERIALIZE_CUSTOM += " __SERIALIZE(ptr: usize): void {\n";
|
|
61
|
+
SERIALIZE_CUSTOM += " const data = this." + serializer.name.text + "(" + (serializer.signature.parameters.length ? "this" : "") + ");\n";
|
|
62
|
+
SERIALIZE_CUSTOM += " const dataSize = data.length << 1;\n";
|
|
63
|
+
SERIALIZE_CUSTOM += " memory.copy(bs.offset, changetype<usize>(data), dataSize);\n";
|
|
64
|
+
SERIALIZE_CUSTOM += " bs.offset += dataSize;\n";
|
|
65
|
+
SERIALIZE_CUSTOM += " }\n";
|
|
64
66
|
}
|
|
65
67
|
if (deserializers.length) {
|
|
68
|
+
this.schema.custom = true;
|
|
66
69
|
const deserializer = deserializers[0];
|
|
67
70
|
if (!deserializer.signature.parameters.length)
|
|
68
71
|
throwError("Could not find any parameters in custom deserializer for " + this.schema.name + ". Deserializers must have one parameter like 'deserializer(data: string): " + this.schema.name + " {}'", deserializer.range);
|
|
@@ -75,15 +78,9 @@ class JSONTransform extends Visitor {
|
|
|
75
78
|
if (!deserializer.decorators.some((v) => v.name.text == "inline")) {
|
|
76
79
|
deserializer.decorators.push(Node.createDecorator(Node.createIdentifierExpression("inline", deserializer.range), null, deserializer.range));
|
|
77
80
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
DESERIALIZER += " }\n";
|
|
82
|
-
if (process.env["JSON_DEBUG"])
|
|
83
|
-
console.log(DESERIALIZER);
|
|
84
|
-
const DESERIALIZER_METHOD = SimpleParser.parseClassMember(DESERIALIZER, node);
|
|
85
|
-
if (!node.members.find((v) => v.name.text == "__DESERIALIZE_CUSTOM"))
|
|
86
|
-
node.members.push(DESERIALIZER_METHOD);
|
|
81
|
+
DESERIALIZE_CUSTOM += " __DESERIALIZE<__JSON_T>(srcStart: usize, srcEnd: usize, out: __JSON_T): __JSON_T {\n";
|
|
82
|
+
DESERIALIZE_CUSTOM += " return inline.always(this." + deserializer.name.text + "(changetype<string>(srcStart)));\n";
|
|
83
|
+
DESERIALIZE_CUSTOM += " }\n";
|
|
87
84
|
}
|
|
88
85
|
if (node.extendsType) {
|
|
89
86
|
const extendsName = node.extendsType?.name.identifier.text;
|
|
@@ -91,7 +88,7 @@ class JSONTransform extends Visitor {
|
|
|
91
88
|
if (!this.schema.parent) {
|
|
92
89
|
const internalSearch = getClasses(node.range.source).find((v) => v.name.text == extendsName);
|
|
93
90
|
if (internalSearch) {
|
|
94
|
-
if (
|
|
91
|
+
if (DEBUG)
|
|
95
92
|
console.log("Found " + extendsName + " internally");
|
|
96
93
|
this.visitClassDeclaration(internalSearch);
|
|
97
94
|
this.visitClassDeclaration(node);
|
|
@@ -99,7 +96,7 @@ class JSONTransform extends Visitor {
|
|
|
99
96
|
}
|
|
100
97
|
const externalSearch = getImportedClass(extendsName, node.range.source, this.parser);
|
|
101
98
|
if (externalSearch) {
|
|
102
|
-
if (
|
|
99
|
+
if (DEBUG)
|
|
103
100
|
console.log("Found " + extendsName + " externally");
|
|
104
101
|
this.visitClassDeclaration(externalSearch);
|
|
105
102
|
this.visitClassDeclaration(node);
|
|
@@ -172,9 +169,6 @@ class JSONTransform extends Visitor {
|
|
|
172
169
|
}
|
|
173
170
|
if (!this.schema.static)
|
|
174
171
|
this.schema.members = sortMembers(this.schema.members);
|
|
175
|
-
let SERIALIZE = "__SERIALIZE(ptr: usize): void {\n";
|
|
176
|
-
let INITIALIZE = "@inline __INITIALIZE(): this {\n";
|
|
177
|
-
let DESERIALIZE = "__DESERIALIZE(keyStart: usize, keyEnd: usize, valStart: usize, valEnd: usize, ptr: usize): void {\n switch (<u32>keyEnd - <u32>keyStart) {\n";
|
|
178
172
|
indent = " ";
|
|
179
173
|
if (this.schema.static == false) {
|
|
180
174
|
if (this.schema.members.some((v) => v.flags.has(PropertyFlags.OmitNull))) {
|
|
@@ -282,86 +276,317 @@ class JSONTransform extends Visitor {
|
|
|
282
276
|
}
|
|
283
277
|
}
|
|
284
278
|
}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
DESERIALIZE += `${indent}case ${memberLen}: {\n`;
|
|
305
|
-
indentInc();
|
|
306
|
-
if (memberLen == 2)
|
|
307
|
-
DESERIALIZE += `${indent}switch (load<u16>(keyStart)) {\n`;
|
|
308
|
-
else if (memberLen == 4)
|
|
309
|
-
DESERIALIZE += `${indent}switch (load<u32>(keyStart)) {\n`;
|
|
310
|
-
else if (memberLen == 6)
|
|
311
|
-
DESERIALIZE += `${indent}let code = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n`;
|
|
312
|
-
else if (memberLen == 8)
|
|
313
|
-
DESERIALIZE += `${indent}let code = load<u64>(keyStart);\n`;
|
|
279
|
+
const sortedMembers = {
|
|
280
|
+
string: [],
|
|
281
|
+
number: [],
|
|
282
|
+
boolean: [],
|
|
283
|
+
null: [],
|
|
284
|
+
array: [],
|
|
285
|
+
object: [],
|
|
286
|
+
};
|
|
287
|
+
for (const member of this.schema.members) {
|
|
288
|
+
if (member.type.endsWith(" | null"))
|
|
289
|
+
sortedMembers.null.push(member);
|
|
290
|
+
if (isString(member.type) || member.type == "JSON.Raw")
|
|
291
|
+
sortedMembers.string.push(member);
|
|
292
|
+
else if (isBoolean(member.type) || member.type.startsWith("JSON.Box<bool"))
|
|
293
|
+
sortedMembers.boolean.push(member);
|
|
294
|
+
else if (isPrimitive(member.type) || member.type.startsWith("JSON.Box<"))
|
|
295
|
+
sortedMembers.number.push(member);
|
|
296
|
+
else if (isArray(member.type))
|
|
297
|
+
sortedMembers.array.push(member);
|
|
314
298
|
else
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
299
|
+
sortedMembers.object.push(member);
|
|
300
|
+
}
|
|
301
|
+
indent = "";
|
|
302
|
+
let shouldGroup = false;
|
|
303
|
+
DESERIALIZE += indent + " console.log(\"data: \" + JSON.Util.ptrToStr(srcStart,srcEnd))\n";
|
|
304
|
+
DESERIALIZE += indent + " let keyStart: usize = 0;\n";
|
|
305
|
+
if (shouldGroup || DEBUG)
|
|
306
|
+
DESERIALIZE += indent + " let keyEnd: usize = 0;\n";
|
|
307
|
+
DESERIALIZE += indent + " let isKey = false;\n";
|
|
308
|
+
if (sortedMembers.object.length || sortedMembers.array.length)
|
|
309
|
+
DESERIALIZE += indent + " let depth: i32 = 0;\n";
|
|
310
|
+
DESERIALIZE += indent + " let lastIndex: usize = 0;\n\n";
|
|
311
|
+
DESERIALIZE += indent + " while (srcStart < srcEnd && JSON.Util.isSpace(load<u16>(srcStart))) srcStart += 2;\n";
|
|
312
|
+
DESERIALIZE += indent + " while (srcEnd > srcStart && JSON.Util.isSpace(load<u16>(srcEnd - 2))) srcEnd -= 2;\n";
|
|
313
|
+
DESERIALIZE += indent + ' if (srcStart - srcEnd == 0) throw new Error("Input string had zero length or was all whitespace");\n';
|
|
314
|
+
DESERIALIZE += indent + " if (load<u16>(srcStart) != 123) throw new Error(\"Expected '{' at start of object at position \" + (srcEnd - srcStart).toString());\n";
|
|
315
|
+
DESERIALIZE += indent + " if (load<u16>(srcEnd - 2) != 125) throw new Error(\"Expected '}' at end of object at position \" + (srcEnd - srcStart).toString());\n";
|
|
316
|
+
DESERIALIZE += indent + " srcStart += 2;\n\n";
|
|
317
|
+
DESERIALIZE += indent + " while (srcStart < srcEnd) {\n";
|
|
318
|
+
DESERIALIZE += indent + " let code = load<u16>(srcStart);\n";
|
|
319
|
+
DESERIALIZE += indent + " while (JSON.Util.isSpace(code)) code = load<u16>(srcStart += 2);\n";
|
|
320
|
+
DESERIALIZE += indent + " if (keyStart == 0) {\n";
|
|
321
|
+
DESERIALIZE += indent + " if (code == 34 && load<u16>(srcStart - 2) !== 92) {\n";
|
|
322
|
+
DESERIALIZE += indent + " if (isKey) {\n";
|
|
323
|
+
DESERIALIZE += indent + " keyStart = lastIndex;\n";
|
|
324
|
+
if (shouldGroup || DEBUG)
|
|
325
|
+
DESERIALIZE += indent + " keyEnd = srcStart;\n";
|
|
326
|
+
DESERIALIZE += indent + " while (JSON.Util.isSpace((code = load<u16>((srcStart += 2))))) {}\n";
|
|
327
|
+
DESERIALIZE += indent + " if (code !== 58) throw new Error(\"Expected ':' after key at position \" + (srcEnd - srcStart).toString());\n";
|
|
328
|
+
DESERIALIZE += indent + " isKey = false;\n";
|
|
329
|
+
DESERIALIZE += indent + " } else {\n";
|
|
330
|
+
DESERIALIZE += indent + " isKey = true;\n";
|
|
331
|
+
DESERIALIZE += indent + " lastIndex = srcStart + 2;\n";
|
|
332
|
+
DESERIALIZE += indent + " }\n";
|
|
333
|
+
DESERIALIZE += indent + " }\n";
|
|
334
|
+
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
335
|
+
DESERIALIZE += indent + " } else {\n";
|
|
336
|
+
const groupMembers = (members) => {
|
|
337
|
+
let sorted = [];
|
|
338
|
+
let len = -1;
|
|
339
|
+
members
|
|
340
|
+
.slice()
|
|
341
|
+
.sort((a, b) => (a.alias?.length || a.name.length) - (b.alias?.length || b.name.length))
|
|
342
|
+
.forEach((member) => {
|
|
343
|
+
const _nameLength = member.alias?.length || member.name.length;
|
|
344
|
+
if (_nameLength === len) {
|
|
345
|
+
sorted[sorted.length - 1].push(member);
|
|
345
346
|
}
|
|
346
347
|
else {
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd, ${dst}), offsetof<this>(${JSON.stringify(member.name)}));\n`;
|
|
350
|
-
DESERIALIZE += `${indent} return;\n`;
|
|
351
|
-
DESERIALIZE += `${indent}}${i < memberGroup.length - 1 ? " else " : "\n"}`;
|
|
348
|
+
sorted.push([member]);
|
|
349
|
+
len = _nameLength;
|
|
352
350
|
}
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
351
|
+
});
|
|
352
|
+
sorted = sorted.sort((a, b) => b.length - a.length);
|
|
353
|
+
return sorted;
|
|
354
|
+
};
|
|
355
|
+
const generateComparisions = (members) => {
|
|
356
|
+
if (members.some((m) => (m.alias || m.name).length << 1 == 2)) {
|
|
357
|
+
DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
|
|
358
|
+
}
|
|
359
|
+
if (members.some((m) => (m.alias || m.name).length << 1 == 4)) {
|
|
360
|
+
DESERIALIZE += " const code32 = load<u32>(keyStart);\n";
|
|
361
|
+
}
|
|
362
|
+
if (members.some((m) => (m.alias || m.name).length << 1 == 6)) {
|
|
363
|
+
DESERIALIZE += " const code48 = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n";
|
|
364
|
+
}
|
|
365
|
+
if (members.some((m) => (m.alias || m.name).length << 1 == 8)) {
|
|
366
|
+
DESERIALIZE += " const code64 = load<u64>(keyStart);\n";
|
|
367
|
+
}
|
|
368
|
+
if (members.some((m) => (m.alias || m.name).length << 1 > 8)) {
|
|
369
|
+
DESERIALIZE += toMemCDecl(Math.max(...members.map((m) => (m.alias || m.name).length << 1)), " ");
|
|
370
|
+
}
|
|
371
|
+
const complex = isStruct(members[0].type) || members[0].type != "JSON.Obj" || isArray(members[0].type);
|
|
372
|
+
const firstMemberName = members[0].alias || members[0].name;
|
|
373
|
+
DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
|
|
374
|
+
DESERIALIZE += indent + " store<" + members[0].type + ">(changetype<usize>(out), JSON.__deserialize<" + members[0].type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(firstMemberName) + "));\n";
|
|
375
|
+
if (!complex)
|
|
376
|
+
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
377
|
+
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
378
|
+
DESERIALIZE += indent + " break;\n";
|
|
379
|
+
DESERIALIZE += indent + " }";
|
|
380
|
+
for (let i = 1; i < members.length; i++) {
|
|
381
|
+
const member = members[i];
|
|
382
|
+
const memberName = member.alias || member.name;
|
|
383
|
+
DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
|
|
384
|
+
DESERIALIZE += indent + " store<" + members[0].type + ">(changetype<usize>(out), JSON.__deserialize<" + members[0].type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(memberName) + "));\n";
|
|
385
|
+
if (isString(members[0].type))
|
|
386
|
+
DESERIALIZE += indent + " srcStart += 4;\n";
|
|
387
|
+
else if (!complex)
|
|
388
|
+
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
389
|
+
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
390
|
+
DESERIALIZE += indent + " break;\n";
|
|
391
|
+
DESERIALIZE += indent + " }";
|
|
392
|
+
}
|
|
393
|
+
DESERIALIZE += " else {\n";
|
|
394
|
+
DESERIALIZE += indent + ' throw new Error("Unexpected key in JSON object \'" + String.fromCharCode(load<u16>(srcStart)) + "\' at position " + (srcEnd - srcStart).toString());\n';
|
|
395
|
+
DESERIALIZE += indent + " }\n";
|
|
396
|
+
};
|
|
397
|
+
let mbElse = " ";
|
|
398
|
+
if (sortedMembers.string.length) {
|
|
399
|
+
DESERIALIZE += mbElse + "if (code == 34) {\n";
|
|
400
|
+
DESERIALIZE += " lastIndex = srcStart;\n";
|
|
401
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
402
|
+
DESERIALIZE += " while (srcStart < srcEnd) {\n";
|
|
403
|
+
DESERIALIZE += " const code = load<u16>(srcStart);\n";
|
|
404
|
+
DESERIALIZE += " if (code == 34 && load<u16>(srcStart - 2) !== 92) {\n";
|
|
405
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
406
|
+
DESERIALIZE += " console.log(JSON.Util.ptrToStr(keyStart,keyEnd) + \" = \" + load<u16>(keyStart).toString() + \" val \" + JSON.Util.ptrToStr(lastIndex, srcStart));\n";
|
|
407
|
+
generateComparisions(sortedMembers.string);
|
|
408
|
+
DESERIALIZE += " }\n";
|
|
409
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
410
|
+
DESERIALIZE += " }\n";
|
|
411
|
+
DESERIALIZE += " }\n";
|
|
412
|
+
mbElse = " else ";
|
|
413
|
+
}
|
|
414
|
+
if (sortedMembers.number.length) {
|
|
415
|
+
DESERIALIZE += mbElse + "if (code - 48 <= 9 || code == 45) {\n";
|
|
416
|
+
DESERIALIZE += " lastIndex = srcStart;\n";
|
|
417
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
418
|
+
DESERIALIZE += " while (srcStart < srcEnd) {\n";
|
|
419
|
+
DESERIALIZE += " const code = load<u16>(srcStart);\n";
|
|
420
|
+
DESERIALIZE += " if (code == 44 || code == 125 || JSON.Util.isSpace(code)) {\n";
|
|
421
|
+
generateComparisions(sortedMembers.number);
|
|
422
|
+
DESERIALIZE += " }\n";
|
|
423
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
424
|
+
DESERIALIZE += " }\n";
|
|
425
|
+
DESERIALIZE += " }";
|
|
426
|
+
mbElse = " else ";
|
|
427
|
+
}
|
|
428
|
+
if (sortedMembers.object.length) {
|
|
429
|
+
DESERIALIZE += mbElse + "if (code == 123) {\n";
|
|
430
|
+
DESERIALIZE += " lastIndex = srcStart;\n";
|
|
431
|
+
DESERIALIZE += " depth++;\n";
|
|
432
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
433
|
+
DESERIALIZE += " while (srcStart < srcEnd) {\n";
|
|
434
|
+
DESERIALIZE += " const code = load<u16>(srcStart);\n";
|
|
435
|
+
DESERIALIZE += " if (code == 34) {\n";
|
|
436
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
437
|
+
DESERIALIZE += " while (!(load<u16>(srcStart) == 34 && load<u16>(srcStart - 2) != 92)) srcStart += 2;\n";
|
|
438
|
+
DESERIALIZE += " } else if (code == 125) {\n";
|
|
439
|
+
DESERIALIZE += " if (--depth == 0) {\n";
|
|
440
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
441
|
+
indent = " ";
|
|
442
|
+
generateComparisions(sortedMembers.object);
|
|
443
|
+
indent = "";
|
|
444
|
+
DESERIALIZE += " }\n";
|
|
445
|
+
DESERIALIZE += " } else if (code == 123) depth++;\n";
|
|
446
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
447
|
+
DESERIALIZE += " }\n";
|
|
448
|
+
DESERIALIZE += " }";
|
|
449
|
+
mbElse = " else ";
|
|
450
|
+
}
|
|
451
|
+
if (sortedMembers.array.length) {
|
|
452
|
+
DESERIALIZE += mbElse + "if (code == 91) {\n";
|
|
453
|
+
DESERIALIZE += " lastIndex = srcStart;\n";
|
|
454
|
+
DESERIALIZE += " depth++;\n";
|
|
455
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
456
|
+
DESERIALIZE += " while (srcStart < srcEnd) {\n";
|
|
457
|
+
DESERIALIZE += " const code = load<u16>(srcStart);\n";
|
|
458
|
+
DESERIALIZE += " if (code == 34) {\n";
|
|
459
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
460
|
+
DESERIALIZE += " while (!(load<u16>(srcStart) == 34 && load<u16>(srcStart - 2) != 92)) srcStart += 2;\n";
|
|
461
|
+
DESERIALIZE += " } else if (code == 93) {\n";
|
|
462
|
+
DESERIALIZE += " if (--depth == 0) {\n";
|
|
463
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
464
|
+
indent = " ";
|
|
465
|
+
generateComparisions(sortedMembers.array);
|
|
466
|
+
indent = "";
|
|
467
|
+
DESERIALIZE += " }\n";
|
|
468
|
+
DESERIALIZE += " } else if (code == 91) depth++;\n";
|
|
469
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
470
|
+
DESERIALIZE += " }\n";
|
|
471
|
+
DESERIALIZE += " }";
|
|
472
|
+
mbElse = " else ";
|
|
473
|
+
}
|
|
474
|
+
if (sortedMembers.boolean.length) {
|
|
475
|
+
DESERIALIZE += mbElse + "if (code == 116) {\n";
|
|
476
|
+
DESERIALIZE += " if (load<u64>(srcStart) == 28429475166421108) {\n";
|
|
477
|
+
DESERIALIZE += " srcStart += 8;\n";
|
|
478
|
+
if (sortedMembers.boolean.some((m) => (m.alias || m.name).length << 1 == 2)) {
|
|
479
|
+
DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
|
|
480
|
+
}
|
|
481
|
+
if (sortedMembers.boolean.some((m) => (m.alias || m.name).length << 1 == 4)) {
|
|
482
|
+
DESERIALIZE += " const code32 = load<u32>(keyStart);\n";
|
|
483
|
+
}
|
|
484
|
+
if (sortedMembers.boolean.some((m) => (m.alias || m.name).length << 1 == 6)) {
|
|
485
|
+
DESERIALIZE += " const code48 = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n";
|
|
486
|
+
}
|
|
487
|
+
if (sortedMembers.boolean.some((m) => (m.alias || m.name).length << 1 == 8)) {
|
|
488
|
+
DESERIALIZE += " const code64 = load<u64>(keyStart);\n";
|
|
489
|
+
}
|
|
490
|
+
if (sortedMembers.boolean.some((m) => (m.alias || m.name).length << 1 > 8)) {
|
|
491
|
+
DESERIALIZE += toMemCDecl(Math.max(...sortedMembers.boolean.map((m) => (m.alias || m.name).length << 1)), " ");
|
|
492
|
+
}
|
|
493
|
+
const firstMemberName = sortedMembers.boolean[0].alias || sortedMembers.boolean[0].name;
|
|
494
|
+
DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
|
|
495
|
+
DESERIALIZE += indent + " store<" + sortedMembers.boolean[0].type + ">(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(sortedMembers.boolean[0].name) + "));\n";
|
|
496
|
+
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
497
|
+
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
498
|
+
DESERIALIZE += indent + " break;\n";
|
|
499
|
+
DESERIALIZE += indent + " }";
|
|
500
|
+
for (let i = 1; i < sortedMembers.boolean.length; i++) {
|
|
501
|
+
const member = sortedMembers.boolean[i];
|
|
502
|
+
const memberName = member.alias || member.name;
|
|
503
|
+
DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
|
|
504
|
+
DESERIALIZE += indent + " store<" + sortedMembers.boolean[0].type + ">(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(sortedMembers.boolean[0].name) + "));\n";
|
|
505
|
+
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
506
|
+
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
507
|
+
DESERIALIZE += indent + " break;\n";
|
|
508
|
+
DESERIALIZE += indent + " }";
|
|
509
|
+
}
|
|
510
|
+
DESERIALIZE += " else {\n";
|
|
511
|
+
DESERIALIZE += indent + ' throw new Error("Unexpected key in JSON object \'" + String.fromCharCode(load<u16>(srcStart)) + "\' at position " + (srcEnd - srcStart).toString());\n';
|
|
512
|
+
DESERIALIZE += indent + " }\n";
|
|
513
|
+
DESERIALIZE += " }";
|
|
514
|
+
mbElse = " else ";
|
|
515
|
+
DESERIALIZE += " else if (load<u64>(srcStart, 2) == 28429466576093281) {\n";
|
|
516
|
+
DESERIALIZE += " srcStart += 10;\n";
|
|
517
|
+
DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
|
|
518
|
+
DESERIALIZE += indent + " store<" + sortedMembers.boolean[0].type + ">(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(sortedMembers.boolean[0].name) + "));\n";
|
|
519
|
+
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
520
|
+
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
521
|
+
DESERIALIZE += indent + " break;\n";
|
|
522
|
+
DESERIALIZE += indent + " }";
|
|
523
|
+
for (let i = 1; i < sortedMembers.boolean.length; i++) {
|
|
524
|
+
const member = sortedMembers.boolean[i];
|
|
525
|
+
const memberName = member.alias || member.name;
|
|
526
|
+
DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
|
|
527
|
+
DESERIALIZE += indent + " store<" + sortedMembers.boolean[0].type + ">(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(sortedMembers.boolean[0].name) + "));\n";
|
|
528
|
+
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
529
|
+
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
530
|
+
DESERIALIZE += indent + " break;\n";
|
|
531
|
+
DESERIALIZE += indent + " }";
|
|
532
|
+
}
|
|
533
|
+
DESERIALIZE += " else {\n";
|
|
534
|
+
DESERIALIZE += indent + ' throw new Error("Unexpected key in JSON object \'" + String.fromCharCode(load<u16>(srcStart)) + "\' at position " + (srcEnd - srcStart).toString());\n';
|
|
535
|
+
DESERIALIZE += indent + " }\n";
|
|
536
|
+
DESERIALIZE += " }\n";
|
|
537
|
+
DESERIALIZE += " }";
|
|
360
538
|
}
|
|
539
|
+
if (sortedMembers.null.length) {
|
|
540
|
+
DESERIALIZE += mbElse + "if (code == 110) {\n";
|
|
541
|
+
DESERIALIZE += " if (load<u64>(srcStart) == 30399761348886638) {\n";
|
|
542
|
+
DESERIALIZE += " srcStart += 8;\n";
|
|
543
|
+
if (sortedMembers.null.some((m) => (m.alias || m.name).length << 1 == 2)) {
|
|
544
|
+
DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
|
|
545
|
+
}
|
|
546
|
+
if (sortedMembers.null.some((m) => (m.alias || m.name).length << 1 == 4)) {
|
|
547
|
+
DESERIALIZE += " const code32 = load<u32>(keyStart);\n";
|
|
548
|
+
}
|
|
549
|
+
if (sortedMembers.null.some((m) => (m.alias || m.name).length << 1 == 6)) {
|
|
550
|
+
DESERIALIZE += " const code48 = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n";
|
|
551
|
+
}
|
|
552
|
+
if (sortedMembers.null.some((m) => (m.alias || m.name).length << 1 == 8)) {
|
|
553
|
+
DESERIALIZE += " const code64 = load<u64>(keyStart);\n";
|
|
554
|
+
}
|
|
555
|
+
if (sortedMembers.null.some((m) => (m.alias || m.name).length << 1 > 8)) {
|
|
556
|
+
DESERIALIZE += toMemCDecl(Math.max(...sortedMembers.null.map((m) => (m.alias || m.name).length << 1)), " ");
|
|
557
|
+
}
|
|
558
|
+
const firstMemberName = sortedMembers.null[0].alias || sortedMembers.null[0].name;
|
|
559
|
+
DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
|
|
560
|
+
DESERIALIZE += indent + " store<" + sortedMembers.null[0].type + ">(changetype<usize>(out), null, offsetof<this>(" + JSON.stringify(sortedMembers.null[0].name) + "));\n";
|
|
561
|
+
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
562
|
+
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
563
|
+
DESERIALIZE += indent + " break;\n";
|
|
564
|
+
DESERIALIZE += indent + " }";
|
|
565
|
+
for (let i = 1; i < sortedMembers.null.length; i++) {
|
|
566
|
+
const member = sortedMembers.null[i];
|
|
567
|
+
const memberName = member.alias || member.name;
|
|
568
|
+
DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
|
|
569
|
+
DESERIALIZE += indent + " store<" + sortedMembers.null[0].type + ">(changetype<usize>(out), null, offsetof<this>(" + JSON.stringify(sortedMembers.null[0].name) + "));\n";
|
|
570
|
+
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
571
|
+
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
572
|
+
DESERIALIZE += indent + " break;\n";
|
|
573
|
+
DESERIALIZE += indent + " }";
|
|
574
|
+
}
|
|
575
|
+
DESERIALIZE += " else {\n";
|
|
576
|
+
DESERIALIZE += indent + ' throw new Error("Unexpected key in JSON object \'" + String.fromCharCode(load<u16>(srcStart)) + "\' at position " + (srcEnd - srcStart).toString());\n';
|
|
577
|
+
DESERIALIZE += indent + " }\n";
|
|
578
|
+
DESERIALIZE += " }";
|
|
579
|
+
DESERIALIZE += "\n }";
|
|
580
|
+
mbElse = " else ";
|
|
581
|
+
}
|
|
582
|
+
DESERIALIZE += " else {\n";
|
|
583
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
584
|
+
DESERIALIZE += "}\n";
|
|
585
|
+
DESERIALIZE += "\n }\n";
|
|
361
586
|
indentDec();
|
|
362
|
-
DESERIALIZE +=
|
|
587
|
+
DESERIALIZE += ` }\n`;
|
|
363
588
|
indentDec();
|
|
364
|
-
DESERIALIZE +=
|
|
589
|
+
DESERIALIZE += ` return out;\n}\n`;
|
|
365
590
|
indent = " ";
|
|
366
591
|
this.schema.byteSize += 2;
|
|
367
592
|
SERIALIZE += indent + "store<u16>(bs.offset, 125, 0); // }\n";
|
|
@@ -370,14 +595,14 @@ class JSONTransform extends Visitor {
|
|
|
370
595
|
SERIALIZE = SERIALIZE.slice(0, 32) + indent + "bs.proposeSize(" + this.schema.byteSize + ");\n" + SERIALIZE.slice(32);
|
|
371
596
|
INITIALIZE += " return this;\n";
|
|
372
597
|
INITIALIZE += "}";
|
|
373
|
-
if (
|
|
374
|
-
console.log(SERIALIZE);
|
|
598
|
+
if (DEBUG) {
|
|
599
|
+
console.log(SERIALIZE_CUSTOM ? SERIALIZE_CUSTOM : SERIALIZE);
|
|
375
600
|
console.log(INITIALIZE);
|
|
376
|
-
console.log(DESERIALIZE);
|
|
601
|
+
console.log(DESERIALIZE_CUSTOM || DESERIALIZE);
|
|
377
602
|
}
|
|
378
|
-
const SERIALIZE_METHOD = SimpleParser.parseClassMember(SERIALIZE, node);
|
|
603
|
+
const SERIALIZE_METHOD = SimpleParser.parseClassMember(SERIALIZE_CUSTOM ? SERIALIZE_CUSTOM : SERIALIZE, node);
|
|
379
604
|
const INITIALIZE_METHOD = SimpleParser.parseClassMember(INITIALIZE, node);
|
|
380
|
-
const DESERIALIZE_METHOD = SimpleParser.parseClassMember(DESERIALIZE, node);
|
|
605
|
+
const DESERIALIZE_METHOD = SimpleParser.parseClassMember(DESERIALIZE_CUSTOM || DESERIALIZE, node);
|
|
381
606
|
if (!node.members.find((v) => v.name.text == "__SERIALIZE"))
|
|
382
607
|
node.members.push(SERIALIZE_METHOD);
|
|
383
608
|
if (!node.members.find((v) => v.name.text == "__INITIALIZE"))
|
|
@@ -389,8 +614,8 @@ class JSONTransform extends Visitor {
|
|
|
389
614
|
generateEmptyMethods(node) {
|
|
390
615
|
let SERIALIZE_EMPTY = "@inline __SERIALIZE(ptr: usize): void {\n bs.proposeSize(4);\n store<u32>(bs.offset, 8192123);\n bs.offset += 4;\n}";
|
|
391
616
|
let INITIALIZE_EMPTY = "@inline __INITIALIZE(): this {\n return this;\n}";
|
|
392
|
-
let DESERIALIZE_EMPTY = "@inline __DESERIALIZE(
|
|
393
|
-
if (
|
|
617
|
+
let DESERIALIZE_EMPTY = "@inline __DESERIALIZE<__JSON_T>(srcStart: usize, srcEnd: usize, out: __JSON_T): __JSON_T {\n return this;\n}";
|
|
618
|
+
if (DEBUG) {
|
|
394
619
|
console.log(SERIALIZE_EMPTY);
|
|
395
620
|
console.log(INITIALIZE_EMPTY);
|
|
396
621
|
console.log(DESERIALIZE_EMPTY);
|
|
@@ -427,7 +652,7 @@ class JSONTransform extends Visitor {
|
|
|
427
652
|
}
|
|
428
653
|
const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("bs", node.range, false), null, node.range)], Node.createStringLiteralExpression(bsPath, node.range), node.range);
|
|
429
654
|
this.topStatements.push(replaceNode);
|
|
430
|
-
if (
|
|
655
|
+
if (DEBUG)
|
|
431
656
|
console.log("Added as-bs import: " + toString(replaceNode) + "\n");
|
|
432
657
|
}
|
|
433
658
|
if (!jsonImport) {
|
|
@@ -436,7 +661,7 @@ class JSONTransform extends Visitor {
|
|
|
436
661
|
}
|
|
437
662
|
const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("JSON", node.range, false), null, node.range)], Node.createStringLiteralExpression(jsonPath, node.range), node.range);
|
|
438
663
|
this.topStatements.push(replaceNode);
|
|
439
|
-
if (
|
|
664
|
+
if (DEBUG)
|
|
440
665
|
console.log("Added json-as import: " + toString(replaceNode) + "\n");
|
|
441
666
|
}
|
|
442
667
|
}
|
|
@@ -488,7 +713,7 @@ class JSONTransform extends Visitor {
|
|
|
488
713
|
}
|
|
489
714
|
export default class Transformer extends Transform {
|
|
490
715
|
afterParse(parser) {
|
|
491
|
-
const transformer =
|
|
716
|
+
const transformer = JSONTransform.SN;
|
|
492
717
|
const sources = parser.sources
|
|
493
718
|
.filter((source) => {
|
|
494
719
|
const p = source.internalPath;
|
|
@@ -575,17 +800,17 @@ function toMemCDecl(n, indent) {
|
|
|
575
800
|
let offset = 0;
|
|
576
801
|
let index = 0;
|
|
577
802
|
while (n >= 8) {
|
|
578
|
-
out += `${indent}const
|
|
803
|
+
out += `${indent}const codeS${(index += 8)} = load<u64>(keyStart, ${offset});\n`;
|
|
579
804
|
offset += 8;
|
|
580
805
|
n -= 8;
|
|
581
806
|
}
|
|
582
807
|
while (n >= 4) {
|
|
583
|
-
out += `${indent}const
|
|
808
|
+
out += `${indent}const codeS${(index += 4)} = load<u32>(keyStart, ${offset});\n`;
|
|
584
809
|
offset += 4;
|
|
585
810
|
n -= 4;
|
|
586
811
|
}
|
|
587
812
|
if (n == 1)
|
|
588
|
-
out += `${indent}const
|
|
813
|
+
out += `${indent}const codeS${(index += 1)} = load<u16>(keyStart, ${offset});\n`;
|
|
589
814
|
return out;
|
|
590
815
|
}
|
|
591
816
|
function toMemCCheck(data) {
|
|
@@ -594,17 +819,17 @@ function toMemCCheck(data) {
|
|
|
594
819
|
let offset = 0;
|
|
595
820
|
let index = 0;
|
|
596
821
|
while (n >= 8) {
|
|
597
|
-
out += ` &&
|
|
822
|
+
out += ` && codeS${(index += 8)} == ${toU64(data, offset >> 1)}`;
|
|
598
823
|
offset += 8;
|
|
599
824
|
n -= 8;
|
|
600
825
|
}
|
|
601
826
|
while (n >= 4) {
|
|
602
|
-
out += ` &&
|
|
827
|
+
out += ` && codeS${(index += 4)} == ${toU32(data, offset >> 1)}`;
|
|
603
828
|
offset += 4;
|
|
604
829
|
n -= 4;
|
|
605
830
|
}
|
|
606
831
|
if (n == 1)
|
|
607
|
-
out += ` &&
|
|
832
|
+
out += ` && codeS${(index += 1)} == ${toU16(data, offset >> 1)}`;
|
|
608
833
|
return out.slice(4);
|
|
609
834
|
}
|
|
610
835
|
function strToNum(data, simd = false, offset = 0) {
|
|
@@ -633,10 +858,6 @@ function strToNum(data, simd = false, offset = 0) {
|
|
|
633
858
|
}
|
|
634
859
|
return out;
|
|
635
860
|
}
|
|
636
|
-
function isPrimitive(type) {
|
|
637
|
-
const primitiveTypes = ["u8", "u16", "u32", "u64", "i8", "i16", "i32", "i64", "f32", "f64", "bool", "boolean"];
|
|
638
|
-
return primitiveTypes.some((v) => type.startsWith(v));
|
|
639
|
-
}
|
|
640
861
|
function throwError(message, range) {
|
|
641
862
|
const err = new Error();
|
|
642
863
|
err.stack = `${message}\n at ${range.source.normalizedPath}:${range.source.lineAt(range.start)}:${range.source.columnAt()}\n`;
|
|
@@ -670,4 +891,46 @@ function sizeof(type) {
|
|
|
670
891
|
else
|
|
671
892
|
return 0;
|
|
672
893
|
}
|
|
894
|
+
function isPrimitive(type) {
|
|
895
|
+
const primitiveTypes = ["u8", "u16", "u32", "u64", "i8", "i16", "i32", "i64", "f32", "f64", "bool", "boolean"];
|
|
896
|
+
return primitiveTypes.some((v) => type.startsWith(v));
|
|
897
|
+
}
|
|
898
|
+
function isBoolean(type) {
|
|
899
|
+
return type == "bool" || type == "boolean";
|
|
900
|
+
}
|
|
901
|
+
function isStruct(type) {
|
|
902
|
+
type = stripNull(type);
|
|
903
|
+
return JSONTransform.SN.schemas.some((v) => v.name == type) || JSONTransform.SN.schema.name == type;
|
|
904
|
+
}
|
|
905
|
+
function isString(type) {
|
|
906
|
+
return stripNull(type) == "string" || stripNull(type) == "String";
|
|
907
|
+
}
|
|
908
|
+
function isArray(type) {
|
|
909
|
+
return type.startsWith("Array<");
|
|
910
|
+
}
|
|
911
|
+
function stripNull(type) {
|
|
912
|
+
if (type.endsWith(" | null")) {
|
|
913
|
+
return type.slice(0, type.length - 7);
|
|
914
|
+
}
|
|
915
|
+
return type;
|
|
916
|
+
}
|
|
917
|
+
function getComparision(data) {
|
|
918
|
+
switch (data.length << 1) {
|
|
919
|
+
case 2: {
|
|
920
|
+
return "code16 == " + data.charCodeAt(0);
|
|
921
|
+
}
|
|
922
|
+
case 4: {
|
|
923
|
+
return "code32 == " + toU32(data);
|
|
924
|
+
}
|
|
925
|
+
case 6: {
|
|
926
|
+
return "code48 == " + toU48(data);
|
|
927
|
+
}
|
|
928
|
+
case 8: {
|
|
929
|
+
return "code64 == " + toU64(data);
|
|
930
|
+
}
|
|
931
|
+
default: {
|
|
932
|
+
return toMemCCheck(data);
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
}
|
|
673
936
|
//# sourceMappingURL=index.js.map
|