json-as 1.0.0-alpha.3 → 1.0.0-beta.1

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.
Files changed (42) hide show
  1. package/CHANGELOG +14 -0
  2. package/README.md +76 -59
  3. package/assembly/__benches__/misc.bench.ts +48 -0
  4. package/assembly/__benches__/schemas.ts +25 -0
  5. package/assembly/__tests__/arbitrary.spec.ts +19 -0
  6. package/assembly/__tests__/box.spec.ts +37 -0
  7. package/assembly/__tests__/date.spec.ts +38 -0
  8. package/assembly/__tests__/types.ts +3 -3
  9. package/assembly/deserialize/simd/string.ts +1 -1
  10. package/assembly/deserialize/simple/arbitrary.ts +1 -1
  11. package/assembly/deserialize/simple/array/arbitrary.ts +47 -24
  12. package/assembly/deserialize/simple/array/{object.ts → struct.ts} +1 -1
  13. package/assembly/deserialize/simple/array.ts +4 -9
  14. package/assembly/deserialize/simple/bool.ts +4 -7
  15. package/assembly/deserialize/simple/date.ts +2 -2
  16. package/assembly/deserialize/simple/integer.ts +2 -1
  17. package/assembly/deserialize/simple/map.ts +1 -1
  18. package/assembly/deserialize/simple/object.ts +13 -17
  19. package/assembly/deserialize/simple/struct.ts +158 -0
  20. package/assembly/index.ts +143 -24
  21. package/assembly/serialize/simd/string.ts +11 -11
  22. package/assembly/serialize/simple/arbitrary.ts +15 -2
  23. package/assembly/serialize/simple/array.ts +4 -3
  24. package/assembly/serialize/simple/float.ts +1 -1
  25. package/assembly/serialize/simple/integer.ts +7 -2
  26. package/assembly/serialize/simple/object.ts +43 -6
  27. package/assembly/serialize/simple/struct.ts +7 -0
  28. package/assembly/test.ts +84 -4
  29. package/assembly/util/atoi.ts +1 -1
  30. package/assembly/util/snp.ts +2 -2
  31. package/bench.js +11 -2
  32. package/modules/as-bs/assembly/index.ts +63 -32
  33. package/modules/as-bs/assembly/state.ts +8 -0
  34. package/package.json +7 -6
  35. package/transform/lib/builder.js +1340 -1262
  36. package/transform/lib/index.js +577 -512
  37. package/transform/lib/index.js.map +1 -1
  38. package/transform/lib/linker.js +12 -10
  39. package/transform/lib/types.js +19 -19
  40. package/transform/lib/util.js +34 -34
  41. package/transform/lib/visitor.js +529 -526
  42. package/transform/src/index.ts +25 -23
package/CHANGELOG CHANGED
@@ -1,5 +1,19 @@
1
1
  # Change Log
2
2
 
3
+ ## 2025-02-13 - 1.0.0-alpha.4
4
+
5
+ - feat: reintroduce support for `Box<T>`-wrapped primitive types
6
+ - tests: add extensive tests to all supported types
7
+ - fix: 6-byte keys being recognized on deserialize
8
+ - perf: take advantage of aligned memory to use a single 64-bit load on 6-byte keys
9
+ - fix: `bs.proposeSize()` should increment `stackSize` by `size` instead of setting it
10
+ - fix: allow runtime to manage `bs.buffer`
11
+ - fix: memory leaks in `bs` module
12
+ - fix: add (possibly temporary) `JSON.Memory.shrink()` to shrink memory in `bs`
13
+ - perf: prefer growing memory by `nextPowerOf2(size + 64)` for less reallocations
14
+ - tests: add boolean tests to `Box<T>`
15
+ - fix: serialization of non-growable data types should grow `bs.stackSize`
16
+
3
17
  ## 2025-01-31 - 1.0.0-alpha.3
4
18
 
5
19
  - fix: write to proper offset when deserializing string with \u0000-type escapes
package/README.md CHANGED
@@ -1,30 +1,44 @@
1
1
  <h5 align="center">
2
2
  <pre>
3
3
  <span style="font-size: 0.8em;"> ██ ███████ ██████ ███ ██ █████ ███████
4
- ██ ██ ██ ██ ████ ██ ██ ██ ██
4
+ ██ ██ ██ ██ ████ ██ ██ ██ ██
5
5
  ██ ███████ ██ ██ ██ ██ ██ █████ ███████ ███████
6
6
  ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
7
7
  █████ ███████ ██████ ██ ████ ██ ██ ███████
8
8
  </span>
9
- AssemblyScript - v1.0.0-alpha.3
9
+ AssemblyScript - v1.0.0-beta.1
10
10
  </pre>
11
11
  </h5>
12
12
 
13
- ## Installation
13
+ ## 📚 Contents
14
+
15
+ - [About](#-about)
16
+ - [Installation](#-installation)
17
+ - [Usage](#-usage)
18
+ - [Examples](#examples)
19
+ - [Performance](#-performance)
20
+ - [License](#-license)
21
+ - [Contact](#-contact)
22
+
23
+ ## 📝 About
24
+
25
+ JSON is the de-facto serialization format of modern web applications, but its serialization and deserialization remain a significant performance bottleneck, especially at scale. Traditional parsing approaches are computationally expensive, adding unnecessary overhead to both clients and servers. This library is designed to mitigate this by leveraging SIMD acceleration and highly optimized transformations.
26
+
27
+ ## 💾 Installation
14
28
 
15
29
  ```bash
16
- npm install json-as@1.0.0-alpha.3
30
+ npm install json-as@1.0.0-beta.1
17
31
  ```
18
32
 
19
33
  Add the `--transform` to your `asc` command (e.g. in package.json)
20
34
 
21
35
  ```bash
22
- --transform json-as
36
+ --transform json-as/transform
23
37
  ```
24
38
 
25
39
  Alternatively, add it to your `asconfig.json`
26
40
 
27
- ```
41
+ ```json
28
42
  {
29
43
  // ...
30
44
  "options": {
@@ -35,12 +49,11 @@ Alternatively, add it to your `asconfig.json`
35
49
 
36
50
  If you'd like to see the code that the transform generates, run with `JSON_DEBUG=true`
37
51
 
38
- ## Usage
52
+ ## 🪄 Usage
39
53
 
40
54
  ```js
41
55
  import { JSON } from "json-as";
42
56
 
43
- // @json or @serializable work here
44
57
  @json
45
58
  class Vec3 {
46
59
  x: f32 = 0.0;
@@ -55,8 +68,7 @@ class Player {
55
68
  lastName!: string;
56
69
  lastActive!: i32[];
57
70
  // Drop in a code block, function, or expression that evaluates to a boolean
58
- @omitif((age) => age < 18)
59
- @omitif('this.age <= 0')
71
+ @omitif((self: Player) => self.age < 18)
60
72
  age!: i32;
61
73
  @omitnull()
62
74
  pos!: Vec3 | null;
@@ -64,10 +76,10 @@ class Player {
64
76
  }
65
77
 
66
78
  const player: Player = {
67
- firstName: "Emmet",
68
- lastName: "West",
69
- lastActive: [8, 27, 2022],
70
- age: 23,
79
+ firstName: "Jairus",
80
+ lastName: "Tanaka",
81
+ lastActive: [2, 13, 2025],
82
+ age: 18,
71
83
  pos: {
72
84
  x: 3.4,
73
85
  y: 1.2,
@@ -76,64 +88,69 @@ const player: Player = {
76
88
  isVerified: true
77
89
  };
78
90
 
79
- const stringified = JSON.stringify<Player>(player);
91
+ const serialized = JSON.stringify<Player>(player);
92
+ const deserialized = JSON.parse<Player>(serialized);
80
93
 
81
- const parsed = JSON.parse<Player>(stringified);
94
+ console.log("Serialized " + serialized);
95
+ console.log("Deserialized " + JSON.stringify(deserialized));
82
96
  ```
83
97
 
84
- Classes can even have inheritance. Here's a nasty example
98
+ ## Examples
85
99
 
86
- ```js
87
- @json
88
- class Base {}
100
+ ## ⚡ Performance
89
101
 
90
- @json
91
- class Vec1 extends Base {
92
- x: f32 = 1.0;
93
- }
94
- @json
95
- class Vec2 extends Vec1 {
96
- y: f32 = 2.0;
97
- }
98
- @json
99
- class Vec3 extends Vec2 {
100
- z: f32 = 3.0;
101
- }
102
+ The `json-as` library has been optimized to achieve near-gigabyte-per-second JSON processing speeds through SIMD acceleration and highly efficient transformations. Below are some key performance benchmarks to give you an idea of how it performs.
102
103
 
103
- const arr: Base[] = [
104
- new Vec1(),
105
- new Vec2(),
106
- new Vec3()
107
- ];
104
+ ### Raw Performance
108
105
 
109
- const serialized = JSON.stringify(arr);
110
- // [{"x":1.0},{"x":1.0,"y":2.0},{"y":2.0,"x":1.0,"z":3.0}]
111
- const parsed = JSON.parse<Base[]>(serialized);
112
- ```
106
+ Simple
113
107
 
114
- You can also add it to your `asconfig.json`
108
+ | Test Case | Serialization (ops/s) | Deserialization (ops/s) | Serialization (MB/s) | Deserialization (MB/s) |
109
+ |--------------------|-----------------------|-------------------------|----------------------|------------------------|
110
+ | Vector3 Object | 32,642,320 ops/s | 9,736,272 ops/s | 1,240 MB/s | 369 MB/s |
111
+ | Alphabet String | 4,928,856 ops/s | 7,567,360 ops/s | 975 MB/s | 1,498 MB/s |
112
+ | Small JSON Object | [Fill Value] | [Fill Value] | [Fill Value] | [Fill Value] |
113
+ | Medium JSON Object | [Fill Value] | [Fill Value] | [Fill Value] | [Fill Value] |
114
+ | Large JSON Object | [Fill Value] | [Fill Value] | [Fill Value] | [Fill Value] |
115
115
 
116
- ```json
117
- {
118
- // ...
119
- "options": {
120
- "transform": ["json-as/transform"]
121
- }
122
- }
123
- ```
116
+ SIMD
117
+
118
+ | Test Case | Serialization (ops/s) | Deserialization (ops/s) | Serialization (MB/s) | Deserialization (MB/s) |
119
+ |--------------------|-----------------------|-------------------------|----------------------|------------------------|
120
+ | Vector3 Object | 32,642,320 ops/s | 9,736,272 ops/s | 1,240 MB/s | 369 MB/s |
121
+ | Alphabet String | 20,368,584 ops/s | 28,467,424 ops/s | 3,910 MB/s | 5,636 MB/s |
122
+ | Small JSON Object | [Fill Value] | [Fill Value] | [Fill Value] | [Fill Value] |
123
+ | Medium JSON Object | [Fill Value] | [Fill Value] | [Fill Value] | [Fill Value] |
124
+ | Large JSON Object | [Fill Value] | [Fill Value] | [Fill Value] | [Fill Value] |
125
+
126
+ JavaScript
127
+
128
+ | Test Case | Serialization (ops/s) | Deserialization (ops/s) | Serialization (MB/s) | Deserialization (MB/s) |
129
+ |--------------------|-----------------------|-------------------------|----------------------|------------------------|
130
+ | Vector3 Object | 2,548,013 ops/s | 1,942,440 ops/s | 97 MB/s | 73 MB/s |
131
+ | Alphabet String | 3,221,556 ops/s | 2,716,617 ops/s | 624 MB/s | 537 MB/s |
132
+ | Small JSON Object | [Fill Value] | [Fill Value] | [Fill Value] | [Fill Value] |
133
+ | Medium JSON Object | [Fill Value] | [Fill Value] | [Fill Value] | [Fill Value] |
134
+ | Large JSON Object | [Fill Value] | [Fill Value] | [Fill Value] | [Fill Value] |
135
+
136
+ ### Real-World Usage
124
137
 
125
- If you use this project in your codebase, consider dropping a [star](https://github.com/JairusSW/as-json). I would really appreciate it!
138
+ | Scenario | JSON Size (kb) | Serialization Time (ops/s) | Deserialization Time (ops/s) | Throughput (GB/s) |
139
+ |--------------------|----------------|----------------------------|------------------------------|-------------------|
140
+ | Web API Response | [Fill Value] | [Fill Value] | [Fill Value] | [Fill Value] |
141
+ | Database Entry | [Fill Value] | [Fill Value] | [Fill Value] | [Fill Value] |
142
+ | File Parsing | [Fill Value] | [Fill Value] | [Fill Value] | [Fill Value] |
126
143
 
127
- ## Notes
128
144
 
129
- If you want a feature, drop an issue (and again, maybe a star). I'll likely add it in less than 7 days.
145
+ ## 📃 License
130
146
 
131
- ## Contact
147
+ This project is distributed under an open source license. You can view the full license using the following link: [License](./LICENSE)
132
148
 
133
- - [Email](mailto:me@jairus.dev)
134
- - [GitHub](https://github.com/JairusSW)
135
- - [Discord](discord.com/users/600700584038760448)
149
+ ## 📫 Contact
136
150
 
137
- ## Issues
151
+ Please send all issues to [GitHub Issues](https://github.com/JairusSW/as-json/issues) and to converse, please send me an email at [me@jairus.dev](mailto:me@jairus.dev)
138
152
 
139
- Please submit an issue to https://github.com/JairusSW/as-json/issues if you find anything wrong with this library
153
+ - **Email:** Send me inquiries, questions, or requests at [me@jairus.dev](mailto:me@jairus.dev)
154
+ - **GitHub:** Visit the official GitHub repository [Here](https://github.com/JairusSW/as-json)
155
+ - **Website:** Visit my official website at [jairus.dev](https://jairus.dev/)
156
+ - **Discord:** Converse with me on [My Discord](discord.com/users/600700584038760448) or on the [AssemblyScript Discord Server](https://discord.gg/assemblyscript/)
@@ -0,0 +1,48 @@
1
+ import { bench } from "as-bench/assembly";
2
+ import { JSON } from "..";
3
+ import { Vec3 } from "./schemas";
4
+ import { bs } from "../../modules/as-bs/assembly";
5
+ import { serializeString_SIMD } from "../serialize/simd/string";
6
+ import { serializeString } from "../serialize/simple/string";
7
+ import { deserializeString } from "../deserialize/simple/string";
8
+ import { bytes } from "../util";
9
+ import { deserializeString_SIMD } from "../deserialize/simd/string";
10
+
11
+ const vec: Vec3 = {
12
+ x: 1,
13
+ y: 2,
14
+ z: 3
15
+ }
16
+
17
+ bs.ensureSize(4096);
18
+ // bench("Serialize Vector3", () => {
19
+ // JSON.stringify(vec);
20
+ // });
21
+
22
+ // bench("Deserialize Vector3", () => {
23
+ // JSON.parse<Vec3>('{"x":1,"y":2,"z":3}');
24
+ // });
25
+
26
+ // bench("Serialize String SIMD", () => {
27
+ // serializeString_SIMD("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~`!@#$%^&*()-_=+{[}]|\\:;\"'?/>.<,'\"}");
28
+ // bs.offset = changetype<usize>(bs.buffer);
29
+ // bs.stackSize = 0;
30
+ // });
31
+
32
+ // bench("Serialize String", () => {
33
+ // serializeString("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~`!@#$%^&*()-_=+{[}]|\\:;\"'?/>.<,'\"}");
34
+ // bs.offset = changetype<usize>(bs.buffer);
35
+ // bs.stackSize = 0;
36
+ // });
37
+
38
+ const src = '"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~`!@#$%^&*()-_=+{[}]|\\\\:;\\"\'?/>.<,\'\\"}"';
39
+ const srcStart = changetype<usize>(src);
40
+ const srcEnd = srcStart + bytes(src);
41
+ const out = changetype<usize>(new ArrayBuffer(256));
42
+ bench("Deserialize String", () => {
43
+ deserializeString(srcStart, srcEnd, out);
44
+ });
45
+
46
+ bench("Deserialize String SIMD", () => {
47
+ deserializeString_SIMD(srcStart, srcEnd, out);
48
+ })
@@ -0,0 +1,25 @@
1
+ import { JSON } from "..";
2
+
3
+ @json
4
+ export class Vec3 {
5
+ public x!: i32;
6
+ public y!: i32;
7
+ public z!: i32;
8
+ __DESERIALIZE(keyStart: usize, keyEnd: usize, valStart: usize, valEnd: usize, ptr: usize): void {
9
+ switch (load<u16>(keyStart)) {
10
+ case 120: { // x
11
+ store<i32>(ptr, JSON.__deserialize<i32>(valStart, valEnd, 0), offsetof<this>("x"));
12
+ return;
13
+ }
14
+ case 121: { // y
15
+ store<i32>(ptr, JSON.__deserialize<i32>(valStart, valEnd, 0), offsetof<this>("y"));
16
+ return;
17
+ }
18
+ case 122: { // z
19
+ store<i32>(ptr, JSON.__deserialize<i32>(valStart, valEnd, 0), offsetof<this>("z"));
20
+ return;
21
+ }
22
+ }
23
+ return;
24
+ }
25
+ }
@@ -0,0 +1,19 @@
1
+ import { JSON } from "..";
2
+ import { describe, expect } from "../../modules/test/assembly";
3
+ import { Vec3 } from "./types";
4
+
5
+ describe("Should serialize arbitrary types", () => {
6
+ expect(JSON.stringify(JSON.Value.from("hello world"))).toBe("\"hello world\"");
7
+ expect(JSON.stringify(JSON.Value.from(0))).toBe("0");
8
+ expect(JSON.stringify(JSON.Value.from(true))).toBe("true");
9
+ expect(JSON.stringify(JSON.Value.from(new Vec3()))).toBe('{"x":1.0,"y":2.0,"z":3.0}');
10
+ expect(JSON.stringify([JSON.Value.from("string"), JSON.Value.from(true), JSON.Value.from(3.14), JSON.Value.from(new Vec3())])).toBe('["string",true,3.14,{"x":1.0,"y":2.0,"z":3.0}]');
11
+ });
12
+
13
+ describe("Should deserialize arbitrary types", () => {
14
+ expect(JSON.parse<JSON.Value>("\"hello world\"").get<string>()).toBe("hello world");
15
+ expect(JSON.parse<JSON.Value>("0.0").toString()).toBe("0.0");
16
+ expect(JSON.parse<JSON.Value>("true").toString()).toBe("true");
17
+ expect(JSON.stringify(JSON.parse<JSON.Value>('{"x":1.0,"y":2.0,"z":3.0}'))).toBe('{"x":1.0,"y":2.0,"z":3.0}');
18
+ expect(JSON.stringify(JSON.parse<JSON.Value[]>('["string",true,3.14,{"x":1.0,"y":2.0,"z":3.0},[1.0,2.0,3,true]]'))).toBe('["string",true,3.14,{"x":1.0,"y":2.0,"z":3.0},[1.0,2.0,3.0,true]]');
19
+ });
@@ -0,0 +1,37 @@
1
+ import { JSON } from "..";
2
+ import { describe, expect } from "../../modules/test/assembly";
3
+
4
+ describe("Should serialize JSON.Box<T>", () => {
5
+ expect(JSON.stringify<JSON.Box<i32> | null>(null))
6
+ .toBe("null");
7
+
8
+ expect(JSON.stringify<JSON.Box<i32> | null>(new JSON.Box<i32>(0)))
9
+ .toBe("0");
10
+
11
+ expect(JSON.stringify<JSON.Box<i32> | null>(new JSON.Box<i32>(1)))
12
+ .toBe("1");
13
+
14
+ expect(JSON.stringify<JSON.Box<boolean> | null>(new JSON.Box<boolean>(false)))
15
+ .toBe("false");
16
+
17
+ expect(JSON.stringify<JSON.Box<boolean> | null>(new JSON.Box<boolean>(true)))
18
+ .toBe("true");
19
+ });
20
+
21
+ // This is somewhat clumsy to use. Perhaps I can redesign it or use some transform to make it more transparent.
22
+ describe("Should deserialize JSON.Box<T>", () => {
23
+ expect((JSON.parse<JSON.Box<i32> | null>("null") == null).toString())
24
+ .toBe("true");
25
+
26
+ expect(JSON.parse<JSON.Box<i32> | null>("0")!.value.toString())
27
+ .toBe("0");
28
+
29
+ expect(JSON.parse<JSON.Box<i32> | null>("1")!.value.toString())
30
+ .toBe("1");
31
+
32
+ expect(JSON.parse<JSON.Box<boolean> | null>("false")!.value.toString())
33
+ .toBe("false");
34
+
35
+ expect(JSON.parse<JSON.Box<boolean> | null>("true")!.value.toString())
36
+ .toBe("true");
37
+ });
@@ -0,0 +1,38 @@
1
+ import { JSON } from "..";
2
+ import { describe, expect } from "../../modules/test/assembly";
3
+
4
+ describe("Should serialize Date", () => {
5
+ expect(JSON.stringify<Date>(new Date(0)))
6
+ .toBe('"1970-01-01T00:00:00.000Z"');
7
+ expect(JSON.stringify<Date>(new Date(1738618120525)))
8
+ .toBe('"2025-02-03T21:28:40.525Z"');
9
+ });
10
+
11
+ describe("Should deserialize booleans", () => {
12
+ // const date = JSON.parse<Date>('"2025-02-03T21:28:40.525Z"');
13
+ // console.log("Year: " + date.getUTCFullYear().toString());
14
+ // console.log("Month: " + date.getUTCMonth().toString());
15
+ // console.log("Day: " + date.getUTCDay().toString());
16
+ // console.log("Hours: " + date.getUTCHours().toString());
17
+ // console.log("Minutes: " + date.getUTCMinutes().toString());
18
+ // console.log("Seconds: " + date.getUTCSeconds().toString());
19
+ // console.log("Milliseconds: " + date.getUTCMilliseconds().toString());
20
+
21
+ const date1 = JSON.parse<Date>('"1970-01-01T00:00:00.000Z"');
22
+ expect(date1.getUTCFullYear().toString()).toBe("1970");
23
+ expect(date1.getUTCMonth().toString()).toBe("0");
24
+ expect(date1.getUTCDay().toString()).toBe("4");
25
+ expect(date1.getUTCHours().toString()).toBe("0");
26
+ expect(date1.getUTCMinutes().toString()).toBe("0");
27
+ expect(date1.getUTCSeconds().toString()).toBe("0");
28
+ expect(date1.getUTCMilliseconds().toString()).toBe("0");
29
+
30
+ const date2 = JSON.parse<Date>('"2025-02-03T21:28:40.525Z"');
31
+ expect(date2.getUTCFullYear().toString()).toBe("2025");
32
+ expect(date2.getUTCMonth().toString()).toBe("1");
33
+ expect(date2.getUTCDay().toString()).toBe("1");
34
+ expect(date2.getUTCHours().toString()).toBe("21");
35
+ expect(date2.getUTCMinutes().toString()).toBe("28");
36
+ expect(date2.getUTCSeconds().toString()).toBe("40");
37
+ expect(date2.getUTCMilliseconds().toString()).toBe("525");
38
+ });
@@ -61,9 +61,9 @@ export class Map4 {
61
61
 
62
62
  @json
63
63
  export class Vec3 {
64
- x: f64;
65
- y: f64;
66
- z: f64;
64
+ x: f64 = 1.0;
65
+ y: f64 = 2.0;
66
+ z: f64 = 3.0;
67
67
 
68
68
  static shouldIgnore: string = "should not be serialized";
69
69
  }
@@ -10,7 +10,7 @@ const SPLAT_92 = i16x8.splat(92); /* \ */
10
10
  * @returns number of bytes written
11
11
  */
12
12
  // todo: optimize and stuff. it works, its not pretty. ideally, i'd like this to be (nearly) branchless
13
- export function deserializeString_SIMD(src: string, srcStart: usize, srcEnd: usize, dst: usize): usize {
13
+ export function deserializeString_SIMD(srcStart: usize, srcEnd: usize, dst: usize): usize {
14
14
  let src_ptr = srcStart + 2;
15
15
  let dst_ptr = changetype<usize>(dst);
16
16
 
@@ -2,8 +2,8 @@ import { JSON } from "../..";
2
2
  import { deserializeArray } from "./array";
3
3
  import { deserializeBoolean } from "./bool";
4
4
  import { deserializeFloat } from "./float";
5
- import { deserializeObject } from "./object";
6
5
  import { deserializeString } from "./string";
6
+ import { deserializeObject } from "./object";
7
7
 
8
8
  export function deserializeArbitrary(srcStart: usize, srcEnd: usize, dst: usize): JSON.Value {
9
9
  const firstChar = load<u16>(srcStart);
@@ -1,45 +1,66 @@
1
1
  import { BACK_SLASH, BRACE_LEFT, BRACE_RIGHT, BRACKET_LEFT, BRACKET_RIGHT, CHAR_F, CHAR_N, CHAR_T, COMMA, QUOTE } from "../../../custom/chars";
2
2
  import { JSON } from "../../../";
3
3
  import { isSpace } from "util/string";
4
+ import { ptrToStr } from "../../../util/ptrToStr";
4
5
 
5
- export function deserializeArbitraryArray<T extends JSON.Value>(srcStart: usize, srcEnd: usize, dst: usize): JSON.Value[] {
6
- const out = dst ? changetype<T>(dst) : instantiate<T>();
6
+ export function deserializeArbitraryArray(srcStart: usize, srcEnd: usize, dst: usize): JSON.Value[] {
7
+ const out = dst ? changetype<JSON.Value[]>(dst) : instantiate<JSON.Value[]>();
7
8
  let lastIndex: usize = 0;
8
9
  let depth: u32 = 0;
10
+ // if (load<u16>(srcStart) != BRACKET_LEFT)
11
+ srcStart += 2;
9
12
  while (srcStart < srcEnd) {
10
13
  const code = load<u16>(srcStart);
11
- if (code == QUOTE) {
14
+ // console.log("code: " + String.fromCharCode(code));
15
+ if (code == BRACE_LEFT) {
12
16
  lastIndex = srcStart;
17
+ depth++;
13
18
  srcStart += 2;
14
19
  while (srcStart < srcEnd) {
15
20
  const code = load<u16>(srcStart);
16
- if (code == QUOTE && load<u16>(srcStart - 2) !== BACK_SLASH) {
17
- while (isSpace(load<u16>((srcStart += 2)))) {
18
- /* empty */
21
+ if (code == BRACE_RIGHT) {
22
+ if (--depth == 0) {
23
+ // @ts-ignore: type
24
+ out.push(JSON.__deserialize<JSON.Value>(lastIndex, srcStart + 2));
25
+ // console.log("Value (object): " + ptrToStr(lastIndex, srcStart + 2));
26
+ break;
19
27
  }
20
- // console.log("Value (string): " + ptrToStr(lastIndex, srcStart));
28
+ } else if (code == BRACE_LEFT) depth++;
29
+ srcStart += 2;
30
+ }
31
+ } else if (code == QUOTE) {
32
+ lastIndex = srcStart;
33
+ srcStart += 2;
34
+ while (srcStart < srcEnd) {
35
+ const code = load<u16>(srcStart);
36
+ if (code == QUOTE && load<u16>(srcStart - 2) !== BACK_SLASH) {
37
+ // while (isSpace(load<u16>((srcStart += 2)))) {
38
+ // /* empty */
39
+ // }
40
+ // console.log("Value (string): " + ptrToStr(lastIndex, srcStart + 2));
21
41
  // @ts-ignore: exists
22
- out.push(JSON.__deserialize<valueof<T>>(lastIndex, srcStart));
42
+ out.push(JSON.__deserialize<JSON.Value>(lastIndex, srcStart + 2));
43
+ srcStart += 2;
23
44
  break;
24
45
  }
25
46
  srcStart += 2;
26
47
  }
48
+ // console.log("next: " + String.fromCharCode(load<u16>(srcStart)));
27
49
  } else if (code - 48 <= 9 || code == 45) {
50
+ // console.log("trigger int")
28
51
  lastIndex = srcStart;
29
52
  srcStart += 2;
30
53
  while (srcStart < srcEnd) {
31
54
  const code = load<u16>(srcStart);
32
- if (code == COMMA || code == BRACE_RIGHT || isSpace(code)) {
55
+ if (code == COMMA || code == BRACKET_RIGHT || isSpace(code)) {
33
56
  // @ts-ignore: type
34
- out.push(JSON.__deserialize<valueof<T>>(lastIndex, srcStart));
57
+ out.push(JSON.__deserialize<JSON.Value>(lastIndex, srcStart));
35
58
  // console.log("Value (number): " + ptrToStr(lastIndex, srcStart));
36
- while (isSpace(load<u16>((srcStart += 2)))) {
37
- /* empty */
38
- }
39
59
  break;
40
60
  }
41
61
  srcStart += 2;
42
62
  }
63
+ // console.log("next: " + String.fromCharCode(load<u16>(srcStart)));
43
64
  } else if (code == BRACE_LEFT) {
44
65
  lastIndex = srcStart;
45
66
  depth++;
@@ -49,7 +70,7 @@ export function deserializeArbitraryArray<T extends JSON.Value>(srcStart: usize,
49
70
  if (code == BRACE_RIGHT) {
50
71
  if (--depth == 0) {
51
72
  // @ts-ignore: type
52
- out.push(JSON.__deserialize<valueof<T>>(lastIndex, srcStart));
73
+ out.push(JSON.__deserialize<JSON.Value>(lastIndex, srcStart));
53
74
  // console.log("Value (object): " + ptrToStr(lastIndex, srcStart));
54
75
  while (isSpace(load<u16>((srcStart += 2)))) {
55
76
  /* empty */
@@ -68,7 +89,7 @@ export function deserializeArbitraryArray<T extends JSON.Value>(srcStart: usize,
68
89
  if (code == BRACKET_RIGHT) {
69
90
  if (--depth == 0) {
70
91
  // @ts-ignore: type
71
- out.push(JSON.__deserialize<valueof<T>>(lastIndex, srcStart));
92
+ out.push(JSON.__deserialize<JSON.Value>(lastIndex, srcStart));
72
93
  // console.log("Value (array): " + ptrToStr(lastIndex, srcStart));
73
94
  while (isSpace(load<u16>((srcStart += 2)))) {
74
95
  /* empty */
@@ -81,25 +102,27 @@ export function deserializeArbitraryArray<T extends JSON.Value>(srcStart: usize,
81
102
  } else if (code == CHAR_T) {
82
103
  if (load<u64>(srcStart) == 28429475166421108) {
83
104
  // @ts-ignore: type
84
- out.push(JSON.__deserialize<valueof<T>>(lastIndex, (srcStart += 8)));
105
+ out.push(JSON.__deserialize<JSON.Value>(srcStart, (srcStart += 8)));
85
106
  // console.log("Value (bool): " + ptrToStr(srcStart - 8, srcStart));
86
- while (isSpace(load<u16>((srcStart += 2)))) {
87
- /* empty */
88
- }
107
+ // while (isSpace(load<u16>((srcStart += 2)))) {
108
+ // /* empty */
109
+ // }
110
+ // console.log("next: " + String.fromCharCode(load<u16>(srcStart)));
89
111
  }
90
112
  } else if (code == CHAR_F) {
91
113
  if (load<u64>(srcStart, 2) == 28429466576093281) {
92
114
  // @ts-ignore: type
93
- out.push(JSON.__deserialize<valueof<T>>(lastIndex, (srcStart += 10)));
115
+ out.push(JSON.__deserialize<JSON.Value>(srcStart, (srcStart += 10)));
94
116
  // console.log("Value (bool): " + ptrToStr(srcStart - 10, srcStart));
95
- while (isSpace(load<u16>((srcStart += 2)))) {
96
- /* empty */
97
- }
117
+ // while (isSpace(load<u16>((srcStart += 2)))) {
118
+ // /* empty */
119
+ // }
120
+ // console.log("next: " + String.fromCharCode(load<u16>(srcStart)));
98
121
  }
99
122
  } else if (code == CHAR_N) {
100
123
  if (load<u64>(srcStart) == 30399761348886638) {
101
124
  // @ts-ignore: type
102
- out.push(JSON.__deserialize<valueof<T>>(lastIndex, (srcStart += 8)));
125
+ out.push(JSON.__deserialize<JSON.Value>(lastIndex, (srcStart += 8)));
103
126
  // console.log("Value (null): " + ptrToStr(srcStart - 8, srcStart));
104
127
  while (isSpace(load<u16>((srcStart += 2)))) {
105
128
  /* empty */
@@ -1,7 +1,7 @@
1
1
  import { BRACE_LEFT, BRACE_RIGHT } from "../../../custom/chars";
2
2
  import { JSON } from "../../..";
3
3
 
4
- export function deserializeObjectArray<T extends unknown[]>(srcStart: usize, srcEnd: usize, dst: usize): T {
4
+ export function deserializeStructArray<T extends unknown[]>(srcStart: usize, srcEnd: usize, dst: usize): T {
5
5
  const out = dst ? changetype<T>(dst) : instantiate<T>();
6
6
  let lastIndex: usize = 0;
7
7
  let depth: u32 = 0;
@@ -5,7 +5,7 @@ import { deserializeBooleanArray } from "./array/bool";
5
5
  import { deserializeFloatArray } from "./array/float";
6
6
  import { deserializeIntegerArray } from "./array/integer";
7
7
  import { deserializeMapArray } from "./array/map";
8
- import { deserializeObjectArray } from "./array/object";
8
+ import { deserializeStructArray } from "./array/struct";
9
9
  import { deserializeStringArray } from "./array/string";
10
10
 
11
11
  // @ts-ignore: Decorator valid here
@@ -28,21 +28,16 @@ export function deserializeArray<T extends unknown[]>(srcStart: usize, srcEnd: u
28
28
  const type = changetype<nonnull<valueof<T>>>(0);
29
29
  if (type instanceof JSON.Value) {
30
30
  // @ts-ignore: type
31
- return deserializeArbitraryArray<T>(srcStart, srcEnd, dst);
31
+ return deserializeArbitraryArray(srcStart, srcEnd, dst);
32
32
  } else if (type instanceof Map) {
33
33
  // @ts-ignore: type
34
34
  return deserializeMapArray<T>(srcStart, srcEnd, dst);
35
35
  // @ts-ignore: defined by transform
36
36
  } else if (isDefined(type.__DESERIALIZE)) {
37
- return deserializeObjectArray<T>(srcStart, srcEnd, dst);
37
+ return deserializeStructArray<T>(srcStart, srcEnd, dst);
38
38
  }
39
39
  throw new Error("Could not parse array of type " + nameof<T>() + "!");
40
40
  } else {
41
41
  throw new Error("Could not parse array of type " + nameof<T>() + "!");
42
42
  }
43
- }
44
-
45
- function isMap<T>(): boolean {
46
- let type: T = changetype<T>(0);
47
- return type instanceof Map;
48
- }
43
+ }
@@ -1,9 +1,6 @@
1
- import { CHAR_F, CHAR_T } from "../../custom/chars";
2
-
3
1
  export function deserializeBoolean(srcStart: usize, srcEnd: usize): boolean {
4
- const srcSize = srcEnd - srcStart;
5
- const firstChar = load<u16>(srcStart);
6
- if (firstChar == CHAR_T && load<u64>(srcStart) == 28429475166421108) return true;
7
- else if (firstChar == CHAR_F && load<u64>(srcSize, 2) == 28429466576093281) return false;
2
+ const block = load<u64>(srcStart);
3
+ if (block == 28429475166421108) return true;
4
+ else if (block == 32370086184550502 && load<u16>(srcStart, 8) == 101) return false;
8
5
  return false; //throw new Error(`Expected to find boolean, but found "${data.slice(0, 100)}" instead!`);
9
- }
6
+ }
@@ -2,10 +2,10 @@ import { ptrToStr } from "../../util/ptrToStr";
2
2
 
3
3
  export function deserializeDate(srcStart: usize, srcEnd: usize): Date {
4
4
  // Use AssemblyScript's date parser
5
- const d = Date.fromString(ptrToStr(srcStart, srcEnd));
5
+ const d = Date.fromString(ptrToStr(srcStart + 2, srcEnd - 2));
6
6
 
7
7
  // Return a new object instead of the one that the parser returned.
8
- // This may seem redundant, but addreses the issue when Date
8
+ // This may seem redundant, but it addresses the issue when Date
9
9
  // is globally aliased to wasi_Date (or some other superclass).
10
10
  return new Date(d.getTime());
11
11
  }
@@ -1,5 +1,6 @@
1
1
  import { atoi } from "../../util/atoi";
2
2
 
3
- export function deserializeInteger<T>(srcStart: usize, srcEnd: usize): T {
3
+ // @ts-ignore: inline
4
+ @inline export function deserializeInteger<T>(srcStart: usize, srcEnd: usize): T {
4
5
  return atoi<T>(srcStart, srcEnd);
5
6
  }