json-as 0.9.17 → 0.9.19
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/FUNDING.yml +1 -1
- package/.github/workflows/nodejs.yml +4 -5
- package/.github/workflows/release-package.yml +2 -2
- package/CHANGELOG +2 -0
- package/README.md +27 -67
- package/as-test.config.json +3 -5
- package/assembly/__tests__/test.spec.ts +201 -311
- package/assembly/__tests__/types.ts +9 -10
- package/assembly/custom/sink.ts +264 -263
- package/assembly/custom/types.ts +1 -1
- package/assembly/deserialize/array.ts +30 -26
- package/assembly/index.d.ts +1 -2
- package/assembly/serialize/object.ts +2 -1
- package/assembly/test.ts +4 -3
- package/assembly/tsconfig.json +8 -10
- package/bench/bench-node.js +6 -6
- package/bench/benchmark.ts +18 -18
- package/bench/tsconfig.json +96 -98
- package/bench.js +9 -9
- package/index.ts +1 -1
- package/package.json +8 -5
- package/transform/lib/index.js +472 -420
- package/transform/package.json +1 -1
- package/transform/src/index.ts +244 -142
- package/transform/tsconfig.json +2 -2
package/transform/package.json
CHANGED
package/transform/src/index.ts
CHANGED
|
@@ -2,25 +2,23 @@ import {
|
|
|
2
2
|
ClassDeclaration,
|
|
3
3
|
FieldDeclaration,
|
|
4
4
|
IdentifierExpression,
|
|
5
|
-
NamedTypeNode,
|
|
6
|
-
StringLiteralExpression,
|
|
7
5
|
Parser,
|
|
8
6
|
Source,
|
|
9
|
-
NodeKind
|
|
7
|
+
NodeKind,
|
|
8
|
+
Expression,
|
|
9
|
+
CommonFlags,
|
|
10
10
|
} from "assemblyscript/dist/assemblyscript.js";
|
|
11
11
|
|
|
12
12
|
import { toString, isStdlib } from "visitor-as/dist/utils.js";
|
|
13
13
|
import { BaseVisitor, SimpleParser } from "visitor-as/dist/index.js";
|
|
14
14
|
import { Transform } from "assemblyscript/dist/transform.js";
|
|
15
|
-
import { CommonFlags } from "types:assemblyscript/src/common";
|
|
16
|
-
import { DecoratorNode } from "types:assemblyscript/src/ast";
|
|
17
15
|
|
|
18
16
|
class JSONTransform extends BaseVisitor {
|
|
19
17
|
public schemasList: SchemaData[] = [];
|
|
20
18
|
public currentClass!: SchemaData;
|
|
21
19
|
public sources = new Set<Source>();
|
|
22
20
|
|
|
23
|
-
visitMethodDeclaration(): void {
|
|
21
|
+
visitMethodDeclaration(): void {}
|
|
24
22
|
visitClassDeclaration(node: ClassDeclaration): void {
|
|
25
23
|
if (!node.decorators?.length) return;
|
|
26
24
|
|
|
@@ -39,21 +37,20 @@ class JSONTransform extends BaseVisitor {
|
|
|
39
37
|
schema.name = node.name.text;
|
|
40
38
|
|
|
41
39
|
const members = [
|
|
42
|
-
...node.members.filter(v => v.kind === NodeKind.FieldDeclaration)
|
|
40
|
+
...node.members.filter((v) => v.kind === NodeKind.FieldDeclaration),
|
|
43
41
|
];
|
|
44
42
|
|
|
45
43
|
if (node.extendsType) {
|
|
46
44
|
schema.parent = this.schemasList.find(
|
|
47
|
-
(v) => v.name == node.extendsType?.name.identifier.text
|
|
45
|
+
(v) => v.name == node.extendsType?.name.identifier.text,
|
|
48
46
|
) as SchemaData | null;
|
|
49
47
|
|
|
50
48
|
if (schema.parent?.members) {
|
|
51
49
|
for (let i = schema.parent.members.length - 1; i >= 0; i--) {
|
|
52
50
|
const replace = schema.members.find(
|
|
53
|
-
(v) => v.name == schema.parent?.members[i]?.name
|
|
51
|
+
(v) => v.name == schema.parent?.members[i]?.name,
|
|
54
52
|
);
|
|
55
53
|
if (!replace) {
|
|
56
|
-
//schema.members.unshift(schema.parent?.members[i]!);
|
|
57
54
|
members.unshift(schema.parent?.members[i]!.node);
|
|
58
55
|
}
|
|
59
56
|
}
|
|
@@ -61,12 +58,13 @@ class JSONTransform extends BaseVisitor {
|
|
|
61
58
|
}
|
|
62
59
|
|
|
63
60
|
if (!members.length) {
|
|
64
|
-
let SERIALIZE_RAW_EMPTY =
|
|
61
|
+
let SERIALIZE_RAW_EMPTY = '__SERIALIZE(): string {\n return "{}";\n}';
|
|
65
62
|
//let SERIALIZE_PRETTY_EMPTY = "__SERIALIZE_PRETTY(): string {\n return \"{}\";\n}";
|
|
66
63
|
|
|
67
64
|
let INITIALIZE_EMPTY = "__INITIALIZE(): this {\n return this;\n}";
|
|
68
65
|
|
|
69
|
-
let DESERIALIZE_EMPTY =
|
|
66
|
+
let DESERIALIZE_EMPTY =
|
|
67
|
+
"__DESERIALIZE(data: string, key_start: i32, key_end: i32, value_start: i32, value_end: i32): boolean {\n return false;\n}";
|
|
70
68
|
|
|
71
69
|
if (process.env["JSON_DEBUG"]) {
|
|
72
70
|
console.log(SERIALIZE_RAW_EMPTY);
|
|
@@ -75,14 +73,26 @@ class JSONTransform extends BaseVisitor {
|
|
|
75
73
|
console.log(DESERIALIZE_EMPTY);
|
|
76
74
|
}
|
|
77
75
|
|
|
78
|
-
const SERIALIZE_RAW_METHOD_EMPTY = SimpleParser.parseClassMember(
|
|
76
|
+
const SERIALIZE_RAW_METHOD_EMPTY = SimpleParser.parseClassMember(
|
|
77
|
+
SERIALIZE_RAW_EMPTY,
|
|
78
|
+
node,
|
|
79
|
+
);
|
|
79
80
|
//const SERIALIZE_PRETTY_METHOD = SimpleParser.parseClassMember(SERIALIZE_PRETTY, node);
|
|
80
|
-
const INITIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
81
|
+
const INITIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(
|
|
82
|
+
INITIALIZE_EMPTY,
|
|
83
|
+
node,
|
|
84
|
+
);
|
|
85
|
+
const DESERIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(
|
|
86
|
+
DESERIALIZE_EMPTY,
|
|
87
|
+
node,
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
if (!node.members.find((v) => v.name.text == "__SERIALIZE"))
|
|
91
|
+
node.members.push(SERIALIZE_RAW_METHOD_EMPTY);
|
|
92
|
+
if (!node.members.find((v) => v.name.text == "__INITIALIZE"))
|
|
93
|
+
node.members.push(INITIALIZE_METHOD_EMPTY);
|
|
94
|
+
if (!node.members.find((v) => v.name.text == "__DESERIALIZE"))
|
|
95
|
+
node.members.push(DESERIALIZE_METHOD_EMPTY);
|
|
86
96
|
|
|
87
97
|
this.schemasList.push(schema);
|
|
88
98
|
}
|
|
@@ -91,7 +101,12 @@ class JSONTransform extends BaseVisitor {
|
|
|
91
101
|
const name = member.name;
|
|
92
102
|
if (!(member instanceof FieldDeclaration)) continue;
|
|
93
103
|
if (!member.type) {
|
|
94
|
-
throw new Error(
|
|
104
|
+
throw new Error(
|
|
105
|
+
"Fields must be strongly typed! Found " +
|
|
106
|
+
toString(member) +
|
|
107
|
+
" at " +
|
|
108
|
+
node.range.source.normalizedPath,
|
|
109
|
+
);
|
|
95
110
|
}
|
|
96
111
|
const type = toString(member.type!);
|
|
97
112
|
if (type.startsWith("(") && type.includes("=>")) continue;
|
|
@@ -100,7 +115,6 @@ class JSONTransform extends BaseVisitor {
|
|
|
100
115
|
if (member.flags == CommonFlags.Static) continue;
|
|
101
116
|
if (member.flags === CommonFlags.Private) continue;
|
|
102
117
|
if (member.flags === CommonFlags.Protected) continue;
|
|
103
|
-
if (member.decorators && member.decorators.find((v) => (<IdentifierExpression>v.name).text == "omit")) continue;
|
|
104
118
|
|
|
105
119
|
const mem = new Property();
|
|
106
120
|
mem.name = name.text;
|
|
@@ -108,95 +122,90 @@ class JSONTransform extends BaseVisitor {
|
|
|
108
122
|
mem.value = value;
|
|
109
123
|
mem.node = member;
|
|
110
124
|
|
|
111
|
-
if (
|
|
112
|
-
|
|
113
|
-
if (decorator = member.decorators.find(v => (<IdentifierExpression>v.name).text == "alias") as DecoratorNode | null) {
|
|
114
|
-
if ((<IdentifierExpression>decorator.name).text == "alias") {
|
|
115
|
-
if (!decorator.args?.length) throw new Error("Expected 1 argument but got zero at @alias in " + node.range.source.normalizedPath);
|
|
116
|
-
mem.flags.push(PropertyFlags.Alias);
|
|
117
|
-
mem.alias = (decorator.args[0] as StringLiteralExpression).value;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
for (let i = 0; i < (member.decorators).length; i++) {
|
|
122
|
-
const decorator = member.decorators[i]!;
|
|
123
|
-
if ((<IdentifierExpression>decorator.name).text == "omitnull") {
|
|
124
|
-
mem.flags.push(PropertyFlags.OmitNull);
|
|
125
|
-
} else if ((<IdentifierExpression>decorator.name).text == "omitif") {
|
|
126
|
-
if (!decorator.args?.length) throw new Error("Expected 1 argument but got zero at @omitif in " + node.range.source.normalizedPath);
|
|
127
|
-
mem.args?.push((decorator.args[0] as StringLiteralExpression).value);
|
|
128
|
-
mem.flags.push(PropertyFlags.OmitIf);
|
|
129
|
-
} else if ((<IdentifierExpression>decorator.name).text == "flatten") {
|
|
130
|
-
if (!decorator.args?.length) throw new Error("Expected 1 argument but got zero at @flatten in " + node.range.source.normalizedPath);
|
|
131
|
-
mem.flags.push(PropertyFlags.Flatten);
|
|
132
|
-
mem.args = [(decorator.args[0] as StringLiteralExpression).value];
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
if (!mem.flags.length) {
|
|
138
|
-
mem.flags = [PropertyFlags.None];
|
|
139
|
-
if (type == "JSON.Raw") {
|
|
140
|
-
mem.serialize = escapeString(JSON.stringify(mem.alias || mem.name)) + ":${this." + name.text + "}";
|
|
141
|
-
mem.deserialize = "this." + name.text + " = " + "data.substring(value_start, value_end);"
|
|
142
|
-
} else {
|
|
143
|
-
mem.serialize = escapeString(JSON.stringify(mem.alias || mem.name)) + ":${__SERIALIZE<" + type + ">(this." + name.text + ")}";
|
|
144
|
-
mem.deserialize = "this." + name.text + " = " + "__DESERIALIZE<" + type + ">(data.substring(value_start, value_end));"
|
|
145
|
-
}
|
|
125
|
+
if (type == "JSON.Raw") {
|
|
126
|
+
mem.flags.set(PropertyFlags.JSON_Raw, []);
|
|
146
127
|
}
|
|
147
128
|
|
|
148
|
-
if (
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
129
|
+
if (member.decorators) {
|
|
130
|
+
for (const decorator of member.decorators) {
|
|
131
|
+
const decoratorName = (decorator.name as IdentifierExpression).text;
|
|
132
|
+
|
|
133
|
+
const args = getArgs(decorator.args);
|
|
134
|
+
|
|
135
|
+
switch (decoratorName) {
|
|
136
|
+
case "alias": {
|
|
137
|
+
if (!args.length)
|
|
138
|
+
throw new Error(
|
|
139
|
+
"Expected 1 argument but got zero at @alias in " +
|
|
140
|
+
node.range.source.normalizedPath,
|
|
141
|
+
);
|
|
142
|
+
mem.alias = args[0]!;
|
|
143
|
+
mem.flags.set(PropertyFlags.Alias, args);
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
case "omit": {
|
|
147
|
+
mem.flags.set(PropertyFlags.Omit, args);
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
case "omitif": {
|
|
151
|
+
if (!decorator.args?.length)
|
|
152
|
+
throw new Error(
|
|
153
|
+
"Expected 1 argument but got zero at @omitif in " +
|
|
154
|
+
node.range.source.normalizedPath,
|
|
155
|
+
);
|
|
156
|
+
mem.flags.set(PropertyFlags.OmitIf, args);
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
case "omitnull": {
|
|
160
|
+
mem.flags.set(PropertyFlags.OmitNull, args);
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
166
164
|
}
|
|
167
|
-
mem.name = name.text;
|
|
168
165
|
}
|
|
169
166
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
167
|
+
mem.generate();
|
|
168
|
+
|
|
169
|
+
if (this.schemasList.find((v) => v.name == type)) {
|
|
170
|
+
mem.initialize =
|
|
171
|
+
"this." +
|
|
172
|
+
name.text +
|
|
173
|
+
" = changetype<nonnull<" +
|
|
174
|
+
mem.type +
|
|
175
|
+
">>(__new(offsetof<nonnull<" +
|
|
176
|
+
mem.type +
|
|
177
|
+
">>(), idof<nonnull<" +
|
|
178
|
+
mem.type +
|
|
179
|
+
">>()));\n changetype<nonnull<" +
|
|
180
|
+
mem.type +
|
|
181
|
+
">>(this." +
|
|
182
|
+
name.text +
|
|
183
|
+
").__INITIALIZE()";
|
|
173
184
|
} else if (mem.value) {
|
|
174
185
|
mem.initialize = "this." + name.text + " = " + mem.value;
|
|
175
|
-
} else if (
|
|
176
|
-
mem.initialize = "this." + name.text + " = new " + mem.type + "()"
|
|
177
|
-
} else if (
|
|
178
|
-
mem.initialize = "this." + name.text +
|
|
179
|
-
} else if (
|
|
180
|
-
mem.initialize =
|
|
181
|
-
|
|
186
|
+
} else if (type === "Map") {
|
|
187
|
+
mem.initialize = "this." + name.text + " = new " + mem.type + "()";
|
|
188
|
+
} else if (type === "string") {
|
|
189
|
+
mem.initialize = "this." + name.text + ' = ""';
|
|
190
|
+
} else if (type === "Array") {
|
|
191
|
+
mem.initialize =
|
|
192
|
+
"this." + name.text + " = instantiate<" + mem.type + ">()";
|
|
193
|
+
} else if (type === "bool" || type === "boolean") {
|
|
182
194
|
mem.initialize = "this." + name.text + " = false";
|
|
183
|
-
} else if (
|
|
184
|
-
mem.initialize = "this." + name.text +
|
|
195
|
+
} else if (type === "JSON.Raw") {
|
|
196
|
+
mem.initialize = "this." + name.text + ' = ""';
|
|
185
197
|
} else if (
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
198
|
+
type === "u8" ||
|
|
199
|
+
type === "u16" ||
|
|
200
|
+
type === "u32" ||
|
|
201
|
+
type === "u64" ||
|
|
202
|
+
type === "i8" ||
|
|
203
|
+
type === "i16" ||
|
|
204
|
+
type === "i32" ||
|
|
205
|
+
type === "i64"
|
|
194
206
|
) {
|
|
195
207
|
mem.initialize = "this." + name.text + " = 0";
|
|
196
|
-
} else if (
|
|
197
|
-
t === "f32" ||
|
|
198
|
-
t === "f64"
|
|
199
|
-
) {
|
|
208
|
+
} else if (type === "f32" || type === "f64") {
|
|
200
209
|
mem.initialize = "this." + name.text + " = 0.0";
|
|
201
210
|
}
|
|
202
211
|
|
|
@@ -208,7 +217,8 @@ class JSONTransform extends BaseVisitor {
|
|
|
208
217
|
|
|
209
218
|
let INITIALIZE = "__INITIALIZE(): this {\n";
|
|
210
219
|
|
|
211
|
-
let DESERIALIZE =
|
|
220
|
+
let DESERIALIZE =
|
|
221
|
+
"__DESERIALIZE(data: string, key_start: i32, key_end: i32, value_start: i32, value_end: i32): boolean {\n const len = key_end - key_start;\n";
|
|
212
222
|
let indent = " ";
|
|
213
223
|
|
|
214
224
|
if (!schema.members.length) return;
|
|
@@ -216,8 +226,8 @@ class JSONTransform extends BaseVisitor {
|
|
|
216
226
|
found = false;
|
|
217
227
|
|
|
218
228
|
if (
|
|
219
|
-
schema.members[0]?.flags.
|
|
220
|
-
|
|
229
|
+
schema.members[0]?.flags.has(PropertyFlags.OmitNull) ||
|
|
230
|
+
schema.members[0]?.flags.has(PropertyFlags.OmitIf)
|
|
221
231
|
) {
|
|
222
232
|
SERIALIZE_RAW += schema.members[0]?.serialize;
|
|
223
233
|
SERIALIZE_PRETTY += "\\n" + schema.members[0]?.serialize;
|
|
@@ -227,14 +237,15 @@ class JSONTransform extends BaseVisitor {
|
|
|
227
237
|
found = true;
|
|
228
238
|
}
|
|
229
239
|
|
|
230
|
-
if (schema.members[0]?.initialize)
|
|
240
|
+
if (schema.members[0]?.initialize)
|
|
241
|
+
INITIALIZE += " " + schema.members[0]?.initialize + ";\n";
|
|
231
242
|
|
|
232
243
|
for (let i = 1; i < schema.members.length; i++) {
|
|
233
244
|
const member = schema.members[i]!;
|
|
234
245
|
if (member.initialize) INITIALIZE += " " + member.initialize + ";\n";
|
|
235
246
|
if (
|
|
236
|
-
member.flags.
|
|
237
|
-
|
|
247
|
+
member.flags.has(PropertyFlags.OmitNull) ||
|
|
248
|
+
member.flags.has(PropertyFlags.OmitIf)
|
|
238
249
|
) {
|
|
239
250
|
SERIALIZE_RAW += member.serialize;
|
|
240
251
|
SERIALIZE_PRETTY += member.serialize;
|
|
@@ -246,17 +257,21 @@ class JSONTransform extends BaseVisitor {
|
|
|
246
257
|
}
|
|
247
258
|
|
|
248
259
|
if (found) {
|
|
249
|
-
SERIALIZE_RAW +=
|
|
250
|
-
|
|
260
|
+
SERIALIZE_RAW +=
|
|
261
|
+
"`;\n store<u16>(changetype<usize>(out) + ((out.length - 1) << 1), 125);\n return out;\n}";
|
|
262
|
+
SERIALIZE_PRETTY +=
|
|
263
|
+
"`;\n store<u32>(changetype<usize>(out) + ((out.length - 2) << 1), 8192010);\n return out;\n}";
|
|
251
264
|
} else {
|
|
252
265
|
SERIALIZE_RAW += "`;\n};";
|
|
253
266
|
SERIALIZE_PRETTY += "`;\n};";
|
|
254
267
|
}
|
|
255
268
|
|
|
256
|
-
INITIALIZE += " return this;\n}"
|
|
269
|
+
INITIALIZE += " return this;\n}";
|
|
257
270
|
|
|
258
271
|
const sortedMembers: Property[][] = [];
|
|
259
|
-
const _sorted = schema.members.sort(
|
|
272
|
+
const _sorted = schema.members.sort(
|
|
273
|
+
(a, b) => a.name.length - b.name.length,
|
|
274
|
+
);
|
|
260
275
|
let len = 0;
|
|
261
276
|
let offset = 0;
|
|
262
277
|
sortedMembers.push([_sorted[0]!]);
|
|
@@ -265,7 +280,7 @@ class JSONTransform extends BaseVisitor {
|
|
|
265
280
|
const member = _sorted[i]!;
|
|
266
281
|
if (member.alias?.length || member.name.length > len) {
|
|
267
282
|
sortedMembers.push([member]);
|
|
268
|
-
len = member.alias?.length || member.name.length
|
|
283
|
+
len = member.alias?.length || member.name.length;
|
|
269
284
|
offset++;
|
|
270
285
|
} else {
|
|
271
286
|
sortedMembers[offset]!.push(member);
|
|
@@ -278,24 +293,30 @@ class JSONTransform extends BaseVisitor {
|
|
|
278
293
|
const name = encodeKey(firstMember.alias || firstMember.name);
|
|
279
294
|
if (name.length === 1) {
|
|
280
295
|
if (first) {
|
|
281
|
-
DESERIALIZE +=
|
|
296
|
+
DESERIALIZE +=
|
|
297
|
+
" if (1 === len) {\n switch (load<u16>(changetype<usize>(data) + (key_start << 1))) {\n";
|
|
282
298
|
first = false;
|
|
283
299
|
} else {
|
|
284
|
-
DESERIALIZE +=
|
|
300
|
+
DESERIALIZE +=
|
|
301
|
+
"else if (1 === len) {\n switch (load<u16>(changetype<usize>(data) + (key_start << 1))) {\n";
|
|
285
302
|
}
|
|
286
303
|
} else if (name.length === 2) {
|
|
287
304
|
if (first) {
|
|
288
|
-
DESERIALIZE +=
|
|
305
|
+
DESERIALIZE +=
|
|
306
|
+
" if (2 === len) {\n switch (load<u32>(changetype<usize>(data) + (key_start << 1))) {\n";
|
|
289
307
|
first = false;
|
|
290
308
|
} else {
|
|
291
|
-
DESERIALIZE +=
|
|
309
|
+
DESERIALIZE +=
|
|
310
|
+
"else if (2 === len) {\n switch (load<u32>(changetype<usize>(data) + (key_start << 1))) {\n";
|
|
292
311
|
}
|
|
293
312
|
} else if (name.length === 4) {
|
|
294
313
|
if (first) {
|
|
295
|
-
DESERIALIZE +=
|
|
314
|
+
DESERIALIZE +=
|
|
315
|
+
" if (4 === len) {\n const code = load<u64>(changetype<usize>(data) + (key_start << 1));\n";
|
|
296
316
|
first = false;
|
|
297
317
|
} else {
|
|
298
|
-
DESERIALIZE +=
|
|
318
|
+
DESERIALIZE +=
|
|
319
|
+
"else if (4 === len) {\n const code = load<u64>(changetype<usize>(data) + (key_start << 1));\n";
|
|
299
320
|
}
|
|
300
321
|
} else {
|
|
301
322
|
if (first) {
|
|
@@ -319,28 +340,36 @@ class JSONTransform extends BaseVisitor {
|
|
|
319
340
|
f = false;
|
|
320
341
|
DESERIALIZE += ` if (${charCodeAt64(name, 0)} === code) {\n ${member.deserialize}\n return true;\n }\n`;
|
|
321
342
|
} else {
|
|
322
|
-
DESERIALIZE =
|
|
343
|
+
DESERIALIZE =
|
|
344
|
+
DESERIALIZE.slice(0, DESERIALIZE.length - 1) +
|
|
345
|
+
`else if (${charCodeAt64(name, 0)} === code) {\n ${member.deserialize}\n return true;\n }\n`;
|
|
323
346
|
}
|
|
324
347
|
} else {
|
|
325
348
|
if (f) {
|
|
326
349
|
f = false;
|
|
327
|
-
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
|
|
350
|
+
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`;
|
|
328
351
|
} else {
|
|
329
|
-
DESERIALIZE =
|
|
352
|
+
DESERIALIZE =
|
|
353
|
+
DESERIALIZE.slice(0, DESERIALIZE.length - 1) +
|
|
354
|
+
` 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`;
|
|
330
355
|
}
|
|
331
356
|
}
|
|
332
357
|
}
|
|
333
358
|
if (name.length < 3) {
|
|
334
|
-
DESERIALIZE += ` default: {\n return false;\n }\n }\n
|
|
359
|
+
DESERIALIZE += ` default: {\n return false;\n }\n }\n`;
|
|
335
360
|
} else if (name.length == 4) {
|
|
336
|
-
DESERIALIZE =
|
|
361
|
+
DESERIALIZE =
|
|
362
|
+
DESERIALIZE.slice(0, DESERIALIZE.length - 1) +
|
|
363
|
+
` else {\n return false;\n }\n`;
|
|
337
364
|
} else {
|
|
338
|
-
DESERIALIZE =
|
|
365
|
+
DESERIALIZE =
|
|
366
|
+
DESERIALIZE.slice(0, DESERIALIZE.length - 1) +
|
|
367
|
+
` else {\n return false;\n }\n`;
|
|
339
368
|
}
|
|
340
369
|
DESERIALIZE += " } ";
|
|
341
370
|
}
|
|
342
371
|
|
|
343
|
-
DESERIALIZE += "\n return false;\n}"
|
|
372
|
+
DESERIALIZE += "\n return false;\n}";
|
|
344
373
|
|
|
345
374
|
//console.log(sortedMembers);
|
|
346
375
|
|
|
@@ -351,14 +380,20 @@ class JSONTransform extends BaseVisitor {
|
|
|
351
380
|
console.log(DESERIALIZE);
|
|
352
381
|
}
|
|
353
382
|
|
|
354
|
-
const SERIALIZE_RAW_METHOD = SimpleParser.parseClassMember(
|
|
383
|
+
const SERIALIZE_RAW_METHOD = SimpleParser.parseClassMember(
|
|
384
|
+
SERIALIZE_RAW,
|
|
385
|
+
node,
|
|
386
|
+
);
|
|
355
387
|
//const SERIALIZE_PRETTY_METHOD = SimpleParser.parseClassMember(SERIALIZE_PRETTY, node);
|
|
356
388
|
const INITIALIZE_METHOD = SimpleParser.parseClassMember(INITIALIZE, node);
|
|
357
389
|
const DESERIALIZE_METHOD = SimpleParser.parseClassMember(DESERIALIZE, node);
|
|
358
390
|
|
|
359
|
-
if (!node.members.find(v => v.name.text == "__SERIALIZE"))
|
|
360
|
-
|
|
361
|
-
if (!node.members.find(v => v.name.text == "
|
|
391
|
+
if (!node.members.find((v) => v.name.text == "__SERIALIZE"))
|
|
392
|
+
node.members.push(SERIALIZE_RAW_METHOD);
|
|
393
|
+
if (!node.members.find((v) => v.name.text == "__INITIALIZE"))
|
|
394
|
+
node.members.push(INITIALIZE_METHOD);
|
|
395
|
+
if (!node.members.find((v) => v.name.text == "__DESERIALIZE"))
|
|
396
|
+
node.members.push(DESERIALIZE_METHOD);
|
|
362
397
|
|
|
363
398
|
this.schemasList.push(schema);
|
|
364
399
|
}
|
|
@@ -405,39 +440,93 @@ export default class Transformer extends Transform {
|
|
|
405
440
|
for (const schema of schemas) {
|
|
406
441
|
if (schema.parent) {
|
|
407
442
|
const parent = schemas.find((v) => v.name === schema.parent?.name);
|
|
408
|
-
if (!parent)
|
|
443
|
+
if (!parent)
|
|
444
|
+
throw new Error(
|
|
445
|
+
`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.`,
|
|
446
|
+
);
|
|
409
447
|
}
|
|
410
448
|
}
|
|
411
449
|
}
|
|
412
450
|
}
|
|
413
451
|
|
|
414
452
|
enum PropertyFlags {
|
|
415
|
-
None,
|
|
416
453
|
Omit,
|
|
417
454
|
OmitNull,
|
|
418
455
|
OmitIf,
|
|
419
456
|
Alias,
|
|
420
|
-
|
|
457
|
+
JSON_Raw,
|
|
421
458
|
}
|
|
422
459
|
|
|
423
460
|
class Property {
|
|
424
|
-
public name: string = ""
|
|
461
|
+
public name: string = "";
|
|
425
462
|
public alias: string | null = null;
|
|
426
463
|
public type: string = "";
|
|
427
464
|
public value: string | null = null;
|
|
428
|
-
public flags: PropertyFlags[] =
|
|
429
|
-
|
|
465
|
+
public flags: Map<PropertyFlags, string[]> = new Map<
|
|
466
|
+
PropertyFlags,
|
|
467
|
+
string[]
|
|
468
|
+
>();
|
|
430
469
|
|
|
431
470
|
public serialize: string | null = null;
|
|
432
471
|
public deserialize: string | null = null;
|
|
433
472
|
public initialize: string | null = null;
|
|
434
473
|
|
|
435
474
|
public node!: FieldDeclaration;
|
|
475
|
+
|
|
476
|
+
private right_s: string = "";
|
|
477
|
+
private right_d: string = "";
|
|
478
|
+
|
|
479
|
+
public generate(): void {
|
|
480
|
+
const name = this.name;
|
|
481
|
+
const escapedName = escapeString(JSON.stringify(this.alias || this.name));
|
|
482
|
+
const type = this.type;
|
|
483
|
+
if (this.flags.has(PropertyFlags.Omit)) return;
|
|
484
|
+
|
|
485
|
+
if (this.flags.has(PropertyFlags.JSON_Raw)) {
|
|
486
|
+
this.right_s = "this." + name;
|
|
487
|
+
this.right_d = "data.substring(value_start, value_end);";
|
|
488
|
+
} else {
|
|
489
|
+
this.right_s = "__SERIALIZE<" + type + ">(this." + name + ")";
|
|
490
|
+
this.right_d =
|
|
491
|
+
"__DESERIALIZE<" + type + ">(data.substring(value_start, value_end))";
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
if (this.flags.has(PropertyFlags.OmitIf)) {
|
|
495
|
+
const condition = this.flags.get(PropertyFlags.OmitIf)![0];
|
|
496
|
+
if (!condition)
|
|
497
|
+
throw new Error(
|
|
498
|
+
"Could not find condition when using decorator @omitif! Provide at least one condition",
|
|
499
|
+
);
|
|
500
|
+
this.serialize =
|
|
501
|
+
"${" +
|
|
502
|
+
condition +
|
|
503
|
+
' ? "" : \'' +
|
|
504
|
+
escapedName +
|
|
505
|
+
":' + " +
|
|
506
|
+
this.right_s +
|
|
507
|
+
' + ","}';
|
|
508
|
+
this.deserialize = "this." + name + " = " + this.right_d + ";";
|
|
509
|
+
} else if (this.flags.has(PropertyFlags.OmitNull)) {
|
|
510
|
+
this.serialize =
|
|
511
|
+
"${changetype<usize>(this." +
|
|
512
|
+
name +
|
|
513
|
+
") == <usize>0" +
|
|
514
|
+
' ? "" : \'' +
|
|
515
|
+
escapedName +
|
|
516
|
+
":' + " +
|
|
517
|
+
this.right_s +
|
|
518
|
+
' + ","}';
|
|
519
|
+
this.deserialize = "this." + name + " = " + this.right_d + ";";
|
|
520
|
+
} else {
|
|
521
|
+
this.serialize = escapedName + ":${" + this.right_s + "}";
|
|
522
|
+
this.deserialize = "this." + name + " = " + this.right_d + ";";
|
|
523
|
+
}
|
|
524
|
+
}
|
|
436
525
|
}
|
|
437
526
|
|
|
438
527
|
class SchemaData {
|
|
439
528
|
public name: string = "";
|
|
440
|
-
public members: Property[] = []
|
|
529
|
+
public members: Property[] = [];
|
|
441
530
|
public parent: SchemaData | null = null;
|
|
442
531
|
public node!: ClassDeclaration;
|
|
443
532
|
}
|
|
@@ -448,7 +537,9 @@ function charCodeAt32(data: string, offset: number): number {
|
|
|
448
537
|
|
|
449
538
|
function charCodeAt64(data: string, offset: number): bigint {
|
|
450
539
|
if (offset + 3 >= data.length) {
|
|
451
|
-
throw new Error(
|
|
540
|
+
throw new Error(
|
|
541
|
+
"The string must have at least 4 characters from the specified offset.",
|
|
542
|
+
);
|
|
452
543
|
}
|
|
453
544
|
|
|
454
545
|
const firstCharCode = BigInt(data.charCodeAt(offset));
|
|
@@ -456,7 +547,11 @@ function charCodeAt64(data: string, offset: number): bigint {
|
|
|
456
547
|
const thirdCharCode = BigInt(data.charCodeAt(offset + 2));
|
|
457
548
|
const fourthCharCode = BigInt(data.charCodeAt(offset + 3));
|
|
458
549
|
|
|
459
|
-
const u64Value =
|
|
550
|
+
const u64Value =
|
|
551
|
+
(fourthCharCode << 48n) |
|
|
552
|
+
(thirdCharCode << 32n) |
|
|
553
|
+
(secondCharCode << 16n) |
|
|
554
|
+
firstCharCode;
|
|
460
555
|
|
|
461
556
|
return u64Value;
|
|
462
557
|
}
|
|
@@ -467,15 +562,22 @@ function encodeKey(key: string): string {
|
|
|
467
562
|
}
|
|
468
563
|
|
|
469
564
|
function escapeString(data: string): string {
|
|
470
|
-
return data.replace(/\\/g, "\\\\")
|
|
471
|
-
.replace(/\`/g, '\\`');
|
|
565
|
+
return data.replace(/\\/g, "\\\\").replace(/\`/g, "\\`");
|
|
472
566
|
}
|
|
473
567
|
|
|
474
568
|
function escapeSlash(data: string): string {
|
|
475
|
-
return data.replace(/\\/g, "\\\\")
|
|
476
|
-
.replace(/\`/g, '\\`');
|
|
569
|
+
return data.replace(/\\/g, "\\\\").replace(/\`/g, "\\`");
|
|
477
570
|
}
|
|
478
571
|
|
|
479
572
|
function escapeQuote(data: string): string {
|
|
480
|
-
return data.replace(/\"/g, "
|
|
481
|
-
}
|
|
573
|
+
return data.replace(/\"/g, '\\"');
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
function getArgs(args: Expression[] | null): string[] {
|
|
577
|
+
if (!args) return [];
|
|
578
|
+
let out: string[] = [];
|
|
579
|
+
for (const arg of args) {
|
|
580
|
+
out.push(toString(arg));
|
|
581
|
+
}
|
|
582
|
+
return out;
|
|
583
|
+
}
|
package/transform/tsconfig.json
CHANGED
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
"module": "ES2015",
|
|
5
5
|
"downlevelIteration": true,
|
|
6
6
|
"outDir": "./lib/",
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
"strict": true,
|
|
9
9
|
"noImplicitAny": true,
|
|
10
10
|
"strictNullChecks": true,
|
|
11
11
|
"strictFunctionTypes": true,
|
|
12
|
-
"strictBindCallApply": true
|
|
12
|
+
"strictBindCallApply": true,
|
|
13
13
|
"strictPropertyInitialization": true,
|
|
14
14
|
"noImplicitThis": true,
|
|
15
15
|
"alwaysStrict": true,
|