json-as 1.0.7 → 1.0.9

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.md +15 -0
  2. package/README.md +18 -2
  3. package/asconfig.json +1 -2
  4. package/assembly/__benches__/abc.bench.ts +5 -5
  5. package/assembly/__benches__/large.bench.ts +5 -51
  6. package/assembly/{custom → __benches__/lib}/bench.ts +4 -0
  7. package/assembly/__benches__/medium.bench.ts +3 -3
  8. package/assembly/__benches__/small.bench.ts +1 -1
  9. package/assembly/__benches__/vec3.bench.ts +3 -49
  10. package/assembly/__tests__/custom.spec.ts +4 -3
  11. package/assembly/__tests__/hierarchy.spec.ts +55 -0
  12. package/assembly/__tests__/lib/index.ts +1 -0
  13. package/assembly/custom/util.ts +0 -4
  14. package/assembly/deserialize/simple/array/box.ts +45 -0
  15. package/assembly/deserialize/simple/array/object.ts +28 -0
  16. package/assembly/deserialize/simple/array.ts +8 -0
  17. package/assembly/index.ts +39 -41
  18. package/assembly/serialize/simd/string.ts +12 -12
  19. package/assembly/test.ts +46 -133
  20. package/assembly/util/idofd.ts +6 -0
  21. package/bench/abc.bench.ts +1 -1
  22. package/bench/large.bench.ts +3 -3
  23. package/bench/lib/bench.ts +12 -0
  24. package/bench/medium.bench.ts +1 -1
  25. package/bench/runners/assemblyscript.js +28 -0
  26. package/bench/small.bench.ts +1 -1
  27. package/bench/tsconfig.json +12 -0
  28. package/bench/vec3.bench.ts +1 -1
  29. package/package.json +3 -4
  30. package/run-bench.as.sh +44 -18
  31. package/run-bench.js.sh +32 -6
  32. package/run-tests.sh +1 -1
  33. package/transform/lib/index.js +381 -122
  34. package/transform/lib/index.js.map +1 -1
  35. package/transform/lib/types.js +1 -0
  36. package/transform/lib/types.js.map +1 -1
  37. package/transform/src/index.ts +430 -117
  38. package/transform/src/types.ts +1 -0
  39. package/assembly/__benches__/lib/index.ts +0 -26
  40. package/assembly/custom/memory.ts +0 -25
  41. package/assembly/custom/sink.ts +0 -231
  42. package/assembly/custom/types.ts +0 -5
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Change Log
2
2
 
3
+ ## 2025-05-22 - 1.0.9
4
+
5
+ - fix: [#132](https://github.com/JairusSW/json-as/issues/132)
6
+ - feat: allow base classes to use their child classes if the signatures match
7
+ - perf: rewrite struct deserialization to be significantly faster
8
+ - fix: [#131](https://github.com/JairusSW/json-as/issues/131) Generic classes with custom deserializer crashing
9
+ - fix: [#66](https://github.com/JairusSW/json-as/issues/66) Throw error when additional keys are in JSON
10
+
11
+ ## 2025-05-21 - 1.0.8
12
+
13
+ - fix: inline warnings on layer-2 serialize and deserialize functions
14
+ - feat: fully support `JSON.Obj` and `JSON.Box` everywhere
15
+ - fix: temp disable SIMD
16
+ - feat: write fair benchmarks with `v8` using `jsvu`
17
+
3
18
  ## 2025-05-14 - 1.0.7
4
19
 
5
20
  - merge: pull request [#128](https://github.com/JairusSW/json-as/pull/128) from [loredanacirstea/nested-custom-serializer-fix](https://github.com/loredanacirstea/nested-custom-serializer-fix)
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
  ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
7
7
  █████ ███████ ██████ ██ ████ ██ ██ ███████
8
8
  </span>
9
- AssemblyScript - v1.0.7
9
+ AssemblyScript - v1.0.9
10
10
  </pre>
11
11
  </h6>
12
12
 
@@ -57,6 +57,7 @@ If you'd like to see the code that the transform generates, run the build step w
57
57
  ```typescript
58
58
  import { JSON } from "json-as";
59
59
 
60
+
60
61
  @json
61
62
  class Vec3 {
62
63
  x: f32 = 0.0;
@@ -64,8 +65,10 @@ class Vec3 {
64
65
  z: f32 = 0.0;
65
66
  }
66
67
 
68
+
67
69
  @json
68
70
  class Player {
71
+
69
72
  @alias("first name")
70
73
  firstName!: string;
71
74
  lastName!: string;
@@ -73,6 +76,7 @@ class Player {
73
76
  // Drop in a code block, function, or expression that evaluates to a boolean
74
77
  @omitif((self: Player) => self.age < 18)
75
78
  age!: i32;
79
+
76
80
  @omitnull()
77
81
  pos!: Vec3 | null;
78
82
  isVerified!: boolean;
@@ -109,9 +113,11 @@ This library allows selective omission of fields during serialization using the
109
113
  This decorator excludes a field from serialization entirely.
110
114
 
111
115
  ```typescript
116
+
112
117
  @json
113
118
  class Example {
114
119
  name!: string;
120
+
115
121
  @omit
116
122
  SSN!: string;
117
123
  }
@@ -128,9 +134,11 @@ console.log(JSON.stringify(obj)); // { "name": "Jairus" }
128
134
  This decorator omits a field only if its value is null.
129
135
 
130
136
  ```typescript
137
+
131
138
  @json
132
139
  class Example {
133
140
  name!: string;
141
+
134
142
  @omitnull()
135
143
  optionalField!: string | null;
136
144
  }
@@ -147,9 +155,11 @@ console.log(JSON.stringify(obj)); // { "name": "Jairus" }
147
155
  This decorator omits a field based on a custom predicate function.
148
156
 
149
157
  ```typescript
158
+
150
159
  @json
151
160
  class Example {
152
161
  name!: string;
162
+
153
163
  @omitif((self: Example) => self.age <= 18)
154
164
  age!: number;
155
165
  }
@@ -174,6 +184,7 @@ AssemblyScript doesn't support using nullable primitive types, so instead, json-
174
184
  For example, this schema won't compile in AssemblyScript:
175
185
 
176
186
  ```typescript
187
+
177
188
  @json
178
189
  class Person {
179
190
  name!: string;
@@ -184,6 +195,7 @@ class Person {
184
195
  Instead, use `JSON.Box` to allow nullable primitives:
185
196
 
186
197
  ```typescript
198
+
187
199
  @json
188
200
  class Person {
189
201
  name: string;
@@ -246,6 +258,7 @@ More often, objects will be completely statically typed except for one or two va
246
258
  In such cases, `JSON.Value` can be used to handle fields that may hold different types at runtime.
247
259
 
248
260
  ```typescript
261
+
249
262
  @json
250
263
  class DynamicObj {
251
264
  id: i32 = 0;
@@ -302,6 +315,7 @@ Here's an example of creating a custom data type called `Point` which serializes
302
315
  ```typescript
303
316
  import { bytes } from "json-as/assembly/util";
304
317
 
318
+
305
319
  @json
306
320
  class Point {
307
321
  x: f64 = 0.0;
@@ -311,11 +325,13 @@ class Point {
311
325
  this.y = y;
312
326
  }
313
327
 
328
+
314
329
  @serializer
315
330
  serializer(self: Point): string {
316
331
  return `(${self.x},${self.y})`;
317
332
  }
318
333
 
334
+
319
335
  @deserializer
320
336
  deserializer(data: string): Point {
321
337
  const dataSize = bytes(data);
@@ -371,7 +387,7 @@ These benchmarks compare this library to JavaScript's native `JSON.stringify` an
371
387
 
372
388
  | Test Case | Size | Serialization (ops/s) | Deserialization (ops/s) | Serialization (MB/s) | Deserialization (MB/s) |
373
389
  | --------------- | ---------- | --------------------- | ----------------------- | -------------------- | ---------------------- |
374
- | Vector3 Object | 38 bytes | 35,714,285 ops/s | 35,435,552 ops/s | 1,357 MB/s | 1,348 MB/s |
390
+ | Vector3 Object | 38 bytes | 26,611,226 ops/s | 32,160,804 ops/s | 1,357 MB/s | 1,348 MB/s |
375
391
  | Alphabet String | 104 bytes | 13,617,021 ops/s | 18,390,804 ops/s | 1,416 MB/s | 1,986 MB/s |
376
392
  | Small Object | 88 bytes | 24,242,424 ops/s | 12,307,692 ops/s | 2,133 MB/s | 1,083 MB/s |
377
393
  | Medium Object | 494 bytes | 4,060,913 ops/s | 1,396,160 ops/s | 2,006 MB/s | 689.7 MB/s |
package/asconfig.json CHANGED
@@ -3,6 +3,5 @@
3
3
  "options": {
4
4
  "transform": [],
5
5
  "disableWarning": []
6
- },
7
- "extends": "./node_modules/@assemblyscript/wasi-shim/asconfig.json"
6
+ }
8
7
  }
@@ -1,5 +1,5 @@
1
1
  import { JSON } from "..";
2
- import { bench } from "../custom/bench";
2
+ import { bench } from "./lib/bench";
3
3
 
4
4
  const v1 = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
5
5
  const v2 = '"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"';
@@ -7,15 +7,15 @@ const v2 = '"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"';
7
7
  bench(
8
8
  "Serialize Alphabet",
9
9
  () => {
10
- JSON.stringify(v1);
10
+ inline.always(JSON.stringify(v1));
11
11
  },
12
- 1_000_00,
12
+ 64_000_00,
13
13
  );
14
14
 
15
15
  bench(
16
16
  "Deserialize Alphabet",
17
17
  () => {
18
- JSON.parse<string>(v2);
18
+ inline.always(JSON.parse<string>(v2));
19
19
  },
20
- 1_000_00,
20
+ 64_000_00,
21
21
  );
@@ -1,5 +1,5 @@
1
1
  import { JSON } from "..";
2
- import { bench } from "../custom/bench";
2
+ import { bench } from "./lib/bench";
3
3
 
4
4
 
5
5
  @json
@@ -7,52 +7,6 @@ class Vec3 {
7
7
  public x!: i32;
8
8
  public y!: i32;
9
9
  public z!: i32;
10
-
11
-
12
- @inline __SERIALIZE(ptr: usize): void {
13
- bs.proposeSize(98);
14
- store<u64>(bs.offset, 9570664606466171, 0); // {"x"
15
- store<u16>(bs.offset, 58, 8); // :
16
- bs.offset += 10;
17
- JSON.__serialize<i32>(load<i32>(ptr, offsetof<this>("x")));
18
- store<u64>(bs.offset, 9570668901433388, 0); // ,"y"
19
- store<u16>(bs.offset, 58, 8); // :
20
- bs.offset += 10;
21
- JSON.__serialize<i32>(load<i32>(ptr, offsetof<this>("y")));
22
- store<u64>(bs.offset, 9570673196400684, 0); // ,"z"
23
- store<u16>(bs.offset, 58, 8); // :
24
- bs.offset += 10;
25
- JSON.__serialize<i32>(load<i32>(ptr, offsetof<this>("z")));
26
- store<u16>(bs.offset, 125, 0); // }
27
- bs.offset += 2;
28
- }
29
-
30
-
31
- @inline __INITIALIZE(): this {
32
- return this;
33
- }
34
-
35
-
36
- @inline __DESERIALIZE(keyStart: usize, keyEnd: usize, valStart: usize, valEnd: usize, ptr: usize): void {
37
- switch (load<u16>(keyStart)) {
38
- case 120: {
39
- // x
40
- store<i32>(ptr, JSON.__deserialize<i32>(valStart, valEnd, 0), offsetof<this>("x"));
41
- return;
42
- }
43
- case 121: {
44
- // y
45
- store<i32>(ptr, JSON.__deserialize<i32>(valStart, valEnd, 0), offsetof<this>("y"));
46
- return;
47
- }
48
- case 122: {
49
- // z
50
- store<i32>(ptr, JSON.__deserialize<i32>(valStart, valEnd, 0), offsetof<this>("z"));
51
- return;
52
- }
53
- }
54
- return;
55
- }
56
10
  }
57
11
 
58
12
 
@@ -161,17 +115,17 @@ const v1: LargeJSON = {
161
115
  const v2 = `{"id":2,"name":"Medium Object","age":18,"email":"me@jairus.dev","street":"I don't want to say my street","city":"I don't want to say this either","state":"It really depends","zip":"I forget what it is","tags":["me","dogs","mountains","bar","foo"],"theme":"Hyper Term Black","notifications":true,"language":"en-US","movement":[{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3},{"x":1,"y":2,"z":3}]}`;
162
116
 
163
117
  bench(
164
- "Serialize Medium Object",
118
+ "Serialize Large Object",
165
119
  () => {
166
120
  JSON.stringify(v1);
167
121
  },
168
- 3_000_00,
122
+ 2_000_00,
169
123
  );
170
124
 
171
125
  bench(
172
- "Deserialize Medium Object",
126
+ "Deserialize Large Object",
173
127
  () => {
174
128
  JSON.parse<LargeJSON>(v2);
175
129
  },
176
- 3_000_00,
130
+ 2_000_00,
177
131
  );
@@ -1,5 +1,9 @@
1
1
  export function bench(description: string, routine: () => void, ops: u64 = 1_000_000): void {
2
2
  console.log(" - Benchmarking " + description);
3
+ let warmup = ops / 10;
4
+ while (--warmup) {
5
+ routine();
6
+ }
3
7
  const start = Date.now();
4
8
  let count = ops;
5
9
  while (count != 0) {
@@ -1,5 +1,5 @@
1
1
  import { JSON } from "..";
2
- import { bench } from "../custom/bench";
2
+ import { bench } from "./lib/bench";
3
3
 
4
4
 
5
5
  @json
@@ -34,7 +34,7 @@ bench(
34
34
  () => {
35
35
  JSON.stringify(v1);
36
36
  },
37
- 8_000_00,
37
+ 6_000_00,
38
38
  );
39
39
 
40
40
  bench(
@@ -42,5 +42,5 @@ bench(
42
42
  () => {
43
43
  JSON.parse<MediumJSON>(v2);
44
44
  },
45
- 8_000_00,
45
+ 6_000_00,
46
46
  );
@@ -1,5 +1,5 @@
1
1
  import { JSON } from "..";
2
- import { bench } from "../custom/bench";
2
+ import { bench } from "./lib/bench";
3
3
 
4
4
 
5
5
  @json
@@ -1,5 +1,5 @@
1
1
  import { JSON } from "..";
2
- import { bench } from "../custom/bench";
2
+ import { bench } from "./lib/bench";
3
3
 
4
4
 
5
5
  @json
@@ -7,52 +7,6 @@ class Vec3 {
7
7
  public x!: i32;
8
8
  public y!: i32;
9
9
  public z!: i32;
10
-
11
-
12
- @inline __SERIALIZE(ptr: usize): void {
13
- bs.proposeSize(98);
14
- store<u64>(bs.offset, 9570664606466171, 0); // {"x"
15
- store<u16>(bs.offset, 58, 8); // :
16
- bs.offset += 10;
17
- JSON.__serialize<i32>(load<i32>(ptr, offsetof<this>("x")));
18
- store<u64>(bs.offset, 9570668901433388, 0); // ,"y"
19
- store<u16>(bs.offset, 58, 8); // :
20
- bs.offset += 10;
21
- JSON.__serialize<i32>(load<i32>(ptr, offsetof<this>("y")));
22
- store<u64>(bs.offset, 9570673196400684, 0); // ,"z"
23
- store<u16>(bs.offset, 58, 8); // :
24
- bs.offset += 10;
25
- JSON.__serialize<i32>(load<i32>(ptr, offsetof<this>("z")));
26
- store<u16>(bs.offset, 125, 0); // }
27
- bs.offset += 2;
28
- }
29
-
30
-
31
- @inline __INITIALIZE(): this {
32
- return this;
33
- }
34
-
35
-
36
- @inline __DESERIALIZE(keyStart: usize, keyEnd: usize, valStart: usize, valEnd: usize, ptr: usize): void {
37
- switch (load<u16>(keyStart)) {
38
- case 120: {
39
- // x
40
- store<i32>(ptr, JSON.__deserialize<i32>(valStart, valEnd, 0), offsetof<this>("x"));
41
- return;
42
- }
43
- case 121: {
44
- // y
45
- store<i32>(ptr, JSON.__deserialize<i32>(valStart, valEnd, 0), offsetof<this>("y"));
46
- return;
47
- }
48
- case 122: {
49
- // z
50
- store<i32>(ptr, JSON.__deserialize<i32>(valStart, valEnd, 0), offsetof<this>("z"));
51
- return;
52
- }
53
- }
54
- return;
55
- }
56
10
  }
57
11
 
58
12
  const v1: Vec3 = { x: 1, y: 2, z: 3 };
@@ -63,7 +17,7 @@ bench(
63
17
  () => {
64
18
  JSON.stringify(v1);
65
19
  },
66
- 16_000_00,
20
+ 128_000_00,
67
21
  );
68
22
 
69
23
  bench(
@@ -71,5 +25,5 @@ bench(
71
25
  () => {
72
26
  JSON.parse<Vec3>(v2);
73
27
  },
74
- 16_000_00,
28
+ 128_000_00,
75
29
  );
@@ -32,11 +32,12 @@ class Point {
32
32
  }
33
33
  }
34
34
 
35
+
35
36
  @json
36
- export class ObjectWithCustom {
37
- value: Point = new Point(0, 0)
37
+ class ObjectWithCustom {
38
+ value: Point = new Point(0, 0);
38
39
  constructor(value: Point) {
39
- this.value = value
40
+ this.value = value;
40
41
  }
41
42
  }
42
43
 
@@ -0,0 +1,55 @@
1
+ import { OBJECT, TOTAL_OVERHEAD } from "rt/common";
2
+ import { JSON } from "..";
3
+ import { describe, expect } from "./lib";
4
+
5
+ @json
6
+ class Foo {
7
+ a: i32 = 0;
8
+ }
9
+
10
+ @json
11
+ class Bar extends Foo {
12
+ b: i32 = 0;
13
+
14
+ @serializer
15
+ serialize(self: Bar): string {
16
+ return `"bar"`;
17
+ }
18
+
19
+ @deserializer
20
+ deserialize(data: string): Bar {
21
+ return data == "\"bar\"" ? {
22
+ a: 1,
23
+ b: 2,
24
+ } : new Bar();
25
+ }
26
+ }
27
+
28
+ describe("should use custom serializer for subclasses", () => {
29
+ const bar = new Bar();
30
+ bar.a = 1;
31
+ bar.b = 2;
32
+ const data = JSON.stringify(bar);
33
+ expect(data).toBe('"bar"');
34
+ });
35
+
36
+ describe("should use custom serializer for subclasses when type is the parent", () => {
37
+ const bar = new Bar();
38
+ bar.a = 1;
39
+ bar.b = 2;
40
+ const data = JSON.stringify<Foo>(bar);
41
+ expect(data).toBe('"bar"');
42
+ });
43
+
44
+ describe("should use custom deserializer for subclass", () => {
45
+ const json = '"bar"';
46
+ const bar = JSON.parse<Bar>(json);
47
+ expect(bar.a.toString()).toBe("1");
48
+ expect(bar.b.toString()).toBe("2");
49
+ });
50
+
51
+ describe("should use custom deserializer even when type is the parent", () => {
52
+ const json = '"bar"';
53
+ const foo = JSON.parse<Bar>(json);
54
+ expect(foo.a.toString()).toBe("1");
55
+ });
@@ -1,5 +1,6 @@
1
1
  export function describe(description: string, routine: () => void): void {
2
2
  routine();
3
+ // console.log(" " + description + " OK");
3
4
  }
4
5
 
5
6
  export function expect(left: string): Expectation {
@@ -1,7 +1,3 @@
1
- import { isSpace } from "util/string";
2
- import { BACK_SLASH, QUOTE } from "./chars";
3
- import { Sink } from "./sink";
4
-
5
1
  /** Scientific Notation Integer Parsing - SNIP
6
2
  * This is absolutely the fastest algorithm I could think of while adding full support for Scientific Notation
7
3
  * Loads 32 bits and retrieves the high/low bits.
@@ -0,0 +1,45 @@
1
+ import { isSpace } from "../../../util";
2
+ import { COMMA, BRACKET_RIGHT } from "../../../custom/chars";
3
+ import { JSON } from "../../..";
4
+
5
+ export function deserializeBoxArray<T extends JSON.Box<any>[]>(srcStart: usize, srcEnd: usize, dst: usize): T {
6
+ const out = changetype<nonnull<T>>(dst || changetype<usize>(instantiate<T>()));
7
+ if (isBoolean<valueof<T>>()) {
8
+ srcStart += 2; // skip [
9
+ while (srcStart < srcEnd) {
10
+ const block = load<u64>(srcStart);
11
+ if (block == 28429475166421108) {
12
+ out.push(JSON.Box.from(true));
13
+ srcStart += 10;
14
+ } else if (block == 32370086184550502 && load<u16>(srcStart, 8) == 101) {
15
+ out.push(JSON.Box.from(false));
16
+ srcStart += 12;
17
+ } else {
18
+ srcStart += 2;
19
+ }
20
+ }
21
+ return out;
22
+ } else {
23
+ let lastIndex: usize = 0;
24
+ while (srcStart < srcEnd) {
25
+ const code = load<u16>(srcStart);
26
+ if (code - 48 <= 9 || code == 45) {
27
+ lastIndex = srcStart;
28
+ srcStart += 2;
29
+ while (srcStart < srcEnd) {
30
+ const code = load<u16>(srcStart);
31
+ if (code == COMMA || code == BRACKET_RIGHT || isSpace(code)) {
32
+ out.push(JSON.__deserialize<valueof<T>>(lastIndex, srcStart));
33
+ // while (isSpace(load<u16>((srcStart += 2)))) {
34
+ // /* empty */
35
+ // }
36
+ break;
37
+ }
38
+ srcStart += 2;
39
+ }
40
+ }
41
+ srcStart += 2;
42
+ }
43
+ }
44
+ return out;
45
+ }
@@ -0,0 +1,28 @@
1
+ import { BRACE_LEFT, BRACE_RIGHT, BRACKET_LEFT, BRACKET_RIGHT } from "../../../custom/chars";
2
+ import { JSON } from "../../..";
3
+ import { isSpace } from "util/string";
4
+
5
+ export function deserializeObjectArray<T extends unknown[]>(srcStart: usize, srcEnd: usize, dst: usize): T {
6
+ const out = changetype<nonnull<T>>(dst || changetype<usize>(instantiate<T>()));
7
+ let lastIndex: usize = 0;
8
+ let depth: u32 = 0;
9
+
10
+ while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
11
+ while (srcEnd > srcStart && isSpace(load<u16>(srcEnd - 2))) srcEnd -= 2;
12
+
13
+ if (srcStart - srcEnd == 0) throw new Error("Input string had zero length or was all whitespace");
14
+
15
+ if (load<u16>(srcStart) != BRACKET_LEFT) throw new Error("Expected '[' at start of object at position " + (srcEnd - srcStart).toString());
16
+ if (load<u16>(srcEnd - 2) != BRACKET_RIGHT) throw new Error("Expected ']' at end of object at position " + (srcEnd - srcStart).toString());
17
+
18
+ while (srcStart < srcEnd) {
19
+ const code = load<u16>(srcStart);
20
+ if (code == BRACE_LEFT && depth++ == 0) {
21
+ lastIndex = srcStart;
22
+ } else if (code == BRACE_RIGHT && --depth == 0) {
23
+ out.push(JSON.__deserialize<valueof<T>>(lastIndex, (srcStart += 2)));
24
+ }
25
+ srcStart += 2;
26
+ }
27
+ return out;
28
+ }
@@ -7,6 +7,8 @@ import { deserializeIntegerArray } from "./array/integer";
7
7
  import { deserializeMapArray } from "./array/map";
8
8
  import { deserializeStructArray } from "./array/struct";
9
9
  import { deserializeStringArray } from "./array/string";
10
+ import { deserializeObjectArray } from "./array/object";
11
+ import { deserializeBoxArray } from "./array/box";
10
12
 
11
13
  // @ts-ignore: Decorator valid here
12
14
  export function deserializeArray<T extends unknown[]>(srcStart: usize, srcEnd: usize, dst: usize): T {
@@ -29,6 +31,12 @@ export function deserializeArray<T extends unknown[]>(srcStart: usize, srcEnd: u
29
31
  if (type instanceof JSON.Value) {
30
32
  // @ts-ignore: type
31
33
  return deserializeArbitraryArray(srcStart, srcEnd, dst);
34
+ } else if (type instanceof JSON.Box) {
35
+ // @ts-ignore: type
36
+ return deserializeBoxArray<T>(srcStart, srcEnd, dst);
37
+ } else if (type instanceof JSON.Obj) {
38
+ // @ts-ignore: type
39
+ return deserializeObjectArray<T>(srcStart, srcEnd, dst);
32
40
  } else if (type instanceof Map) {
33
41
  // @ts-ignore: type
34
42
  return deserializeMapArray<T>(srcStart, srcEnd, dst);