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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@json-as/transform",
3
- "version": "0.9.17",
3
+ "version": "0.9.19",
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,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 = "__SERIALIZE(): string {\n return \"{}\";\n}";
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 = "__DESERIALIZE(data: string, key_start: i32, key_end: i32, value_start: i32, value_end: i32): boolean {\n return false;\n}";
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(SERIALIZE_RAW_EMPTY, node);
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(INITIALIZE_EMPTY, node);
81
- const DESERIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(DESERIALIZE_EMPTY, node);
82
-
83
- if (!node.members.find(v => v.name.text == "__SERIALIZE")) node.members.push(SERIALIZE_RAW_METHOD_EMPTY);
84
- if (!node.members.find(v => v.name.text == "__INITIALIZE")) node.members.push(INITIALIZE_METHOD_EMPTY);
85
- if (!node.members.find(v => v.name.text == "__DESERIALIZE")) node.members.push(DESERIALIZE_METHOD_EMPTY);
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("Fields must be strongly typed! Found " + toString(member) + " at " + node.range.source.normalizedPath);
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 (member.decorators) {
112
- let decorator: DecoratorNode | null = null;
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 (mem.flags.includes(PropertyFlags.OmitNull)) {
149
- mem.serialize = "${changetype<usize>(this." + mem.name + ") == <usize>0" + " ? \"\" : '" + escapeString(JSON.stringify(mem.alias || mem.name)) + ":' + __SERIALIZE<" + type + ">(this." + name.text + ") + \",\"}";
150
- mem.deserialize = "this." + name.text + " = " + "__DESERIALIZE<" + type + ">(data.substring(value_start, value_end));"
151
- } else if (mem.flags.includes(PropertyFlags.OmitIf)) {
152
- mem.serialize = "${" + mem.args![0]! + " ? \"\" : '" + escapeString(JSON.stringify(mem.alias || mem.name)) + ":' + __SERIALIZE<" + type + ">(this." + name.text + ") + \",\"}";
153
- mem.deserialize = "this." + name.text + " = " + "__DESERIALIZE<" + type + ">(data.substring(value_start, value_end));"
154
- } else if (mem.flags.includes(PropertyFlags.Alias)) {
155
- mem.serialize = escapeString(JSON.stringify(mem.alias || mem.name)) + ":${__SERIALIZE<" + type + ">(this." + name.text + ")}";
156
- mem.deserialize = "this." + name.text + " = " + "__DESERIALIZE<" + type + ">(data.substring(value_start, value_end));"
157
- mem.name = name.text;
158
- } else if (mem.flags.includes(PropertyFlags.Flatten)) {
159
- const nullable = (mem.node.type as NamedTypeNode).isNullable;
160
- if (nullable) {
161
- 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\"}";
162
- 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 }";
163
- } else {
164
- mem.serialize = escapeString(JSON.stringify(mem.alias || mem.name)) + ":${this." + name.text + " ? __SERIALIZE(this." + name.text + (mem.args?.length ? '.' + mem.args.join(".") : '') + ") : \"null\"}";
165
- mem.deserialize = "this." + name.text + " = " + "__DESERIALIZE<" + type + ">('{\"" + mem.args![0]! + "\":' + data.substring(value_start, value_end) + \"}\");";
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
- const t = (mem.node.type as NamedTypeNode).name?.identifier.text;
171
- if (this.schemasList.find(v => v.name == t)) {
172
- 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()";
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 (t === "Map") {
176
- mem.initialize = "this." + name.text + " = new " + mem.type + "()"
177
- } else if (t === "string") {
178
- mem.initialize = "this." + name.text + " = \"\"";
179
- } else if (t === "Array") {
180
- mem.initialize = "this." + name.text + " = instantiate<" + mem.type + ">()";
181
- } else if (t === "bool" || t === "boolean") {
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 (t === "JSON.Raw") {
184
- mem.initialize = "this." + name.text + " = \"\"";
195
+ } else if (type === "JSON.Raw") {
196
+ mem.initialize = "this." + name.text + ' = ""';
185
197
  } else if (
186
- t === "u8" ||
187
- t === "u16" ||
188
- t === "u32" ||
189
- t === "u64" ||
190
- t === "i8" ||
191
- t === "i16" ||
192
- t === "i32" ||
193
- t === "i64"
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 = "__DESERIALIZE(data: string, key_start: i32, key_end: i32, value_start: i32, value_end: i32): boolean {\n const len = key_end - key_start;\n"
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.includes(PropertyFlags.OmitNull)
220
- || schema.members[0]?.flags.includes(PropertyFlags.OmitIf)
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) INITIALIZE += " " + schema.members[0]?.initialize + ";\n";
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.includes(PropertyFlags.OmitNull)
237
- || member.flags.includes(PropertyFlags.OmitIf)
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 += "`;\n store<u16>(changetype<usize>(out) + ((out.length - 1) << 1), 125);\n return out;\n}";
250
- SERIALIZE_PRETTY += "`;\n store<u32>(changetype<usize>(out) + ((out.length - 2) << 1), 8192010);\n return out;\n}";
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((a, b) => a.name.length - b.name.length);
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 += " if (1 === len) {\n switch (load<u16>(changetype<usize>(data) + (key_start << 1))) {\n";
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 += "else if (1 === len) {\n switch (load<u16>(changetype<usize>(data) + (key_start << 1))) {\n";
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 += " if (2 === len) {\n switch (load<u32>(changetype<usize>(data) + (key_start << 1))) {\n";
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 += "else if (2 === len) {\n switch (load<u32>(changetype<usize>(data) + (key_start << 1))) {\n";
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 += " if (4 === len) {\n const code = load<u64>(changetype<usize>(data) + (key_start << 1));\n";
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 += "else if (4 === len) {\n const code = load<u64>(changetype<usize>(data) + (key_start << 1));\n";
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 = DESERIALIZE.slice(0, DESERIALIZE.length - 1) + `else if (${charCodeAt64(name, 0)} === code) {\n ${member.deserialize}\n return true;\n }\n`;
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 = 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`
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 = DESERIALIZE.slice(0, DESERIALIZE.length - 1) + ` else {\n return false;\n }\n`
361
+ DESERIALIZE =
362
+ DESERIALIZE.slice(0, DESERIALIZE.length - 1) +
363
+ ` else {\n return false;\n }\n`;
337
364
  } else {
338
- DESERIALIZE = DESERIALIZE.slice(0, DESERIALIZE.length - 1) + ` else {\n return false;\n }\n`
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(SERIALIZE_RAW, node);
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")) node.members.push(SERIALIZE_RAW_METHOD);
360
- if (!node.members.find(v => v.name.text == "__INITIALIZE")) node.members.push(INITIALIZE_METHOD);
361
- if (!node.members.find(v => v.name.text == "__DESERIALIZE")) node.members.push(DESERIALIZE_METHOD);
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) 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.`);
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
- Flatten
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
- public args: string[] | null = [];
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("The string must have at least 4 characters from the specified offset.");
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 = (fourthCharCode << 48n) | (thirdCharCode << 32n) | (secondCharCode << 16n) | firstCharCode;
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
+ }
@@ -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,