json-as 1.0.8 → 1.0.9
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 +8 -0
- package/README.md +17 -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 +49 -208
- 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 +381 -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 +430 -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<T>(srcStart: usize, srcEnd: usize, out: T): 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<T>(srcStart: usize, srcEnd: usize, out: T): 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,315 @@ 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 + " let keyStart: usize = 0;\n";
|
|
304
|
+
if (shouldGroup || DEBUG)
|
|
305
|
+
DESERIALIZE += indent + " let keyEnd: usize = 0;\n";
|
|
306
|
+
DESERIALIZE += indent + " let isKey = false;\n";
|
|
307
|
+
if (sortedMembers.object.length || sortedMembers.array.length)
|
|
308
|
+
DESERIALIZE += indent + " let depth: i32 = 0;\n";
|
|
309
|
+
DESERIALIZE += indent + " let lastIndex: usize = 0;\n\n";
|
|
310
|
+
DESERIALIZE += indent + " while (srcStart < srcEnd && JSON.Util.isSpace(load<u16>(srcStart))) srcStart += 2;\n";
|
|
311
|
+
DESERIALIZE += indent + " while (srcEnd > srcStart && JSON.Util.isSpace(load<u16>(srcEnd - 2))) srcEnd -= 2;\n";
|
|
312
|
+
DESERIALIZE += indent + ' if (srcStart - srcEnd == 0) throw new Error("Input string had zero length or was all whitespace");\n';
|
|
313
|
+
DESERIALIZE += indent + " if (load<u16>(srcStart) != 123) throw new Error(\"Expected '{' at start of object at position \" + (srcEnd - srcStart).toString());\n";
|
|
314
|
+
DESERIALIZE += indent + " if (load<u16>(srcEnd - 2) != 125) throw new Error(\"Expected '}' at end of object at position \" + (srcEnd - srcStart).toString());\n";
|
|
315
|
+
DESERIALIZE += indent + " srcStart += 2;\n\n";
|
|
316
|
+
DESERIALIZE += indent + " while (srcStart < srcEnd) {\n";
|
|
317
|
+
DESERIALIZE += indent + " let code = load<u16>(srcStart);\n";
|
|
318
|
+
DESERIALIZE += indent + " while (JSON.Util.isSpace(code)) code = load<u16>(srcStart += 2);\n";
|
|
319
|
+
DESERIALIZE += indent + " if (keyStart == 0) {\n";
|
|
320
|
+
DESERIALIZE += indent + " if (code == 34 && load<u16>(srcStart - 2) !== 92) {\n";
|
|
321
|
+
DESERIALIZE += indent + " if (isKey) {\n";
|
|
322
|
+
DESERIALIZE += indent + " keyStart = lastIndex;\n";
|
|
323
|
+
if (shouldGroup || DEBUG)
|
|
324
|
+
DESERIALIZE += indent + " keyEnd = srcStart;\n";
|
|
325
|
+
DESERIALIZE += indent + " while (JSON.Util.isSpace((code = load<u16>((srcStart += 2))))) {}\n";
|
|
326
|
+
DESERIALIZE += indent + " if (code !== 58) throw new Error(\"Expected ':' after key at position \" + (srcEnd - srcStart).toString());\n";
|
|
327
|
+
DESERIALIZE += indent + " isKey = false;\n";
|
|
328
|
+
DESERIALIZE += indent + " } else {\n";
|
|
329
|
+
DESERIALIZE += indent + " isKey = true;\n";
|
|
330
|
+
DESERIALIZE += indent + " lastIndex = srcStart + 2;\n";
|
|
331
|
+
DESERIALIZE += indent + " }\n";
|
|
332
|
+
DESERIALIZE += indent + " }\n";
|
|
333
|
+
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
334
|
+
DESERIALIZE += indent + " } else {\n";
|
|
335
|
+
const groupMembers = (members) => {
|
|
336
|
+
let sorted = [];
|
|
337
|
+
let len = -1;
|
|
338
|
+
members
|
|
339
|
+
.slice()
|
|
340
|
+
.sort((a, b) => (a.alias?.length || a.name.length) - (b.alias?.length || b.name.length))
|
|
341
|
+
.forEach((member) => {
|
|
342
|
+
const _nameLength = member.alias?.length || member.name.length;
|
|
343
|
+
if (_nameLength === len) {
|
|
344
|
+
sorted[sorted.length - 1].push(member);
|
|
345
345
|
}
|
|
346
346
|
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"}`;
|
|
347
|
+
sorted.push([member]);
|
|
348
|
+
len = _nameLength;
|
|
352
349
|
}
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
350
|
+
});
|
|
351
|
+
sorted = sorted.sort((a, b) => b.length - a.length);
|
|
352
|
+
return sorted;
|
|
353
|
+
};
|
|
354
|
+
const generateComparisions = (members) => {
|
|
355
|
+
if (members.some((m) => (m.alias || m.name).length << 1 == 2)) {
|
|
356
|
+
DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
|
|
357
|
+
}
|
|
358
|
+
if (members.some((m) => (m.alias || m.name).length << 1 == 4)) {
|
|
359
|
+
DESERIALIZE += " const code32 = load<u32>(keyStart);\n";
|
|
360
|
+
}
|
|
361
|
+
if (members.some((m) => (m.alias || m.name).length << 1 == 6)) {
|
|
362
|
+
DESERIALIZE += " const code48 = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n";
|
|
363
|
+
}
|
|
364
|
+
if (members.some((m) => (m.alias || m.name).length << 1 == 8)) {
|
|
365
|
+
DESERIALIZE += " const code64 = load<u64>(keyStart);\n";
|
|
366
|
+
}
|
|
367
|
+
if (members.some((m) => (m.alias || m.name).length << 1 > 8)) {
|
|
368
|
+
DESERIALIZE += toMemCDecl(Math.max(...members.map((m) => (m.alias || m.name).length << 1)), " ");
|
|
369
|
+
}
|
|
370
|
+
const complex = isStruct(members[0].type) || members[0].type != "JSON.Obj" || isArray(members[0].type);
|
|
371
|
+
const firstMemberName = members[0].alias || members[0].name;
|
|
372
|
+
DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
|
|
373
|
+
DESERIALIZE += indent + " store<" + members[0].type + ">(changetype<usize>(out), JSON.__deserialize<" + members[0].type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(firstMemberName) + "));\n";
|
|
374
|
+
if (!complex)
|
|
375
|
+
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
376
|
+
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
377
|
+
DESERIALIZE += indent + " break;\n";
|
|
378
|
+
DESERIALIZE += indent + " }";
|
|
379
|
+
for (let i = 1; i < members.length; i++) {
|
|
380
|
+
const member = members[i];
|
|
381
|
+
const memberName = member.alias || member.name;
|
|
382
|
+
DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
|
|
383
|
+
DESERIALIZE += indent + " store<" + members[0].type + ">(changetype<usize>(out), JSON.__deserialize<" + members[0].type + ">(lastIndex, srcStart), offsetof<this>(" + JSON.stringify(memberName) + "));\n";
|
|
384
|
+
if (isString(members[0].type))
|
|
385
|
+
DESERIALIZE += indent + " srcStart += 4;\n";
|
|
386
|
+
else if (!complex)
|
|
387
|
+
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
388
|
+
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
389
|
+
DESERIALIZE += indent + " break;\n";
|
|
390
|
+
DESERIALIZE += indent + " }";
|
|
391
|
+
}
|
|
392
|
+
DESERIALIZE += " else {\n";
|
|
393
|
+
DESERIALIZE += indent + ' throw new Error("Unexpected key in JSON object \'" + String.fromCharCode(load<u16>(srcStart)) + "\' at position " + (srcEnd - srcStart).toString());\n';
|
|
394
|
+
DESERIALIZE += indent + " }\n";
|
|
395
|
+
};
|
|
396
|
+
let mbElse = " ";
|
|
397
|
+
if (sortedMembers.string.length) {
|
|
398
|
+
DESERIALIZE += mbElse + "if (code == 34) {\n";
|
|
399
|
+
DESERIALIZE += " lastIndex = srcStart;\n";
|
|
400
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
401
|
+
DESERIALIZE += " while (srcStart < srcEnd) {\n";
|
|
402
|
+
DESERIALIZE += " const code = load<u16>(srcStart);\n";
|
|
403
|
+
DESERIALIZE += " if (code == 34 && load<u16>(srcStart - 2) !== 92) {\n";
|
|
404
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
405
|
+
generateComparisions(sortedMembers.string);
|
|
406
|
+
DESERIALIZE += " }\n";
|
|
407
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
408
|
+
DESERIALIZE += " }\n";
|
|
409
|
+
DESERIALIZE += " }\n";
|
|
410
|
+
mbElse = " else ";
|
|
411
|
+
}
|
|
412
|
+
if (sortedMembers.number.length) {
|
|
413
|
+
DESERIALIZE += mbElse + "if (code - 48 <= 9 || code == 45) {\n";
|
|
414
|
+
DESERIALIZE += " lastIndex = srcStart;\n";
|
|
415
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
416
|
+
DESERIALIZE += " while (srcStart < srcEnd) {\n";
|
|
417
|
+
DESERIALIZE += " const code = load<u16>(srcStart);\n";
|
|
418
|
+
DESERIALIZE += " if (code == 44 || code == 125 || JSON.Util.isSpace(code)) {\n";
|
|
419
|
+
generateComparisions(sortedMembers.number);
|
|
420
|
+
DESERIALIZE += " }\n";
|
|
421
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
422
|
+
DESERIALIZE += " }\n";
|
|
423
|
+
DESERIALIZE += " }";
|
|
424
|
+
mbElse = " else ";
|
|
425
|
+
}
|
|
426
|
+
if (sortedMembers.object.length) {
|
|
427
|
+
DESERIALIZE += mbElse + "if (code == 123) {\n";
|
|
428
|
+
DESERIALIZE += " lastIndex = srcStart;\n";
|
|
429
|
+
DESERIALIZE += " depth++;\n";
|
|
430
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
431
|
+
DESERIALIZE += " while (srcStart < srcEnd) {\n";
|
|
432
|
+
DESERIALIZE += " const code = load<u16>(srcStart);\n";
|
|
433
|
+
DESERIALIZE += " if (code == 34) {\n";
|
|
434
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
435
|
+
DESERIALIZE += " while (!(load<u16>(srcStart) == 34 && load<u16>(srcStart - 2) != 92)) srcStart += 2;\n";
|
|
436
|
+
DESERIALIZE += " } else if (code == 125) {\n";
|
|
437
|
+
DESERIALIZE += " if (--depth == 0) {\n";
|
|
438
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
439
|
+
indent = " ";
|
|
440
|
+
generateComparisions(sortedMembers.object);
|
|
441
|
+
indent = "";
|
|
442
|
+
DESERIALIZE += " }\n";
|
|
443
|
+
DESERIALIZE += " } else if (code == 123) depth++;\n";
|
|
444
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
445
|
+
DESERIALIZE += " }\n";
|
|
446
|
+
DESERIALIZE += " }";
|
|
447
|
+
mbElse = " else ";
|
|
448
|
+
}
|
|
449
|
+
if (sortedMembers.array.length) {
|
|
450
|
+
DESERIALIZE += mbElse + "if (code == 91) {\n";
|
|
451
|
+
DESERIALIZE += " lastIndex = srcStart;\n";
|
|
452
|
+
DESERIALIZE += " depth++;\n";
|
|
453
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
454
|
+
DESERIALIZE += " while (srcStart < srcEnd) {\n";
|
|
455
|
+
DESERIALIZE += " const code = load<u16>(srcStart);\n";
|
|
456
|
+
DESERIALIZE += " if (code == 34) {\n";
|
|
457
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
458
|
+
DESERIALIZE += " while (!(load<u16>(srcStart) == 34 && load<u16>(srcStart - 2) != 92)) srcStart += 2;\n";
|
|
459
|
+
DESERIALIZE += " } else if (code == 93) {\n";
|
|
460
|
+
DESERIALIZE += " if (--depth == 0) {\n";
|
|
461
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
462
|
+
indent = " ";
|
|
463
|
+
generateComparisions(sortedMembers.array);
|
|
464
|
+
indent = "";
|
|
465
|
+
DESERIALIZE += " }\n";
|
|
466
|
+
DESERIALIZE += " } else if (code == 91) depth++;\n";
|
|
467
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
468
|
+
DESERIALIZE += " }\n";
|
|
469
|
+
DESERIALIZE += " }";
|
|
470
|
+
mbElse = " else ";
|
|
471
|
+
}
|
|
472
|
+
if (sortedMembers.boolean.length) {
|
|
473
|
+
DESERIALIZE += mbElse + "if (code == 116) {\n";
|
|
474
|
+
DESERIALIZE += " if (load<u64>(srcStart) == 28429475166421108) {\n";
|
|
475
|
+
DESERIALIZE += " srcStart += 8;\n";
|
|
476
|
+
if (sortedMembers.boolean.some((m) => (m.alias || m.name).length << 1 == 2)) {
|
|
477
|
+
DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
|
|
478
|
+
}
|
|
479
|
+
if (sortedMembers.boolean.some((m) => (m.alias || m.name).length << 1 == 4)) {
|
|
480
|
+
DESERIALIZE += " const code32 = load<u32>(keyStart);\n";
|
|
481
|
+
}
|
|
482
|
+
if (sortedMembers.boolean.some((m) => (m.alias || m.name).length << 1 == 6)) {
|
|
483
|
+
DESERIALIZE += " const code48 = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n";
|
|
484
|
+
}
|
|
485
|
+
if (sortedMembers.boolean.some((m) => (m.alias || m.name).length << 1 == 8)) {
|
|
486
|
+
DESERIALIZE += " const code64 = load<u64>(keyStart);\n";
|
|
487
|
+
}
|
|
488
|
+
if (sortedMembers.boolean.some((m) => (m.alias || m.name).length << 1 > 8)) {
|
|
489
|
+
DESERIALIZE += toMemCDecl(Math.max(...sortedMembers.boolean.map((m) => (m.alias || m.name).length << 1)), " ");
|
|
490
|
+
}
|
|
491
|
+
const firstMemberName = sortedMembers.boolean[0].alias || sortedMembers.boolean[0].name;
|
|
492
|
+
DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
|
|
493
|
+
DESERIALIZE += indent + " store<" + sortedMembers.boolean[0].type + ">(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(sortedMembers.boolean[0].name) + "));\n";
|
|
494
|
+
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
495
|
+
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
496
|
+
DESERIALIZE += indent + " break;\n";
|
|
497
|
+
DESERIALIZE += indent + " }";
|
|
498
|
+
for (let i = 1; i < sortedMembers.boolean.length; i++) {
|
|
499
|
+
const member = sortedMembers.boolean[i];
|
|
500
|
+
const memberName = member.alias || member.name;
|
|
501
|
+
DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
|
|
502
|
+
DESERIALIZE += indent + " store<" + sortedMembers.boolean[0].type + ">(changetype<usize>(out), true, offsetof<this>(" + JSON.stringify(sortedMembers.boolean[0].name) + "));\n";
|
|
503
|
+
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
504
|
+
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
505
|
+
DESERIALIZE += indent + " break;\n";
|
|
506
|
+
DESERIALIZE += indent + " }";
|
|
507
|
+
}
|
|
508
|
+
DESERIALIZE += " else {\n";
|
|
509
|
+
DESERIALIZE += indent + ' throw new Error("Unexpected key in JSON object \'" + String.fromCharCode(load<u16>(srcStart)) + "\' at position " + (srcEnd - srcStart).toString());\n';
|
|
510
|
+
DESERIALIZE += indent + " }\n";
|
|
511
|
+
DESERIALIZE += " }";
|
|
512
|
+
mbElse = " else ";
|
|
513
|
+
DESERIALIZE += " else if (load<u64>(srcStart, 2) == 28429466576093281) {\n";
|
|
514
|
+
DESERIALIZE += " srcStart += 10;\n";
|
|
515
|
+
DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
|
|
516
|
+
DESERIALIZE += indent + " store<" + sortedMembers.boolean[0].type + ">(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(sortedMembers.boolean[0].name) + "));\n";
|
|
517
|
+
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
518
|
+
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
519
|
+
DESERIALIZE += indent + " break;\n";
|
|
520
|
+
DESERIALIZE += indent + " }";
|
|
521
|
+
for (let i = 1; i < sortedMembers.boolean.length; i++) {
|
|
522
|
+
const member = sortedMembers.boolean[i];
|
|
523
|
+
const memberName = member.alias || member.name;
|
|
524
|
+
DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
|
|
525
|
+
DESERIALIZE += indent + " store<" + sortedMembers.boolean[0].type + ">(changetype<usize>(out), false, offsetof<this>(" + JSON.stringify(sortedMembers.boolean[0].name) + "));\n";
|
|
526
|
+
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
527
|
+
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
528
|
+
DESERIALIZE += indent + " break;\n";
|
|
529
|
+
DESERIALIZE += indent + " }";
|
|
530
|
+
}
|
|
531
|
+
DESERIALIZE += " else {\n";
|
|
532
|
+
DESERIALIZE += indent + ' throw new Error("Unexpected key in JSON object \'" + String.fromCharCode(load<u16>(srcStart)) + "\' at position " + (srcEnd - srcStart).toString());\n';
|
|
533
|
+
DESERIALIZE += indent + " }\n";
|
|
534
|
+
DESERIALIZE += " }\n";
|
|
535
|
+
DESERIALIZE += " }";
|
|
360
536
|
}
|
|
537
|
+
if (sortedMembers.null.length) {
|
|
538
|
+
DESERIALIZE += mbElse + "if (code == 110) {\n";
|
|
539
|
+
DESERIALIZE += " if (load<u64>(srcStart) == 30399761348886638) {\n";
|
|
540
|
+
DESERIALIZE += " srcStart += 8;\n";
|
|
541
|
+
if (sortedMembers.null.some((m) => (m.alias || m.name).length << 1 == 2)) {
|
|
542
|
+
DESERIALIZE += " const code16 = load<u16>(keyStart);\n";
|
|
543
|
+
}
|
|
544
|
+
if (sortedMembers.null.some((m) => (m.alias || m.name).length << 1 == 4)) {
|
|
545
|
+
DESERIALIZE += " const code32 = load<u32>(keyStart);\n";
|
|
546
|
+
}
|
|
547
|
+
if (sortedMembers.null.some((m) => (m.alias || m.name).length << 1 == 6)) {
|
|
548
|
+
DESERIALIZE += " const code48 = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n";
|
|
549
|
+
}
|
|
550
|
+
if (sortedMembers.null.some((m) => (m.alias || m.name).length << 1 == 8)) {
|
|
551
|
+
DESERIALIZE += " const code64 = load<u64>(keyStart);\n";
|
|
552
|
+
}
|
|
553
|
+
if (sortedMembers.null.some((m) => (m.alias || m.name).length << 1 > 8)) {
|
|
554
|
+
DESERIALIZE += toMemCDecl(Math.max(...sortedMembers.null.map((m) => (m.alias || m.name).length << 1)), " ");
|
|
555
|
+
}
|
|
556
|
+
const firstMemberName = sortedMembers.null[0].alias || sortedMembers.null[0].name;
|
|
557
|
+
DESERIALIZE += indent + " if (" + getComparision(firstMemberName) + ") { // " + firstMemberName + "\n";
|
|
558
|
+
DESERIALIZE += indent + " store<" + sortedMembers.null[0].type + ">(changetype<usize>(out), null, offsetof<this>(" + JSON.stringify(sortedMembers.null[0].name) + "));\n";
|
|
559
|
+
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
560
|
+
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
561
|
+
DESERIALIZE += indent + " break;\n";
|
|
562
|
+
DESERIALIZE += indent + " }";
|
|
563
|
+
for (let i = 1; i < sortedMembers.null.length; i++) {
|
|
564
|
+
const member = sortedMembers.null[i];
|
|
565
|
+
const memberName = member.alias || member.name;
|
|
566
|
+
DESERIALIZE += indent + " else if (" + getComparision(memberName) + ") { // " + memberName + "\n";
|
|
567
|
+
DESERIALIZE += indent + " store<" + sortedMembers.null[0].type + ">(changetype<usize>(out), null, offsetof<this>(" + JSON.stringify(sortedMembers.null[0].name) + "));\n";
|
|
568
|
+
DESERIALIZE += indent + " srcStart += 2;\n";
|
|
569
|
+
DESERIALIZE += indent + " keyStart = 0;\n";
|
|
570
|
+
DESERIALIZE += indent + " break;\n";
|
|
571
|
+
DESERIALIZE += indent + " }";
|
|
572
|
+
}
|
|
573
|
+
DESERIALIZE += " else {\n";
|
|
574
|
+
DESERIALIZE += indent + ' throw new Error("Unexpected key in JSON object \'" + String.fromCharCode(load<u16>(srcStart)) + "\' at position " + (srcEnd - srcStart).toString());\n';
|
|
575
|
+
DESERIALIZE += indent + " }\n";
|
|
576
|
+
DESERIALIZE += " }";
|
|
577
|
+
DESERIALIZE += "\n }";
|
|
578
|
+
mbElse = " else ";
|
|
579
|
+
}
|
|
580
|
+
DESERIALIZE += " else {\n";
|
|
581
|
+
DESERIALIZE += " srcStart += 2;\n";
|
|
582
|
+
DESERIALIZE += "}\n";
|
|
583
|
+
DESERIALIZE += "\n }\n";
|
|
361
584
|
indentDec();
|
|
362
|
-
DESERIALIZE +=
|
|
585
|
+
DESERIALIZE += ` }\n`;
|
|
363
586
|
indentDec();
|
|
364
|
-
DESERIALIZE +=
|
|
587
|
+
DESERIALIZE += ` return out;\n}\n`;
|
|
365
588
|
indent = " ";
|
|
366
589
|
this.schema.byteSize += 2;
|
|
367
590
|
SERIALIZE += indent + "store<u16>(bs.offset, 125, 0); // }\n";
|
|
@@ -370,14 +593,14 @@ class JSONTransform extends Visitor {
|
|
|
370
593
|
SERIALIZE = SERIALIZE.slice(0, 32) + indent + "bs.proposeSize(" + this.schema.byteSize + ");\n" + SERIALIZE.slice(32);
|
|
371
594
|
INITIALIZE += " return this;\n";
|
|
372
595
|
INITIALIZE += "}";
|
|
373
|
-
if (
|
|
374
|
-
console.log(SERIALIZE);
|
|
596
|
+
if (DEBUG) {
|
|
597
|
+
console.log(SERIALIZE_CUSTOM ? SERIALIZE_CUSTOM : SERIALIZE);
|
|
375
598
|
console.log(INITIALIZE);
|
|
376
|
-
console.log(DESERIALIZE);
|
|
599
|
+
console.log(DESERIALIZE_CUSTOM || DESERIALIZE);
|
|
377
600
|
}
|
|
378
|
-
const SERIALIZE_METHOD = SimpleParser.parseClassMember(SERIALIZE, node);
|
|
601
|
+
const SERIALIZE_METHOD = SimpleParser.parseClassMember(SERIALIZE_CUSTOM ? SERIALIZE_CUSTOM : SERIALIZE, node);
|
|
379
602
|
const INITIALIZE_METHOD = SimpleParser.parseClassMember(INITIALIZE, node);
|
|
380
|
-
const DESERIALIZE_METHOD = SimpleParser.parseClassMember(DESERIALIZE, node);
|
|
603
|
+
const DESERIALIZE_METHOD = SimpleParser.parseClassMember(DESERIALIZE_CUSTOM || DESERIALIZE, node);
|
|
381
604
|
if (!node.members.find((v) => v.name.text == "__SERIALIZE"))
|
|
382
605
|
node.members.push(SERIALIZE_METHOD);
|
|
383
606
|
if (!node.members.find((v) => v.name.text == "__INITIALIZE"))
|
|
@@ -389,8 +612,8 @@ class JSONTransform extends Visitor {
|
|
|
389
612
|
generateEmptyMethods(node) {
|
|
390
613
|
let SERIALIZE_EMPTY = "@inline __SERIALIZE(ptr: usize): void {\n bs.proposeSize(4);\n store<u32>(bs.offset, 8192123);\n bs.offset += 4;\n}";
|
|
391
614
|
let INITIALIZE_EMPTY = "@inline __INITIALIZE(): this {\n return this;\n}";
|
|
392
|
-
let DESERIALIZE_EMPTY = "@inline __DESERIALIZE(
|
|
393
|
-
if (
|
|
615
|
+
let DESERIALIZE_EMPTY = "@inline __DESERIALIZE(srcStart: usize, srcEnd: usize): this {\n return this;\n}";
|
|
616
|
+
if (DEBUG) {
|
|
394
617
|
console.log(SERIALIZE_EMPTY);
|
|
395
618
|
console.log(INITIALIZE_EMPTY);
|
|
396
619
|
console.log(DESERIALIZE_EMPTY);
|
|
@@ -427,7 +650,7 @@ class JSONTransform extends Visitor {
|
|
|
427
650
|
}
|
|
428
651
|
const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("bs", node.range, false), null, node.range)], Node.createStringLiteralExpression(bsPath, node.range), node.range);
|
|
429
652
|
this.topStatements.push(replaceNode);
|
|
430
|
-
if (
|
|
653
|
+
if (DEBUG)
|
|
431
654
|
console.log("Added as-bs import: " + toString(replaceNode) + "\n");
|
|
432
655
|
}
|
|
433
656
|
if (!jsonImport) {
|
|
@@ -436,7 +659,7 @@ class JSONTransform extends Visitor {
|
|
|
436
659
|
}
|
|
437
660
|
const replaceNode = Node.createImportStatement([Node.createImportDeclaration(Node.createIdentifierExpression("JSON", node.range, false), null, node.range)], Node.createStringLiteralExpression(jsonPath, node.range), node.range);
|
|
438
661
|
this.topStatements.push(replaceNode);
|
|
439
|
-
if (
|
|
662
|
+
if (DEBUG)
|
|
440
663
|
console.log("Added json-as import: " + toString(replaceNode) + "\n");
|
|
441
664
|
}
|
|
442
665
|
}
|
|
@@ -488,7 +711,7 @@ class JSONTransform extends Visitor {
|
|
|
488
711
|
}
|
|
489
712
|
export default class Transformer extends Transform {
|
|
490
713
|
afterParse(parser) {
|
|
491
|
-
const transformer =
|
|
714
|
+
const transformer = JSONTransform.SN;
|
|
492
715
|
const sources = parser.sources
|
|
493
716
|
.filter((source) => {
|
|
494
717
|
const p = source.internalPath;
|
|
@@ -575,17 +798,17 @@ function toMemCDecl(n, indent) {
|
|
|
575
798
|
let offset = 0;
|
|
576
799
|
let index = 0;
|
|
577
800
|
while (n >= 8) {
|
|
578
|
-
out += `${indent}const
|
|
801
|
+
out += `${indent}const codeS${(index += 8)} = load<u64>(keyStart, ${offset});\n`;
|
|
579
802
|
offset += 8;
|
|
580
803
|
n -= 8;
|
|
581
804
|
}
|
|
582
805
|
while (n >= 4) {
|
|
583
|
-
out += `${indent}const
|
|
806
|
+
out += `${indent}const codeS${(index += 4)} = load<u32>(keyStart, ${offset});\n`;
|
|
584
807
|
offset += 4;
|
|
585
808
|
n -= 4;
|
|
586
809
|
}
|
|
587
810
|
if (n == 1)
|
|
588
|
-
out += `${indent}const
|
|
811
|
+
out += `${indent}const codeS${(index += 1)} = load<u16>(keyStart, ${offset});\n`;
|
|
589
812
|
return out;
|
|
590
813
|
}
|
|
591
814
|
function toMemCCheck(data) {
|
|
@@ -594,17 +817,17 @@ function toMemCCheck(data) {
|
|
|
594
817
|
let offset = 0;
|
|
595
818
|
let index = 0;
|
|
596
819
|
while (n >= 8) {
|
|
597
|
-
out += ` &&
|
|
820
|
+
out += ` && codeS${(index += 8)} == ${toU64(data, offset >> 1)}`;
|
|
598
821
|
offset += 8;
|
|
599
822
|
n -= 8;
|
|
600
823
|
}
|
|
601
824
|
while (n >= 4) {
|
|
602
|
-
out += ` &&
|
|
825
|
+
out += ` && codeS${(index += 4)} == ${toU32(data, offset >> 1)}`;
|
|
603
826
|
offset += 4;
|
|
604
827
|
n -= 4;
|
|
605
828
|
}
|
|
606
829
|
if (n == 1)
|
|
607
|
-
out += ` &&
|
|
830
|
+
out += ` && codeS${(index += 1)} == ${toU16(data, offset >> 1)}`;
|
|
608
831
|
return out.slice(4);
|
|
609
832
|
}
|
|
610
833
|
function strToNum(data, simd = false, offset = 0) {
|
|
@@ -633,10 +856,6 @@ function strToNum(data, simd = false, offset = 0) {
|
|
|
633
856
|
}
|
|
634
857
|
return out;
|
|
635
858
|
}
|
|
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
859
|
function throwError(message, range) {
|
|
641
860
|
const err = new Error();
|
|
642
861
|
err.stack = `${message}\n at ${range.source.normalizedPath}:${range.source.lineAt(range.start)}:${range.source.columnAt()}\n`;
|
|
@@ -670,4 +889,46 @@ function sizeof(type) {
|
|
|
670
889
|
else
|
|
671
890
|
return 0;
|
|
672
891
|
}
|
|
892
|
+
function isPrimitive(type) {
|
|
893
|
+
const primitiveTypes = ["u8", "u16", "u32", "u64", "i8", "i16", "i32", "i64", "f32", "f64", "bool", "boolean"];
|
|
894
|
+
return primitiveTypes.some((v) => type.startsWith(v));
|
|
895
|
+
}
|
|
896
|
+
function isBoolean(type) {
|
|
897
|
+
return type == "bool" || type == "boolean";
|
|
898
|
+
}
|
|
899
|
+
function isStruct(type) {
|
|
900
|
+
type = stripNull(type);
|
|
901
|
+
return JSONTransform.SN.schemas.some((v) => v.name == type) || JSONTransform.SN.schema.name == type;
|
|
902
|
+
}
|
|
903
|
+
function isString(type) {
|
|
904
|
+
return stripNull(type) == "string" || stripNull(type) == "String";
|
|
905
|
+
}
|
|
906
|
+
function isArray(type) {
|
|
907
|
+
return type.startsWith("Array<");
|
|
908
|
+
}
|
|
909
|
+
function stripNull(type) {
|
|
910
|
+
if (type.endsWith(" | null")) {
|
|
911
|
+
return type.slice(0, type.length - 7);
|
|
912
|
+
}
|
|
913
|
+
return type;
|
|
914
|
+
}
|
|
915
|
+
function getComparision(data) {
|
|
916
|
+
switch (data.length << 1) {
|
|
917
|
+
case 2: {
|
|
918
|
+
return "code16 == " + data.charCodeAt(0);
|
|
919
|
+
}
|
|
920
|
+
case 4: {
|
|
921
|
+
return "code32 == " + toU32(data);
|
|
922
|
+
}
|
|
923
|
+
case 6: {
|
|
924
|
+
return "code48 == " + toU48(data);
|
|
925
|
+
}
|
|
926
|
+
case 8: {
|
|
927
|
+
return "code64 == " + toU64(data);
|
|
928
|
+
}
|
|
929
|
+
default: {
|
|
930
|
+
return toMemCCheck(data);
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
}
|
|
673
934
|
//# sourceMappingURL=index.js.map
|