json-as 0.9.23 → 0.9.24
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 +1 -0
- package/README.md +1 -1
- package/assembly/__benches__/string.bench.ts +0 -5
- package/assembly/deserialize/string.ts +0 -1
- package/assembly/serialize/bool.ts +0 -12
- package/assembly/serialize/string.ts +0 -11
- package/package.json +2 -1
- package/transform/lib/index.js +151 -160
- package/transform/package.json +1 -1
- package/transform/src/index.ts +229 -188
package/CHANGELOG
CHANGED
|
@@ -30,6 +30,7 @@ v0.9.19 - Fix arguments in @omitif declarations not working properly
|
|
|
30
30
|
v0.9.20 - Strings were being received with quotes attached via the toString functionality. Removed that.
|
|
31
31
|
v0.9.22 - Fix #89 and #93. Several bug fixes some severe such as ",null" being prepended when using @omit. Properly warn when a schema has fields that are not compatible with json
|
|
32
32
|
v0.9.23 - Comment out SIMD-related code for now
|
|
33
|
+
v9.9.24 - Remove transform changes from previous release
|
|
33
34
|
|
|
34
35
|
[UNRELEASED] v1.0.0
|
|
35
36
|
- Allow nullable primitives
|
package/README.md
CHANGED
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
import { bs } from "../custom/bs";
|
|
2
|
-
import { serializeBool, serializeBool_BS } from "../serialize/bool";
|
|
3
|
-
import { serialize_simd_v1, serializeString, serializeString_BS } from "../serialize/string";
|
|
4
|
-
|
|
5
|
-
const out = memory.data(65536);
|
|
6
1
|
|
|
7
2
|
bench("UTF-16 to UTF-8", () => {
|
|
8
3
|
blackbox<ArrayBuffer>(String.UTF8.encode(blackbox<string>("hello world")));
|
|
@@ -4,19 +4,7 @@
|
|
|
4
4
|
* @returns string
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { bs } from "../custom/bs";
|
|
8
|
-
|
|
9
7
|
// @ts-ignore: Decorator valid here
|
|
10
8
|
@inline export function serializeBool(data: bool): string {
|
|
11
9
|
return data ? "true" : "false";
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
@inline export function serializeBool_BS(data: bool): void {
|
|
15
|
-
if (data === true) {
|
|
16
|
-
bs.write_64(28429475166421108); /* true */
|
|
17
|
-
} else {
|
|
18
|
-
//bs.write_128_n(i16x8(102, 97, 108, 115, 101, 0, 0, 0), 10);
|
|
19
|
-
bs.write_64(32370086184550502); /* fals */
|
|
20
|
-
bs.write_16(101); /* e */
|
|
21
|
-
}
|
|
22
10
|
}
|
|
@@ -1,14 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
BACK_SLASH,
|
|
3
|
-
BACKSPACE,
|
|
4
|
-
CARRIAGE_RETURN,
|
|
5
|
-
FORM_FEED,
|
|
6
|
-
NEW_LINE,
|
|
7
|
-
QUOTE,
|
|
8
|
-
TAB
|
|
9
|
-
} from "../custom/chars";
|
|
10
|
-
import { OBJECT, TOTAL_OVERHEAD } from "rt/common";
|
|
11
|
-
import { bs } from "../custom/bs";
|
|
12
1
|
import { _intTo16, intTo16, unsafeCharCodeAt } from "../custom/util";
|
|
13
2
|
import { Sink } from "../custom/sink";
|
|
14
3
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "json-as",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.24",
|
|
4
4
|
"description": "The only JSON library you'll need for AssemblyScript. SIMD enabled",
|
|
5
5
|
"types": "assembly/index.ts",
|
|
6
6
|
"author": "Jairus Tanaka",
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
"visitor-as": "^0.11.4"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
+
"@hypermode/modus-sdk-as": "^0.13.0-prerelease-test-1",
|
|
47
48
|
"as-virtual": "^0.2.0",
|
|
48
49
|
"chalk": "^5.3.0"
|
|
49
50
|
},
|
package/transform/lib/index.js
CHANGED
|
@@ -1,76 +1,74 @@
|
|
|
1
|
-
import { FieldDeclaration, IdentifierExpression, StringLiteralExpression, IntegerLiteralExpression, FloatLiteralExpression, NullExpression, TrueExpression, FalseExpression,
|
|
1
|
+
import { FieldDeclaration, IdentifierExpression, StringLiteralExpression, IntegerLiteralExpression, FloatLiteralExpression, NullExpression, TrueExpression, FalseExpression, } 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
|
-
import chalk from "chalk";
|
|
6
|
-
const json_types = ["Array", "string", "String", "u8", "i8", "u16", "i16", "u32", "i32", "u64", "i64", "f32", "f64", "bool", "boolean", "Map", "Date"];
|
|
7
5
|
class JSONTransform extends BaseVisitor {
|
|
8
|
-
types = json_types;
|
|
9
6
|
schemasList = [];
|
|
10
7
|
currentClass;
|
|
11
8
|
sources = new Set();
|
|
12
|
-
|
|
13
|
-
if (node.extendsType) {
|
|
14
|
-
if (schema.parent?.members) {
|
|
15
|
-
for (let i = schema.parent.members.length - 1; i >= 0; i--) {
|
|
16
|
-
const replace = schema.members.find((v) => v.name == schema.parent?.members[i]?.name);
|
|
17
|
-
if (!replace) {
|
|
18
|
-
members.unshift(schema.parent?.members[i].node);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
this.appendParentFields(schema.parent.node, schema, members);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
handleEmptyClass(node, schema, members) {
|
|
26
|
-
let SERIALIZE_RAW_EMPTY = '__SERIALIZE(): string {\n return "{}";\n}';
|
|
27
|
-
let SERIALIZE_PRETTY_EMPTY = '__SERIALIZE_PRETTY(): string {\n return "{}";\n}';
|
|
28
|
-
let INITIALIZE_EMPTY = "__INITIALIZE(): this {\n return this;\n}";
|
|
29
|
-
let DESERIALIZE_EMPTY = "__DESERIALIZE(data: string, key_start: i32, key_end: i32, value_start: i32, value_end: i32): boolean {\n return false;\n}";
|
|
30
|
-
if (process.env["JSON_DEBUG"]) {
|
|
31
|
-
console.log(SERIALIZE_RAW_EMPTY);
|
|
32
|
-
console.log(SERIALIZE_PRETTY_EMPTY);
|
|
33
|
-
console.log(INITIALIZE_EMPTY);
|
|
34
|
-
console.log(DESERIALIZE_EMPTY);
|
|
35
|
-
}
|
|
36
|
-
const SERIALIZE_RAW_METHOD_EMPTY = SimpleParser.parseClassMember(SERIALIZE_RAW_EMPTY, node);
|
|
37
|
-
const SERIALIZE_PRETTY_METHOD_EMPTY = SimpleParser.parseClassMember(SERIALIZE_PRETTY_EMPTY, node);
|
|
38
|
-
const INITIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(INITIALIZE_EMPTY, node);
|
|
39
|
-
const DESERIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(DESERIALIZE_EMPTY, node);
|
|
40
|
-
if (!node.members.find((v) => v.name.text == "__SERIALIZE"))
|
|
41
|
-
node.members.push(SERIALIZE_RAW_METHOD_EMPTY);
|
|
42
|
-
if (!node.members.find((v) => v.name.text == "__SERIALIZE_PRETTY"))
|
|
43
|
-
node.members.push(SERIALIZE_PRETTY_METHOD_EMPTY);
|
|
44
|
-
if (!node.members.find((v) => v.name.text == "__INITIALIZE"))
|
|
45
|
-
node.members.push(INITIALIZE_METHOD_EMPTY);
|
|
46
|
-
if (!node.members.find((v) => v.name.text == "__DESERIALIZE"))
|
|
47
|
-
node.members.push(DESERIALIZE_METHOD_EMPTY);
|
|
48
|
-
}
|
|
49
|
-
filterMembers(members) {
|
|
50
|
-
return members.filter((v) => v instanceof FieldDeclaration && !v.decorators?.find((v) => v.name.text == "omit"));
|
|
51
|
-
}
|
|
9
|
+
visitMethodDeclaration() { }
|
|
52
10
|
visitClassDeclaration(node) {
|
|
53
11
|
if (!node.decorators?.length)
|
|
54
12
|
return;
|
|
55
|
-
|
|
13
|
+
let found = false;
|
|
14
|
+
for (const decorator of node.decorators) {
|
|
15
|
+
const name = decorator.name.text;
|
|
16
|
+
if (name === "json" || name === "serializable") {
|
|
17
|
+
found = true;
|
|
18
|
+
break;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (!found)
|
|
56
22
|
return;
|
|
57
|
-
this.types = json_types;
|
|
58
23
|
const schema = new SchemaData();
|
|
59
24
|
schema.node = node;
|
|
60
25
|
schema.name = node.name.text;
|
|
26
|
+
const members = [
|
|
27
|
+
...node.members.filter((v) => v.kind === 54 /* NodeKind.FieldDeclaration */),
|
|
28
|
+
];
|
|
61
29
|
if (node.extendsType) {
|
|
62
30
|
schema.parent = this.schemasList.find((v) => v.name == node.extendsType?.name.identifier.text);
|
|
31
|
+
if (schema.parent?.members) {
|
|
32
|
+
for (let i = schema.parent.members.length - 1; i >= 0; i--) {
|
|
33
|
+
const replace = schema.members.find((v) => v.name == schema.parent?.members[i]?.name);
|
|
34
|
+
if (!replace) {
|
|
35
|
+
members.unshift(schema.parent?.members[i].node);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
63
39
|
}
|
|
64
|
-
const _members = [...node.members];
|
|
65
|
-
this.appendParentFields(node, schema, _members);
|
|
66
|
-
const members = this.filterMembers(_members);
|
|
67
40
|
if (!members.length) {
|
|
68
|
-
|
|
41
|
+
let SERIALIZE_RAW_EMPTY = '__SERIALIZE(): string {\n return "{}";\n}';
|
|
42
|
+
//let SERIALIZE_PRETTY_EMPTY = "__SERIALIZE_PRETTY(): string {\n return \"{}\";\n}";
|
|
43
|
+
let INITIALIZE_EMPTY = "__INITIALIZE(): this {\n return this;\n}";
|
|
44
|
+
let DESERIALIZE_EMPTY = "__DESERIALIZE(data: string, key_start: i32, key_end: i32, value_start: i32, value_end: i32): boolean {\n return false;\n}";
|
|
45
|
+
if (process.env["JSON_DEBUG"]) {
|
|
46
|
+
console.log(SERIALIZE_RAW_EMPTY);
|
|
47
|
+
//console.log(SERIALIZE_PRETTY_EMPTY);
|
|
48
|
+
console.log(INITIALIZE_EMPTY);
|
|
49
|
+
console.log(DESERIALIZE_EMPTY);
|
|
50
|
+
}
|
|
51
|
+
const SERIALIZE_RAW_METHOD_EMPTY = SimpleParser.parseClassMember(SERIALIZE_RAW_EMPTY, node);
|
|
52
|
+
//const SERIALIZE_PRETTY_METHOD = SimpleParser.parseClassMember(SERIALIZE_PRETTY, node);
|
|
53
|
+
const INITIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(INITIALIZE_EMPTY, node);
|
|
54
|
+
const DESERIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(DESERIALIZE_EMPTY, node);
|
|
55
|
+
if (!node.members.find((v) => v.name.text == "__SERIALIZE"))
|
|
56
|
+
node.members.push(SERIALIZE_RAW_METHOD_EMPTY);
|
|
57
|
+
if (!node.members.find((v) => v.name.text == "__INITIALIZE"))
|
|
58
|
+
node.members.push(INITIALIZE_METHOD_EMPTY);
|
|
59
|
+
if (!node.members.find((v) => v.name.text == "__DESERIALIZE"))
|
|
60
|
+
node.members.push(DESERIALIZE_METHOD_EMPTY);
|
|
61
|
+
this.schemasList.push(schema);
|
|
69
62
|
}
|
|
70
63
|
for (const member of members) {
|
|
71
64
|
const name = member.name;
|
|
65
|
+
if (!(member instanceof FieldDeclaration))
|
|
66
|
+
continue;
|
|
72
67
|
if (!member.type) {
|
|
73
|
-
throw new Error("Fields must be strongly typed! Found " +
|
|
68
|
+
throw new Error("Fields must be strongly typed! Found " +
|
|
69
|
+
toString(member) +
|
|
70
|
+
" at " +
|
|
71
|
+
node.range.source.normalizedPath);
|
|
74
72
|
}
|
|
75
73
|
const type = toString(member.type);
|
|
76
74
|
if (type.startsWith("(") && type.includes("=>"))
|
|
@@ -100,7 +98,8 @@ class JSONTransform extends BaseVisitor {
|
|
|
100
98
|
switch (decoratorName) {
|
|
101
99
|
case "alias": {
|
|
102
100
|
if (!args.length)
|
|
103
|
-
throw new Error("Expected 1 argument but got zero at @alias in " +
|
|
101
|
+
throw new Error("Expected 1 argument but got zero at @alias in " +
|
|
102
|
+
node.range.source.normalizedPath);
|
|
104
103
|
mem.alias = args[0];
|
|
105
104
|
mem.flags.set(PropertyFlags.Alias, args);
|
|
106
105
|
break;
|
|
@@ -111,7 +110,8 @@ class JSONTransform extends BaseVisitor {
|
|
|
111
110
|
}
|
|
112
111
|
case "omitif": {
|
|
113
112
|
if (!decorator.args?.length)
|
|
114
|
-
throw new Error("Expected 1 argument but got zero at @omitif in " +
|
|
113
|
+
throw new Error("Expected 1 argument but got zero at @omitif in " +
|
|
114
|
+
node.range.source.normalizedPath);
|
|
115
115
|
mem.flags.set(PropertyFlags.OmitIf, args);
|
|
116
116
|
break;
|
|
117
117
|
}
|
|
@@ -122,10 +122,22 @@ class JSONTransform extends BaseVisitor {
|
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
|
-
|
|
126
|
-
mem.generate();
|
|
125
|
+
mem.generate();
|
|
127
126
|
if (this.schemasList.find((v) => v.name == type)) {
|
|
128
|
-
mem.initialize =
|
|
127
|
+
mem.initialize =
|
|
128
|
+
"this." +
|
|
129
|
+
name.text +
|
|
130
|
+
" = changetype<nonnull<" +
|
|
131
|
+
mem.type +
|
|
132
|
+
">>(__new(offsetof<nonnull<" +
|
|
133
|
+
mem.type +
|
|
134
|
+
">>(), idof<nonnull<" +
|
|
135
|
+
mem.type +
|
|
136
|
+
">>()));\n changetype<nonnull<" +
|
|
137
|
+
mem.type +
|
|
138
|
+
">>(this." +
|
|
139
|
+
name.text +
|
|
140
|
+
").__INITIALIZE()";
|
|
129
141
|
}
|
|
130
142
|
else if (mem.value) {
|
|
131
143
|
mem.initialize = "this." + name.text + " = " + mem.value;
|
|
@@ -137,7 +149,8 @@ class JSONTransform extends BaseVisitor {
|
|
|
137
149
|
mem.initialize = "this." + name.text + ' = ""';
|
|
138
150
|
}
|
|
139
151
|
else if (type === "Array") {
|
|
140
|
-
mem.initialize =
|
|
152
|
+
mem.initialize =
|
|
153
|
+
"this." + name.text + " = instantiate<" + mem.type + ">()";
|
|
141
154
|
}
|
|
142
155
|
else if (type === "bool" || type === "boolean") {
|
|
143
156
|
mem.initialize = "this." + name.text + " = false";
|
|
@@ -145,7 +158,14 @@ class JSONTransform extends BaseVisitor {
|
|
|
145
158
|
else if (type === "JSON.Raw") {
|
|
146
159
|
mem.initialize = "this." + name.text + ' = ""';
|
|
147
160
|
}
|
|
148
|
-
else if (type === "u8" ||
|
|
161
|
+
else if (type === "u8" ||
|
|
162
|
+
type === "u16" ||
|
|
163
|
+
type === "u32" ||
|
|
164
|
+
type === "u64" ||
|
|
165
|
+
type === "i8" ||
|
|
166
|
+
type === "i16" ||
|
|
167
|
+
type === "i32" ||
|
|
168
|
+
type === "i64") {
|
|
149
169
|
mem.initialize = "this." + name.text + " = 0";
|
|
150
170
|
}
|
|
151
171
|
else if (type === "f32" || type === "f64") {
|
|
@@ -160,14 +180,15 @@ class JSONTransform extends BaseVisitor {
|
|
|
160
180
|
let indent = " ";
|
|
161
181
|
if (!schema.members.length)
|
|
162
182
|
return;
|
|
163
|
-
|
|
164
|
-
if (schema.members[0]?.flags.has(PropertyFlags.OmitNull) ||
|
|
183
|
+
found = false;
|
|
184
|
+
if (schema.members[0]?.flags.has(PropertyFlags.OmitNull) ||
|
|
185
|
+
schema.members[0]?.flags.has(PropertyFlags.OmitIf)) {
|
|
165
186
|
SERIALIZE_RAW += schema.members[0]?.serialize;
|
|
166
|
-
SERIALIZE_PRETTY += "\\n" +
|
|
187
|
+
SERIALIZE_PRETTY += "\\n" + schema.members[0]?.serialize;
|
|
167
188
|
}
|
|
168
189
|
else {
|
|
169
190
|
SERIALIZE_RAW += schema.members[0]?.serialize + ",";
|
|
170
|
-
SERIALIZE_PRETTY += "\\n" +
|
|
191
|
+
SERIALIZE_PRETTY += "\\n" + schema.members[0]?.serialize + ",\\n";
|
|
171
192
|
found = true;
|
|
172
193
|
}
|
|
173
194
|
if (schema.members[0]?.initialize)
|
|
@@ -176,21 +197,22 @@ class JSONTransform extends BaseVisitor {
|
|
|
176
197
|
const member = schema.members[i];
|
|
177
198
|
if (member.initialize)
|
|
178
199
|
INITIALIZE += " " + member.initialize + ";\n";
|
|
179
|
-
if (member.flags.has(PropertyFlags.
|
|
180
|
-
|
|
181
|
-
if (member.flags.has(PropertyFlags.OmitNull) || member.flags.has(PropertyFlags.OmitIf)) {
|
|
200
|
+
if (member.flags.has(PropertyFlags.OmitNull) ||
|
|
201
|
+
member.flags.has(PropertyFlags.OmitIf)) {
|
|
182
202
|
SERIALIZE_RAW += member.serialize;
|
|
183
|
-
SERIALIZE_PRETTY += member.
|
|
203
|
+
SERIALIZE_PRETTY += member.serialize;
|
|
184
204
|
}
|
|
185
205
|
else {
|
|
186
206
|
SERIALIZE_RAW += member.serialize + ",";
|
|
187
|
-
SERIALIZE_PRETTY += indent + member.
|
|
207
|
+
SERIALIZE_PRETTY += indent + member.serialize + ",\\n";
|
|
188
208
|
found = true;
|
|
189
209
|
}
|
|
190
210
|
}
|
|
191
211
|
if (found) {
|
|
192
|
-
SERIALIZE_RAW +=
|
|
193
|
-
|
|
212
|
+
SERIALIZE_RAW +=
|
|
213
|
+
"`;\n store<u16>(changetype<usize>(out) + ((out.length - 1) << 1), 125);\n return out;\n}";
|
|
214
|
+
SERIALIZE_PRETTY +=
|
|
215
|
+
"`;\n store<u32>(changetype<usize>(out) + ((out.length - 2) << 1), 8192010);\n return out;\n}";
|
|
194
216
|
}
|
|
195
217
|
else {
|
|
196
218
|
SERIALIZE_RAW += "}`;\n return out;\n}";
|
|
@@ -219,29 +241,35 @@ class JSONTransform extends BaseVisitor {
|
|
|
219
241
|
const _name = encodeKey(firstMember.alias || firstMember.name);
|
|
220
242
|
if (_name.length === 1) {
|
|
221
243
|
if (first) {
|
|
222
|
-
DESERIALIZE +=
|
|
244
|
+
DESERIALIZE +=
|
|
245
|
+
" if (1 === len) {\n switch (load<u16>(changetype<usize>(data) + (key_start << 1))) {\n";
|
|
223
246
|
first = false;
|
|
224
247
|
}
|
|
225
248
|
else {
|
|
226
|
-
DESERIALIZE +=
|
|
249
|
+
DESERIALIZE +=
|
|
250
|
+
"else if (1 === len) {\n switch (load<u16>(changetype<usize>(data) + (key_start << 1))) {\n";
|
|
227
251
|
}
|
|
228
252
|
}
|
|
229
253
|
else if (_name.length === 2) {
|
|
230
254
|
if (first) {
|
|
231
|
-
DESERIALIZE +=
|
|
255
|
+
DESERIALIZE +=
|
|
256
|
+
" if (2 === len) {\n switch (load<u32>(changetype<usize>(data) + (key_start << 1))) {\n";
|
|
232
257
|
first = false;
|
|
233
258
|
}
|
|
234
259
|
else {
|
|
235
|
-
DESERIALIZE +=
|
|
260
|
+
DESERIALIZE +=
|
|
261
|
+
"else if (2 === len) {\n switch (load<u32>(changetype<usize>(data) + (key_start << 1))) {\n";
|
|
236
262
|
}
|
|
237
263
|
}
|
|
238
264
|
else if (_name.length === 4) {
|
|
239
265
|
if (first) {
|
|
240
|
-
DESERIALIZE +=
|
|
266
|
+
DESERIALIZE +=
|
|
267
|
+
" if (4 === len) {\n const code = load<u64>(changetype<usize>(data) + (key_start << 1));\n";
|
|
241
268
|
first = false;
|
|
242
269
|
}
|
|
243
270
|
else {
|
|
244
|
-
DESERIALIZE +=
|
|
271
|
+
DESERIALIZE +=
|
|
272
|
+
"else if (4 === len) {\n const code = load<u64>(changetype<usize>(data) + (key_start << 1));\n";
|
|
245
273
|
}
|
|
246
274
|
}
|
|
247
275
|
else {
|
|
@@ -271,7 +299,9 @@ class JSONTransform extends BaseVisitor {
|
|
|
271
299
|
DESERIALIZE += ` if (${charCodeAt64(_name, 0)} === code) { /* ${_name} */\n ${member.deserialize}\n return true;\n }\n`;
|
|
272
300
|
}
|
|
273
301
|
else {
|
|
274
|
-
DESERIALIZE =
|
|
302
|
+
DESERIALIZE =
|
|
303
|
+
DESERIALIZE.slice(0, DESERIALIZE.length - 1) +
|
|
304
|
+
`else if (${charCodeAt64(_name, 0)} === code) {\n ${member.deserialize}\n return true;\n }\n`;
|
|
275
305
|
}
|
|
276
306
|
}
|
|
277
307
|
else {
|
|
@@ -280,7 +310,9 @@ class JSONTransform extends BaseVisitor {
|
|
|
280
310
|
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`;
|
|
281
311
|
}
|
|
282
312
|
else {
|
|
283
|
-
DESERIALIZE =
|
|
313
|
+
DESERIALIZE =
|
|
314
|
+
DESERIALIZE.slice(0, DESERIALIZE.length - 1) +
|
|
315
|
+
` 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`;
|
|
284
316
|
}
|
|
285
317
|
}
|
|
286
318
|
}
|
|
@@ -288,10 +320,14 @@ class JSONTransform extends BaseVisitor {
|
|
|
288
320
|
DESERIALIZE += ` default: {\n return false;\n }\n }\n`;
|
|
289
321
|
}
|
|
290
322
|
else if (_name.length == 4) {
|
|
291
|
-
DESERIALIZE =
|
|
323
|
+
DESERIALIZE =
|
|
324
|
+
DESERIALIZE.slice(0, DESERIALIZE.length - 1) +
|
|
325
|
+
` else {\n return false;\n }\n`;
|
|
292
326
|
}
|
|
293
327
|
else {
|
|
294
|
-
DESERIALIZE =
|
|
328
|
+
DESERIALIZE =
|
|
329
|
+
DESERIALIZE.slice(0, DESERIALIZE.length - 1) +
|
|
330
|
+
` else {\n return false;\n }\n`;
|
|
295
331
|
}
|
|
296
332
|
DESERIALIZE += " } ";
|
|
297
333
|
}
|
|
@@ -299,18 +335,16 @@ class JSONTransform extends BaseVisitor {
|
|
|
299
335
|
//console.log(sortedMembers);
|
|
300
336
|
if (process.env["JSON_DEBUG"]) {
|
|
301
337
|
console.log(SERIALIZE_RAW);
|
|
302
|
-
console.log(SERIALIZE_PRETTY);
|
|
338
|
+
//console.log(SERIALIZE_PRETTY);
|
|
303
339
|
console.log(INITIALIZE);
|
|
304
340
|
console.log(DESERIALIZE);
|
|
305
341
|
}
|
|
306
342
|
const SERIALIZE_RAW_METHOD = SimpleParser.parseClassMember(SERIALIZE_RAW, node);
|
|
307
|
-
const SERIALIZE_PRETTY_METHOD = SimpleParser.parseClassMember(SERIALIZE_PRETTY, node);
|
|
343
|
+
//const SERIALIZE_PRETTY_METHOD = SimpleParser.parseClassMember(SERIALIZE_PRETTY, node);
|
|
308
344
|
const INITIALIZE_METHOD = SimpleParser.parseClassMember(INITIALIZE, node);
|
|
309
345
|
const DESERIALIZE_METHOD = SimpleParser.parseClassMember(DESERIALIZE, node);
|
|
310
346
|
if (!node.members.find((v) => v.name.text == "__SERIALIZE"))
|
|
311
347
|
node.members.push(SERIALIZE_RAW_METHOD);
|
|
312
|
-
if (!node.members.find((v) => v.name.text == "__SERIALIZE_PRETTY"))
|
|
313
|
-
node.members.push(SERIALIZE_PRETTY_METHOD);
|
|
314
348
|
if (!node.members.find((v) => v.name.text == "__INITIALIZE"))
|
|
315
349
|
node.members.push(INITIALIZE_METHOD);
|
|
316
350
|
if (!node.members.find((v) => v.name.text == "__DESERIALIZE"))
|
|
@@ -336,13 +370,15 @@ export default class Transformer extends Transform {
|
|
|
336
370
|
.sort((_a, _b) => {
|
|
337
371
|
const a = _a.internalPath;
|
|
338
372
|
const b = _b.internalPath;
|
|
339
|
-
if (a[0] !== "~" && b[0] === "~") {
|
|
340
|
-
return 1;
|
|
341
|
-
}
|
|
342
373
|
if (a[0] === "~" && b[0] !== "~") {
|
|
343
374
|
return -1;
|
|
344
375
|
}
|
|
345
|
-
|
|
376
|
+
else if (a[0] !== "~" && b[0] === "~") {
|
|
377
|
+
return 1;
|
|
378
|
+
}
|
|
379
|
+
else {
|
|
380
|
+
return 0;
|
|
381
|
+
}
|
|
346
382
|
});
|
|
347
383
|
// Loop over every source
|
|
348
384
|
for (const source of sources) {
|
|
@@ -354,70 +390,14 @@ export default class Transformer extends Transform {
|
|
|
354
390
|
// Check that every parent and child class is hooked up correctly
|
|
355
391
|
const schemas = transformer.schemasList;
|
|
356
392
|
for (const schema of schemas) {
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
393
|
+
if (schema.parent) {
|
|
394
|
+
const parent = schemas.find((v) => v.name === schema.parent?.name);
|
|
395
|
+
if (!parent)
|
|
396
|
+
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.`);
|
|
361
397
|
}
|
|
362
398
|
}
|
|
363
399
|
}
|
|
364
400
|
}
|
|
365
|
-
function checkInheritance(schema, schemas) {
|
|
366
|
-
if (!schema.parent && schema.node.extendsType) {
|
|
367
|
-
if (schemas.find(v => v.node.name.text === schema.node.extendsType?.name.identifier.text))
|
|
368
|
-
return;
|
|
369
|
-
const extending = toString(schema.node.extendsType);
|
|
370
|
-
logError(`Schema ${schema.name} extends ${extending}, but ${extending} does not include the @json decorator!`);
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
function checkTypeCorrectness(schema, schemas) {
|
|
374
|
-
const parent = schemas.find((v) => v.name === schema.parent?.name);
|
|
375
|
-
const generic_types = [...(schema?.node.typeParameters?.map((v) => v.name.text) || []), ...(parent?.node.typeParameters?.map((v) => v.name.text) || [])];
|
|
376
|
-
const member_types = [...(schema.members.map((v) => v.node.type.name.identifier.text) || [])];
|
|
377
|
-
const scopeTypes = new Set([...json_types, ...generic_types, ...member_types]);
|
|
378
|
-
for (const typ of member_types) {
|
|
379
|
-
if (typ === "JSON")
|
|
380
|
-
continue; // JSON.Raw, JSON.Box, JSON.Any, ect...
|
|
381
|
-
if (json_types.includes(typ))
|
|
382
|
-
continue;
|
|
383
|
-
if (generic_types.includes(typ))
|
|
384
|
-
continue;
|
|
385
|
-
const check = schemas.find((v) => v.name == typ);
|
|
386
|
-
if (!check)
|
|
387
|
-
logError(`Type ${typ} is not a JSON compatible type or does not include the @json flag!`);
|
|
388
|
-
}
|
|
389
|
-
for (const member of schema.members) {
|
|
390
|
-
const invalidType = checkType(schema, schemas, member.node.type, member, scopeTypes, schema.name);
|
|
391
|
-
if (invalidType)
|
|
392
|
-
logError(`Type ${invalidType.type} in ${invalidType.path} does not implement a JSON compatible type!\n${chalk.dim(` at ${member.node.range.source.normalizedPath.replace("~lib/", "./node_modules/")}`)}`);
|
|
393
|
-
}
|
|
394
|
-
return null;
|
|
395
|
-
}
|
|
396
|
-
function checkType(schema, schemas, typ, member, scopeTypes, path) {
|
|
397
|
-
path += "." + member.name;
|
|
398
|
-
if (schemas.find(v => v.node.name.text === typ.name.identifier.text))
|
|
399
|
-
scopeTypes.add(typ.name.identifier.text);
|
|
400
|
-
if (!scopeTypes.has(typ.name.identifier.text))
|
|
401
|
-
return { type: toString(typ), path };
|
|
402
|
-
if (typ.isNullable && isPrimitive(typ))
|
|
403
|
-
return { type: toString(typ), path };
|
|
404
|
-
if (typ.typeArguments?.length && typ.typeArguments?.length > 0) {
|
|
405
|
-
for (const ty of typ.typeArguments.filter((v) => v instanceof NamedTypeNode)) {
|
|
406
|
-
const check = checkType(schema, schemas, ty, member, scopeTypes, path);
|
|
407
|
-
if (check)
|
|
408
|
-
return { type: toString(typ), path };
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
else {
|
|
412
|
-
if (scopeTypes.has(typ.name.identifier.text))
|
|
413
|
-
return null;
|
|
414
|
-
}
|
|
415
|
-
return null;
|
|
416
|
-
}
|
|
417
|
-
function logError(message) {
|
|
418
|
-
console.log("\n" + chalk.bold.bgRed(" Error ") + chalk.dim(":") + " " + message + "\n");
|
|
419
|
-
process.exit(1);
|
|
420
|
-
}
|
|
421
401
|
var PropertyFlags;
|
|
422
402
|
(function (PropertyFlags) {
|
|
423
403
|
PropertyFlags[PropertyFlags["Null"] = 0] = "Null";
|
|
@@ -434,7 +414,6 @@ class Property {
|
|
|
434
414
|
value = null;
|
|
435
415
|
flags = new Map();
|
|
436
416
|
serialize = null;
|
|
437
|
-
serialize_pretty = null;
|
|
438
417
|
deserialize = null;
|
|
439
418
|
initialize = null;
|
|
440
419
|
node;
|
|
@@ -448,7 +427,7 @@ class Property {
|
|
|
448
427
|
return;
|
|
449
428
|
if (this.flags.has(PropertyFlags.JSON_Raw)) {
|
|
450
429
|
if (this.flags.has(PropertyFlags.Null)) {
|
|
451
|
-
this.right_s = "(this." + name +
|
|
430
|
+
this.right_s = "(this." + name + " || \"null\")";
|
|
452
431
|
this.right_d = "value_start === value_end - 4 && 30399761348886638 === load<u64>(changetype<usize>(data) + (value_start << 1)) ? null : data.substring(value_start, value_end)";
|
|
453
432
|
}
|
|
454
433
|
else {
|
|
@@ -458,24 +437,37 @@ class Property {
|
|
|
458
437
|
}
|
|
459
438
|
else {
|
|
460
439
|
this.right_s = "__SERIALIZE<" + type + ">(this." + name + ")";
|
|
461
|
-
this.right_d =
|
|
440
|
+
this.right_d =
|
|
441
|
+
"__DESERIALIZE<" + type + ">(data.substring(value_start, value_end))";
|
|
462
442
|
}
|
|
463
443
|
if (this.flags.has(PropertyFlags.OmitIf)) {
|
|
464
444
|
const condition = this.flags.get(PropertyFlags.OmitIf)[0];
|
|
465
445
|
if (!condition)
|
|
466
446
|
throw new Error("Could not find condition when using decorator @omitif! Provide at least one condition");
|
|
467
|
-
this.serialize =
|
|
468
|
-
|
|
447
|
+
this.serialize =
|
|
448
|
+
"${" +
|
|
449
|
+
condition +
|
|
450
|
+
' ? "" : \'' +
|
|
451
|
+
escapedName +
|
|
452
|
+
":' + " +
|
|
453
|
+
this.right_s +
|
|
454
|
+
' + ","}';
|
|
469
455
|
this.deserialize = "this." + name + " = " + this.right_d + ";";
|
|
470
456
|
}
|
|
471
457
|
else if (this.flags.has(PropertyFlags.OmitNull)) {
|
|
472
|
-
this.serialize =
|
|
473
|
-
|
|
458
|
+
this.serialize =
|
|
459
|
+
"${changetype<usize>(this." +
|
|
460
|
+
name +
|
|
461
|
+
") == <usize>0" +
|
|
462
|
+
' ? "" : \'' +
|
|
463
|
+
escapedName +
|
|
464
|
+
":' + " +
|
|
465
|
+
this.right_s +
|
|
466
|
+
' + ","}';
|
|
474
467
|
this.deserialize = "this." + name + " = " + this.right_d + ";";
|
|
475
468
|
}
|
|
476
469
|
else {
|
|
477
470
|
this.serialize = escapedName + ":${" + this.right_s + "}";
|
|
478
|
-
this.serialize_pretty = escapedName + ": ${" + this.right_s + "}";
|
|
479
471
|
this.deserialize = "this." + name + " = " + this.right_d + ";";
|
|
480
472
|
}
|
|
481
473
|
}
|
|
@@ -497,7 +489,10 @@ function charCodeAt64(data, offset) {
|
|
|
497
489
|
const secondCharCode = BigInt(data.charCodeAt(offset + 1));
|
|
498
490
|
const thirdCharCode = BigInt(data.charCodeAt(offset + 2));
|
|
499
491
|
const fourthCharCode = BigInt(data.charCodeAt(offset + 3));
|
|
500
|
-
const u64Value = (fourthCharCode << 48n) |
|
|
492
|
+
const u64Value = (fourthCharCode << 48n) |
|
|
493
|
+
(thirdCharCode << 32n) |
|
|
494
|
+
(secondCharCode << 16n) |
|
|
495
|
+
firstCharCode;
|
|
501
496
|
return u64Value;
|
|
502
497
|
}
|
|
503
498
|
function encodeKey(key) {
|
|
@@ -542,7 +537,3 @@ function getArgs(args) {
|
|
|
542
537
|
}
|
|
543
538
|
return out;
|
|
544
539
|
}
|
|
545
|
-
function isPrimitive(type) {
|
|
546
|
-
const primitives = new Set(["u8", "i8", "u16", "i16", "u32", "i32", "u64", "i64", "f32", "f64", "bool", "boolean"]);
|
|
547
|
-
return primitives.has(type.name.identifier.text);
|
|
548
|
-
}
|
package/transform/package.json
CHANGED
package/transform/src/index.ts
CHANGED
|
@@ -1,89 +1,119 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
ClassDeclaration,
|
|
3
|
+
FieldDeclaration,
|
|
4
|
+
IdentifierExpression,
|
|
5
|
+
Parser,
|
|
6
|
+
Source,
|
|
7
|
+
NodeKind,
|
|
8
|
+
Expression,
|
|
9
|
+
CommonFlags,
|
|
10
|
+
StringLiteralExpression,
|
|
11
|
+
IntegerLiteralExpression,
|
|
12
|
+
FloatLiteralExpression,
|
|
13
|
+
NullExpression,
|
|
14
|
+
TrueExpression,
|
|
15
|
+
FalseExpression,
|
|
16
|
+
} from "assemblyscript/dist/assemblyscript.js";
|
|
2
17
|
|
|
3
18
|
import { toString, isStdlib } from "visitor-as/dist/utils.js";
|
|
4
19
|
import { BaseVisitor, SimpleParser } from "visitor-as/dist/index.js";
|
|
5
20
|
import { Transform } from "assemblyscript/dist/transform.js";
|
|
6
|
-
import chalk from "chalk";
|
|
7
|
-
|
|
8
|
-
const json_types = ["Array", "string", "String", "u8", "i8", "u16", "i16", "u32", "i32", "u64", "i64", "f32", "f64", "bool", "boolean", "Map", "Date"];
|
|
9
21
|
|
|
10
22
|
class JSONTransform extends BaseVisitor {
|
|
11
|
-
public types = json_types;
|
|
12
23
|
public schemasList: SchemaData[] = [];
|
|
13
24
|
public currentClass!: SchemaData;
|
|
14
25
|
public sources = new Set<Source>();
|
|
15
26
|
|
|
16
|
-
|
|
27
|
+
visitMethodDeclaration(): void { }
|
|
28
|
+
visitClassDeclaration(node: ClassDeclaration): void {
|
|
29
|
+
if (!node.decorators?.length) return;
|
|
30
|
+
|
|
31
|
+
let found = false;
|
|
32
|
+
for (const decorator of node.decorators) {
|
|
33
|
+
const name = (<IdentifierExpression>decorator.name).text;
|
|
34
|
+
if (name === "json" || name === "serializable") {
|
|
35
|
+
found = true;
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (!found) return;
|
|
40
|
+
|
|
41
|
+
const schema = new SchemaData();
|
|
42
|
+
schema.node = node;
|
|
43
|
+
schema.name = node.name.text;
|
|
44
|
+
|
|
45
|
+
const members = [
|
|
46
|
+
...node.members.filter((v) => v.kind === NodeKind.FieldDeclaration),
|
|
47
|
+
];
|
|
48
|
+
|
|
17
49
|
if (node.extendsType) {
|
|
50
|
+
schema.parent = this.schemasList.find(
|
|
51
|
+
(v) => v.name == node.extendsType?.name.identifier.text,
|
|
52
|
+
) as SchemaData | null;
|
|
53
|
+
|
|
18
54
|
if (schema.parent?.members) {
|
|
19
55
|
for (let i = schema.parent.members.length - 1; i >= 0; i--) {
|
|
20
|
-
const replace = schema.members.find(
|
|
56
|
+
const replace = schema.members.find(
|
|
57
|
+
(v) => v.name == schema.parent?.members[i]?.name,
|
|
58
|
+
);
|
|
21
59
|
if (!replace) {
|
|
22
60
|
members.unshift(schema.parent?.members[i]!.node);
|
|
23
61
|
}
|
|
24
62
|
}
|
|
25
|
-
this.appendParentFields(schema.parent.node, schema, members);
|
|
26
63
|
}
|
|
27
64
|
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
handleEmptyClass(node: ClassDeclaration, schema: SchemaData, members: DeclarationStatement[]): void {
|
|
31
|
-
let SERIALIZE_RAW_EMPTY = '__SERIALIZE(): string {\n return "{}";\n}';
|
|
32
|
-
let SERIALIZE_PRETTY_EMPTY = '__SERIALIZE_PRETTY(): string {\n return "{}";\n}';
|
|
33
|
-
|
|
34
|
-
let INITIALIZE_EMPTY = "__INITIALIZE(): this {\n return this;\n}";
|
|
35
|
-
|
|
36
|
-
let DESERIALIZE_EMPTY = "__DESERIALIZE(data: string, key_start: i32, key_end: i32, value_start: i32, value_end: i32): boolean {\n return false;\n}";
|
|
37
|
-
|
|
38
|
-
if (process.env["JSON_DEBUG"]) {
|
|
39
|
-
console.log(SERIALIZE_RAW_EMPTY);
|
|
40
|
-
console.log(SERIALIZE_PRETTY_EMPTY);
|
|
41
|
-
console.log(INITIALIZE_EMPTY);
|
|
42
|
-
console.log(DESERIALIZE_EMPTY);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const SERIALIZE_RAW_METHOD_EMPTY = SimpleParser.parseClassMember(SERIALIZE_RAW_EMPTY, node);
|
|
46
|
-
const SERIALIZE_PRETTY_METHOD_EMPTY = SimpleParser.parseClassMember(SERIALIZE_PRETTY_EMPTY, node);
|
|
47
|
-
const INITIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(INITIALIZE_EMPTY, node);
|
|
48
|
-
const DESERIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(DESERIALIZE_EMPTY, node);
|
|
49
|
-
|
|
50
|
-
if (!node.members.find((v) => v.name.text == "__SERIALIZE")) node.members.push(SERIALIZE_RAW_METHOD_EMPTY);
|
|
51
|
-
if (!node.members.find((v) => v.name.text == "__SERIALIZE_PRETTY")) node.members.push(SERIALIZE_PRETTY_METHOD_EMPTY);
|
|
52
|
-
if (!node.members.find((v) => v.name.text == "__INITIALIZE")) node.members.push(INITIALIZE_METHOD_EMPTY);
|
|
53
|
-
if (!node.members.find((v) => v.name.text == "__DESERIALIZE")) node.members.push(DESERIALIZE_METHOD_EMPTY);
|
|
54
|
-
}
|
|
55
|
-
filterMembers(members: DeclarationStatement[]): FieldDeclaration[] {
|
|
56
|
-
return members.filter((v) => v instanceof FieldDeclaration && !v.decorators?.find((v) => (<IdentifierExpression>v.name).text == "omit")) as FieldDeclaration[];
|
|
57
|
-
}
|
|
58
|
-
visitClassDeclaration(node: ClassDeclaration): void {
|
|
59
|
-
if (!node.decorators?.length) return;
|
|
60
|
-
if (!node.decorators.find((v) => (<IdentifierExpression>v.name).text == "json" || (<IdentifierExpression>v.name).text == "serializable")) return;
|
|
61
|
-
this.types = json_types;
|
|
62
|
-
|
|
63
|
-
const schema = new SchemaData();
|
|
64
|
-
schema.node = node;
|
|
65
|
-
schema.name = node.name.text;
|
|
66
65
|
|
|
67
|
-
if (
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
if (!members.length) {
|
|
67
|
+
let SERIALIZE_RAW_EMPTY = '__SERIALIZE(): string {\n return "{}";\n}';
|
|
68
|
+
//let SERIALIZE_PRETTY_EMPTY = "__SERIALIZE_PRETTY(): string {\n return \"{}\";\n}";
|
|
70
69
|
|
|
71
|
-
|
|
70
|
+
let INITIALIZE_EMPTY = "__INITIALIZE(): this {\n return this;\n}";
|
|
72
71
|
|
|
73
|
-
|
|
72
|
+
let DESERIALIZE_EMPTY =
|
|
73
|
+
"__DESERIALIZE(data: string, key_start: i32, key_end: i32, value_start: i32, value_end: i32): boolean {\n return false;\n}";
|
|
74
74
|
|
|
75
|
-
|
|
75
|
+
if (process.env["JSON_DEBUG"]) {
|
|
76
|
+
console.log(SERIALIZE_RAW_EMPTY);
|
|
77
|
+
//console.log(SERIALIZE_PRETTY_EMPTY);
|
|
78
|
+
console.log(INITIALIZE_EMPTY);
|
|
79
|
+
console.log(DESERIALIZE_EMPTY);
|
|
80
|
+
}
|
|
76
81
|
|
|
77
|
-
|
|
78
|
-
|
|
82
|
+
const SERIALIZE_RAW_METHOD_EMPTY = SimpleParser.parseClassMember(
|
|
83
|
+
SERIALIZE_RAW_EMPTY,
|
|
84
|
+
node,
|
|
85
|
+
);
|
|
86
|
+
//const SERIALIZE_PRETTY_METHOD = SimpleParser.parseClassMember(SERIALIZE_PRETTY, node);
|
|
87
|
+
const INITIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(
|
|
88
|
+
INITIALIZE_EMPTY,
|
|
89
|
+
node,
|
|
90
|
+
);
|
|
91
|
+
const DESERIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(
|
|
92
|
+
DESERIALIZE_EMPTY,
|
|
93
|
+
node,
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
if (!node.members.find((v) => v.name.text == "__SERIALIZE"))
|
|
97
|
+
node.members.push(SERIALIZE_RAW_METHOD_EMPTY);
|
|
98
|
+
if (!node.members.find((v) => v.name.text == "__INITIALIZE"))
|
|
99
|
+
node.members.push(INITIALIZE_METHOD_EMPTY);
|
|
100
|
+
if (!node.members.find((v) => v.name.text == "__DESERIALIZE"))
|
|
101
|
+
node.members.push(DESERIALIZE_METHOD_EMPTY);
|
|
102
|
+
|
|
103
|
+
this.schemasList.push(schema);
|
|
79
104
|
}
|
|
80
105
|
|
|
81
106
|
for (const member of members) {
|
|
82
107
|
const name = member.name;
|
|
108
|
+
if (!(member instanceof FieldDeclaration)) continue;
|
|
83
109
|
if (!member.type) {
|
|
84
|
-
throw new Error(
|
|
110
|
+
throw new Error(
|
|
111
|
+
"Fields must be strongly typed! Found " +
|
|
112
|
+
toString(member) +
|
|
113
|
+
" at " +
|
|
114
|
+
node.range.source.normalizedPath,
|
|
115
|
+
);
|
|
85
116
|
}
|
|
86
|
-
|
|
87
117
|
const type = toString(member.type!);
|
|
88
118
|
if (type.startsWith("(") && type.includes("=>")) continue;
|
|
89
119
|
const value = member.initializer ? toString(member.initializer!) : null;
|
|
@@ -114,7 +144,11 @@ class JSONTransform extends BaseVisitor {
|
|
|
114
144
|
|
|
115
145
|
switch (decoratorName) {
|
|
116
146
|
case "alias": {
|
|
117
|
-
if (!args.length)
|
|
147
|
+
if (!args.length)
|
|
148
|
+
throw new Error(
|
|
149
|
+
"Expected 1 argument but got zero at @alias in " +
|
|
150
|
+
node.range.source.normalizedPath,
|
|
151
|
+
);
|
|
118
152
|
mem.alias = args[0]!;
|
|
119
153
|
mem.flags.set(PropertyFlags.Alias, args);
|
|
120
154
|
break;
|
|
@@ -124,7 +158,11 @@ class JSONTransform extends BaseVisitor {
|
|
|
124
158
|
break;
|
|
125
159
|
}
|
|
126
160
|
case "omitif": {
|
|
127
|
-
if (!decorator.args?.length)
|
|
161
|
+
if (!decorator.args?.length)
|
|
162
|
+
throw new Error(
|
|
163
|
+
"Expected 1 argument but got zero at @omitif in " +
|
|
164
|
+
node.range.source.normalizedPath,
|
|
165
|
+
);
|
|
128
166
|
mem.flags.set(PropertyFlags.OmitIf, args);
|
|
129
167
|
break;
|
|
130
168
|
}
|
|
@@ -136,10 +174,23 @@ class JSONTransform extends BaseVisitor {
|
|
|
136
174
|
}
|
|
137
175
|
}
|
|
138
176
|
|
|
139
|
-
|
|
177
|
+
mem.generate();
|
|
140
178
|
|
|
141
179
|
if (this.schemasList.find((v) => v.name == type)) {
|
|
142
|
-
mem.initialize =
|
|
180
|
+
mem.initialize =
|
|
181
|
+
"this." +
|
|
182
|
+
name.text +
|
|
183
|
+
" = changetype<nonnull<" +
|
|
184
|
+
mem.type +
|
|
185
|
+
">>(__new(offsetof<nonnull<" +
|
|
186
|
+
mem.type +
|
|
187
|
+
">>(), idof<nonnull<" +
|
|
188
|
+
mem.type +
|
|
189
|
+
">>()));\n changetype<nonnull<" +
|
|
190
|
+
mem.type +
|
|
191
|
+
">>(this." +
|
|
192
|
+
name.text +
|
|
193
|
+
").__INITIALIZE()";
|
|
143
194
|
} else if (mem.value) {
|
|
144
195
|
mem.initialize = "this." + name.text + " = " + mem.value;
|
|
145
196
|
} else if (type === "Map") {
|
|
@@ -147,12 +198,22 @@ class JSONTransform extends BaseVisitor {
|
|
|
147
198
|
} else if (type === "string") {
|
|
148
199
|
mem.initialize = "this." + name.text + ' = ""';
|
|
149
200
|
} else if (type === "Array") {
|
|
150
|
-
mem.initialize =
|
|
201
|
+
mem.initialize =
|
|
202
|
+
"this." + name.text + " = instantiate<" + mem.type + ">()";
|
|
151
203
|
} else if (type === "bool" || type === "boolean") {
|
|
152
204
|
mem.initialize = "this." + name.text + " = false";
|
|
153
205
|
} else if (type === "JSON.Raw") {
|
|
154
206
|
mem.initialize = "this." + name.text + ' = ""';
|
|
155
|
-
} else if (
|
|
207
|
+
} else if (
|
|
208
|
+
type === "u8" ||
|
|
209
|
+
type === "u16" ||
|
|
210
|
+
type === "u32" ||
|
|
211
|
+
type === "u64" ||
|
|
212
|
+
type === "i8" ||
|
|
213
|
+
type === "i16" ||
|
|
214
|
+
type === "i32" ||
|
|
215
|
+
type === "i64"
|
|
216
|
+
) {
|
|
156
217
|
mem.initialize = "this." + name.text + " = 0";
|
|
157
218
|
} else if (type === "f32" || type === "f64") {
|
|
158
219
|
mem.initialize = "this." + name.text + " = 0.0";
|
|
@@ -166,41 +227,50 @@ class JSONTransform extends BaseVisitor {
|
|
|
166
227
|
|
|
167
228
|
let INITIALIZE = "__INITIALIZE(): this {\n";
|
|
168
229
|
|
|
169
|
-
let DESERIALIZE =
|
|
230
|
+
let DESERIALIZE =
|
|
231
|
+
"__DESERIALIZE(data: string, key_start: i32, key_end: i32, value_start: i32, value_end: i32): boolean {\n const len = key_end - key_start;\n";
|
|
170
232
|
let indent = " ";
|
|
171
233
|
|
|
172
234
|
if (!schema.members.length) return;
|
|
173
235
|
|
|
174
|
-
|
|
236
|
+
found = false;
|
|
175
237
|
|
|
176
|
-
if (
|
|
238
|
+
if (
|
|
239
|
+
schema.members[0]?.flags.has(PropertyFlags.OmitNull) ||
|
|
240
|
+
schema.members[0]?.flags.has(PropertyFlags.OmitIf)
|
|
241
|
+
) {
|
|
177
242
|
SERIALIZE_RAW += schema.members[0]?.serialize;
|
|
178
|
-
SERIALIZE_PRETTY += "\\n" +
|
|
243
|
+
SERIALIZE_PRETTY += "\\n" + schema.members[0]?.serialize;
|
|
179
244
|
} else {
|
|
180
245
|
SERIALIZE_RAW += schema.members[0]?.serialize + ",";
|
|
181
|
-
SERIALIZE_PRETTY += "\\n" +
|
|
246
|
+
SERIALIZE_PRETTY += "\\n" + schema.members[0]?.serialize + ",\\n";
|
|
182
247
|
found = true;
|
|
183
248
|
}
|
|
184
249
|
|
|
185
|
-
if (schema.members[0]?.initialize)
|
|
250
|
+
if (schema.members[0]?.initialize)
|
|
251
|
+
INITIALIZE += " " + schema.members[0]?.initialize + ";\n";
|
|
186
252
|
|
|
187
253
|
for (let i = 1; i < schema.members.length; i++) {
|
|
188
254
|
const member = schema.members[i]!;
|
|
189
255
|
if (member.initialize) INITIALIZE += " " + member.initialize + ";\n";
|
|
190
|
-
if (
|
|
191
|
-
|
|
256
|
+
if (
|
|
257
|
+
member.flags.has(PropertyFlags.OmitNull) ||
|
|
258
|
+
member.flags.has(PropertyFlags.OmitIf)
|
|
259
|
+
) {
|
|
192
260
|
SERIALIZE_RAW += member.serialize;
|
|
193
|
-
SERIALIZE_PRETTY += member.
|
|
261
|
+
SERIALIZE_PRETTY += member.serialize;
|
|
194
262
|
} else {
|
|
195
263
|
SERIALIZE_RAW += member.serialize + ",";
|
|
196
|
-
SERIALIZE_PRETTY += indent + member.
|
|
264
|
+
SERIALIZE_PRETTY += indent + member.serialize + ",\\n";
|
|
197
265
|
found = true;
|
|
198
266
|
}
|
|
199
267
|
}
|
|
200
268
|
|
|
201
269
|
if (found) {
|
|
202
|
-
SERIALIZE_RAW +=
|
|
203
|
-
|
|
270
|
+
SERIALIZE_RAW +=
|
|
271
|
+
"`;\n store<u16>(changetype<usize>(out) + ((out.length - 1) << 1), 125);\n return out;\n}";
|
|
272
|
+
SERIALIZE_PRETTY +=
|
|
273
|
+
"`;\n store<u32>(changetype<usize>(out) + ((out.length - 2) << 1), 8192010);\n return out;\n}";
|
|
204
274
|
} else {
|
|
205
275
|
SERIALIZE_RAW += "}`;\n return out;\n}";
|
|
206
276
|
SERIALIZE_PRETTY += "}`;\n return out;\n}";
|
|
@@ -209,7 +279,9 @@ class JSONTransform extends BaseVisitor {
|
|
|
209
279
|
INITIALIZE += " return this;\n}";
|
|
210
280
|
|
|
211
281
|
const sortedMembers: Property[][] = [];
|
|
212
|
-
const _sorted = schema.members.sort(
|
|
282
|
+
const _sorted = schema.members.sort(
|
|
283
|
+
(a, b) => (a.alias?.length! || a.name.length) - (b.alias?.length! || b.name.length),
|
|
284
|
+
);
|
|
213
285
|
let len = -1;
|
|
214
286
|
let offset = -1;
|
|
215
287
|
for (let i = 0; i < _sorted.length; i++) {
|
|
@@ -230,24 +302,30 @@ class JSONTransform extends BaseVisitor {
|
|
|
230
302
|
const _name = encodeKey(firstMember.alias || firstMember.name);
|
|
231
303
|
if (_name.length === 1) {
|
|
232
304
|
if (first) {
|
|
233
|
-
DESERIALIZE +=
|
|
305
|
+
DESERIALIZE +=
|
|
306
|
+
" if (1 === len) {\n switch (load<u16>(changetype<usize>(data) + (key_start << 1))) {\n";
|
|
234
307
|
first = false;
|
|
235
308
|
} else {
|
|
236
|
-
DESERIALIZE +=
|
|
309
|
+
DESERIALIZE +=
|
|
310
|
+
"else if (1 === len) {\n switch (load<u16>(changetype<usize>(data) + (key_start << 1))) {\n";
|
|
237
311
|
}
|
|
238
312
|
} else if (_name.length === 2) {
|
|
239
313
|
if (first) {
|
|
240
|
-
DESERIALIZE +=
|
|
314
|
+
DESERIALIZE +=
|
|
315
|
+
" if (2 === len) {\n switch (load<u32>(changetype<usize>(data) + (key_start << 1))) {\n";
|
|
241
316
|
first = false;
|
|
242
317
|
} else {
|
|
243
|
-
DESERIALIZE +=
|
|
318
|
+
DESERIALIZE +=
|
|
319
|
+
"else if (2 === len) {\n switch (load<u32>(changetype<usize>(data) + (key_start << 1))) {\n";
|
|
244
320
|
}
|
|
245
321
|
} else if (_name.length === 4) {
|
|
246
322
|
if (first) {
|
|
247
|
-
DESERIALIZE +=
|
|
323
|
+
DESERIALIZE +=
|
|
324
|
+
" if (4 === len) {\n const code = load<u64>(changetype<usize>(data) + (key_start << 1));\n";
|
|
248
325
|
first = false;
|
|
249
326
|
} else {
|
|
250
|
-
DESERIALIZE +=
|
|
327
|
+
DESERIALIZE +=
|
|
328
|
+
"else if (4 === len) {\n const code = load<u64>(changetype<usize>(data) + (key_start << 1));\n";
|
|
251
329
|
}
|
|
252
330
|
} else {
|
|
253
331
|
if (first) {
|
|
@@ -271,23 +349,31 @@ class JSONTransform extends BaseVisitor {
|
|
|
271
349
|
f = false;
|
|
272
350
|
DESERIALIZE += ` if (${charCodeAt64(_name, 0)} === code) { /* ${_name} */\n ${member.deserialize}\n return true;\n }\n`;
|
|
273
351
|
} else {
|
|
274
|
-
DESERIALIZE =
|
|
352
|
+
DESERIALIZE =
|
|
353
|
+
DESERIALIZE.slice(0, DESERIALIZE.length - 1) +
|
|
354
|
+
`else if (${charCodeAt64(_name, 0)} === code) {\n ${member.deserialize}\n return true;\n }\n`;
|
|
275
355
|
}
|
|
276
356
|
} else {
|
|
277
357
|
if (f) {
|
|
278
358
|
f = false;
|
|
279
359
|
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`;
|
|
280
360
|
} else {
|
|
281
|
-
DESERIALIZE =
|
|
361
|
+
DESERIALIZE =
|
|
362
|
+
DESERIALIZE.slice(0, DESERIALIZE.length - 1) +
|
|
363
|
+
` 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`;
|
|
282
364
|
}
|
|
283
365
|
}
|
|
284
366
|
}
|
|
285
367
|
if (_name.length < 3) {
|
|
286
368
|
DESERIALIZE += ` default: {\n return false;\n }\n }\n`;
|
|
287
369
|
} else if (_name.length == 4) {
|
|
288
|
-
DESERIALIZE =
|
|
370
|
+
DESERIALIZE =
|
|
371
|
+
DESERIALIZE.slice(0, DESERIALIZE.length - 1) +
|
|
372
|
+
` else {\n return false;\n }\n`;
|
|
289
373
|
} else {
|
|
290
|
-
DESERIALIZE =
|
|
374
|
+
DESERIALIZE =
|
|
375
|
+
DESERIALIZE.slice(0, DESERIALIZE.length - 1) +
|
|
376
|
+
` else {\n return false;\n }\n`;
|
|
291
377
|
}
|
|
292
378
|
DESERIALIZE += " } ";
|
|
293
379
|
}
|
|
@@ -298,20 +384,25 @@ class JSONTransform extends BaseVisitor {
|
|
|
298
384
|
|
|
299
385
|
if (process.env["JSON_DEBUG"]) {
|
|
300
386
|
console.log(SERIALIZE_RAW);
|
|
301
|
-
console.log(SERIALIZE_PRETTY);
|
|
387
|
+
//console.log(SERIALIZE_PRETTY);
|
|
302
388
|
console.log(INITIALIZE);
|
|
303
389
|
console.log(DESERIALIZE);
|
|
304
390
|
}
|
|
305
391
|
|
|
306
|
-
const SERIALIZE_RAW_METHOD = SimpleParser.parseClassMember(
|
|
307
|
-
|
|
392
|
+
const SERIALIZE_RAW_METHOD = SimpleParser.parseClassMember(
|
|
393
|
+
SERIALIZE_RAW,
|
|
394
|
+
node,
|
|
395
|
+
);
|
|
396
|
+
//const SERIALIZE_PRETTY_METHOD = SimpleParser.parseClassMember(SERIALIZE_PRETTY, node);
|
|
308
397
|
const INITIALIZE_METHOD = SimpleParser.parseClassMember(INITIALIZE, node);
|
|
309
398
|
const DESERIALIZE_METHOD = SimpleParser.parseClassMember(DESERIALIZE, node);
|
|
310
399
|
|
|
311
|
-
if (!node.members.find((v) => v.name.text == "__SERIALIZE"))
|
|
312
|
-
|
|
313
|
-
if (!node.members.find((v) => v.name.text == "__INITIALIZE"))
|
|
314
|
-
|
|
400
|
+
if (!node.members.find((v) => v.name.text == "__SERIALIZE"))
|
|
401
|
+
node.members.push(SERIALIZE_RAW_METHOD);
|
|
402
|
+
if (!node.members.find((v) => v.name.text == "__INITIALIZE"))
|
|
403
|
+
node.members.push(INITIALIZE_METHOD);
|
|
404
|
+
if (!node.members.find((v) => v.name.text == "__DESERIALIZE"))
|
|
405
|
+
node.members.push(DESERIALIZE_METHOD);
|
|
315
406
|
|
|
316
407
|
this.schemasList.push(schema);
|
|
317
408
|
}
|
|
@@ -337,13 +428,13 @@ export default class Transformer extends Transform {
|
|
|
337
428
|
.sort((_a, _b) => {
|
|
338
429
|
const a = _a.internalPath;
|
|
339
430
|
const b = _b.internalPath;
|
|
340
|
-
if (a[0] !== "~" && b[0] === "~") {
|
|
341
|
-
return 1;
|
|
342
|
-
}
|
|
343
431
|
if (a[0] === "~" && b[0] !== "~") {
|
|
344
432
|
return -1;
|
|
433
|
+
} else if (a[0] !== "~" && b[0] === "~") {
|
|
434
|
+
return 1;
|
|
435
|
+
} else {
|
|
436
|
+
return 0;
|
|
345
437
|
}
|
|
346
|
-
return 0;
|
|
347
438
|
});
|
|
348
439
|
|
|
349
440
|
// Loop over every source
|
|
@@ -356,85 +447,17 @@ export default class Transformer extends Transform {
|
|
|
356
447
|
// Check that every parent and child class is hooked up correctly
|
|
357
448
|
const schemas = transformer.schemasList;
|
|
358
449
|
for (const schema of schemas) {
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
450
|
+
if (schema.parent) {
|
|
451
|
+
const parent = schemas.find((v) => v.name === schema.parent?.name);
|
|
452
|
+
if (!parent)
|
|
453
|
+
throw new Error(
|
|
454
|
+
`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.`,
|
|
455
|
+
);
|
|
363
456
|
}
|
|
364
457
|
}
|
|
365
458
|
}
|
|
366
459
|
}
|
|
367
460
|
|
|
368
|
-
function checkInheritance(schema: SchemaData, schemas: SchemaData[]): void {
|
|
369
|
-
if (!schema.parent && schema.node.extendsType) {
|
|
370
|
-
if (schemas.find(v => v.node.name.text === schema.node.extendsType?.name.identifier.text!)) return;
|
|
371
|
-
const extending = toString(schema.node.extendsType);
|
|
372
|
-
logError(`Schema ${schema.name} extends ${extending}, but ${extending} does not include the @json decorator!`);
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
function checkTypeCorrectness(
|
|
377
|
-
schema: SchemaData,
|
|
378
|
-
schemas: SchemaData[]
|
|
379
|
-
): {
|
|
380
|
-
type: string;
|
|
381
|
-
path: string;
|
|
382
|
-
} | null {
|
|
383
|
-
const parent = schemas.find((v) => v.name === schema.parent?.name);
|
|
384
|
-
const generic_types = [...(schema?.node.typeParameters?.map<string>((v) => v.name.text) || []), ...(parent?.node.typeParameters?.map<string>((v) => v.name.text) || [])];
|
|
385
|
-
const member_types = [...(schema.members.map((v) => (<NamedTypeNode>v.node.type).name.identifier.text) || [])];
|
|
386
|
-
const scopeTypes = new Set<string>([...json_types, ...generic_types, ...member_types]);
|
|
387
|
-
|
|
388
|
-
for (const typ of member_types) {
|
|
389
|
-
if (typ === "JSON") continue; // JSON.Raw, JSON.Box, JSON.Any, ect...
|
|
390
|
-
if (json_types.includes(typ)) continue;
|
|
391
|
-
if (generic_types.includes(typ)) continue;
|
|
392
|
-
const check = schemas.find((v) => v.name == typ);
|
|
393
|
-
if (!check) logError(`Type ${typ} is not a JSON compatible type or does not include the @json flag!`);
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
for (const member of schema.members) {
|
|
397
|
-
const invalidType = checkType(schema, schemas, member.node.type as NamedTypeNode, member, scopeTypes, schema.name);
|
|
398
|
-
if (invalidType) logError(`Type ${invalidType.type} in ${invalidType.path} does not implement a JSON compatible type!\n${chalk.dim(` at ${member.node.range.source.normalizedPath.replace("~lib/", "./node_modules/")}`)}`);
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
return null;
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
function checkType(
|
|
405
|
-
schema: SchemaData,
|
|
406
|
-
schemas: SchemaData[],
|
|
407
|
-
typ: NamedTypeNode,
|
|
408
|
-
member: Property,
|
|
409
|
-
scopeTypes: Set<string>,
|
|
410
|
-
path: string,
|
|
411
|
-
): {
|
|
412
|
-
type: string;
|
|
413
|
-
path: string;
|
|
414
|
-
} | null {
|
|
415
|
-
path += "." + member.name;
|
|
416
|
-
if (schemas.find(v => v.node.name.text === typ.name.identifier.text)) scopeTypes.add(typ.name.identifier.text);
|
|
417
|
-
if (!scopeTypes.has(typ.name.identifier.text)) return { type: toString(typ), path };
|
|
418
|
-
|
|
419
|
-
if (typ.isNullable && isPrimitive(typ)) return { type: toString(typ), path };
|
|
420
|
-
|
|
421
|
-
if (typ.typeArguments?.length && typ.typeArguments?.length > 0) {
|
|
422
|
-
for (const ty of typ.typeArguments.filter((v) => v instanceof NamedTypeNode)) {
|
|
423
|
-
const check = checkType(schema, schemas, ty, member, scopeTypes, path);
|
|
424
|
-
if (check) return { type: toString(typ), path };
|
|
425
|
-
}
|
|
426
|
-
} else {
|
|
427
|
-
if (scopeTypes.has(typ.name.identifier.text)) return null;
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
return null;
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
function logError(message: string): never {
|
|
434
|
-
console.log("\n" + chalk.bold.bgRed(" Error ") + chalk.dim(":") + " " + message + "\n");
|
|
435
|
-
process.exit(1);
|
|
436
|
-
}
|
|
437
|
-
|
|
438
461
|
enum PropertyFlags {
|
|
439
462
|
Null,
|
|
440
463
|
Omit,
|
|
@@ -449,10 +472,12 @@ class Property {
|
|
|
449
472
|
public alias: string | null = null;
|
|
450
473
|
public type: string = "";
|
|
451
474
|
public value: string | null = null;
|
|
452
|
-
public flags: Map<PropertyFlags, string[]> = new Map<
|
|
475
|
+
public flags: Map<PropertyFlags, string[]> = new Map<
|
|
476
|
+
PropertyFlags,
|
|
477
|
+
string[]
|
|
478
|
+
>();
|
|
453
479
|
|
|
454
480
|
public serialize: string | null = null;
|
|
455
|
-
public serialize_pretty: string | null = null;
|
|
456
481
|
public deserialize: string | null = null;
|
|
457
482
|
public initialize: string | null = null;
|
|
458
483
|
|
|
@@ -469,7 +494,7 @@ class Property {
|
|
|
469
494
|
|
|
470
495
|
if (this.flags.has(PropertyFlags.JSON_Raw)) {
|
|
471
496
|
if (this.flags.has(PropertyFlags.Null)) {
|
|
472
|
-
this.right_s = "(this." + name +
|
|
497
|
+
this.right_s = "(this." + name + " || \"null\")";
|
|
473
498
|
this.right_d = "value_start === value_end - 4 && 30399761348886638 === load<u64>(changetype<usize>(data) + (value_start << 1)) ? null : data.substring(value_start, value_end)";
|
|
474
499
|
} else {
|
|
475
500
|
this.right_s = "this." + name;
|
|
@@ -477,22 +502,38 @@ class Property {
|
|
|
477
502
|
}
|
|
478
503
|
} else {
|
|
479
504
|
this.right_s = "__SERIALIZE<" + type + ">(this." + name + ")";
|
|
480
|
-
this.right_d =
|
|
505
|
+
this.right_d =
|
|
506
|
+
"__DESERIALIZE<" + type + ">(data.substring(value_start, value_end))";
|
|
481
507
|
}
|
|
482
508
|
|
|
483
509
|
if (this.flags.has(PropertyFlags.OmitIf)) {
|
|
484
510
|
const condition = this.flags.get(PropertyFlags.OmitIf)![0];
|
|
485
|
-
if (!condition)
|
|
486
|
-
|
|
487
|
-
|
|
511
|
+
if (!condition)
|
|
512
|
+
throw new Error(
|
|
513
|
+
"Could not find condition when using decorator @omitif! Provide at least one condition",
|
|
514
|
+
);
|
|
515
|
+
this.serialize =
|
|
516
|
+
"${" +
|
|
517
|
+
condition +
|
|
518
|
+
' ? "" : \'' +
|
|
519
|
+
escapedName +
|
|
520
|
+
":' + " +
|
|
521
|
+
this.right_s +
|
|
522
|
+
' + ","}';
|
|
488
523
|
this.deserialize = "this." + name + " = " + this.right_d + ";";
|
|
489
524
|
} else if (this.flags.has(PropertyFlags.OmitNull)) {
|
|
490
|
-
this.serialize =
|
|
491
|
-
|
|
525
|
+
this.serialize =
|
|
526
|
+
"${changetype<usize>(this." +
|
|
527
|
+
name +
|
|
528
|
+
") == <usize>0" +
|
|
529
|
+
' ? "" : \'' +
|
|
530
|
+
escapedName +
|
|
531
|
+
":' + " +
|
|
532
|
+
this.right_s +
|
|
533
|
+
' + ","}';
|
|
492
534
|
this.deserialize = "this." + name + " = " + this.right_d + ";";
|
|
493
535
|
} else {
|
|
494
536
|
this.serialize = escapedName + ":${" + this.right_s + "}";
|
|
495
|
-
this.serialize_pretty = escapedName + ": ${" + this.right_s + "}";
|
|
496
537
|
this.deserialize = "this." + name + " = " + this.right_d + ";";
|
|
497
538
|
}
|
|
498
539
|
}
|
|
@@ -511,7 +552,9 @@ function charCodeAt32(data: string, offset: number): number {
|
|
|
511
552
|
|
|
512
553
|
function charCodeAt64(data: string, offset: number): bigint {
|
|
513
554
|
if (offset + 3 >= data.length) {
|
|
514
|
-
throw new Error(
|
|
555
|
+
throw new Error(
|
|
556
|
+
"The string must have at least 4 characters from the specified offset.",
|
|
557
|
+
);
|
|
515
558
|
}
|
|
516
559
|
|
|
517
560
|
const firstCharCode = BigInt(data.charCodeAt(offset));
|
|
@@ -519,7 +562,11 @@ function charCodeAt64(data: string, offset: number): bigint {
|
|
|
519
562
|
const thirdCharCode = BigInt(data.charCodeAt(offset + 2));
|
|
520
563
|
const fourthCharCode = BigInt(data.charCodeAt(offset + 3));
|
|
521
564
|
|
|
522
|
-
const u64Value =
|
|
565
|
+
const u64Value =
|
|
566
|
+
(fourthCharCode << 48n) |
|
|
567
|
+
(thirdCharCode << 32n) |
|
|
568
|
+
(secondCharCode << 16n) |
|
|
569
|
+
firstCharCode;
|
|
523
570
|
|
|
524
571
|
return u64Value;
|
|
525
572
|
}
|
|
@@ -563,9 +610,3 @@ function getArgs(args: Expression[] | null): string[] {
|
|
|
563
610
|
}
|
|
564
611
|
return out;
|
|
565
612
|
}
|
|
566
|
-
|
|
567
|
-
function isPrimitive(type: NamedTypeNode): boolean {
|
|
568
|
-
const primitives = new Set(["u8", "i8", "u16", "i16", "u32", "i32", "u64", "i64", "f32", "f64", "bool", "boolean"]);
|
|
569
|
-
|
|
570
|
-
return primitives.has(type.name.identifier.text);
|
|
571
|
-
}
|