json-as 0.9.17 → 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.17",
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,21 +38,20 @@ 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
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]!);
57
55
  members.unshift(schema.parent?.members[i]!.node);
58
56
  }
59
57
  }
@@ -61,12 +59,13 @@ class JSONTransform extends BaseVisitor {
61
59
  }
62
60
 
63
61
  if (!members.length) {
64
- let SERIALIZE_RAW_EMPTY = "__SERIALIZE(): string {\n return \"{}\";\n}";
62
+ let SERIALIZE_RAW_EMPTY = '__SERIALIZE(): string {\n return "{}";\n}';
65
63
  //let SERIALIZE_PRETTY_EMPTY = "__SERIALIZE_PRETTY(): string {\n return \"{}\";\n}";
66
64
 
67
65
  let INITIALIZE_EMPTY = "__INITIALIZE(): this {\n return this;\n}";
68
66
 
69
- 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}";
70
69
 
71
70
  if (process.env["JSON_DEBUG"]) {
72
71
  console.log(SERIALIZE_RAW_EMPTY);
@@ -75,14 +74,26 @@ class JSONTransform extends BaseVisitor {
75
74
  console.log(DESERIALIZE_EMPTY);
76
75
  }
77
76
 
78
- 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
+ );
79
81
  //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);
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);
86
97
 
87
98
  this.schemasList.push(schema);
88
99
  }
@@ -91,7 +102,12 @@ class JSONTransform extends BaseVisitor {
91
102
  const name = member.name;
92
103
  if (!(member instanceof FieldDeclaration)) continue;
93
104
  if (!member.type) {
94
- 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
+ );
95
111
  }
96
112
  const type = toString(member.type!);
97
113
  if (type.startsWith("(") && type.includes("=>")) continue;
@@ -100,7 +116,6 @@ class JSONTransform extends BaseVisitor {
100
116
  if (member.flags == CommonFlags.Static) continue;
101
117
  if (member.flags === CommonFlags.Private) continue;
102
118
  if (member.flags === CommonFlags.Protected) continue;
103
- if (member.decorators && member.decorators.find((v) => (<IdentifierExpression>v.name).text == "omit")) continue;
104
119
 
105
120
  const mem = new Property();
106
121
  mem.name = name.text;
@@ -108,95 +123,90 @@ class JSONTransform extends BaseVisitor {
108
123
  mem.value = value;
109
124
  mem.node = member;
110
125
 
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
- }
126
+ if (type == "JSON.Raw") {
127
+ mem.flags.set(PropertyFlags.JSON_Raw, []);
146
128
  }
147
129
 
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) + \"}\");";
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
+ }
166
165
  }
167
- mem.name = name.text;
168
166
  }
169
167
 
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()";
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()";
173
185
  } else if (mem.value) {
174
186
  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") {
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") {
182
195
  mem.initialize = "this." + name.text + " = false";
183
- } else if (t === "JSON.Raw") {
184
- mem.initialize = "this." + name.text + " = \"\"";
196
+ } else if (type === "JSON.Raw") {
197
+ mem.initialize = "this." + name.text + ' = ""';
185
198
  } 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"
199
+ type === "u8" ||
200
+ type === "u16" ||
201
+ type === "u32" ||
202
+ type === "u64" ||
203
+ type === "i8" ||
204
+ type === "i16" ||
205
+ type === "i32" ||
206
+ type === "i64"
194
207
  ) {
195
208
  mem.initialize = "this." + name.text + " = 0";
196
- } else if (
197
- t === "f32" ||
198
- t === "f64"
199
- ) {
209
+ } else if (type === "f32" || type === "f64") {
200
210
  mem.initialize = "this." + name.text + " = 0.0";
201
211
  }
202
212
 
@@ -208,7 +218,8 @@ class JSONTransform extends BaseVisitor {
208
218
 
209
219
  let INITIALIZE = "__INITIALIZE(): this {\n";
210
220
 
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"
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";
212
223
  let indent = " ";
213
224
 
214
225
  if (!schema.members.length) return;
@@ -216,8 +227,8 @@ class JSONTransform extends BaseVisitor {
216
227
  found = false;
217
228
 
218
229
  if (
219
- schema.members[0]?.flags.includes(PropertyFlags.OmitNull)
220
- || schema.members[0]?.flags.includes(PropertyFlags.OmitIf)
230
+ schema.members[0]?.flags.has(PropertyFlags.OmitNull) ||
231
+ schema.members[0]?.flags.has(PropertyFlags.OmitIf)
221
232
  ) {
222
233
  SERIALIZE_RAW += schema.members[0]?.serialize;
223
234
  SERIALIZE_PRETTY += "\\n" + schema.members[0]?.serialize;
@@ -227,14 +238,15 @@ class JSONTransform extends BaseVisitor {
227
238
  found = true;
228
239
  }
229
240
 
230
- if (schema.members[0]?.initialize) INITIALIZE += " " + schema.members[0]?.initialize + ";\n";
241
+ if (schema.members[0]?.initialize)
242
+ INITIALIZE += " " + schema.members[0]?.initialize + ";\n";
231
243
 
232
244
  for (let i = 1; i < schema.members.length; i++) {
233
245
  const member = schema.members[i]!;
234
246
  if (member.initialize) INITIALIZE += " " + member.initialize + ";\n";
235
247
  if (
236
- member.flags.includes(PropertyFlags.OmitNull)
237
- || member.flags.includes(PropertyFlags.OmitIf)
248
+ member.flags.has(PropertyFlags.OmitNull) ||
249
+ member.flags.has(PropertyFlags.OmitIf)
238
250
  ) {
239
251
  SERIALIZE_RAW += member.serialize;
240
252
  SERIALIZE_PRETTY += member.serialize;
@@ -246,17 +258,21 @@ class JSONTransform extends BaseVisitor {
246
258
  }
247
259
 
248
260
  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}";
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}";
251
265
  } else {
252
266
  SERIALIZE_RAW += "`;\n};";
253
267
  SERIALIZE_PRETTY += "`;\n};";
254
268
  }
255
269
 
256
- INITIALIZE += " return this;\n}"
270
+ INITIALIZE += " return this;\n}";
257
271
 
258
272
  const sortedMembers: Property[][] = [];
259
- 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
+ );
260
276
  let len = 0;
261
277
  let offset = 0;
262
278
  sortedMembers.push([_sorted[0]!]);
@@ -265,7 +281,7 @@ class JSONTransform extends BaseVisitor {
265
281
  const member = _sorted[i]!;
266
282
  if (member.alias?.length || member.name.length > len) {
267
283
  sortedMembers.push([member]);
268
- len = member.alias?.length || member.name.length
284
+ len = member.alias?.length || member.name.length;
269
285
  offset++;
270
286
  } else {
271
287
  sortedMembers[offset]!.push(member);
@@ -278,24 +294,30 @@ class JSONTransform extends BaseVisitor {
278
294
  const name = encodeKey(firstMember.alias || firstMember.name);
279
295
  if (name.length === 1) {
280
296
  if (first) {
281
- 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";
282
299
  first = false;
283
300
  } else {
284
- 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";
285
303
  }
286
304
  } else if (name.length === 2) {
287
305
  if (first) {
288
- 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";
289
308
  first = false;
290
309
  } else {
291
- 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";
292
312
  }
293
313
  } else if (name.length === 4) {
294
314
  if (first) {
295
- 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";
296
317
  first = false;
297
318
  } else {
298
- 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";
299
321
  }
300
322
  } else {
301
323
  if (first) {
@@ -319,28 +341,36 @@ class JSONTransform extends BaseVisitor {
319
341
  f = false;
320
342
  DESERIALIZE += ` if (${charCodeAt64(name, 0)} === code) {\n ${member.deserialize}\n return true;\n }\n`;
321
343
  } else {
322
- 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`;
323
347
  }
324
348
  } else {
325
349
  if (f) {
326
350
  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`
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`;
328
352
  } 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`
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`;
330
356
  }
331
357
  }
332
358
  }
333
359
  if (name.length < 3) {
334
- DESERIALIZE += ` default: {\n return false;\n }\n }\n`
360
+ DESERIALIZE += ` default: {\n return false;\n }\n }\n`;
335
361
  } else if (name.length == 4) {
336
- 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`;
337
365
  } else {
338
- 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`;
339
369
  }
340
370
  DESERIALIZE += " } ";
341
371
  }
342
372
 
343
- DESERIALIZE += "\n return false;\n}"
373
+ DESERIALIZE += "\n return false;\n}";
344
374
 
345
375
  //console.log(sortedMembers);
346
376
 
@@ -351,14 +381,20 @@ class JSONTransform extends BaseVisitor {
351
381
  console.log(DESERIALIZE);
352
382
  }
353
383
 
354
- const SERIALIZE_RAW_METHOD = SimpleParser.parseClassMember(SERIALIZE_RAW, node);
384
+ const SERIALIZE_RAW_METHOD = SimpleParser.parseClassMember(
385
+ SERIALIZE_RAW,
386
+ node,
387
+ );
355
388
  //const SERIALIZE_PRETTY_METHOD = SimpleParser.parseClassMember(SERIALIZE_PRETTY, node);
356
389
  const INITIALIZE_METHOD = SimpleParser.parseClassMember(INITIALIZE, node);
357
390
  const DESERIALIZE_METHOD = SimpleParser.parseClassMember(DESERIALIZE, node);
358
391
 
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);
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);
362
398
 
363
399
  this.schemasList.push(schema);
364
400
  }
@@ -405,27 +441,32 @@ export default class Transformer extends Transform {
405
441
  for (const schema of schemas) {
406
442
  if (schema.parent) {
407
443
  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.`);
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
+ );
409
448
  }
410
449
  }
411
450
  }
412
451
  }
413
452
 
414
453
  enum PropertyFlags {
415
- None,
416
454
  Omit,
417
455
  OmitNull,
418
456
  OmitIf,
419
457
  Alias,
420
- Flatten
458
+ JSON_Raw,
421
459
  }
422
460
 
423
461
  class Property {
424
- public name: string = ""
462
+ public name: string = "";
425
463
  public alias: string | null = null;
426
464
  public type: string = "";
427
465
  public value: string | null = null;
428
- public flags: PropertyFlags[] = [];
466
+ public flags: Map<PropertyFlags, string[]> = new Map<
467
+ PropertyFlags,
468
+ string[]
469
+ >();
429
470
  public args: string[] | null = [];
430
471
 
431
472
  public serialize: string | null = null;
@@ -433,11 +474,57 @@ class Property {
433
474
  public initialize: string | null = null;
434
475
 
435
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
+ }
436
523
  }
437
524
 
438
525
  class SchemaData {
439
526
  public name: string = "";
440
- public members: Property[] = []
527
+ public members: Property[] = [];
441
528
  public parent: SchemaData | null = null;
442
529
  public node!: ClassDeclaration;
443
530
  }
@@ -448,7 +535,9 @@ function charCodeAt32(data: string, offset: number): number {
448
535
 
449
536
  function charCodeAt64(data: string, offset: number): bigint {
450
537
  if (offset + 3 >= data.length) {
451
- 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
+ );
452
541
  }
453
542
 
454
543
  const firstCharCode = BigInt(data.charCodeAt(offset));
@@ -456,7 +545,11 @@ function charCodeAt64(data: string, offset: number): bigint {
456
545
  const thirdCharCode = BigInt(data.charCodeAt(offset + 2));
457
546
  const fourthCharCode = BigInt(data.charCodeAt(offset + 3));
458
547
 
459
- const u64Value = (fourthCharCode << 48n) | (thirdCharCode << 32n) | (secondCharCode << 16n) | firstCharCode;
548
+ const u64Value =
549
+ (fourthCharCode << 48n) |
550
+ (thirdCharCode << 32n) |
551
+ (secondCharCode << 16n) |
552
+ firstCharCode;
460
553
 
461
554
  return u64Value;
462
555
  }
@@ -467,15 +560,24 @@ function encodeKey(key: string): string {
467
560
  }
468
561
 
469
562
  function escapeString(data: string): string {
470
- return data.replace(/\\/g, "\\\\")
471
- .replace(/\`/g, '\\`');
563
+ return data.replace(/\\/g, "\\\\").replace(/\`/g, "\\`");
472
564
  }
473
565
 
474
566
  function escapeSlash(data: string): string {
475
- return data.replace(/\\/g, "\\\\")
476
- .replace(/\`/g, '\\`');
567
+ return data.replace(/\\/g, "\\\\").replace(/\`/g, "\\`");
477
568
  }
478
569
 
479
570
  function escapeQuote(data: string): string {
480
- return data.replace(/\"/g, "\\\"");
481
- }
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,