json-as 0.5.6 → 0.5.8

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/README.md CHANGED
@@ -1,10 +1,6 @@
1
1
  # AS-JSON
2
2
  ![AssemblyScript](https://img.shields.io/badge/AssemblyScript-blue)
3
3
  ![WebAssembly](https://img.shields.io/badge/WebAssemby-purple)
4
-
5
- ## Features
6
-
7
- Full
8
4
  ## Installation
9
5
 
10
6
  ```bash
@@ -90,6 +86,19 @@ const stringified = JSON.stringify<Player>(data);
90
86
  const parsed = JSON.parse<Player>(stringified);
91
87
  ```
92
88
 
89
+ # FAQ
90
+
91
+ **Does it support the JSON specification?**
92
+ Yes, it does. However, dynamic objects and arrays are not supported, but planned in the near future.
93
+
94
+ **Is it fast?**
95
+ Look below
96
+
97
+ **How does it compare to other librarys?**
98
+ Its pretty much the same as the other libraries out there (near/assemblyscript-json and @serial-as/json), but it focuses highly on performance
99
+
100
+ **Will it catch invalid JSON?**
101
+ No, it does not check for invalid JSON, but gives its best shot at parsing instead. Will probably throw an error.
93
102
 
94
103
  ## Performance
95
104
 
package/asconfig.json CHANGED
@@ -12,7 +12,7 @@
12
12
  "options": {
13
13
  "transform": ["./transform"],
14
14
  "bindings": "esm",
15
- "extends": "./node_modules/@assemblyscript/wasi-shim/asconfig.json"
15
+ "exportStart": "_start"
16
16
  },
17
17
  "extends": "./node_modules/@assemblyscript/wasi-shim/asconfig.json"
18
18
  }
@@ -40,16 +40,16 @@ describe("Ser/de Numbers", () => {
40
40
  canSerde<u64>(101);
41
41
  canSerde<i32>(-100);
42
42
  canSerde<i64>(-101);
43
-
43
+ /*
44
44
  canSerde<u128>(u128.from("0"))
45
45
  canSerde<u128>(u128.from("100"))
46
46
  canSerde<u128>(u128.from("101"))
47
-
47
+ `
48
48
  canSerde<u128Safe>(u128Safe.from("0"))
49
49
  canSerde<u128Safe>(u128Safe.from("100"))
50
50
  canSerde<u128Safe>(u128Safe.from("101"))
51
51
 
52
- /* canSerde<u256>(u256.fromU128(u128.from("0")))
52
+ canSerde<u256>(u256.fromU128(u128.from("0")))
53
53
  canSerde<u256>(u256.fromU128(u128.from("100")))
54
54
  canSerde<u256>(u256.fromU128(u128.from("101")))
55
55
 
@@ -65,9 +65,9 @@ describe("Ser/de Numbers", () => {
65
65
  canSerde<i128Safe>(i128Safe.from("100"))
66
66
  canSerde<i128Safe>(i128Safe.from("101"))
67
67
  canSerde<i128Safe>(i128Safe.from("-100"))
68
- canSerde<i128Safe>(i128Safe.from("-101"))
68
+ canSerde<i128Safe>(i128Safe.from("-101"))*/
69
69
 
70
- canSerde<i256Safe>(new i256Safe(10, 11, 500, 501))*/
70
+ //canSerde<i256Safe>(new i256Safe(10, 11, 500, 501))
71
71
  });
72
72
 
73
73
  it("should ser/de floats", () => {
@@ -81,6 +81,8 @@ export namespace JSON {
81
81
  } else if ((isManaged<T>() || isReference<T>()) && isBigNum<T>()) {
82
82
  // @ts-ignore
83
83
  return data.toString();
84
+ } else if (data instanceof Date) {
85
+ return data.toISOString();
84
86
  } else {
85
87
  throw new Error(`Could not serialize data of type ${nameof<T>()}. Invalid data provided.`);
86
88
  }
@@ -152,21 +154,17 @@ export namespace JSON {
152
154
  throw new Error(`Could not deserialize data ${data} to type ${nameof<T>()}. Invalide data provided.`)
153
155
  }
154
156
  }
155
- /*export class Arr extends Array<Variant> {
156
- public data: Variant[] = [];
157
- push<T>(data: T): i32 {
158
- return this.data.push(Variant.from<T>(data));
159
- }
160
- at<T>(index: i32): T {
161
- return this.data.at(index).get<T>();
162
- }
163
- }*/
157
+ // @ts-ignore
158
+ @unsafe
159
+ export function createObjectUnsafe<T>(): T {
160
+ return changetype<nonnull<T>>(__new(offsetof<nonnull<T>>(), idof<nonnull<T>>()))
161
+ }
164
162
  }
165
163
 
166
164
  // @ts-ignore
167
165
  @inline
168
- // @ts-ignore
169
- function parseBigNum<T>(data: string): T {
166
+ // @ts-ignore
167
+ function parseBigNum<T>(data: string): T {
170
168
  // @ts-ignore
171
169
  if (idof<T>() == idof<u128>()) return u128.fromString(data);
172
170
  // @ts-ignore
@@ -180,18 +178,18 @@ export namespace JSON {
180
178
  // @ts-ignore
181
179
  if (idof<T>() == idof<i128Safe>()) return i128Safe.fromString(data);
182
180
  // @ts-ignore
183
- if (idof<T>() == idof<i256Safe>()) return i256Safe.fromString(data);
181
+ //if (idof<T>() == idof<i256Safe>()) return data.
184
182
  }
185
183
 
186
184
  // @ts-ignore
187
185
  @inline
188
- function parseString(data: string): string {
186
+ function parseString(data: string): string {
189
187
  return data.slice(1, data.length - 1).replaceAll('\\"', '"');
190
188
  }
191
189
 
192
190
  // @ts-ignore
193
191
  @inline
194
- function parseBoolean<T extends boolean>(data: string): T {
192
+ function parseBoolean<T extends boolean>(data: string): T {
195
193
  if (data.length > 3 && data.startsWith("true")) return <T>true;
196
194
  else if (data.length > 4 && data.startsWith("false")) return <T>false;
197
195
  else throw new Error(`JSON: Cannot parse "${data}" as boolean`);
@@ -199,7 +197,7 @@ export namespace JSON {
199
197
 
200
198
  // @ts-ignore
201
199
  @inline
202
- function parseNumber<T>(data: string): T {
200
+ function parseNumber<T>(data: string): T {
203
201
  let type: T;
204
202
  // @ts-ignore
205
203
  if (type instanceof f64) return F64.parseFloat(data);
@@ -221,15 +219,15 @@ export namespace JSON {
221
219
  else if (type instanceof i16) return I16.parseInt(data);
222
220
  // @ts-ignore
223
221
  else if (type instanceof i8) return I8.parseInt(data);
224
- else
225
- throw new Error(
226
- `JSON: Cannot parse invalid data into a number. Either "${data}" is not a valid number, or <${nameof<T>()}> is an invald number type.`
227
- );
222
+
223
+ throw new Error(
224
+ `JSON: Cannot parse invalid data into a number. Either "${data}" is not a valid number, or <${nameof<T>()}> is an invald number type.`
225
+ );
228
226
  }
229
227
 
230
228
  // @ts-ignore
231
229
  @inline
232
- export function parseObject<T>(data: string): T {
230
+ export function parseObject<T>(data: string): T {
233
231
  let schema: nonnull<T> = changetype<nonnull<T>>(__new(offsetof<nonnull<T>>(), idof<nonnull<T>>()));
234
232
  let key = "";
235
233
  let isKey = false;
@@ -251,6 +249,7 @@ export namespace JSON {
251
249
  depth = depth >> 1;
252
250
  if (depth === 1) {
253
251
  ++arrayValueIndex;
252
+ // @ts-ignore
254
253
  schema.__JSON_Set_Key(key, data.slice(outerLoopIndex, arrayValueIndex));
255
254
  outerLoopIndex = arrayValueIndex;
256
255
  isKey = false;
@@ -271,6 +270,7 @@ export namespace JSON {
271
270
  depth = depth >> 1;
272
271
  if (depth === 1) {
273
272
  ++objectValueIndex;
273
+ // @ts-ignore
274
274
  schema.__JSON_Set_Key(key, data.slice(outerLoopIndex, objectValueIndex));
275
275
  outerLoopIndex = objectValueIndex;
276
276
  isKey = false;
@@ -293,6 +293,7 @@ export namespace JSON {
293
293
  key = data.slice(outerLoopIndex, stringValueIndex);
294
294
  isKey = true;
295
295
  } else {
296
+ // @ts-ignore
296
297
  schema.__JSON_Set_Key(key, data.slice(outerLoopIndex, stringValueIndex));
297
298
  isKey = false;
298
299
  }
@@ -301,6 +302,7 @@ export namespace JSON {
301
302
  }
302
303
  }
303
304
  } else if (char == nCode) {
305
+ // @ts-ignore
304
306
  schema.__JSON_Set_Key(key, nullWord);
305
307
  isKey = false;
306
308
  } else if (
@@ -309,6 +311,7 @@ export namespace JSON {
309
311
  unsafeCharCodeAt(data, ++outerLoopIndex) === uCode &&
310
312
  unsafeCharCodeAt(data, ++outerLoopIndex) === eCode
311
313
  ) {
314
+ // @ts-ignore
312
315
  schema.__JSON_Set_Key(key, trueWord);
313
316
  isKey = false;
314
317
  } else if (
@@ -318,6 +321,7 @@ export namespace JSON {
318
321
  unsafeCharCodeAt(data, ++outerLoopIndex) === "s".charCodeAt(0) &&
319
322
  unsafeCharCodeAt(data, ++outerLoopIndex) === eCode
320
323
  ) {
324
+ // @ts-ignore
321
325
  schema.__JSON_Set_Key(key, "false");
322
326
  isKey = false;
323
327
  } else if ((char >= 48 && char <= 57) || char === 45) {
@@ -325,6 +329,7 @@ export namespace JSON {
325
329
  for (; numberValueIndex < data.length; numberValueIndex++) {
326
330
  char = unsafeCharCodeAt(data, numberValueIndex);
327
331
  if (char === commaCode || char === rightBraceCode || isSpace(char)) {
332
+ // @ts-ignore
328
333
  schema.__JSON_Set_Key(key, data.slice(outerLoopIndex - 1, numberValueIndex));
329
334
  outerLoopIndex = numberValueIndex;
330
335
  isKey = false;
@@ -338,8 +343,8 @@ export namespace JSON {
338
343
 
339
344
  // @ts-ignore
340
345
  @inline
341
- // @ts-ignore
342
- export function parseArray<T extends unknown[]>(data: string): T {
346
+ // @ts-ignore
347
+ export function parseArray<T extends unknown[]>(data: string): T {
343
348
  let type!: valueof<T>;
344
349
  if (type instanceof String) {
345
350
  return <T>parseStringArray(data);
@@ -361,7 +366,7 @@ export namespace JSON {
361
366
 
362
367
  // @ts-ignore
363
368
  @inline
364
- export function parseStringArray(data: string): string[] {
369
+ export function parseStringArray(data: string): string[] {
365
370
  const result: string[] = [];
366
371
  let lastPos = 0;
367
372
  let instr = false;
@@ -381,7 +386,7 @@ export namespace JSON {
381
386
 
382
387
  // @ts-ignore
383
388
  @inline
384
- export function parseBooleanArray<T extends boolean[]>(data: string): T {
389
+ export function parseBooleanArray<T extends boolean[]>(data: string): T {
385
390
  const result = instantiate<T>();
386
391
  let lastPos = 1;
387
392
  let char = 0;
@@ -409,7 +414,7 @@ export namespace JSON {
409
414
 
410
415
  // @ts-ignore
411
416
  @inline
412
- export function parseNumberArray<T extends number[]>(data: string): T {
417
+ export function parseNumberArray<T extends number[]>(data: string): T {
413
418
  const result = instantiate<T>();
414
419
  let lastPos = 0;
415
420
  let char = 0;
@@ -435,7 +440,7 @@ export namespace JSON {
435
440
 
436
441
  // @ts-ignore
437
442
  @inline
438
- export function parseArrayArray<T extends unknown[][]>(data: string): T {
443
+ export function parseArrayArray<T extends unknown[][]>(data: string): T {
439
444
  const result = instantiate<T>();
440
445
  let char = 0;
441
446
  let lastPos = 0;
@@ -465,7 +470,7 @@ export namespace JSON {
465
470
 
466
471
  // @ts-ignore
467
472
  @inline
468
- export function parseObjectArray<T extends unknown[][]>(data: string): T {
473
+ export function parseObjectArray<T extends unknown[][]>(data: string): T {
469
474
  const result = instantiate<T>();
470
475
  let char = 0;
471
476
  let lastPos = 1;
package/assembly/test.ts CHANGED
@@ -1,15 +1,50 @@
1
- import "wasi";
2
- import { u128 } from "as-bignum/assembly";
1
+ import { wasi_console } from "@assemblyscript/wasi-shim/assembly/wasi_console";
3
2
  import {
4
3
  JSON
5
4
  } from ".";
5
+ @json
6
+ class Player {
7
+ firstName: string;
8
+ lastName: string;
9
+ lastActive: i32[];
10
+ age: i32;
11
+ pos: Vec3 | null;
12
+ isVerified: boolean;
13
+ stats: Stats
14
+ }
15
+
16
+ @json
17
+ class Contacts {
18
+ type: string
19
+ player: string
20
+ }
6
21
 
22
+ const player = JSON.createObjectUnsafe<Player>()
23
+
24
+ player.firstName = "John";
25
+ player.lastName = "West";
26
+ player.age = 23;
27
+
28
+ const contact: Contacts = {
29
+ player: JSON.stringify(player),
30
+ type: "friends"
31
+ }
32
+
33
+ let stringifiedContact = JSON.stringify(contact);
34
+ console.log("Input (Should see backslashes logged): " + stringifiedContact);
35
+ const contacts = JSON.parse<Contacts>(stringifiedContact)
36
+ console.log("Player: " + contacts.player);
37
+ console.log("Type: " + contacts.type);
38
+ const parsedPlayer = JSON.parse<Player>(contacts.player);
39
+ console.log("Final Player: " + JSON.stringify(parsedPlayer));
40
+ console.log("Final Result (Contacts): " + JSON.stringify(contacts));/*
41
+ /*
7
42
  // @ts-ignore
8
43
  @json
9
44
  class Stats {
10
45
  wins: u128
11
46
  loss: u128
12
- }
47
+ }*/
13
48
  // @ts-ignore
14
49
  @json
15
50
  class Vec3 {
@@ -17,7 +52,20 @@ class Vec3 {
17
52
  y: f32;
18
53
  z: f32;
19
54
  }
20
-
55
+ // @ts-ignore
56
+ @json
57
+ class Test {
58
+ data: string
59
+ }
60
+ const vec: Vec3 = {
61
+ x: 3.4,
62
+ y: 1.2,
63
+ z: 8.3
64
+ }
65
+ const test: Test = {
66
+ data: JSON.stringify(vec)
67
+ }
68
+ /*
21
69
  // @ts-ignore
22
70
  @json
23
71
  class Player {
@@ -46,8 +94,10 @@ const player: Player = {
46
94
  loss: u128.fromString("693")
47
95
  }
48
96
  };
49
-
50
- const serializedPlayer = JSON.stringify<Player>(player);
51
- console.log("Serialized Player: " + serializedPlayer);
52
- const deserializedPlayer = JSON.parse<Player>(serializedPlayer);
53
- console.log("Deserialized Player: " + JSON.stringify(deserializedPlayer));
97
+ *//*
98
+ const serializedPlayer = JSON.stringify<Test>(test);
99
+ wasi_console.log("Serialized Player: " + serializedPlayer);
100
+ const deserializedPlayer = JSON.parse<Test>(serializedPlayer);
101
+ wasi_console.log("Deserialized Player: " + JSON.stringify(deserializedPlayer));
102
+ wasi_console.log("Deserialize Vec3: " + JSON.stringify(JSON.parse<Vec3>(deserializedPlayer.data)))
103
+ */
@@ -1,9 +1,6 @@
1
- {
2
- "extends": "assemblyscript/std/assembly.json",
3
- "compilerOptions": {
4
- "experimentalDecorators": true
5
- },
6
- "include": [
7
- "./**/*.ts"
8
- ]
1
+ {
2
+ "extends": "assemblyscript/std/assembly.json",
3
+ "include": [
4
+ "./**/*.ts"
5
+ ]
9
6
  }
@@ -0,0 +1,2 @@
1
+ *
2
+ !.gitignore
package/index.html ADDED
@@ -0,0 +1,10 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <script type="module">
5
+ import { add } from "./build/release.js";
6
+ document.body.innerText = add(1, 2);
7
+ </script>
8
+ </head>
9
+ <body></body>
10
+ </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "json-as",
3
- "version": "0.5.6",
3
+ "version": "0.5.8",
4
4
  "description": "JSON encoder/decoder for AssemblyScript",
5
5
  "types": "assembly/index.ts",
6
6
  "author": "Jairus Tanaka",
@@ -16,14 +16,20 @@
16
16
  "test:wasmtime": "wasmtime ./build/test.wasm",
17
17
  "test:lunatic": "lunatic ./build/test.wasm",
18
18
  "test:wasm3": "wasm3 ./build/test.wasm",
19
- "prettier": "as-prettier -w ."
19
+ "prettier": "as-prettier -w .",
20
+ "asbuild:debug": "asc assembly/index.ts --target debug",
21
+ "asbuild:release": "asc assembly/index.ts --target release",
22
+ "asbuild": "yarn asbuild:debug && yarn asbuild:release",
23
+ "test": "node tests",
24
+ "start": "npx serve ."
20
25
  },
21
26
  "devDependencies": {
22
27
  "@as-pect/cli": "^7.0.7",
23
- "@as-tral/cli": "^1.1.1",
28
+ "@as-tral/cli": "^1.2.0",
24
29
  "@assemblyscript/loader": "^0.21.3",
25
- "@serial-as/json": "^2.0.0",
26
- "assemblyscript": "^0.20.7",
30
+ "@assemblyscript/wasi-shim": "^0.1.0",
31
+ "as-bignum": "^0.2.23",
32
+ "assemblyscript": "^0.24.1",
27
33
  "assemblyscript-prettier": "^1.0.2",
28
34
  "prettier": "^2.7.1",
29
35
  "typescript": "^4.7.2"
@@ -48,5 +54,11 @@
48
54
  "url": "https://github.com/JairusSW/as-json/issues"
49
55
  },
50
56
  "homepage": "https://github.com/JairusSW/as-json#readme",
51
- "type": "module"
57
+ "type": "module",
58
+ "exports": {
59
+ ".": {
60
+ "import": "./build/release.js",
61
+ "types": "./build/release.d.ts"
62
+ }
63
+ }
52
64
  }
@@ -1,15 +1,23 @@
1
1
  import { ClassDecorator, registerDecorator, } from "visitor-as/dist/decorator.js";
2
2
  import { getName, toString } from "visitor-as/dist/utils.js";
3
3
  import { SimpleParser } from "visitor-as/dist/index.js";
4
+ class SchemaData {
5
+ constructor() {
6
+ this.keys = [];
7
+ this.values = [];
8
+ this.types = [];
9
+ this.name = "";
10
+ this.parent = "";
11
+ this.encodeStmts = [];
12
+ this.setDataStmts = [];
13
+ }
14
+ }
4
15
  class AsJSONTransform extends ClassDecorator {
5
16
  constructor() {
6
17
  super(...arguments);
18
+ this.schemasList = [];
7
19
  this.sources = [];
8
- this.encodeStmts = [];
9
- //public decodeStmts: string[] = [];
10
- this.setDataStmts = [];
11
20
  }
12
- //public checkDecodeStmts: string[] = [];
13
21
  visitMethodDeclaration() { }
14
22
  visitFieldDeclaration(node) {
15
23
  const lineText = toString(node);
@@ -21,13 +29,13 @@ class AsJSONTransform extends ClassDecorator {
21
29
  }
22
30
  let type = getName(node.type);
23
31
  // @ts-ignore
24
- this.encodeStmts.push(`"${name}":\${JSON.stringify<${type}>(this.${name})},`);
32
+ this.currentClass.encodeStmts.push(`"${name}":\${JSON.stringify<${type}>(this.${name})},`);
25
33
  // @ts-ignore
26
34
  //this.decodeStmts.push(
27
35
  // `${name}: JSON.parseObjectValue<${type}>(values.get("${name}")),\n`
28
36
  //);
29
37
  // @ts-ignore
30
- this.setDataStmts.push(`if (key.length === ${name.length} && (memory.compare(changetype<usize>("${name}"), changetype<usize>(key), ${name.length}) == 0)) {
38
+ this.currentClass.setDataStmts.push(`if (key.length === ${name.length} && (memory.compare(changetype<usize>("${name}"), changetype<usize>(key), ${name.length}) == 0)) {
31
39
  this.${name} = JSON.parseObjectValue<${type}>(value);
32
40
  return;
33
41
  }
@@ -38,19 +46,43 @@ class AsJSONTransform extends ClassDecorator {
38
46
  //);
39
47
  }
40
48
  visitClassDeclaration(node) {
49
+ var _a, _b, _c;
41
50
  if (!node.members) {
42
51
  return;
43
52
  }
44
- this.currentClass = node;
53
+ this.currentClass = {
54
+ name: toString(node.name),
55
+ keys: [],
56
+ values: [],
57
+ types: [],
58
+ parent: node.extendsType ? toString(node.extendsType) : "",
59
+ node: node,
60
+ encodeStmts: [],
61
+ setDataStmts: []
62
+ };
63
+ if (this.currentClass.parent.length > 0) {
64
+ const parentSchema = this.schemasList.map((v) => {
65
+ if (v.name == this.currentClass.parent) {
66
+ return v;
67
+ }
68
+ });
69
+ if (parentSchema.length > 0) {
70
+ (_a = parentSchema[0]) === null || _a === void 0 ? void 0 : _a.encodeStmts.push(((_b = parentSchema[0]) === null || _b === void 0 ? void 0 : _b.encodeStmts.pop()) + ",");
71
+ this.currentClass.encodeStmts.push(...(_c = parentSchema[0]) === null || _c === void 0 ? void 0 : _c.encodeStmts);
72
+ }
73
+ else {
74
+ //console.log("Class extends " + this.currentClass.parent + ", but parent class not found. Maybe add the @json decorator over parent class?")
75
+ }
76
+ }
45
77
  this.visit(node.members);
46
- const serializedProp = '__JSON_Serialized: string = "";';
78
+ // const serializedProp = '__JSON_Serialized: string = "";';
47
79
  let serializeFunc = "";
48
- if (this.encodeStmts.length > 0) {
49
- const stmt = this.encodeStmts[this.encodeStmts.length - 1];
50
- this.encodeStmts[this.encodeStmts.length - 1] = stmt.slice(0, stmt.length - 1);
80
+ if (this.currentClass.encodeStmts.length > 0) {
81
+ const stmt = this.currentClass.encodeStmts[this.currentClass.encodeStmts.length - 1];
82
+ this.currentClass.encodeStmts[this.currentClass.encodeStmts.length - 1] = stmt.slice(0, stmt.length - 1);
51
83
  serializeFunc = `
52
84
  __JSON_Serialize(): string {
53
- return \`{${this.encodeStmts.join("")}}\`;
85
+ return \`{${this.currentClass.encodeStmts.join("")}}\`;
54
86
  }
55
87
  `;
56
88
  }
@@ -61,44 +93,24 @@ class AsJSONTransform extends ClassDecorator {
61
93
  }
62
94
  `;
63
95
  }
64
- /*const deserializeFunc = `
65
- __JSON_Deserialize<T>(values: Map<string, string>): T {
66
- ${
67
- process.argv.includes("--debugJSON")
68
- ? this.checkDecodeStmts.join("else")
69
- : ""
70
- }
71
- return {
72
- ${
73
- // @ts-ignore
74
- this.decodeStmts.join("")
75
- }
76
- }
77
- }
78
- `;*/
79
96
  const setKeyFunc = `
80
97
  __JSON_Set_Key(key: string, value: string): void {
81
98
  ${
82
99
  // @ts-ignore
83
- this.setDataStmts.join("")}
100
+ this.currentClass.setDataStmts.join("")}
84
101
  }
85
102
  `;
86
- //console.log(setKeyFunc, deserializeFunc, serializeFunc)
87
- this.encodeStmts = [];
88
- //this.decodeStmts = [];
89
- this.setDataStmts = [];
90
- //this.checkDecodeStmts = [];
91
- const serializedProperty = SimpleParser.parseClassMember(serializedProp, node);
92
- node.members.push(serializedProperty);
93
- const serializeMethod = SimpleParser.parseClassMember(serializeFunc, node);
94
- node.members.push(serializeMethod);
95
- //const deserializeMethod = SimpleParser.parseClassMember(
96
- // deserializeFunc,
103
+ //console.log(serializeFunc)
104
+ //const serializedProperty = SimpleParser.parseClassMember(
105
+ // serializedProp,
97
106
  // node
98
107
  //);
99
- //node.members.push(deserializeMethod);
108
+ //node.members.push(serializedProperty);
109
+ const serializeMethod = SimpleParser.parseClassMember(serializeFunc, node);
110
+ node.members.push(serializeMethod);
100
111
  const setDataMethod = SimpleParser.parseClassMember(setKeyFunc, node);
101
112
  node.members.push(setDataMethod);
113
+ this.schemasList.push(this.currentClass);
102
114
  }
103
115
  get name() {
104
116
  return "json";
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@json-as/transform",
3
- "version": "0.5.6",
3
+ "version": "0.5.8",
4
4
  "description": "JSON encoder/decoder for AssemblyScript",
5
5
  "main": "./lib/index.js",
6
6
  "author": "Jairus Tanaka",
@@ -10,7 +10,7 @@
10
10
  "license": "MIT",
11
11
  "devDependencies": {},
12
12
  "dependencies": {
13
- "visitor-as": "^0.10.2"
13
+ "visitor-as": "^0.11.3"
14
14
  },
15
15
  "repository": {
16
16
  "type": "git",
@@ -10,15 +10,22 @@ import {
10
10
  import { getName, toString } from "visitor-as/dist/utils.js";
11
11
  import { SimpleParser } from "visitor-as/dist/index.js";
12
12
 
13
- class AsJSONTransform extends ClassDecorator {
14
- public currentClass!: ClassDeclaration;
15
- public sources: Source[] = [];
13
+ class SchemaData {
14
+ public keys: string[] = [];
15
+ public values: string[] = [];
16
+ public types: string[] = [];
17
+ public name: string = "";
18
+ public parent: string = "";
19
+ public node!: ClassDeclaration;
16
20
  public encodeStmts: string[] = [];
17
- //public decodeStmts: string[] = [];
18
21
  public setDataStmts: string[] = [];
19
- //public checkDecodeStmts: string[] = [];
22
+ }
23
+ class AsJSONTransform extends ClassDecorator {
24
+ public schemasList: SchemaData[] = [];
25
+ public currentClass!: SchemaData;
26
+ public sources: Source[] = [];
20
27
 
21
- visitMethodDeclaration(): void {}
28
+ visitMethodDeclaration(): void { }
22
29
  visitFieldDeclaration(node: FieldDeclaration): void {
23
30
  const lineText = toString(node);
24
31
  if (lineText.startsWith("private")) return;
@@ -29,17 +36,17 @@ class AsJSONTransform extends ClassDecorator {
29
36
 
30
37
  let type = getName(node.type);
31
38
  // @ts-ignore
32
- this.encodeStmts.push(
39
+ this.currentClass.encodeStmts.push(
33
40
  `"${name}":\${JSON.stringify<${type}>(this.${name})},`
34
41
  );
35
42
 
36
43
  // @ts-ignore
37
44
  //this.decodeStmts.push(
38
- // `${name}: JSON.parseObjectValue<${type}>(values.get("${name}")),\n`
45
+ // `${name}: JSON.parseObjectValue<${type}>(values.get("${name}")),\n`
39
46
  //);
40
47
 
41
48
  // @ts-ignore
42
- this.setDataStmts.push(
49
+ this.currentClass.setDataStmts.push(
43
50
  `if (key.length === ${name.length} && (memory.compare(changetype<usize>("${name}"), changetype<usize>(key), ${name.length}) == 0)) {
44
51
  this.${name} = JSON.parseObjectValue<${type}>(value);
45
52
  return;
@@ -57,23 +64,46 @@ class AsJSONTransform extends ClassDecorator {
57
64
  return;
58
65
  }
59
66
 
60
- this.currentClass = node;
67
+ this.currentClass = {
68
+ name: toString(node.name),
69
+ keys: [],
70
+ values: [],
71
+ types: [],
72
+ parent: node.extendsType ? toString(node.extendsType) : "",
73
+ node: node,
74
+ encodeStmts: [],
75
+ setDataStmts: []
76
+ }
77
+
78
+ if (this.currentClass.parent.length > 0) {
79
+ const parentSchema = this.schemasList.map((v) => {
80
+ if (v.name == this.currentClass.parent) {
81
+ return v;
82
+ }
83
+ });
84
+ if (parentSchema.length > 0) {
85
+ parentSchema[0]?.encodeStmts.push(parentSchema[0]?.encodeStmts.pop() + ",")
86
+ this.currentClass.encodeStmts.push(...parentSchema[0]?.encodeStmts)
87
+ } else {
88
+ //console.log("Class extends " + this.currentClass.parent + ", but parent class not found. Maybe add the @json decorator over parent class?")
89
+ }
90
+ }
61
91
 
62
92
  this.visit(node.members);
63
93
 
64
- const serializedProp = '__JSON_Serialized: string = "";';
94
+ // const serializedProp = '__JSON_Serialized: string = "";';
65
95
 
66
96
  let serializeFunc = "";
67
97
 
68
- if (this.encodeStmts.length > 0) {
69
- const stmt = this.encodeStmts[this.encodeStmts.length - 1]!;
70
- this.encodeStmts[this.encodeStmts.length - 1] = stmt!.slice(
98
+ if (this.currentClass.encodeStmts.length > 0) {
99
+ const stmt = this.currentClass.encodeStmts[this.currentClass.encodeStmts.length - 1]!;
100
+ this.currentClass.encodeStmts[this.currentClass.encodeStmts.length - 1] = stmt!.slice(
71
101
  0,
72
102
  stmt.length - 1
73
103
  );
74
104
  serializeFunc = `
75
105
  __JSON_Serialize(): string {
76
- return \`{${this.encodeStmts.join("")}}\`;
106
+ return \`{${this.currentClass.encodeStmts.join("")}}\`;
77
107
  }
78
108
  `;
79
109
  } else {
@@ -83,53 +113,32 @@ class AsJSONTransform extends ClassDecorator {
83
113
  }
84
114
  `;
85
115
  }
86
- /*const deserializeFunc = `
87
- __JSON_Deserialize<T>(values: Map<string, string>): T {
88
- ${
89
- process.argv.includes("--debugJSON")
90
- ? this.checkDecodeStmts.join("else")
91
- : ""
92
- }
93
- return {
94
- ${
95
- // @ts-ignore
96
- this.decodeStmts.join("")
97
- }
98
- }
99
- }
100
- `;*/
116
+
101
117
  const setKeyFunc = `
102
118
  __JSON_Set_Key(key: string, value: string): void {
103
119
  ${
104
- // @ts-ignore
105
- this.setDataStmts.join("")
106
- }
120
+ // @ts-ignore
121
+ this.currentClass.setDataStmts.join("")
122
+ }
107
123
  }
108
124
  `
109
- //console.log(setKeyFunc, deserializeFunc, serializeFunc)
110
- this.encodeStmts = [];
111
- //this.decodeStmts = [];
112
- this.setDataStmts = [];
113
- //this.checkDecodeStmts = [];
114
- const serializedProperty = SimpleParser.parseClassMember(
115
- serializedProp,
116
- node
117
- );
118
- node.members.push(serializedProperty);
125
+ //console.log(serializeFunc)
126
+ //const serializedProperty = SimpleParser.parseClassMember(
127
+ // serializedProp,
128
+ // node
129
+ //);
130
+ //node.members.push(serializedProperty);
119
131
 
120
132
  const serializeMethod = SimpleParser.parseClassMember(serializeFunc, node);
121
133
  node.members.push(serializeMethod);
122
134
 
123
- //const deserializeMethod = SimpleParser.parseClassMember(
124
- // deserializeFunc,
125
- // node
126
- //);
127
- //node.members.push(deserializeMethod);
128
135
  const setDataMethod = SimpleParser.parseClassMember(
129
136
  setKeyFunc,
130
137
  node
131
138
  );
132
139
  node.members.push(setDataMethod);
140
+
141
+ this.schemasList.push(this.currentClass);
133
142
  }
134
143
  get name(): string {
135
144
  return "json";
package/assembly/json.ts DELETED
@@ -1,451 +0,0 @@
1
- import { StringSink } from "as-string-sink/assembly";
2
- import { isSpace } from "util/string";
3
- import {
4
- backSlashCode,
5
- commaCode,
6
- eCode,
7
- fCode,
8
- leftBraceCode,
9
- leftBracketCode,
10
- nCode,
11
- quoteCode,
12
- rightBraceCode,
13
- rightBracketCode,
14
- tCode,
15
- } from "./chars";
16
- import { unsafeCharCodeAt } from "./util";
17
-
18
- /**
19
- * JSON Encoder/Decoder for AssemblyScript
20
- */
21
- export class JSON {
22
- /**
23
- * Stringifies valid JSON data.
24
- * ```js
25
- * JSON.stringify<T>(data)
26
- * ```
27
- * @param data T
28
- * @returns string
29
- */
30
- static stringify<T>(data: T): string {
31
- // String
32
- if (isString<T>()) {
33
- return '"' + (<string>data).replaceAll('"', '\\"') + '"';
34
- }
35
- // Boolean
36
- else if (isBoolean<T>()) {
37
- return data ? "true" : "false";
38
- }
39
- // Nullable
40
- else if (isNullable<T>() && data == null) {
41
- return "null";
42
- }
43
- // Integers/Floats
44
- // @ts-ignore
45
- else if ((isInteger<T>() || isFloat<T>()) && isFinite(data)) {
46
- // @ts-ignore
47
- return data.toString();
48
- }
49
- // Class-Based serialization
50
- // @ts-ignore
51
- else if (isDefined(data.__JSON_Serialize)) {
52
- // @ts-ignore
53
- //if (isNullable<T>()) return "null";
54
- // @ts-ignore
55
- return data.__JSON_Serialize();
56
- }
57
- // ArrayLike
58
- else if (isArrayLike<T>()) {
59
- let result = new StringSink("[");
60
- // @ts-ignore
61
- if (data.length == 0) return "[]";
62
- // @ts-ignore
63
- for (let i = 0; i < data.length - 1; i++) {
64
- // @ts-ignore
65
- result.write(JSON.stringify(unchecked(data[i])) + ",");
66
- }
67
- // @ts-ignore
68
- result.write(JSON.stringify(unchecked(data[data.length - 1])));
69
- result.write("]");
70
- return result.toString();
71
- } else {
72
- return "null";
73
- }
74
- }
75
- /**
76
- * Parses valid JSON strings into their original format.
77
- * ```js
78
- * JSON.parse<T>(data)
79
- * ```
80
- * @param data string
81
- * @returns T
82
- */
83
- static parse<T>(data: string): T {
84
- let type!: T;
85
- if (isString<T>()) {
86
- // @ts-ignore
87
- return parseString(data);
88
- } else if (isBoolean<T>()) {
89
- // @ts-ignore
90
- return parseBoolean<T>(data);
91
- } else if (isFloat<T>() || isInteger<T>()) {
92
- return parseNumber<T>(data);
93
- } else if (isArrayLike<T>()) {
94
- // @ts-ignore
95
- return parseArray<T>(data.trimStart());
96
- // @ts-ignore
97
- } else if (isNullable<T>() && data == "null") {
98
- // @ts-ignore
99
- return null;
100
- // @ts-ignore
101
- } else if (isDefined(type.__JSON_Deserialize)) {
102
- return parseObject<T>(data.trimStart());
103
- } else {
104
- // @ts-ignore
105
- return null;
106
- }
107
- }
108
- private static parseObjectValue<T>(data: string): T {
109
- let type!: T;
110
- if (isString<T>()) {
111
- // @ts-ignore
112
- return data.replaceAll('\\"', '"');
113
- } else if (isBoolean<T>()) {
114
- // @ts-ignore
115
- return parseBoolean<T>(data);
116
- } else if (isFloat<T>() || isInteger<T>()) {
117
- return parseNumber<T>(data);
118
- } else if (isArrayLike<T>()) {
119
- // @ts-ignore
120
- return parseArray<T>(data);
121
- // @ts-ignore
122
- } else if (isNullable<T>() && data == "null") {
123
- // @ts-ignore
124
- return null;
125
- // @ts-ignore
126
- } else if (isDefined(type.__JSON_Deserialize)) {
127
- // @ts-ignore
128
- //if (isNullable<T>()) return null;
129
- return parseObject<T>(data);
130
- } else {
131
- // @ts-ignore
132
- //return null;
133
- throw new Error(`Could not parse value: ${data}`);
134
- }
135
- }
136
- }
137
-
138
- // @ts-ignore
139
- @inline
140
- function parseString(data: string): string {
141
- return data.slice(1, data.length - 1).replaceAll('\\"', '"');
142
- }
143
-
144
- // @ts-ignore
145
- @inline
146
- function parseBoolean<T extends boolean>(data: string): T {
147
- if (data.length > 3 && data.startsWith("true")) return <T>true;
148
- else if (data.length > 4 && data.startsWith("false")) return <T>false;
149
- else throw new Error(`JSON: Cannot parse "${data}" as boolean`);
150
- }
151
-
152
- // @ts-ignore
153
- @inline
154
- function parseNumber<T>(data: string): T {
155
- let type: T;
156
- // @ts-ignore
157
- if (type instanceof f64) return F64.parseFloat(data);
158
- // @ts-ignore
159
- else if (type instanceof f32) return F32.parseFloat(data);
160
- // @ts-ignore
161
- else if (type instanceof u64) return U64.parseInt(data);
162
- // @ts-ignore
163
- else if (type instanceof u32) return U32.parseInt(data);
164
- // @ts-ignore
165
- else if (type instanceof u8) return U8.parseInt(data);
166
- // @ts-ignore
167
- else if (type instanceof u16) return U16.parseInt(data);
168
- // @ts-ignore
169
- else if (type instanceof i64) return I64.parseInt(data);
170
- // @ts-ignore
171
- else if (type instanceof i32) return I32.parseInt(data);
172
- // @ts-ignore
173
- else if (type instanceof i16) return I16.parseInt(data);
174
- // @ts-ignore
175
- else if (type instanceof i8) return I8.parseInt(data);
176
- else
177
- throw new Error(
178
- `JSON: Cannot parse invalid data into a number. Either "${data}" is not a valid number, or <${nameof<T>()}> is an invald number type.`
179
- );
180
- }
181
-
182
- // @ts-ignore
183
- @inline
184
- export function parseObject<T>(data: string): T {
185
- let schema: T = changetype<T>(__new(offsetof<T>(), idof<T>()));
186
- const result = new Map<string, string>();
187
- let key = "";
188
- let isKey = false;
189
- let depth = 1;
190
- let char = 0;
191
- let outerLoopIndex = 1;
192
- for (; outerLoopIndex < data.length - 1; outerLoopIndex++) {
193
- char = unsafeCharCodeAt(data, outerLoopIndex);
194
- if (char === leftBracketCode) {
195
- for (
196
- let arrayValueIndex = outerLoopIndex;
197
- arrayValueIndex < data.length - 1;
198
- arrayValueIndex++
199
- ) {
200
- char = unsafeCharCodeAt(data, arrayValueIndex);
201
- if (char === leftBracketCode) {
202
- depth = depth << 1;
203
- } else if (char === rightBracketCode) {
204
- depth = depth >> 1;
205
- if (depth === 1) {
206
- ++arrayValueIndex;
207
- result.set(key, data.slice(outerLoopIndex, arrayValueIndex));
208
- outerLoopIndex = arrayValueIndex;
209
- isKey = false;
210
- break;
211
- }
212
- }
213
- }
214
- } else if (char === leftBraceCode) {
215
- for (
216
- let objectValueIndex = outerLoopIndex;
217
- objectValueIndex < data.length - 1;
218
- objectValueIndex++
219
- ) {
220
- char = unsafeCharCodeAt(data, objectValueIndex);
221
- if (char === leftBraceCode) {
222
- depth = depth << 1;
223
- } else if (char === rightBraceCode) {
224
- depth = depth >> 1;
225
- if (depth === 1) {
226
- ++objectValueIndex;
227
- result.set(key, data.slice(outerLoopIndex, objectValueIndex));
228
- outerLoopIndex = objectValueIndex;
229
- isKey = false;
230
- break;
231
- }
232
- }
233
- }
234
- } else if (char === quoteCode) {
235
- for (
236
- let stringValueIndex = ++outerLoopIndex;
237
- stringValueIndex < data.length - 1;
238
- stringValueIndex++
239
- ) {
240
- char = unsafeCharCodeAt(data, stringValueIndex);
241
- if (
242
- char === quoteCode &&
243
- unsafeCharCodeAt(data, stringValueIndex - 1) !== backSlashCode
244
- ) {
245
- if (isKey === false) {
246
- key = data.slice(outerLoopIndex, stringValueIndex);
247
- isKey = true;
248
- } else {
249
- result.set(key, data.slice(outerLoopIndex, stringValueIndex));
250
- isKey = false;
251
- }
252
- outerLoopIndex = ++stringValueIndex;
253
- break;
254
- }
255
- }
256
- } else if (char == nCode) {
257
- result.set(key, "null");
258
- isKey = false;
259
- } else if (
260
- char === tCode &&
261
- unsafeCharCodeAt(data, ++outerLoopIndex) === "r".charCodeAt(0) &&
262
- unsafeCharCodeAt(data, ++outerLoopIndex) === "u".charCodeAt(0) &&
263
- unsafeCharCodeAt(data, ++outerLoopIndex) === eCode
264
- ) {
265
- result.set(key, "true");
266
- isKey = false;
267
- } else if (
268
- char === fCode &&
269
- unsafeCharCodeAt(data, ++outerLoopIndex) === "a".charCodeAt(0) &&
270
- unsafeCharCodeAt(data, ++outerLoopIndex) === "l".charCodeAt(0) &&
271
- unsafeCharCodeAt(data, ++outerLoopIndex) === "s".charCodeAt(0) &&
272
- unsafeCharCodeAt(data, ++outerLoopIndex) === eCode
273
- ) {
274
- result.set(key, "false");
275
- isKey = false;
276
- } else if ((char >= 48 && char <= 57) || char === 45) {
277
- let numberValueIndex = ++outerLoopIndex;
278
- for (; numberValueIndex < data.length; numberValueIndex++) {
279
- char = unsafeCharCodeAt(data, numberValueIndex);
280
- if (char === commaCode || char === rightBraceCode || isSpace(char)) {
281
- result.set(key, data.slice(outerLoopIndex - 1, numberValueIndex));
282
- outerLoopIndex = numberValueIndex;
283
- isKey = false;
284
- break;
285
- }
286
- }
287
- }
288
- }
289
- // @ts-ignore
290
- //const deserialized =
291
- //changetype<nonnull<T>>(schema).__JSON_Deserialize<T>(result);
292
- //heap.free(changetype<usize>(schema));
293
- return changetype<nonnull<T>>(schema).__JSON_Deserialize<T>(result);
294
- }
295
-
296
- // @ts-ignore
297
- @inline
298
- // @ts-ignore
299
- export function parseArray<T extends unknown[]>(data: string): T {
300
- let type!: valueof<T>;
301
- if (type instanceof String) {
302
- return <T>parseStringArray(data);
303
- } else if (isBoolean<valueof<T>>()) {
304
- // @ts-ignore
305
- return parseBooleanArray<T>(data);
306
- } else if (isFloat<valueof<T>>() || isInteger<valueof<T>>()) {
307
- // @ts-ignore
308
- return parseNumberArray<T>(data);
309
- } else if (isArrayLike<valueof<T>>()) {
310
- // @ts-ignore
311
- return parseArrayArray<T>(data);
312
- // @ts-ignore
313
- } else if (isDefined(type.__JSON_Deserialize)) {
314
- // @ts-ignore
315
- return parseObjectArray<T>(data);
316
- }
317
- }
318
-
319
- // @ts-ignore
320
- @inline
321
- export function parseStringArray(data: string): string[] {
322
- const result: string[] = [];
323
- let lastPos = 0;
324
- let instr = false;
325
- for (let i = 1; i < data.length - 1; i++) {
326
- if (unsafeCharCodeAt(data, i) === quoteCode) {
327
- if (instr === false) {
328
- instr = true;
329
- lastPos = i;
330
- } else if (unsafeCharCodeAt(data, i - 1) !== backSlashCode) {
331
- instr = false;
332
- result.push(data.slice(lastPos + 1, i).replaceAll('\\"', '"'));
333
- }
334
- }
335
- }
336
- return result;
337
- }
338
-
339
- // @ts-ignore
340
- @inline
341
- export function parseBooleanArray<T extends boolean[]>(data: string): T {
342
- const result = instantiate<T>();
343
- let lastPos = 1;
344
- let char = 0;
345
- for (let i = 1; i < data.length - 1; i++) {
346
- char = unsafeCharCodeAt(data, i);
347
- /*// if char == "t" && i+3 == "e"
348
- if (char === tCode && data.charCodeAt(i + 3) === eCode) {
349
- //i += 3;
350
- result.push(parseBoolean<valueof<T>>(data.slice(lastPos, i+2)));
351
- //i++;
352
- } else if (char === fCode && data.charCodeAt(i + 4) === eCode) {
353
- //i += 4;
354
- result.push(parseBoolean<valueof<T>>(data.slice(lastPos, i+3)));
355
- //i++;
356
- }*/
357
- if (char === tCode || char === fCode) {
358
- lastPos = i;
359
- } else if (char === eCode) {
360
- i++;
361
- result.push(parseBoolean<valueof<T>>(data.slice(lastPos, i)));
362
- }
363
- }
364
- return result;
365
- }
366
-
367
- // @ts-ignore
368
- @inline
369
- export function parseNumberArray<T extends number[]>(data: string): T {
370
- const result = instantiate<T>();
371
- let lastPos = 0;
372
- let char = 0;
373
- let i = 1;
374
- for (; i < data.length - 1; i++) {
375
- char = unsafeCharCodeAt(data, i);
376
- if ((lastPos === 0 && char >= 48 && char <= 57) || char === 45) {
377
- lastPos = i;
378
- } else if ((isSpace(char) || char == commaCode) && lastPos > 0) {
379
- result.push(parseNumber<valueof<T>>(data.slice(lastPos, i)));
380
- lastPos = 0;
381
- }
382
- }
383
- for (; i > lastPos - 1; i--) {
384
- char = unsafeCharCodeAt(data, i);
385
- if (char !== rightBracketCode) {
386
- result.push(parseNumber<valueof<T>>(data.slice(lastPos, i + 1)));
387
- break;
388
- }
389
- }
390
- return result;
391
- }
392
-
393
- // @ts-ignore
394
- @inline
395
- export function parseArrayArray<T extends unknown[][]>(data: string): T {
396
- const result = instantiate<T>();
397
- let char = 0;
398
- let lastPos = 0;
399
- let depth = 1;
400
- let i = 1;
401
- // Find start of bracket
402
- //for (; unsafeCharCodeAt(data, i) !== leftBracketCode; i++) {}
403
- //i++;
404
- for (; i < data.length - 1; i++) {
405
- char = unsafeCharCodeAt(data, i);
406
- if (char === leftBracketCode) {
407
- if (depth === 1) {
408
- lastPos = i;
409
- }
410
- // Shifting is 6% faster than incrementing
411
- depth = depth << 1;
412
- } else if (char === rightBracketCode) {
413
- depth = depth >> 1;
414
- if (depth === 1) {
415
- i++;
416
- result.push(JSON.parse<valueof<T>>(data.slice(lastPos, i)));
417
- }
418
- }
419
- }
420
- return result;
421
- }
422
-
423
- // @ts-ignore
424
- @inline
425
- export function parseObjectArray<T extends unknown[][]>(data: string): T {
426
- const result = instantiate<T>();
427
- let char = 0;
428
- let lastPos = 1;
429
- let depth = 1;
430
- let i = 1;
431
- // Find start of bracket
432
- //for (; unsafeCharCodeAt(data, i) !== leftBracketCode; i++) { }
433
- //i++;
434
- for (; i < data.length - 1; i++) {
435
- char = unsafeCharCodeAt(data, i);
436
- if (char === leftBraceCode) {
437
- if (depth === 1) {
438
- lastPos = i;
439
- }
440
- // Shifting is 6% faster than incrementing
441
- depth = depth << 1;
442
- } else if (char === rightBraceCode) {
443
- depth = depth >> 1;
444
- if (depth === 1) {
445
- i++;
446
- result.push(JSON.parse<valueof<T>>(data.slice(lastPos, i)));
447
- }
448
- }
449
- }
450
- return result;
451
- }