json-as 0.9.16 → 0.9.18

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