json-as 0.9.29 → 1.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/nodejs.yml +0 -3
- package/.prettierrc.json +3 -2
- package/CHANGELOG +13 -0
- package/LICENSE +1 -1
- package/README.md +22 -7
- package/as-test.config.json +1 -1
- package/asconfig.json +2 -2
- package/assembly/__benches__/misc.bench.ts +17 -32
- package/assembly/__tests__/bool.spec.ts +1 -1
- package/assembly/__tests__/simd/string.spec.ts +32 -0
- package/assembly/custom/memory.ts +25 -0
- package/assembly/custom/util.ts +14 -92
- package/assembly/deserialize/simd/string.ts +103 -0
- package/assembly/deserialize/simple/arbitrary.ts +17 -0
- package/assembly/deserialize/simple/array/arbitrary.ts +113 -0
- package/assembly/deserialize/simple/array/array.ts +18 -0
- package/assembly/deserialize/simple/array/bool.ts +17 -0
- package/assembly/deserialize/simple/array/float.ts +28 -0
- package/assembly/deserialize/simple/array/integer.ts +27 -0
- package/assembly/deserialize/simple/array/map.ts +18 -0
- package/assembly/deserialize/simple/array/object.ts +18 -0
- package/assembly/deserialize/simple/array/string.ts +22 -0
- package/assembly/deserialize/simple/array.ts +48 -0
- package/assembly/deserialize/simple/bool.ts +9 -0
- package/assembly/deserialize/simple/date.ts +11 -0
- package/assembly/deserialize/simple/float.ts +10 -0
- package/assembly/deserialize/simple/integer.ts +5 -0
- package/assembly/deserialize/simple/map.ts +154 -0
- package/assembly/deserialize/simple/object.ts +159 -0
- package/assembly/deserialize/simple/string.ts +48 -0
- package/assembly/globals/tables.ts +417 -0
- package/assembly/index.d.ts +9 -13
- package/assembly/index.ts +266 -146
- package/assembly/serialize/simd/string.ts +176 -0
- package/assembly/serialize/simple/arbitrary.ts +36 -0
- package/assembly/serialize/simple/array.ts +32 -0
- package/assembly/serialize/simple/bool.ts +19 -0
- package/assembly/serialize/simple/date.ts +13 -0
- package/assembly/serialize/simple/float.ts +7 -0
- package/assembly/serialize/simple/integer.ts +7 -0
- package/assembly/serialize/simple/map.ts +43 -0
- package/assembly/serialize/simple/object.ts +7 -0
- package/assembly/serialize/simple/string.ts +48 -0
- package/assembly/test.ts +41 -27
- package/assembly/tsconfig.json +2 -91
- package/assembly/types.ts +0 -0
- package/assembly/util/atoi.ts +35 -0
- package/assembly/util/bytes.ts +12 -0
- package/assembly/util/concat.ts +9 -0
- package/assembly/util/getArrayDepth.ts +17 -0
- package/assembly/util/index.ts +5 -0
- package/assembly/util/isSpace.ts +4 -0
- package/assembly/util/nextPowerOf2.ts +4 -0
- package/assembly/util/ptrToStr.ts +7 -0
- package/assembly/util/snp.ts +69 -0
- package/bench.js +5 -5
- package/modules/bs/index.ts +167 -0
- package/modules/tsconfig.json +8 -0
- package/package.json +42 -48
- package/transform/lib/builder.js +1353 -0
- package/transform/lib/builder.js.map +1 -0
- package/transform/lib/index.js +497 -332
- package/transform/lib/index.js.map +1 -1
- package/transform/lib/index.old.js +404 -0
- package/transform/lib/index.old.js.map +1 -0
- package/transform/lib/linker.js +18 -0
- package/transform/lib/linker.js.map +1 -0
- package/transform/lib/types.js +25 -0
- package/transform/lib/types.js.map +1 -0
- package/transform/lib/util.js +47 -0
- package/transform/lib/util.js.map +1 -0
- package/transform/lib/visitor.js +529 -446
- package/transform/lib/visitor.js.map +1 -0
- package/transform/package.json +1 -34
- package/transform/src/builder.ts +1371 -0
- package/transform/src/index.ts +564 -341
- package/transform/src/linker.ts +21 -0
- package/transform/src/types.ts +27 -0
- package/transform/src/util.ts +56 -0
- package/transform/src/visitor.ts +531 -0
- package/transform/tsconfig.json +3 -1
- package/assembly/__benches__/as-tral.d.ts +0 -1
- package/assembly/__tests__/date.spec.ts +0 -12
- package/assembly/custom/bs.ts +0 -202
- package/assembly/deserialize/array/array.ts +0 -31
- package/assembly/deserialize/array/bool.ts +0 -19
- package/assembly/deserialize/array/float.ts +0 -24
- package/assembly/deserialize/array/integer.ts +0 -24
- package/assembly/deserialize/array/map.ts +0 -27
- package/assembly/deserialize/array/object.ts +0 -27
- package/assembly/deserialize/array/string.ts +0 -29
- package/assembly/deserialize/array.ts +0 -46
- package/assembly/deserialize/bool.ts +0 -34
- package/assembly/deserialize/date.ts +0 -19
- package/assembly/deserialize/float.ts +0 -21
- package/assembly/deserialize/integer.ts +0 -16
- package/assembly/deserialize/map.ts +0 -139
- package/assembly/deserialize/object.ts +0 -211
- package/assembly/deserialize/string.ts +0 -149
- package/assembly/serialize/array.ts +0 -44
- package/assembly/serialize/bool.ts +0 -10
- package/assembly/serialize/date.ts +0 -4
- package/assembly/serialize/float.ts +0 -4
- package/assembly/serialize/integer.ts +0 -5
- package/assembly/serialize/map.ts +0 -24
- package/assembly/serialize/object.ts +0 -13
- package/assembly/serialize/string.ts +0 -284
package/transform/lib/index.js
CHANGED
|
@@ -1,440 +1,490 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { toString, isStdlib } from "visitor-as/dist/utils.js";
|
|
3
|
-
import { BaseVisitor, SimpleParser } from "visitor-as/dist/index.js";
|
|
1
|
+
import { IdentifierExpression, Source, StringLiteralExpression, IntegerLiteralExpression, FloatLiteralExpression, NullExpression, TrueExpression, FalseExpression, Node, Tokenizer } from "assemblyscript/dist/assemblyscript.js";
|
|
4
2
|
import { Transform } from "assemblyscript/dist/transform.js";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
import { Visitor } from "./visitor.js";
|
|
4
|
+
import { SimpleParser, toString } from "./util.js";
|
|
5
|
+
import * as path from "path";
|
|
6
|
+
import { fileURLToPath } from "url";
|
|
7
|
+
import { Property, PropertyFlags, Schema } from "./types.js";
|
|
8
|
+
import { getClasses, getImportedClass } from "./linker.js";
|
|
9
|
+
let indent = " ";
|
|
10
|
+
class JSONTransform extends Visitor {
|
|
11
|
+
parser;
|
|
12
|
+
schemas = [];
|
|
13
|
+
schema;
|
|
8
14
|
sources = new Set();
|
|
9
|
-
|
|
15
|
+
imports = [];
|
|
16
|
+
jsonImport = null;
|
|
17
|
+
bsImport = null;
|
|
18
|
+
newStmts = { simd: [] };
|
|
10
19
|
visitClassDeclaration(node) {
|
|
11
20
|
if (!node.decorators?.length)
|
|
12
21
|
return;
|
|
13
|
-
|
|
14
|
-
for (const decorator of node.decorators) {
|
|
22
|
+
if (!node.decorators.some((decorator) => {
|
|
15
23
|
const name = decorator.name.text;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
break;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
if (!found)
|
|
24
|
+
return name === "json" || name === "serializable";
|
|
25
|
+
}))
|
|
22
26
|
return;
|
|
23
|
-
|
|
24
|
-
schema.node = node;
|
|
25
|
-
schema.name = node.name.text;
|
|
26
|
-
|
|
27
|
+
this.schema = new Schema();
|
|
28
|
+
this.schema.node = node;
|
|
29
|
+
this.schema.name = node.name.text;
|
|
30
|
+
this.schemas.push(this.schema);
|
|
31
|
+
if (process.env["JSON_DEBUG"])
|
|
32
|
+
console.log("Created schema: " + this.schema.name);
|
|
33
|
+
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"))];
|
|
27
34
|
if (node.extendsType) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
35
|
+
const extendsName = node.extendsType?.name.identifier.text;
|
|
36
|
+
this.schema.parent = this.schemas.find((v) => v.name == extendsName);
|
|
37
|
+
if (!this.schema.parent) {
|
|
38
|
+
const internalSearch = getClasses(node.range.source).find((v) => v.name.text == extendsName);
|
|
39
|
+
if (internalSearch) {
|
|
40
|
+
if (process.env["JSON_DEBUG"])
|
|
41
|
+
console.log("Found " + extendsName + " internally");
|
|
42
|
+
this.visitClassDeclaration(internalSearch);
|
|
43
|
+
this.visitClassDeclaration(node);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const externalSearch = getImportedClass(extendsName, node.range.source, this.parser);
|
|
47
|
+
if (externalSearch) {
|
|
48
|
+
if (process.env["JSON_DEBUG"])
|
|
49
|
+
console.log("Found " + extendsName + " externally");
|
|
50
|
+
this.visitClassDeclaration(externalSearch);
|
|
51
|
+
this.visitClassDeclaration(node);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (this.schema.parent?.members) {
|
|
56
|
+
for (let i = this.schema.parent.members.length - 1; i >= 0; i--) {
|
|
57
|
+
const replace = this.schema.members.find((v) => v.name == this.schema.parent?.members[i]?.name);
|
|
32
58
|
if (!replace) {
|
|
33
|
-
members.unshift(schema.parent?.members[i].node);
|
|
59
|
+
members.unshift(this.schema.parent?.members[i].node);
|
|
34
60
|
}
|
|
35
61
|
}
|
|
36
62
|
}
|
|
37
63
|
}
|
|
38
64
|
if (!members.length) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
let DESERIALIZE_EMPTY = "__DESERIALIZE(data: string, key_start: i32, key_end: i32, value_start: i32, value_end: i32): boolean {\n return false;\n}";
|
|
42
|
-
if (process.env["JSON_DEBUG"]) {
|
|
43
|
-
console.log(SERIALIZE_RAW_EMPTY);
|
|
44
|
-
console.log(INITIALIZE_EMPTY);
|
|
45
|
-
console.log(DESERIALIZE_EMPTY);
|
|
46
|
-
}
|
|
47
|
-
const SERIALIZE_RAW_METHOD_EMPTY = SimpleParser.parseClassMember(SERIALIZE_RAW_EMPTY, node);
|
|
48
|
-
const INITIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(INITIALIZE_EMPTY, node);
|
|
49
|
-
const DESERIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(DESERIALIZE_EMPTY, node);
|
|
50
|
-
if (!node.members.find((v) => v.name.text == "__SERIALIZE"))
|
|
51
|
-
node.members.push(SERIALIZE_RAW_METHOD_EMPTY);
|
|
52
|
-
if (!node.members.find((v) => v.name.text == "__INITIALIZE"))
|
|
53
|
-
node.members.push(INITIALIZE_METHOD_EMPTY);
|
|
54
|
-
if (!node.members.find((v) => v.name.text == "__DESERIALIZE"))
|
|
55
|
-
node.members.push(DESERIALIZE_METHOD_EMPTY);
|
|
56
|
-
this.schemasList.push(schema);
|
|
65
|
+
this.generateEmptyMethods(node);
|
|
66
|
+
return;
|
|
57
67
|
}
|
|
68
|
+
this.addRequiredImports(node);
|
|
58
69
|
for (const member of members) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
continue;
|
|
62
|
-
if (!member.type) {
|
|
63
|
-
throw new Error("Fields must be strongly typed! Found " + toString(member) + " at " + node.range.source.normalizedPath);
|
|
64
|
-
}
|
|
70
|
+
if (!member.type)
|
|
71
|
+
throwError("Fields must be strongly typed", node.range);
|
|
65
72
|
const type = toString(member.type);
|
|
66
|
-
|
|
67
|
-
continue;
|
|
73
|
+
const name = member.name;
|
|
68
74
|
const value = member.initializer ? toString(member.initializer) : null;
|
|
69
|
-
if (
|
|
70
|
-
continue;
|
|
71
|
-
if (member.flags === 512)
|
|
72
|
-
continue;
|
|
73
|
-
if (member.flags === 1024)
|
|
74
|
-
continue;
|
|
75
|
-
if (member.decorators && node.decorators.some((v) => v.name.text == "omit"))
|
|
75
|
+
if (type.startsWith("(") && type.includes("=>"))
|
|
76
76
|
continue;
|
|
77
77
|
const mem = new Property();
|
|
78
78
|
mem.name = name.text;
|
|
79
79
|
mem.type = type;
|
|
80
80
|
mem.value = value;
|
|
81
81
|
mem.node = member;
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
mem.flags.set(PropertyFlags.Null, []);
|
|
87
|
-
}
|
|
82
|
+
mem.byteSize = sizeof(mem.type);
|
|
83
|
+
this.schema.byteSize += mem.byteSize;
|
|
84
|
+
if (type.includes("JSON.Raw"))
|
|
85
|
+
mem.flags.set(PropertyFlags.Raw, null);
|
|
88
86
|
if (member.decorators) {
|
|
89
87
|
for (const decorator of member.decorators) {
|
|
90
|
-
const decoratorName = decorator.name.text;
|
|
91
|
-
const args = getArgs(decorator.args);
|
|
88
|
+
const decoratorName = decorator.name.text.toLowerCase().trim();
|
|
92
89
|
switch (decoratorName) {
|
|
93
90
|
case "alias": {
|
|
91
|
+
const args = getArgs(decorator.args);
|
|
94
92
|
if (!args.length)
|
|
95
|
-
|
|
93
|
+
throwError("@alias must have an argument of type string or number", member.range);
|
|
96
94
|
mem.alias = args[0];
|
|
97
|
-
mem.flags.set(PropertyFlags.Alias, args);
|
|
98
|
-
break;
|
|
99
|
-
}
|
|
100
|
-
case "omit": {
|
|
101
|
-
mem.flags.set(PropertyFlags.Omit, args);
|
|
102
95
|
break;
|
|
103
96
|
}
|
|
104
97
|
case "omitif": {
|
|
98
|
+
let arg = decorator.args[0];
|
|
105
99
|
if (!decorator.args?.length)
|
|
106
|
-
|
|
107
|
-
mem.flags.set(PropertyFlags.OmitIf,
|
|
100
|
+
throwError("@omitif must have an argument or callback that resolves to type bool", member.range);
|
|
101
|
+
mem.flags.set(PropertyFlags.OmitIf, arg);
|
|
102
|
+
this.schema.static = false;
|
|
108
103
|
break;
|
|
109
104
|
}
|
|
110
105
|
case "omitnull": {
|
|
111
|
-
|
|
106
|
+
if (isPrimitive(type)) {
|
|
107
|
+
throwError("@omitnull cannot be used on primitive types!", member.range);
|
|
108
|
+
}
|
|
109
|
+
else if (!member.type.isNullable) {
|
|
110
|
+
throwError("@omitnull cannot be used on non-nullable types!", member.range);
|
|
111
|
+
}
|
|
112
|
+
mem.flags.set(PropertyFlags.OmitNull, null);
|
|
113
|
+
this.schema.static = false;
|
|
112
114
|
break;
|
|
113
115
|
}
|
|
114
116
|
}
|
|
115
117
|
}
|
|
116
118
|
}
|
|
117
|
-
|
|
118
|
-
if (this.schemasList.find((v) => v.name == type)) {
|
|
119
|
-
mem.initialize = "this." + name.text + " = changetype<nonnull<" + mem.type + ">>(__new(offsetof<nonnull<" + mem.type + ">>(), idof<nonnull<" + mem.type + ">>()));\n changetype<nonnull<" + mem.type + ">>(this." + name.text + ").__INITIALIZE()";
|
|
120
|
-
}
|
|
121
|
-
else if (mem.value) {
|
|
122
|
-
mem.initialize = "this." + name.text + " = " + mem.value;
|
|
123
|
-
}
|
|
124
|
-
else if (type === "Map") {
|
|
125
|
-
mem.initialize = "this." + name.text + " = new " + mem.type + "()";
|
|
126
|
-
}
|
|
127
|
-
else if (type === "string") {
|
|
128
|
-
mem.initialize = "this." + name.text + ' = ""';
|
|
129
|
-
}
|
|
130
|
-
else if (type === "Array") {
|
|
131
|
-
mem.initialize = "this." + name.text + " = instantiate<" + mem.type + ">()";
|
|
132
|
-
}
|
|
133
|
-
else if (type === "bool" || type === "boolean") {
|
|
134
|
-
mem.initialize = "this." + name.text + " = false";
|
|
135
|
-
}
|
|
136
|
-
else if (type === "JSON.Raw") {
|
|
137
|
-
mem.initialize = "this." + name.text + ' = ""';
|
|
138
|
-
}
|
|
139
|
-
else if (type === "u8" || type === "u16" || type === "u32" || type === "u64" || type === "i8" || type === "i16" || type === "i32" || type === "i64") {
|
|
140
|
-
mem.initialize = "this." + name.text + " = 0";
|
|
141
|
-
}
|
|
142
|
-
else if (type === "f32" || type === "f64") {
|
|
143
|
-
mem.initialize = "this." + name.text + " = 0.0";
|
|
144
|
-
}
|
|
145
|
-
schema.members.push(mem);
|
|
146
|
-
}
|
|
147
|
-
let SERIALIZE_RAW = "__SERIALIZE(): string {\n let out = `{";
|
|
148
|
-
let SERIALIZE_PRETTY = "__SERIALIZE_PRETTY(): string {\n let out = `{";
|
|
149
|
-
let INITIALIZE = "__INITIALIZE(): this {\n";
|
|
150
|
-
let DESERIALIZE = "__DESERIALIZE(data: string, key_start: i32, key_end: i32, value_start: i32, value_end: i32): boolean {\n const len = key_end - key_start;\n";
|
|
151
|
-
let indent = " ";
|
|
152
|
-
if (!schema.members.length)
|
|
153
|
-
return;
|
|
154
|
-
found = false;
|
|
155
|
-
if (schema.members[0]?.flags.has(PropertyFlags.OmitNull) || schema.members[0]?.flags.has(PropertyFlags.OmitIf)) {
|
|
156
|
-
SERIALIZE_RAW += schema.members[0]?.serialize;
|
|
157
|
-
SERIALIZE_PRETTY += "\\n" + schema.members[0]?.serialize;
|
|
119
|
+
this.schema.members.push(mem);
|
|
158
120
|
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
121
|
+
if (!this.schema.static)
|
|
122
|
+
this.schema.members = sortMembers(this.schema.members);
|
|
123
|
+
let SERIALIZE = "__SERIALIZE(ptr: usize): void {\n";
|
|
124
|
+
let INITIALIZE = "@inline __INITIALIZE(): this {\n";
|
|
125
|
+
let DESERIALIZE = "__DESERIALIZE(keyStart: usize, keyEnd: usize, valStart: usize, valEnd: usize, ptr: usize): void {\n switch (keyEnd - keyStart) {\n";
|
|
126
|
+
let ALLOCATE = "@inline __ALLOCATE(): void {\n";
|
|
127
|
+
indent = " ";
|
|
128
|
+
if (this.schema.static == false) {
|
|
129
|
+
if (this.schema.members.some((v) => v.flags.has(PropertyFlags.OmitNull))) {
|
|
130
|
+
SERIALIZE += indent + "let block: usize = 0;\n";
|
|
131
|
+
}
|
|
132
|
+
this.schema.byteSize += 2;
|
|
133
|
+
SERIALIZE += indent + "store<u16>(bs.offset, 123, 0); // {\n";
|
|
134
|
+
SERIALIZE += indent + "bs.offset += 2;\n";
|
|
163
135
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
136
|
+
let isPure = this.schema.static;
|
|
137
|
+
let isRegular = isPure;
|
|
138
|
+
let isFirst = true;
|
|
139
|
+
for (let i = 0; i < this.schema.members.length; i++) {
|
|
140
|
+
const member = this.schema.members[i];
|
|
141
|
+
const aliasName = JSON.stringify(member.alias || member.name);
|
|
142
|
+
const realName = member.name;
|
|
143
|
+
const isLast = i == this.schema.members.length - 1;
|
|
144
|
+
const nonNullType = member.type.replace(" | null", "");
|
|
145
|
+
if (member.value) {
|
|
146
|
+
INITIALIZE += ` this.${member.name} = ${member.value};\n`;
|
|
147
|
+
}
|
|
148
|
+
else if (this.schemas.find((v) => nonNullType == v.name)) {
|
|
149
|
+
INITIALIZE += ` this.${member.name} = changetype<nonnull<${member.type}>>(__new(offsetof<nonnull<${member.type}>>(), idof<nonnull<${member.type}>>())).__INITIALIZE();\n`;
|
|
150
|
+
}
|
|
151
|
+
else if (member.type.startsWith("Array<") || member.type.startsWith("Map<")) {
|
|
152
|
+
INITIALIZE += ` this.${member.name} = [];\n`;
|
|
153
|
+
}
|
|
154
|
+
else if (member.type == "string" || member.type == "String" || member.type == "JSON.Raw") {
|
|
155
|
+
INITIALIZE += ` this.${member.name} = "";\n`;
|
|
156
|
+
}
|
|
157
|
+
if (!isRegular && !member.flags.has(PropertyFlags.OmitIf) && !member.flags.has(PropertyFlags.OmitNull))
|
|
158
|
+
isRegular = true;
|
|
159
|
+
if (isRegular && isPure) {
|
|
160
|
+
const keyPart = (isFirst ? "{" : ",") + aliasName + ":";
|
|
161
|
+
this.schema.byteSize += keyPart.length << 1;
|
|
162
|
+
SERIALIZE += this.getStores(keyPart)
|
|
163
|
+
.map((v) => indent + v + "\n")
|
|
164
|
+
.join("");
|
|
165
|
+
SERIALIZE += indent + `JSON.__serialize<${member.type}>(load<${member.type}>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`;
|
|
166
|
+
if (isFirst)
|
|
167
|
+
isFirst = false;
|
|
168
|
+
}
|
|
169
|
+
else if (isRegular && !isPure) {
|
|
170
|
+
const keyPart = (isFirst ? "" : ",") + aliasName + ":";
|
|
171
|
+
this.schema.byteSize += keyPart.length << 1;
|
|
172
|
+
SERIALIZE += this.getStores(keyPart)
|
|
173
|
+
.map((v) => indent + v + "\n")
|
|
174
|
+
.join("");
|
|
175
|
+
SERIALIZE += indent + `JSON.__serialize<${member.type}>(load<${member.type}>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`;
|
|
176
|
+
if (isFirst)
|
|
177
|
+
isFirst = false;
|
|
173
178
|
}
|
|
174
179
|
else {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
180
|
+
if (member.flags.has(PropertyFlags.OmitNull)) {
|
|
181
|
+
SERIALIZE += indent + `if ((block = load<usize>(ptr, offsetof<this>(${JSON.stringify(realName)}))) !== 0) {\n`;
|
|
182
|
+
indentInc();
|
|
183
|
+
const keyPart = aliasName + ":";
|
|
184
|
+
this.schema.byteSize += keyPart.length << 1;
|
|
185
|
+
SERIALIZE += this.getStores(keyPart)
|
|
186
|
+
.map((v) => indent + v + "\n")
|
|
187
|
+
.join("");
|
|
188
|
+
SERIALIZE += indent + `JSON.__serialize<${member.type}>(load<${member.type}>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`;
|
|
189
|
+
if (!isLast) {
|
|
190
|
+
this.schema.byteSize += 2;
|
|
191
|
+
SERIALIZE += indent + `store<u16>(bs.offset, 44, 0); // ,\n`;
|
|
192
|
+
SERIALIZE += indent + `bs.offset += 2;\n`;
|
|
193
|
+
}
|
|
194
|
+
indentDec();
|
|
195
|
+
this.schema.byteSize += 2;
|
|
196
|
+
SERIALIZE += indent + `}\n`;
|
|
197
|
+
}
|
|
198
|
+
else if (member.flags.has(PropertyFlags.OmitIf)) {
|
|
199
|
+
if (member.flags.get(PropertyFlags.OmitIf).kind == 14) {
|
|
200
|
+
const arg = member.flags.get(PropertyFlags.OmitIf);
|
|
201
|
+
arg.declaration.signature.returnType.name = Node.createSimpleTypeName("boolean", arg.declaration.signature.returnType.name.range);
|
|
202
|
+
SERIALIZE += indent + `if ((${toString(member.flags.get(PropertyFlags.OmitIf))})(this)) {\n`;
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
SERIALIZE += indent + `if (${toString(member.flags.get(PropertyFlags.OmitIf))}) {\n`;
|
|
206
|
+
}
|
|
207
|
+
indentInc();
|
|
208
|
+
SERIALIZE += this.getStores(aliasName + ":")
|
|
209
|
+
.map((v) => indent + v + "\n")
|
|
210
|
+
.join("");
|
|
211
|
+
SERIALIZE += indent + `JSON.__serialize<${member.type}>(load<${member.type}>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`;
|
|
212
|
+
if (!isLast) {
|
|
213
|
+
this.schema.byteSize += 2;
|
|
214
|
+
SERIALIZE += indent + `store<u16>(bs.offset, 44, 0); // ,\n`;
|
|
215
|
+
SERIALIZE += indent + `bs.offset += 2;\n`;
|
|
216
|
+
}
|
|
217
|
+
indentDec();
|
|
218
|
+
SERIALIZE += indent + `}\n`;
|
|
219
|
+
}
|
|
178
220
|
}
|
|
179
221
|
}
|
|
180
|
-
|
|
181
|
-
SERIALIZE_RAW += "`;\n store<u16>(changetype<usize>(out) + ((out.length - 1) << 1), 125);\n return out;\n}";
|
|
182
|
-
SERIALIZE_PRETTY += "`;\n store<u32>(changetype<usize>(out) + ((out.length - 2) << 1), 8192010);\n return out;\n}";
|
|
183
|
-
}
|
|
184
|
-
else {
|
|
185
|
-
SERIALIZE_RAW += "}`;\n return out;\n}";
|
|
186
|
-
SERIALIZE_PRETTY += "}`;\n return out;\n}";
|
|
187
|
-
}
|
|
188
|
-
INITIALIZE += " return this;\n}";
|
|
189
|
-
const sortedMembers = [];
|
|
190
|
-
const _sorted = schema.members.sort((a, b) => (a.alias?.length || a.name.length) - (b.alias?.length || b.name.length));
|
|
222
|
+
let sortedMembers = [];
|
|
191
223
|
let len = -1;
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
224
|
+
this.schema.members
|
|
225
|
+
.slice()
|
|
226
|
+
.sort((a, b) => (a.alias?.length || a.name.length) - (b.alias?.length || b.name.length))
|
|
227
|
+
.forEach((member) => {
|
|
228
|
+
const _nameLength = member.alias?.length || member.name.length;
|
|
229
|
+
if (_nameLength === len) {
|
|
230
|
+
sortedMembers[sortedMembers.length - 1].push(member);
|
|
198
231
|
}
|
|
199
232
|
else {
|
|
200
233
|
sortedMembers.push([member]);
|
|
201
|
-
len =
|
|
202
|
-
offset++;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
let first = true;
|
|
206
|
-
for (const memberSet of sortedMembers) {
|
|
207
|
-
const firstMember = memberSet[0];
|
|
208
|
-
const _name = encodeKey(firstMember.alias || firstMember.name);
|
|
209
|
-
if (_name.length === 1) {
|
|
210
|
-
if (first) {
|
|
211
|
-
DESERIALIZE += " if (1 === len) {\n switch (load<u16>(changetype<usize>(data) + (key_start << 1))) {\n";
|
|
212
|
-
first = false;
|
|
213
|
-
}
|
|
214
|
-
else {
|
|
215
|
-
DESERIALIZE += "else if (1 === len) {\n switch (load<u16>(changetype<usize>(data) + (key_start << 1))) {\n";
|
|
216
|
-
}
|
|
234
|
+
len = _nameLength;
|
|
217
235
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
236
|
+
});
|
|
237
|
+
sortedMembers = sortedMembers.sort((a, b) => b.length - a.length);
|
|
238
|
+
indentInc();
|
|
239
|
+
for (const memberGroup of sortedMembers) {
|
|
240
|
+
const memberLen = (memberGroup[0].alias || memberGroup[0].name).length << 1;
|
|
241
|
+
DESERIALIZE += `${indent}case ${memberLen}: {\n`;
|
|
242
|
+
indentInc();
|
|
243
|
+
if (memberLen == 2)
|
|
244
|
+
DESERIALIZE += `${indent}switch (load<u16>(keyStart)) {\n`;
|
|
245
|
+
else if (memberLen == 4)
|
|
246
|
+
DESERIALIZE += `${indent}switch (load<u32>(keyStart)) {\n`;
|
|
247
|
+
else if (memberLen == 6)
|
|
248
|
+
DESERIALIZE += `${indent}let code = (<u64>load<u32>(keyStart) << 16) | <u64>load<u16>(keyStart, 4);\n`;
|
|
249
|
+
else
|
|
250
|
+
DESERIALIZE += toMemCDecl(memberLen, indent);
|
|
251
|
+
for (let i = 0; i < memberGroup.length; i++) {
|
|
252
|
+
const member = memberGroup[i];
|
|
253
|
+
const memberName = member.alias || member.name;
|
|
254
|
+
if (memberLen == 2) {
|
|
255
|
+
DESERIALIZE += `${indent} case ${memberName.charCodeAt(0)}: { // ${memberName}\n`;
|
|
256
|
+
DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd), offsetof<this>(${JSON.stringify(member.name)}));\n`;
|
|
257
|
+
DESERIALIZE += `${indent} return;\n`;
|
|
258
|
+
DESERIALIZE += `${indent} }\n`;
|
|
222
259
|
}
|
|
223
|
-
else {
|
|
224
|
-
DESERIALIZE +=
|
|
260
|
+
else if (memberLen == 4) {
|
|
261
|
+
DESERIALIZE += `${indent} case ${toU32(memberName)}: { // ${memberName}\n`;
|
|
262
|
+
DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd), offsetof<this>(${JSON.stringify(member.name)}));\n`;
|
|
263
|
+
DESERIALIZE += `${indent} return;\n`;
|
|
264
|
+
DESERIALIZE += `${indent} }\n`;
|
|
225
265
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
DESERIALIZE +=
|
|
230
|
-
|
|
266
|
+
else if (memberLen == 6) {
|
|
267
|
+
DESERIALIZE += i == 0 ? indent : "";
|
|
268
|
+
DESERIALIZE += `if (code == ${toU48(memberName)}) { // ${memberName}\n`;
|
|
269
|
+
DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd), offsetof<this>(${JSON.stringify(member.name)}));\n`;
|
|
270
|
+
DESERIALIZE += `${indent} return;\n`;
|
|
271
|
+
DESERIALIZE += `${indent}}${i < memberGroup.length - 1 ? " else " : "\n"}`;
|
|
231
272
|
}
|
|
232
273
|
else {
|
|
233
|
-
DESERIALIZE +=
|
|
274
|
+
DESERIALIZE += i == 0 ? indent : "";
|
|
275
|
+
DESERIALIZE += `if (${toMemCCheck(memberName)}) { // ${memberName}\n`;
|
|
276
|
+
DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd), offsetof<this>(${JSON.stringify(member.name)}));\n`;
|
|
277
|
+
DESERIALIZE += `${indent} return;\n`;
|
|
278
|
+
DESERIALIZE += `${indent}}${i < memberGroup.length - 1 ? " else " : "\n"}`;
|
|
234
279
|
}
|
|
235
280
|
}
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
DESERIALIZE += " if (" + _name.length + " === len) {\n";
|
|
239
|
-
first = false;
|
|
240
|
-
}
|
|
241
|
-
else {
|
|
242
|
-
DESERIALIZE += "else if (" + _name.length + " === len) {\n";
|
|
243
|
-
}
|
|
281
|
+
if (memberLen < 6) {
|
|
282
|
+
DESERIALIZE += `${indent}}\n`;
|
|
244
283
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
if (!member.deserialize)
|
|
249
|
-
continue;
|
|
250
|
-
const _name = encodeKey(member.alias || member.name);
|
|
251
|
-
if (_name.length === 1) {
|
|
252
|
-
DESERIALIZE += ` case ${_name.charCodeAt(0)}: { /* ${_name} */\n ${member.deserialize}\n return true;\n }\n`;
|
|
253
|
-
}
|
|
254
|
-
else if (_name.length === 2) {
|
|
255
|
-
DESERIALIZE += ` case ${charCodeAt32(_name, 0)}: { /* ${_name} */\n ${member.deserialize}\n return true;\n }\n`;
|
|
256
|
-
}
|
|
257
|
-
else if (_name.length === 4) {
|
|
258
|
-
if (f) {
|
|
259
|
-
f = false;
|
|
260
|
-
DESERIALIZE += ` if (${charCodeAt64(_name, 0)} === code) { /* ${_name} */\n ${member.deserialize}\n return true;\n }\n`;
|
|
261
|
-
}
|
|
262
|
-
else {
|
|
263
|
-
DESERIALIZE = DESERIALIZE.slice(0, DESERIALIZE.length - 1) + `else if (${charCodeAt64(_name, 0)} === code) {\n ${member.deserialize}\n return true;\n }\n`;
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
else {
|
|
267
|
-
if (f) {
|
|
268
|
-
f = false;
|
|
269
|
-
DESERIALIZE += ` if (0 === memory.compare(changetype<usize>("${escapeQuote(escapeSlash(_name))}"), changetype<usize>(data) + (key_start << 1), ${_name.length << 1})) { /* ${_name} */\n ${member.deserialize}\n return true;\n }\n`;
|
|
270
|
-
}
|
|
271
|
-
else {
|
|
272
|
-
DESERIALIZE = DESERIALIZE.slice(0, DESERIALIZE.length - 1) + ` else if (0 === memory.compare(changetype<usize>("${escapeQuote(escapeSlash(_name))}"), changetype<usize>(data) + (key_start << 1), ${_name.length << 1})) { /* ${_name} */\n ${member.deserialize}\n return true;\n }\n`;
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
if (_name.length < 3) {
|
|
277
|
-
DESERIALIZE += ` default: {\n return false;\n }\n }\n`;
|
|
278
|
-
}
|
|
279
|
-
else if (_name.length == 4) {
|
|
280
|
-
DESERIALIZE = DESERIALIZE.slice(0, DESERIALIZE.length - 1) + ` else {\n return false;\n }\n`;
|
|
281
|
-
}
|
|
282
|
-
else {
|
|
283
|
-
DESERIALIZE = DESERIALIZE.slice(0, DESERIALIZE.length - 1) + ` else {\n return false;\n }\n`;
|
|
284
|
-
}
|
|
285
|
-
DESERIALIZE += " } ";
|
|
284
|
+
indentDec();
|
|
285
|
+
DESERIALIZE += `${indent} return;\n`;
|
|
286
|
+
DESERIALIZE += `${indent}}\n`;
|
|
286
287
|
}
|
|
287
|
-
|
|
288
|
+
indentDec();
|
|
289
|
+
DESERIALIZE += `${indent}}\n`;
|
|
290
|
+
indentDec();
|
|
291
|
+
DESERIALIZE += `${indent}}\n`;
|
|
292
|
+
indent = " ";
|
|
293
|
+
this.schema.byteSize += 2;
|
|
294
|
+
SERIALIZE += indent + "store<u16>(bs.offset, 125, 0); // }\n";
|
|
295
|
+
SERIALIZE += indent + "bs.offset += 2;\n";
|
|
296
|
+
SERIALIZE += "}";
|
|
297
|
+
ALLOCATE += indent + "bs.ensureSize(" + this.schema.byteSize + ");\n";
|
|
298
|
+
ALLOCATE += "}";
|
|
299
|
+
INITIALIZE += " return this;\n";
|
|
300
|
+
INITIALIZE += "}";
|
|
288
301
|
if (process.env["JSON_DEBUG"]) {
|
|
289
|
-
console.log(
|
|
302
|
+
console.log(SERIALIZE);
|
|
290
303
|
console.log(INITIALIZE);
|
|
291
304
|
console.log(DESERIALIZE);
|
|
305
|
+
console.log(ALLOCATE);
|
|
292
306
|
}
|
|
293
|
-
const
|
|
294
|
-
const DESERIALIZE_SAFE = DESERIALIZE.replaceAll("__DESERIALIZE", "__DESERIALIZE_SAFE");
|
|
307
|
+
const SERIALIZE_METHOD = SimpleParser.parseClassMember(SERIALIZE, node);
|
|
295
308
|
const INITIALIZE_METHOD = SimpleParser.parseClassMember(INITIALIZE, node);
|
|
296
309
|
const DESERIALIZE_METHOD = SimpleParser.parseClassMember(DESERIALIZE, node);
|
|
297
|
-
const
|
|
310
|
+
const ALLOCATE_METHOD = SimpleParser.parseClassMember(ALLOCATE, node);
|
|
298
311
|
if (!node.members.find((v) => v.name.text == "__SERIALIZE"))
|
|
299
|
-
node.members.push(
|
|
312
|
+
node.members.push(SERIALIZE_METHOD);
|
|
300
313
|
if (!node.members.find((v) => v.name.text == "__INITIALIZE"))
|
|
301
314
|
node.members.push(INITIALIZE_METHOD);
|
|
302
315
|
if (!node.members.find((v) => v.name.text == "__DESERIALIZE"))
|
|
303
316
|
node.members.push(DESERIALIZE_METHOD);
|
|
304
|
-
if (!node.members.find((v) => v.name.text == "
|
|
305
|
-
node.members.push(
|
|
306
|
-
|
|
317
|
+
if (!node.members.find((v) => v.name.text == "__ALLOCATE"))
|
|
318
|
+
node.members.push(ALLOCATE_METHOD);
|
|
319
|
+
super.visitClassDeclaration(node);
|
|
320
|
+
}
|
|
321
|
+
generateEmptyMethods(node) {
|
|
322
|
+
let SERIALIZE_RAW_EMPTY = '@inline __SERIALIZE(ptr: usize = changetype<usize>(this)): string {\n return "{}";\n}';
|
|
323
|
+
let SERIALIZE_BS_EMPTY = "@inline __SERIALIZE(ptr: usize: bool): void {\n store<u32>(bs.offset, 8192123);\n bs.offset += 4;\n}";
|
|
324
|
+
let INITIALIZE_EMPTY = "@inline __INITIALIZE(): this {\n return this;\n}";
|
|
325
|
+
let DESERIALIZE_EMPTY = "@inline __DESERIALIZE(keyStart: usize, keyEnd: usize, valStart: usize, valEnd: usize, ptr: usize): void {\n return false;\n}";
|
|
326
|
+
let ALLOCATE_EMPTY = "@inline __ALLOCATE(): void {\n bs.ensureSize(4);\n}";
|
|
327
|
+
if (process.env["JSON_DEBUG"]) {
|
|
328
|
+
console.log(SERIALIZE_RAW_EMPTY);
|
|
329
|
+
console.log(SERIALIZE_BS_EMPTY);
|
|
330
|
+
console.log(INITIALIZE_EMPTY);
|
|
331
|
+
console.log(DESERIALIZE_EMPTY);
|
|
332
|
+
console.log(ALLOCATE_EMPTY);
|
|
333
|
+
}
|
|
334
|
+
const SERIALIZE_RAW_METHOD_EMPTY = SimpleParser.parseClassMember(SERIALIZE_RAW_EMPTY, node);
|
|
335
|
+
const SERIALIZE_BS_METHOD_EMPTY = SimpleParser.parseClassMember(SERIALIZE_BS_EMPTY, node);
|
|
336
|
+
const INITIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(INITIALIZE_EMPTY, node);
|
|
337
|
+
const DESERIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(DESERIALIZE_EMPTY, node);
|
|
338
|
+
const ALLOCATE_METHOD_EMPTY = SimpleParser.parseClassMember(ALLOCATE_EMPTY, node);
|
|
339
|
+
if (!node.members.find((v) => v.name.text == "__SERIALIZE"))
|
|
340
|
+
node.members.push(SERIALIZE_RAW_METHOD_EMPTY);
|
|
341
|
+
if (!node.members.find((v) => v.name.text == "__SERIALIZE"))
|
|
342
|
+
node.members.push(SERIALIZE_BS_METHOD_EMPTY);
|
|
343
|
+
if (!node.members.find((v) => v.name.text == "__INITIALIZE"))
|
|
344
|
+
node.members.push(INITIALIZE_METHOD_EMPTY);
|
|
345
|
+
if (!node.members.find((v) => v.name.text == "__DESERIALIZE"))
|
|
346
|
+
node.members.push(DESERIALIZE_METHOD_EMPTY);
|
|
347
|
+
if (!node.members.find((v) => v.name.text == "__ALLOCATE"))
|
|
348
|
+
node.members.push(ALLOCATE_METHOD_EMPTY);
|
|
349
|
+
}
|
|
350
|
+
visitImportStatement(node) {
|
|
351
|
+
super.visitImportStatement(node);
|
|
352
|
+
const source = this.parser.sources.find((src) => src.internalPath == node.internalPath);
|
|
353
|
+
if (!source)
|
|
354
|
+
return;
|
|
355
|
+
if (source.statements.some((stmt) => stmt.kind === 59 && stmt.name.text === "JSON"))
|
|
356
|
+
this.imports.push(node);
|
|
307
357
|
}
|
|
308
358
|
visitSource(node) {
|
|
359
|
+
this.imports = [];
|
|
309
360
|
super.visitSource(node);
|
|
310
|
-
|
|
311
|
-
|
|
361
|
+
}
|
|
362
|
+
addRequiredImports(node) {
|
|
363
|
+
if (!this.imports.find((i) => i.declarations.find((d) => d.foreignName.text == "bs"))) {
|
|
364
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
365
|
+
const __dirname = path.dirname(__filename);
|
|
366
|
+
let relativePath = path.relative(path.dirname(node.range.source.normalizedPath), path.resolve(__dirname, "../../modules/bs/index.ts"));
|
|
367
|
+
if (!relativePath.startsWith(".") && !relativePath.startsWith("/"))
|
|
368
|
+
relativePath = "./" + relativePath;
|
|
369
|
+
const txt = `import { bs } from "${relativePath}";`;
|
|
370
|
+
if (!this.jsonImport) {
|
|
371
|
+
this.jsonImport = txt;
|
|
372
|
+
if (process.env["JSON_DEBUG"])
|
|
373
|
+
console.log("Added bs import: " + txt + "\n");
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
if (!this.imports.find((i) => i.declarations.find((d) => d.foreignName.text == "JSON"))) {
|
|
377
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
378
|
+
const __dirname = path.dirname(__filename);
|
|
379
|
+
let relativePath = path.relative(path.dirname(node.range.source.normalizedPath), path.resolve(__dirname, "../../assembly/index.ts"));
|
|
380
|
+
if (!relativePath.startsWith(".") && !relativePath.startsWith("/"))
|
|
381
|
+
relativePath = "./" + relativePath;
|
|
382
|
+
const txt = `import { JSON } from "${relativePath}";`;
|
|
383
|
+
if (!this.jsonImport) {
|
|
384
|
+
this.jsonImport = txt;
|
|
385
|
+
if (process.env["JSON_DEBUG"])
|
|
386
|
+
console.log("Added json-as import: " + txt + "\n");
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
getStores(data, simd = true) {
|
|
391
|
+
const out = [];
|
|
392
|
+
const sizes = strToNum(data, simd);
|
|
393
|
+
let offset = 0;
|
|
394
|
+
for (const [size, num] of sizes) {
|
|
395
|
+
if (size == "v128") {
|
|
396
|
+
let index = this.newStmts.simd.findIndex((v) => v.includes(num));
|
|
397
|
+
let name = "SIMD_" + (index == -1 ? this.newStmts.simd.length : index);
|
|
398
|
+
if (index && !this.newStmts.simd.includes(`const ${name} = ${num};`))
|
|
399
|
+
this.newStmts.simd.push(`const ${name} = ${num};`);
|
|
400
|
+
out.push("store<v128>(bs.offset, " + name + ", " + offset + "); // " + data.slice(offset >> 1, (offset >> 1) + 8));
|
|
401
|
+
offset += 16;
|
|
402
|
+
}
|
|
403
|
+
if (size == "u64") {
|
|
404
|
+
out.push("store<u64>(bs.offset, " + num + ", " + offset + "); // " + data.slice(offset >> 1, (offset >> 1) + 4));
|
|
405
|
+
offset += 8;
|
|
406
|
+
}
|
|
407
|
+
else if (size == "u32") {
|
|
408
|
+
out.push("store<u32>(bs.offset, " + num + ", " + offset + "); // " + data.slice(offset >> 1, (offset >> 1) + 2));
|
|
409
|
+
offset += 4;
|
|
410
|
+
}
|
|
411
|
+
else if (size == "u16") {
|
|
412
|
+
out.push("store<u16>(bs.offset, " + num + ", " + offset + "); // " + data.slice(offset >> 1, (offset >> 1) + 1));
|
|
413
|
+
offset += 2;
|
|
414
|
+
}
|
|
312
415
|
}
|
|
416
|
+
out.push("bs.offset += " + offset + ";");
|
|
417
|
+
return out;
|
|
313
418
|
}
|
|
314
419
|
}
|
|
315
420
|
export default class Transformer extends Transform {
|
|
316
421
|
afterParse(parser) {
|
|
317
422
|
const transformer = new JSONTransform();
|
|
318
|
-
const sources = parser.sources
|
|
319
|
-
.filter((source) => !isStdlib(source))
|
|
320
|
-
.sort((_a, _b) => {
|
|
423
|
+
const sources = parser.sources.sort((_a, _b) => {
|
|
321
424
|
const a = _a.internalPath;
|
|
322
425
|
const b = _b.internalPath;
|
|
323
|
-
if (a[0]
|
|
426
|
+
if (a[0] == "~" && b[0] !== "~") {
|
|
324
427
|
return -1;
|
|
325
428
|
}
|
|
326
|
-
else if (a[0] !== "~" && b[0]
|
|
429
|
+
else if (a[0] !== "~" && b[0] == "~") {
|
|
327
430
|
return 1;
|
|
328
431
|
}
|
|
329
432
|
else {
|
|
330
433
|
return 0;
|
|
331
434
|
}
|
|
332
435
|
});
|
|
436
|
+
transformer.parser = parser;
|
|
333
437
|
for (const source of sources) {
|
|
334
|
-
|
|
335
|
-
|
|
438
|
+
transformer.imports = [];
|
|
439
|
+
transformer.currentSource = source;
|
|
440
|
+
transformer.visit(source);
|
|
441
|
+
if (transformer.newStmts.simd) {
|
|
442
|
+
const tokenizer = new Tokenizer(new Source(0, source.normalizedPath, transformer.newStmts.simd.join("\n")));
|
|
443
|
+
parser.currentSource = tokenizer.source;
|
|
444
|
+
for (let i = 0; i < transformer.newStmts.simd.length; i++)
|
|
445
|
+
source.statements.unshift(parser.parseTopLevelStatement(tokenizer));
|
|
446
|
+
parser.currentSource = source;
|
|
447
|
+
transformer.newStmts.simd = [];
|
|
448
|
+
}
|
|
449
|
+
if (transformer.jsonImport) {
|
|
450
|
+
const tokenizer = new Tokenizer(new Source(0, source.normalizedPath, transformer.jsonImport));
|
|
451
|
+
parser.currentSource = tokenizer.source;
|
|
452
|
+
source.statements.unshift(parser.parseTopLevelStatement(tokenizer));
|
|
453
|
+
parser.currentSource = source;
|
|
454
|
+
transformer.jsonImport = null;
|
|
455
|
+
}
|
|
456
|
+
if (transformer.bsImport) {
|
|
457
|
+
const tokenizer = new Tokenizer(new Source(0, source.normalizedPath, transformer.bsImport));
|
|
458
|
+
parser.currentSource = tokenizer.source;
|
|
459
|
+
source.statements.unshift(parser.parseTopLevelStatement(tokenizer));
|
|
460
|
+
parser.currentSource = source;
|
|
461
|
+
transformer.bsImport = null;
|
|
336
462
|
}
|
|
337
463
|
}
|
|
338
|
-
const schemas = transformer.
|
|
464
|
+
const schemas = transformer.schemas;
|
|
339
465
|
for (const schema of schemas) {
|
|
340
466
|
if (schema.parent) {
|
|
341
|
-
const parent = schemas.find((v) => v.name
|
|
467
|
+
const parent = schemas.find((v) => v.name == schema.parent?.name);
|
|
342
468
|
if (!parent)
|
|
343
|
-
|
|
469
|
+
throwError(`Class ${schema.name} extends its parent class ${schema.parent}, but ${schema.parent} does not include a @json or @serializable decorator!`, schema.parent.node.range);
|
|
344
470
|
}
|
|
345
471
|
}
|
|
346
472
|
}
|
|
347
473
|
}
|
|
348
|
-
|
|
349
|
-
(
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
PropertyFlags[PropertyFlags["Alias"] = 4] = "Alias";
|
|
355
|
-
PropertyFlags[PropertyFlags["JSON_Raw"] = 5] = "JSON_Raw";
|
|
356
|
-
})(PropertyFlags || (PropertyFlags = {}));
|
|
357
|
-
class Property {
|
|
358
|
-
name = "";
|
|
359
|
-
alias = null;
|
|
360
|
-
type = "";
|
|
361
|
-
value = null;
|
|
362
|
-
flags = new Map();
|
|
363
|
-
serialize = null;
|
|
364
|
-
deserialize = null;
|
|
365
|
-
initialize = null;
|
|
366
|
-
node;
|
|
367
|
-
right_s = "";
|
|
368
|
-
right_d = "";
|
|
369
|
-
generate(safe) {
|
|
370
|
-
const name = this.name;
|
|
371
|
-
const escapedName = escapeString(JSON.stringify(this.alias || this.name));
|
|
372
|
-
const type = this.type;
|
|
373
|
-
if (this.flags.has(PropertyFlags.Omit))
|
|
374
|
-
return;
|
|
375
|
-
if (this.flags.has(PropertyFlags.JSON_Raw)) {
|
|
376
|
-
if (this.flags.has(PropertyFlags.Null)) {
|
|
377
|
-
this.right_s = "(this." + name + ' || "null")';
|
|
378
|
-
this.right_d = "value_start === value_end - 4 && 30399761348886638 === load<u64>(changetype<usize>(data) + (value_start << 1)) ? null : data.substring(value_start, value_end)";
|
|
379
|
-
}
|
|
380
|
-
else {
|
|
381
|
-
this.right_s = "this." + name;
|
|
382
|
-
this.right_d = "data.substring(value_start, value_end);";
|
|
383
|
-
}
|
|
474
|
+
function sortMembers(members) {
|
|
475
|
+
return members.sort((a, b) => {
|
|
476
|
+
const aMove = a.flags.has(PropertyFlags.OmitIf) || a.flags.has(PropertyFlags.OmitNull);
|
|
477
|
+
const bMove = b.flags.has(PropertyFlags.OmitIf) || b.flags.has(PropertyFlags.OmitNull);
|
|
478
|
+
if (aMove && !bMove) {
|
|
479
|
+
return -1;
|
|
384
480
|
}
|
|
385
|
-
else {
|
|
386
|
-
|
|
387
|
-
this.right_d = (safe ? "__DESERIALIZE_SAFE" : "__DESERIALIZE") + "<" + type + ">(data.substring(value_start, value_end))";
|
|
388
|
-
}
|
|
389
|
-
if (this.flags.has(PropertyFlags.OmitIf)) {
|
|
390
|
-
const condition = this.flags.get(PropertyFlags.OmitIf)[0];
|
|
391
|
-
if (!condition)
|
|
392
|
-
throw new Error("Could not find condition when using decorator @omitif! Provide at least one condition");
|
|
393
|
-
this.serialize = "${" + condition + ' ? "" : \'' + escapedName + ":' + " + this.right_s + ' + ","}';
|
|
394
|
-
this.deserialize = "this." + name + " = " + this.right_d + ";";
|
|
395
|
-
}
|
|
396
|
-
else if (this.flags.has(PropertyFlags.OmitNull)) {
|
|
397
|
-
this.serialize = "${changetype<usize>(this." + name + ") == <usize>0" + ' ? "" : \'' + escapedName + ":' + " + this.right_s + ' + ","}';
|
|
398
|
-
this.deserialize = "this." + name + " = " + this.right_d + ";";
|
|
481
|
+
else if (!aMove && bMove) {
|
|
482
|
+
return 1;
|
|
399
483
|
}
|
|
400
484
|
else {
|
|
401
|
-
|
|
402
|
-
this.deserialize = "this." + name + " = " + this.right_d + ";";
|
|
485
|
+
return 0;
|
|
403
486
|
}
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
class SchemaData {
|
|
407
|
-
name = "";
|
|
408
|
-
members = [];
|
|
409
|
-
parent = null;
|
|
410
|
-
node;
|
|
411
|
-
}
|
|
412
|
-
function charCodeAt32(data, offset) {
|
|
413
|
-
return (data.charCodeAt(offset + 1) << 16) | data.charCodeAt(offset);
|
|
414
|
-
}
|
|
415
|
-
function charCodeAt64(data, offset) {
|
|
416
|
-
if (offset + 3 >= data.length) {
|
|
417
|
-
throw new Error("The string must have at least 4 characters from the specified offset.");
|
|
418
|
-
}
|
|
419
|
-
const firstCharCode = BigInt(data.charCodeAt(offset));
|
|
420
|
-
const secondCharCode = BigInt(data.charCodeAt(offset + 1));
|
|
421
|
-
const thirdCharCode = BigInt(data.charCodeAt(offset + 2));
|
|
422
|
-
const fourthCharCode = BigInt(data.charCodeAt(offset + 3));
|
|
423
|
-
const u64Value = (fourthCharCode << 48n) | (thirdCharCode << 32n) | (secondCharCode << 16n) | firstCharCode;
|
|
424
|
-
return u64Value;
|
|
425
|
-
}
|
|
426
|
-
function encodeKey(key) {
|
|
427
|
-
const data = JSON.stringify(key);
|
|
428
|
-
return data.slice(1, data.length - 1);
|
|
429
|
-
}
|
|
430
|
-
function escapeString(data) {
|
|
431
|
-
return data.replace(/\\/g, "\\\\").replace(/\`/g, "\\`");
|
|
432
|
-
}
|
|
433
|
-
function escapeSlash(data) {
|
|
434
|
-
return data.replace(/\\/g, "\\\\").replace(/\`/g, "\\`");
|
|
435
|
-
}
|
|
436
|
-
function escapeQuote(data) {
|
|
437
|
-
return data.replace(/\"/g, '\\"');
|
|
487
|
+
});
|
|
438
488
|
}
|
|
439
489
|
function getArgs(args) {
|
|
440
490
|
if (!args)
|
|
@@ -465,4 +515,119 @@ function getArgs(args) {
|
|
|
465
515
|
}
|
|
466
516
|
return out;
|
|
467
517
|
}
|
|
518
|
+
function toU16(data, offset = 0) {
|
|
519
|
+
return data.charCodeAt(offset + 0).toString();
|
|
520
|
+
}
|
|
521
|
+
function toU32(data, offset = 0) {
|
|
522
|
+
return ((data.charCodeAt(offset + 1) << 16) | data.charCodeAt(offset + 0)).toString();
|
|
523
|
+
}
|
|
524
|
+
function toU48(data, offset = 0) {
|
|
525
|
+
return ((BigInt(data.charCodeAt(offset + 2)) << 32n) | (BigInt(data.charCodeAt(offset + 1)) << 16n) | BigInt(data.charCodeAt(offset + 0))).toString();
|
|
526
|
+
}
|
|
527
|
+
function toU64(data, offset = 0) {
|
|
528
|
+
return ((BigInt(data.charCodeAt(offset + 3)) << 48n) | (BigInt(data.charCodeAt(offset + 2)) << 32n) | (BigInt(data.charCodeAt(offset + 1)) << 16n) | BigInt(data.charCodeAt(offset + 0))).toString();
|
|
529
|
+
}
|
|
530
|
+
function toMemCDecl(n, indent) {
|
|
531
|
+
let out = "";
|
|
532
|
+
let offset = 0;
|
|
533
|
+
let index = 0;
|
|
534
|
+
while (n >= 8) {
|
|
535
|
+
out += `${indent}const code${index++} = load<u64>(keyStart, ${offset});\n`;
|
|
536
|
+
offset += 8;
|
|
537
|
+
n -= 8;
|
|
538
|
+
}
|
|
539
|
+
while (n >= 4) {
|
|
540
|
+
out += `${indent}const code${index++} = load<u32>(keyStart, ${offset});\n`;
|
|
541
|
+
offset += 4;
|
|
542
|
+
n -= 4;
|
|
543
|
+
}
|
|
544
|
+
if (n == 1)
|
|
545
|
+
out += `${indent}const code${index++} = load<u16>(keyStart, ${offset});\n`;
|
|
546
|
+
return out;
|
|
547
|
+
}
|
|
548
|
+
function toMemCCheck(data) {
|
|
549
|
+
let n = data.length << 1;
|
|
550
|
+
let out = "";
|
|
551
|
+
let offset = 0;
|
|
552
|
+
let index = 0;
|
|
553
|
+
while (n >= 8) {
|
|
554
|
+
out += ` && code${index++} == ${toU64(data, offset >> 1)}`;
|
|
555
|
+
offset += 8;
|
|
556
|
+
n -= 8;
|
|
557
|
+
}
|
|
558
|
+
while (n >= 4) {
|
|
559
|
+
out += ` && code${index++} == ${toU32(data, offset >> 1)}`;
|
|
560
|
+
offset += 4;
|
|
561
|
+
n -= 4;
|
|
562
|
+
}
|
|
563
|
+
if (n == 1)
|
|
564
|
+
out += ` && code${index++} == ${toU16(data, offset >> 1)}`;
|
|
565
|
+
return out.slice(4);
|
|
566
|
+
}
|
|
567
|
+
function strToNum(data, simd = false, offset = 0) {
|
|
568
|
+
const out = [];
|
|
569
|
+
let n = data.length;
|
|
570
|
+
while (n >= 8 && simd) {
|
|
571
|
+
out.push(["v128", "i16x8(" + data.charCodeAt(offset + 0) + ", " + data.charCodeAt(offset + 1) + ", " + data.charCodeAt(offset + 2) + ", " + data.charCodeAt(offset + 3) + ", " + data.charCodeAt(offset + 4) + ", " + data.charCodeAt(offset + 5) + ", " + data.charCodeAt(offset + 6) + ", " + data.charCodeAt(offset + 7) + ")"]);
|
|
572
|
+
offset += 8;
|
|
573
|
+
n -= 8;
|
|
574
|
+
}
|
|
575
|
+
while (n >= 4) {
|
|
576
|
+
const value = (BigInt(data.charCodeAt(offset + 3)) << 48n) | (BigInt(data.charCodeAt(offset + 2)) << 32n) | (BigInt(data.charCodeAt(offset + 1)) << 16n) | BigInt(data.charCodeAt(offset + 0));
|
|
577
|
+
out.push(["u64", value.toString()]);
|
|
578
|
+
offset += 4;
|
|
579
|
+
n -= 4;
|
|
580
|
+
}
|
|
581
|
+
while (n >= 2) {
|
|
582
|
+
const value = (data.charCodeAt(offset + 1) << 16) | data.charCodeAt(offset + 0);
|
|
583
|
+
out.push(["u32", value.toString()]);
|
|
584
|
+
offset += 2;
|
|
585
|
+
n -= 2;
|
|
586
|
+
}
|
|
587
|
+
if (n === 1) {
|
|
588
|
+
const value = data.charCodeAt(offset + 0);
|
|
589
|
+
out.push(["u16", value.toString()]);
|
|
590
|
+
}
|
|
591
|
+
return out;
|
|
592
|
+
}
|
|
593
|
+
function isPrimitive(type) {
|
|
594
|
+
const primitiveTypes = ["u8", "u16", "u32", "u64", "i8", "i16", "i32", "i64", "f32", "f64", "bool", "boolean"];
|
|
595
|
+
return primitiveTypes.some((v) => type.includes(v));
|
|
596
|
+
}
|
|
597
|
+
function throwError(message, range) {
|
|
598
|
+
const err = new Error();
|
|
599
|
+
err.stack = `${message}\n at ${range.source.normalizedPath}:${range.source.lineAt(range.start)}:${range.source.columnAt()}\n`;
|
|
600
|
+
throw err;
|
|
601
|
+
}
|
|
602
|
+
function indentInc() {
|
|
603
|
+
indent += " ";
|
|
604
|
+
}
|
|
605
|
+
function indentDec() {
|
|
606
|
+
indent = indent.slice(0, Math.max(0, indent.length - 2));
|
|
607
|
+
}
|
|
608
|
+
function sizeof(type) {
|
|
609
|
+
if (type == "u8")
|
|
610
|
+
return 6;
|
|
611
|
+
else if (type == "i8")
|
|
612
|
+
return 8;
|
|
613
|
+
else if (type == "u16")
|
|
614
|
+
return 10;
|
|
615
|
+
else if (type == "i16")
|
|
616
|
+
return 12;
|
|
617
|
+
else if (type == "u32")
|
|
618
|
+
return 20;
|
|
619
|
+
else if (type == "i32")
|
|
620
|
+
return 22;
|
|
621
|
+
else if (type == "u64")
|
|
622
|
+
return 40;
|
|
623
|
+
else if (type == "i64")
|
|
624
|
+
return 40;
|
|
625
|
+
else if (type == "bool" || type == "boolean")
|
|
626
|
+
return 10;
|
|
627
|
+
else
|
|
628
|
+
return 0;
|
|
629
|
+
}
|
|
630
|
+
function allPrimitive(schema) {
|
|
631
|
+
return !schema.members.some((p) => p.byteSize == 0);
|
|
632
|
+
}
|
|
468
633
|
//# sourceMappingURL=index.js.map
|