json-as 0.8.5 → 0.8.7
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 +7 -1
- package/CHANGELOG +6 -1
- package/README.md +26 -16
- package/assembly/__tests__/deserialize.spec.ts +298 -0
- package/assembly/__tests__/serialize.spec.ts +375 -0
- package/assembly/deserialize/array/array.ts +31 -0
- package/assembly/deserialize/array/bool.ts +19 -0
- package/assembly/deserialize/array/float.ts +24 -0
- package/assembly/deserialize/array/integer.ts +24 -0
- package/assembly/deserialize/array/map.ts +27 -0
- package/assembly/deserialize/array/object.ts +27 -0
- package/assembly/deserialize/array/string.ts +29 -0
- package/assembly/deserialize/array.ts +37 -0
- package/assembly/deserialize/bool.ts +18 -0
- package/assembly/deserialize/box.ts +17 -0
- package/assembly/deserialize/date.ts +11 -0
- package/assembly/deserialize/float.ts +9 -0
- package/assembly/deserialize/integer.ts +7 -0
- package/assembly/deserialize/map.ts +182 -0
- package/assembly/deserialize/object.ts +136 -0
- package/assembly/deserialize/string.ts +88 -0
- package/assembly/index.d.ts +7 -1
- package/assembly/index.ts +129 -1
- package/assembly/serialize/array.ts +52 -0
- package/assembly/serialize/bool.ts +4 -0
- package/assembly/serialize/box.ts +10 -0
- package/assembly/serialize/date.ts +4 -0
- package/assembly/serialize/float.ts +4 -0
- package/assembly/serialize/integer.ts +5 -0
- package/assembly/serialize/map.ts +24 -0
- package/assembly/serialize/object.ts +7 -0
- package/assembly/serialize/string.ts +64 -0
- package/assembly/src/sink.ts +286 -0
- package/assembly/src/util.ts +6 -0
- package/assembly/test.ts +34 -16
- package/bench/benchmark.ts +7 -3
- package/bench.js +14 -3
- package/index.ts +1 -1
- package/package.json +6 -8
- package/transform/lib/index.js +296 -198
- package/transform/lib/index.old.js +257 -0
- package/transform/lib/types.js +17 -0
- package/transform/package.json +1 -1
- package/transform/src/index.old.ts +312 -0
- package/transform/src/index.ts +298 -234
- package/transform/tsconfig.json +2 -2
- package/tsconfig.json +94 -102
- package/assembly/__benches__/as-json.ts +0 -88
- package/assembly/__benches__/as-tral.d.ts +0 -1
- package/assembly/__tests__/as-json.spec.ts +0 -671
- package/assembly/__tests__/as-pect.d.ts +0 -1
- package/assembly/src/json.ts +0 -941
package/transform/lib/index.js
CHANGED
|
@@ -1,20 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FieldDeclaration, } from "assemblyscript/dist/assemblyscript.js";
|
|
2
2
|
import { toString, isStdlib } from "visitor-as/dist/utils.js";
|
|
3
3
|
import { BaseVisitor, SimpleParser } from "visitor-as/dist/index.js";
|
|
4
4
|
import { Transform } from "assemblyscript/dist/transform.js";
|
|
5
|
-
class
|
|
6
|
-
constructor() {
|
|
7
|
-
this.keys = [];
|
|
8
|
-
this.values = [];
|
|
9
|
-
this.types = [];
|
|
10
|
-
this.name = "";
|
|
11
|
-
this.parent = "";
|
|
12
|
-
this.encodeStmts = [];
|
|
13
|
-
this.setDataStmts = [];
|
|
14
|
-
this.initializeStmts = [];
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
class AsJSONTransform extends BaseVisitor {
|
|
5
|
+
class JSONTransform extends BaseVisitor {
|
|
18
6
|
constructor() {
|
|
19
7
|
super(...arguments);
|
|
20
8
|
this.schemasList = [];
|
|
@@ -22,195 +10,265 @@ class AsJSONTransform extends BaseVisitor {
|
|
|
22
10
|
}
|
|
23
11
|
visitMethodDeclaration() { }
|
|
24
12
|
visitClassDeclaration(node) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
if (!
|
|
13
|
+
if (!node.decorators?.length)
|
|
14
|
+
return;
|
|
15
|
+
if (!node.members?.length)
|
|
28
16
|
return;
|
|
29
|
-
let
|
|
17
|
+
let found = false;
|
|
30
18
|
for (const decorator of node.decorators) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
foundDecorator = true;
|
|
19
|
+
const name = decorator.name.text;
|
|
20
|
+
if (name === "json" || name === "serializable") {
|
|
21
|
+
found = true;
|
|
22
|
+
break;
|
|
23
|
+
}
|
|
37
24
|
}
|
|
38
|
-
if (!
|
|
25
|
+
if (!found)
|
|
39
26
|
return;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
27
|
+
const schema = new SchemaData();
|
|
28
|
+
schema.node = node;
|
|
29
|
+
schema.name = node.name.text;
|
|
30
|
+
const members = [
|
|
31
|
+
...node.members
|
|
32
|
+
];
|
|
33
|
+
if (node.extendsType) {
|
|
34
|
+
schema.parent = this.schemasList.find((v) => v.name == node.extendsType?.name.identifier.text);
|
|
35
|
+
if (schema.parent?.members) {
|
|
36
|
+
for (let i = 0; i < schema.parent.members.length; i++) {
|
|
37
|
+
const replace = schema.members.find((v) => v.name == schema.parent?.members[i]?.name);
|
|
38
|
+
if (!replace)
|
|
39
|
+
schema.members.unshift(schema.parent.members[i]);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
44
42
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
if (
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
43
|
+
for (const member of members) {
|
|
44
|
+
if (!(member instanceof FieldDeclaration))
|
|
45
|
+
continue;
|
|
46
|
+
const name = member.name;
|
|
47
|
+
if (!member.type) {
|
|
48
|
+
throw new Error("Fields must be strongly typed! Found " + toString(member) + " at " + node.range.source.normalizedPath);
|
|
49
|
+
}
|
|
50
|
+
const type = toString(member.type);
|
|
51
|
+
const value = member.initializer ? toString(member.initializer) : null;
|
|
52
|
+
if (member.flags == 32 /* CommonFlags.Static */)
|
|
53
|
+
continue;
|
|
54
|
+
if (member.flags === 512 /* CommonFlags.Private */)
|
|
55
|
+
continue;
|
|
56
|
+
if (member.flags === 1024 /* CommonFlags.Protected */)
|
|
57
|
+
continue;
|
|
58
|
+
const mem = new Property();
|
|
59
|
+
mem.name = name.text;
|
|
60
|
+
mem.type = type;
|
|
61
|
+
mem.value = value;
|
|
62
|
+
mem.node = member;
|
|
63
|
+
for (const decorator of member.decorators || []) {
|
|
64
|
+
if (decorator.name.text == "alias") {
|
|
65
|
+
if (!decorator.args?.length)
|
|
66
|
+
throw new Error("Expected 1 argument but got zero at @alias in " + node.range.source.normalizedPath);
|
|
67
|
+
mem.flag = PropertyFlags.Alias;
|
|
68
|
+
mem.alias = decorator.args[0].value;
|
|
69
|
+
}
|
|
70
|
+
else if (decorator.name.text == "omit") {
|
|
71
|
+
mem.flag = PropertyFlags.Omit;
|
|
72
|
+
}
|
|
73
|
+
else if (decorator.name.text == "omitnull") {
|
|
74
|
+
mem.flag = PropertyFlags.OmitNull;
|
|
64
75
|
}
|
|
76
|
+
else if (decorator.name.text == "omitif") {
|
|
77
|
+
if (!decorator.args?.length)
|
|
78
|
+
throw new Error("Expected 1 argument but got zero at @omitif in " + node.range.source.normalizedPath);
|
|
79
|
+
mem.args?.push(decorator.args[0].value);
|
|
80
|
+
mem.flag = PropertyFlags.OmitIf;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (mem.flag === PropertyFlags.Alias) {
|
|
84
|
+
mem.name = mem.alias;
|
|
85
|
+
}
|
|
86
|
+
else if (mem.flag === PropertyFlags.None) {
|
|
87
|
+
mem.serialize = escapeString(JSON.stringify(mem.name)) + ":${__SERIALIZE<" + type + ">(this." + name.text + ")}";
|
|
88
|
+
mem.deserialize = "this." + name.text + " = " + "__DESERIALIZE<" + type + ">(data.substring(value_start, value_end));";
|
|
65
89
|
}
|
|
90
|
+
if (mem.flag == PropertyFlags.OmitNull) {
|
|
91
|
+
mem.serialize = "${changetype<usize>(this." + mem.name + ") == <usize>0" + " ? \"\" : '" + escapeString(JSON.stringify(mem.name)) + ":' + __SERIALIZE<" + type + ">(this." + name.text + ") + \",\"}";
|
|
92
|
+
mem.deserialize = "this." + name.text + " = " + "__DESERIALIZE<" + type + ">(data.substring(value_start, value_end));";
|
|
93
|
+
}
|
|
94
|
+
else if (mem.flag == PropertyFlags.OmitIf) {
|
|
95
|
+
mem.serialize = "${" + mem.args[0] + " ? \"\" : '" + escapeString(JSON.stringify(mem.name)) + ":' + __SERIALIZE<" + type + ">(this." + name.text + ")}";
|
|
96
|
+
mem.deserialize = "this." + name.text + " = " + "__DESERIALIZE<" + type + ">(data.substring(value_start, value_end));";
|
|
97
|
+
}
|
|
98
|
+
else if (mem.flag == PropertyFlags.Alias) {
|
|
99
|
+
mem.serialize = escapeString(JSON.stringify(mem.name)) + ":${__SERIALIZE<" + type + ">(this." + name.text + ")}";
|
|
100
|
+
mem.deserialize = "this." + name.text + " = " + "__DESERIALIZE<" + type + ">(data.substring(value_start, value_end));";
|
|
101
|
+
mem.name = name.text;
|
|
102
|
+
}
|
|
103
|
+
const t = mem.node.type.name.identifier.text;
|
|
104
|
+
if (this.schemasList.find(v => v.name == t)) {
|
|
105
|
+
mem.initialize = "this." + name.text + " = changetype<nonnull<" + t + ">>(__new(offsetof<nonnull<" + t + ">>(), idof<nonnull<" + t + ">>()));\n changetype<nonnull<" + t + ">>(this." + name.text + ").__INITIALIZE()";
|
|
106
|
+
}
|
|
107
|
+
else if (mem.value) {
|
|
108
|
+
mem.initialize = "this." + name.text + " = " + mem.value;
|
|
109
|
+
}
|
|
110
|
+
schema.members.push(mem);
|
|
66
111
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
112
|
+
let SERIALIZE_RAW = "@inline __SERIALIZE(): string {\n let out = `{";
|
|
113
|
+
let SERIALIZE_PRETTY = "@inline __SERIALIZE_PRETTY(): string {\n let out = `{";
|
|
114
|
+
let INITIALIZE = "@inline __INITIALIZE(): this {\n";
|
|
115
|
+
let DESERIALIZE = "@inline __DESERIALIZE(data: string, key_start: i32, key_end: i32, value_start: i32, value_end: i32): boolean {\n const len = key_end - key_start;\n";
|
|
116
|
+
let indent = " ";
|
|
117
|
+
if (!schema.members.length)
|
|
118
|
+
return;
|
|
119
|
+
found = false;
|
|
120
|
+
if (schema.members[0]?.flag === PropertyFlags.OmitNull
|
|
121
|
+
|| schema.members[0]?.flag === PropertyFlags.OmitIf) {
|
|
122
|
+
SERIALIZE_RAW += schema.members[0]?.serialize;
|
|
123
|
+
SERIALIZE_PRETTY += "\\n" + schema.members[0]?.serialize;
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
SERIALIZE_RAW += schema.members[0]?.serialize + ",";
|
|
127
|
+
SERIALIZE_PRETTY += "\\n" + schema.members[0]?.serialize + ",\\n";
|
|
128
|
+
found = true;
|
|
129
|
+
}
|
|
130
|
+
if (schema.members[0]?.initialize)
|
|
131
|
+
INITIALIZE += " " + schema.members[0]?.initialize + ";\n";
|
|
132
|
+
for (let i = 1; i < schema.members.length; i++) {
|
|
133
|
+
const member = schema.members[i];
|
|
134
|
+
if (member.initialize)
|
|
135
|
+
INITIALIZE += " " + member.initialize + ";\n";
|
|
136
|
+
if (member.flag === PropertyFlags.OmitNull
|
|
137
|
+
|| member.flag === PropertyFlags.OmitIf) {
|
|
138
|
+
SERIALIZE_RAW += member.serialize;
|
|
139
|
+
SERIALIZE_PRETTY += member.serialize;
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
SERIALIZE_RAW += member.serialize + ",";
|
|
143
|
+
SERIALIZE_PRETTY += indent + member.serialize + ",\\n";
|
|
144
|
+
found = true;
|
|
75
145
|
}
|
|
76
146
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
147
|
+
if (found) {
|
|
148
|
+
SERIALIZE_RAW += "`;\n store<u16>(changetype<usize>(out) + ((out.length - 1) << 1), 125);\n return out;\n}";
|
|
149
|
+
SERIALIZE_PRETTY += "`;\n store<u32>(changetype<usize>(out) + ((out.length - 2) << 1), 8192010);\n return out;\n}";
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
SERIALIZE_RAW += "`;\n};";
|
|
153
|
+
SERIALIZE_PRETTY += "`;\n};";
|
|
154
|
+
}
|
|
155
|
+
INITIALIZE += " return this;\n}";
|
|
156
|
+
const sortedMembers = [];
|
|
157
|
+
const _sorted = schema.members.sort((a, b) => a.name.length - b.name.length);
|
|
158
|
+
let len = 0;
|
|
159
|
+
let offset = 0;
|
|
160
|
+
sortedMembers.push([_sorted[0]]);
|
|
161
|
+
len = _sorted[0]?.name.length;
|
|
162
|
+
for (let i = 1; i < _sorted.length; i++) {
|
|
163
|
+
const member = _sorted[i];
|
|
164
|
+
if (member.alias?.length || member.name.length > len) {
|
|
165
|
+
sortedMembers.push([member]);
|
|
166
|
+
len = member.alias?.length || member.name.length;
|
|
167
|
+
offset++;
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
sortedMembers[offset].push(member);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
let first = true;
|
|
174
|
+
for (const memberSet of sortedMembers) {
|
|
175
|
+
const firstMember = memberSet[0];
|
|
176
|
+
const name = encodeKey(firstMember.alias || firstMember.name);
|
|
177
|
+
if (name.length === 1) {
|
|
178
|
+
if (first) {
|
|
179
|
+
DESERIALIZE += " if (1 === len) {\n switch (load<u16>(changetype<usize>(data) + (key_start << 1))) {\n";
|
|
180
|
+
first = false;
|
|
98
181
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
this.currentClass.types.push(type);
|
|
102
|
-
// @ts-ignore
|
|
103
|
-
if ([
|
|
104
|
-
"u8",
|
|
105
|
-
"i8",
|
|
106
|
-
"u16",
|
|
107
|
-
"i16",
|
|
108
|
-
"u32",
|
|
109
|
-
"i32",
|
|
110
|
-
"u64",
|
|
111
|
-
"i64",
|
|
112
|
-
].includes(type.toLowerCase())) {
|
|
113
|
-
if (omitif) {
|
|
114
|
-
this.currentClass.encodeStmts.push(`\${${omitif} ? "" : \`,${encodeKey(aliasName)}:\${this.${name}}\`}`);
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
this.currentClass.encodeStmts.push(`,${encodeKey(aliasName)}:\${this.${name}}`);
|
|
118
|
-
}
|
|
119
|
-
// @ts-ignore
|
|
120
|
-
this.currentClass.setDataStmts.push(`if (key.equals(${JSON.stringify(aliasName)})) {
|
|
121
|
-
this.${name} = __atoi_fast<${type}>(data, val_start << 1, val_end << 1);
|
|
122
|
-
return;
|
|
123
|
-
}`);
|
|
124
|
-
if (member.initializer) {
|
|
125
|
-
this.currentClass.initializeStmts.push(`this.${name} = ${toString(member.initializer)}`);
|
|
126
|
-
}
|
|
182
|
+
else {
|
|
183
|
+
DESERIALIZE += "else if (1 === len) {\n switch (load<u16>(changetype<usize>(data) + (key_start << 1))) {\n";
|
|
127
184
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
185
|
+
}
|
|
186
|
+
else if (name.length === 2) {
|
|
187
|
+
if (first) {
|
|
188
|
+
DESERIALIZE += " if (2 === len) {\n switch (load<u32>(changetype<usize>(data) + (key_start << 1))) {\n";
|
|
189
|
+
first = false;
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
DESERIALIZE += "else if (2 === len) {\n switch (load<u32>(changetype<usize>(data) + (key_start << 1))) {\n";
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
else if (name.length === 4) {
|
|
196
|
+
if (first) {
|
|
197
|
+
DESERIALIZE += " if (4 === len) {\n const code = load<u64>(changetype<usize>(data) + (key_start << 1));\n";
|
|
198
|
+
first = false;
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
DESERIALIZE += "else if (4 === len) {\n const code = load<u64>(changetype<usize>(data) + (key_start << 1));\n";
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
if (first) {
|
|
206
|
+
DESERIALIZE += " if (" + name.length + " === len) {\n";
|
|
207
|
+
first = false;
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
DESERIALIZE += "else if (" + name.length + " === len) {\n";
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
let f = true;
|
|
214
|
+
for (let i = 0; i < memberSet.length; i++) {
|
|
215
|
+
const member = memberSet[i];
|
|
216
|
+
const name = encodeKey(member.alias || member.name);
|
|
217
|
+
if (name.length === 1) {
|
|
218
|
+
DESERIALIZE += ` case ${name.charCodeAt(0)}: {\n ${member.deserialize}\n return true;\n }\n`;
|
|
219
|
+
}
|
|
220
|
+
else if (name.length === 2) {
|
|
221
|
+
DESERIALIZE += ` case ${charCodeAt32(name, 0)}: {\n ${member.deserialize}\n return true;\n }\n`;
|
|
222
|
+
}
|
|
223
|
+
else if (name.length === 4) {
|
|
224
|
+
if (f) {
|
|
225
|
+
f = false;
|
|
226
|
+
DESERIALIZE += ` if (${charCodeAt64(name, 0)} === code) {\n ${member.deserialize}\n return true;\n }\n`;
|
|
134
227
|
}
|
|
135
228
|
else {
|
|
136
|
-
|
|
137
|
-
}
|
|
138
|
-
// @ts-ignore
|
|
139
|
-
this.currentClass.setDataStmts.push(`if (key.equals(${JSON.stringify(aliasName)})) {
|
|
140
|
-
this.${name} = __parseObjectValue<${type}>(data.slice(val_start, val_end), initializeDefaultValues);
|
|
141
|
-
return;
|
|
142
|
-
}`);
|
|
143
|
-
if (member.initializer) {
|
|
144
|
-
this.currentClass.initializeStmts.push(`this.${name} = ${toString(member.initializer)}`);
|
|
229
|
+
DESERIALIZE = DESERIALIZE.slice(0, DESERIALIZE.length - 1) + `else if (${charCodeAt64(name, 0)} === code) {\n ${member.deserialize}\n return true;\n }\n`;
|
|
145
230
|
}
|
|
146
231
|
}
|
|
147
232
|
else {
|
|
148
|
-
if (
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
}
|
|
152
|
-
else if (omitif) {
|
|
153
|
-
this.currentClass.encodeStmts.push(`\${${omitif} ? "" : \`${encodeKey(aliasName)}:,\${__JSON_Stringify<${type}>(this.${name})}\`}`);
|
|
233
|
+
if (f) {
|
|
234
|
+
f = false;
|
|
235
|
+
DESERIALIZE += ` if (0 == memory.compare(changetype<usize>("${escapeQuote(escapeSlash(name))}"), changetype<usize>(data) + (key_start << 1), ${name.length << 1})) {\n ${member.deserialize}\n return true;\n }\n`;
|
|
154
236
|
}
|
|
155
237
|
else {
|
|
156
|
-
|
|
157
|
-
}
|
|
158
|
-
// @ts-ignore
|
|
159
|
-
this.currentClass.setDataStmts.push(`if (key.equals(${JSON.stringify(aliasName)})) {
|
|
160
|
-
this.${name} = __parseObjectValue<${type}>(val_start ? data.slice(val_start, val_end) : data, initializeDefaultValues);
|
|
161
|
-
return;
|
|
162
|
-
}`);
|
|
163
|
-
if (member.initializer) {
|
|
164
|
-
this.currentClass.initializeStmts.push(`this.${name} = ${toString(member.initializer)}`);
|
|
238
|
+
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})) {\n ${member.deserialize}\n return true;\n }\n`;
|
|
165
239
|
}
|
|
166
240
|
}
|
|
167
241
|
}
|
|
242
|
+
if (name.length < 3) {
|
|
243
|
+
DESERIALIZE += ` default: {\n return false;\n }\n }\n`;
|
|
244
|
+
}
|
|
245
|
+
else if (name.length == 4) {
|
|
246
|
+
DESERIALIZE = DESERIALIZE.slice(0, DESERIALIZE.length - 1) + ` else {\n return false;\n }\n`;
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
DESERIALIZE = DESERIALIZE.slice(0, DESERIALIZE.length - 1) + ` else {\n return false;\n }\n`;
|
|
250
|
+
}
|
|
251
|
+
DESERIALIZE += " } ";
|
|
168
252
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
}`;
|
|
177
|
-
}
|
|
178
|
-
else {
|
|
179
|
-
serializeFunc = `
|
|
180
|
-
__JSON_Serialize(): string {
|
|
181
|
-
return "{}";
|
|
182
|
-
}`;
|
|
183
|
-
}
|
|
184
|
-
const setKeyFunc = `
|
|
185
|
-
__JSON_Set_Key(key: __Virtual<string>, data: string, val_start: i32, val_end: i32, initializeDefaultValues: boolean): void {
|
|
186
|
-
${this.currentClass.setDataStmts.join("\n ")}
|
|
187
|
-
}
|
|
188
|
-
`;
|
|
189
|
-
let initializeFunc = "";
|
|
190
|
-
if (this.currentClass.initializeStmts.length > 0) {
|
|
191
|
-
initializeFunc = `
|
|
192
|
-
__JSON_Initialize(): void {
|
|
193
|
-
${this.currentClass.initializeStmts.join(";\n")};
|
|
194
|
-
}
|
|
195
|
-
`;
|
|
196
|
-
}
|
|
197
|
-
else {
|
|
198
|
-
initializeFunc = `
|
|
199
|
-
__JSON_Initialize(): void {}
|
|
200
|
-
`;
|
|
253
|
+
DESERIALIZE += "\n return false;\n}";
|
|
254
|
+
//console.log(sortedMembers);
|
|
255
|
+
if (process.env["JSON_DEBUG"]) {
|
|
256
|
+
console.log(SERIALIZE_RAW);
|
|
257
|
+
//console.log(SERIALIZE_PRETTY);
|
|
258
|
+
console.log(INITIALIZE);
|
|
259
|
+
console.log(DESERIALIZE);
|
|
201
260
|
}
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
//console.log(initializeFunc);
|
|
261
|
+
const SERIALIZE_RAW_METHOD = SimpleParser.parseClassMember(SERIALIZE_RAW, node);
|
|
262
|
+
//const SERIALIZE_PRETTY_METHOD = SimpleParser.parseClassMember(SERIALIZE_PRETTY, node);
|
|
263
|
+
const INITIALIZE_METHOD = SimpleParser.parseClassMember(INITIALIZE, node);
|
|
264
|
+
const DESERIALIZE_METHOD = SimpleParser.parseClassMember(DESERIALIZE, node);
|
|
265
|
+
if (!node.members.find(v => v.name.text == "__SERIALIZE"))
|
|
266
|
+
node.members.push(SERIALIZE_RAW_METHOD);
|
|
267
|
+
if (!node.members.find(v => v.name.text == "__INITIALIZE"))
|
|
268
|
+
node.members.push(INITIALIZE_METHOD);
|
|
269
|
+
if (!node.members.find(v => v.name.text == "__DESERIALIZE"))
|
|
270
|
+
node.members.push(DESERIALIZE_METHOD);
|
|
271
|
+
this.schemasList.push(schema);
|
|
214
272
|
}
|
|
215
273
|
visitSource(node) {
|
|
216
274
|
super.visitSource(node);
|
|
@@ -218,30 +276,13 @@ class AsJSONTransform extends BaseVisitor {
|
|
|
218
276
|
if (!this.sources.has(node)) {
|
|
219
277
|
return;
|
|
220
278
|
}
|
|
221
|
-
// Note, the following one liner would be easier, but it fails with an assertion error
|
|
222
|
-
// because as-virtual's SimpleParser doesn't set the parser.currentSource correctly.
|
|
223
|
-
//
|
|
224
|
-
// const stmt = SimpleParser.parseTopLevelStatement('import { Virtual as __Virtual } from "as-virtual/assembly";');
|
|
225
|
-
// ... So we have to do it the long way:
|
|
226
|
-
const txt = 'import { Virtual as __Virtual } from "as-virtual/assembly";';
|
|
227
|
-
const tokenizer = new Tokenizer(new Source(0 /* SourceKind.User */, node.normalizedPath, txt));
|
|
228
|
-
const parser = new Parser();
|
|
229
|
-
parser.currentSource = tokenizer.source;
|
|
230
|
-
const stmt = parser.parseTopLevelStatement(tokenizer);
|
|
231
|
-
// Add the import statement to the top of the source.
|
|
232
|
-
node.statements.unshift(stmt);
|
|
233
279
|
}
|
|
234
280
|
}
|
|
235
|
-
function encodeKey(aliasName) {
|
|
236
|
-
return JSON.stringify(aliasName)
|
|
237
|
-
.replace(/\\/g, "\\\\")
|
|
238
|
-
.replace(/\`/g, '\\`');
|
|
239
|
-
}
|
|
240
281
|
export default class Transformer extends Transform {
|
|
241
282
|
// Trigger the transform after parse.
|
|
242
283
|
afterParse(parser) {
|
|
243
284
|
// Create new transform
|
|
244
|
-
const transformer = new
|
|
285
|
+
const transformer = new JSONTransform();
|
|
245
286
|
// Sort the sources so that user scripts are visited last
|
|
246
287
|
const sources = parser.sources
|
|
247
288
|
.filter((source) => !isStdlib(source))
|
|
@@ -269,10 +310,67 @@ export default class Transformer extends Transform {
|
|
|
269
310
|
const schemas = transformer.schemasList;
|
|
270
311
|
for (const schema of schemas) {
|
|
271
312
|
if (schema.parent) {
|
|
272
|
-
const parent = schemas.find((v) => v.name === schema.parent);
|
|
313
|
+
const parent = schemas.find((v) => v.name === schema.parent?.name);
|
|
273
314
|
if (!parent)
|
|
274
315
|
throw new Error(`Class ${schema.name} extends its parent class ${schema.parent}, but ${schema.parent} does not include a @json or @serializable decorator! Add the decorator and rebuild.`);
|
|
275
316
|
}
|
|
276
317
|
}
|
|
277
318
|
}
|
|
278
319
|
}
|
|
320
|
+
var PropertyFlags;
|
|
321
|
+
(function (PropertyFlags) {
|
|
322
|
+
PropertyFlags[PropertyFlags["None"] = 0] = "None";
|
|
323
|
+
PropertyFlags[PropertyFlags["Omit"] = 1] = "Omit";
|
|
324
|
+
PropertyFlags[PropertyFlags["OmitNull"] = 2] = "OmitNull";
|
|
325
|
+
PropertyFlags[PropertyFlags["OmitIf"] = 3] = "OmitIf";
|
|
326
|
+
PropertyFlags[PropertyFlags["Alias"] = 4] = "Alias";
|
|
327
|
+
})(PropertyFlags || (PropertyFlags = {}));
|
|
328
|
+
class Property {
|
|
329
|
+
constructor() {
|
|
330
|
+
this.name = "";
|
|
331
|
+
this.alias = null;
|
|
332
|
+
this.type = "";
|
|
333
|
+
this.value = null;
|
|
334
|
+
this.flag = PropertyFlags.None;
|
|
335
|
+
this.args = [];
|
|
336
|
+
this.serialize = null;
|
|
337
|
+
this.deserialize = null;
|
|
338
|
+
this.initialize = null;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
class SchemaData {
|
|
342
|
+
constructor() {
|
|
343
|
+
this.name = "";
|
|
344
|
+
this.members = [];
|
|
345
|
+
this.parent = null;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
function charCodeAt32(data, offset) {
|
|
349
|
+
return (data.charCodeAt(offset + 1) << 16) | data.charCodeAt(offset);
|
|
350
|
+
}
|
|
351
|
+
function charCodeAt64(data, offset) {
|
|
352
|
+
if (offset + 3 >= data.length) {
|
|
353
|
+
throw new Error("The string must have at least 4 characters from the specified offset.");
|
|
354
|
+
}
|
|
355
|
+
const firstCharCode = BigInt(data.charCodeAt(offset));
|
|
356
|
+
const secondCharCode = BigInt(data.charCodeAt(offset + 1));
|
|
357
|
+
const thirdCharCode = BigInt(data.charCodeAt(offset + 2));
|
|
358
|
+
const fourthCharCode = BigInt(data.charCodeAt(offset + 3));
|
|
359
|
+
const u64Value = (fourthCharCode << 48n) | (thirdCharCode << 32n) | (secondCharCode << 16n) | firstCharCode;
|
|
360
|
+
return u64Value;
|
|
361
|
+
}
|
|
362
|
+
function encodeKey(key) {
|
|
363
|
+
const data = JSON.stringify(key);
|
|
364
|
+
return data.slice(1, data.length - 1);
|
|
365
|
+
}
|
|
366
|
+
function escapeString(data) {
|
|
367
|
+
return data.replace(/\\/g, "\\\\")
|
|
368
|
+
.replace(/\`/g, '\\`');
|
|
369
|
+
}
|
|
370
|
+
function escapeSlash(data) {
|
|
371
|
+
return data.replace(/\\/g, "\\\\")
|
|
372
|
+
.replace(/\`/g, '\\`');
|
|
373
|
+
}
|
|
374
|
+
function escapeQuote(data) {
|
|
375
|
+
return data.replace(/\"/g, "\\\"");
|
|
376
|
+
}
|