json-as 1.0.0-beta.1 → 1.0.0-beta.11

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 (72) hide show
  1. package/.trunk/configs/.markdownlint.yaml +2 -0
  2. package/.trunk/configs/.shellcheckrc +7 -0
  3. package/.trunk/configs/.yamllint.yaml +7 -0
  4. package/.trunk/trunk.yaml +37 -0
  5. package/CHANGELOG +65 -0
  6. package/README.md +275 -25
  7. package/assembly/__benches__/misc.bench.ts +0 -1
  8. package/assembly/__benches__/string.bench.ts +23 -0
  9. package/assembly/__benches__/struct.bench.ts +21 -0
  10. package/assembly/__tests__/arbitrary.spec.ts +1 -1
  11. package/assembly/__tests__/array.spec.ts +42 -1
  12. package/assembly/__tests__/bool.spec.ts +1 -1
  13. package/assembly/__tests__/box.spec.ts +1 -1
  14. package/assembly/__tests__/custom.spec.ts +42 -0
  15. package/assembly/__tests__/date.spec.ts +1 -1
  16. package/assembly/__tests__/float.spec.ts +4 -4
  17. package/assembly/__tests__/integer.spec.ts +1 -1
  18. package/assembly/__tests__/map.spec.ts +7 -0
  19. package/assembly/__tests__/null.spec.ts +1 -1
  20. package/assembly/__tests__/raw.spec.ts +23 -0
  21. package/assembly/__tests__/string.spec.ts +1 -1
  22. package/assembly/__tests__/{obj.spec.ts → struct.spec.ts} +18 -4
  23. package/assembly/__tests__/test.spec.ts +1 -1
  24. package/assembly/as-bs.d.ts +53 -0
  25. package/assembly/custom/bench.ts +26 -0
  26. package/assembly/deserialize/simple/arbitrary.ts +5 -4
  27. package/assembly/deserialize/simple/array/arbitrary.ts +1 -2
  28. package/assembly/deserialize/simple/array/array.ts +4 -3
  29. package/assembly/deserialize/simple/array/bool.ts +7 -7
  30. package/assembly/deserialize/simple/array/float.ts +2 -2
  31. package/assembly/deserialize/simple/array/integer.ts +1 -1
  32. package/assembly/deserialize/simple/array/map.ts +1 -1
  33. package/assembly/deserialize/simple/array/string.ts +3 -3
  34. package/assembly/deserialize/simple/array/struct.ts +14 -3
  35. package/assembly/deserialize/simple/array.ts +3 -0
  36. package/assembly/deserialize/simple/map.ts +93 -75
  37. package/assembly/deserialize/simple/object.ts +26 -16
  38. package/assembly/deserialize/simple/raw.ts +6 -0
  39. package/assembly/deserialize/simple/struct.ts +29 -16
  40. package/assembly/index.d.ts +15 -1
  41. package/assembly/index.ts +94 -13
  42. package/assembly/serialize/simd/string.ts +0 -1
  43. package/assembly/serialize/simple/array.ts +0 -1
  44. package/assembly/serialize/simple/bool.ts +0 -2
  45. package/assembly/serialize/simple/date.ts +0 -1
  46. package/assembly/serialize/simple/float.ts +0 -1
  47. package/assembly/serialize/simple/integer.ts +0 -1
  48. package/assembly/serialize/simple/map.ts +0 -1
  49. package/assembly/serialize/simple/object.ts +0 -1
  50. package/assembly/serialize/simple/raw.ts +14 -0
  51. package/assembly/serialize/simple/string.ts +0 -1
  52. package/assembly/test.ts +69 -28
  53. package/bench/bench.ts +15 -0
  54. package/bench/schemas.ts +5 -0
  55. package/bench/string.bench.ts +16 -0
  56. package/index.ts +1 -1
  57. package/lib/tsconfig.json +8 -0
  58. package/package.json +10 -6
  59. package/run-tests.sh +1 -1
  60. package/transform/lib/index.js +120 -46
  61. package/transform/lib/index.js.map +1 -1
  62. package/transform/src/index.ts +137 -54
  63. package/.gitmodules +0 -0
  64. package/as-test.config.json +0 -18
  65. package/modules/as-bs/LICENSE +0 -21
  66. package/modules/as-bs/README.md +0 -95
  67. package/modules/as-bs/assembly/state.ts +0 -8
  68. package/modules/as-bs/assembly/tsconfig.json +0 -97
  69. package/modules/as-bs/index.ts +0 -1
  70. package/modules/as-bs/package.json +0 -32
  71. /package/{modules/test/assembly → assembly/__tests__/lib}/index.ts +0 -0
  72. /package/{modules/as-bs/assembly/index.ts → lib/as-bs.ts} +0 -0
@@ -0,0 +1,42 @@
1
+ import { JSON } from "..";
2
+ import { describe, expect } from "./lib";
3
+ import { bytes } from "../util";
4
+
5
+ @json
6
+ class Point {
7
+ x: f64 = 0.0;
8
+ y: f64 = 0.0;
9
+ constructor(x: f64, y: f64) {
10
+ this.x = x;
11
+ this.y = y;
12
+ }
13
+ @serializer
14
+ serializer(self: Point): string {
15
+ return `(${self.x},${self.y})`;
16
+ }
17
+ @deserializer
18
+ deserializer(data: string): Point {
19
+ const dataSize = bytes(data);
20
+ if (dataSize <= 2) throw new Error("Could not deserialize provided data as type Point");
21
+
22
+ const c = data.indexOf(",");
23
+ const x = data.slice(1, c);
24
+ const y = data.slice(c + 1, data.length - 1);
25
+
26
+ return new Point(
27
+ f64.parse(x),
28
+ f64.parse(y)
29
+ );
30
+ }
31
+ }
32
+
33
+
34
+ describe("Should serialize using custom serializers", () => {
35
+ expect(JSON.stringify<Point>(new Point(1,2))).toBe("(1.0,2.0)");
36
+ });
37
+
38
+ describe("Should deserialize using custom deserializers", () => {
39
+ const p1 = JSON.parse<Point>("(1.0,2.0)");
40
+ expect(p1.x.toString()).toBe("1.0");
41
+ expect(p1.y.toString()).toBe("2.0");
42
+ });
@@ -1,5 +1,5 @@
1
1
  import { JSON } from "..";
2
- import { describe, expect } from "../../modules/test/assembly";
2
+ import { describe, expect } from "./lib";
3
3
 
4
4
  describe("Should serialize Date", () => {
5
5
  expect(JSON.stringify<Date>(new Date(0)))
@@ -1,5 +1,5 @@
1
1
  import { JSON } from "..";
2
- import { describe, expect } from "../../modules/test/assembly";
2
+ import { describe, expect } from "./lib";
3
3
 
4
4
  describe("Should serialize floats", () => {
5
5
  expect(JSON.stringify<f64>(7.23)).toBe("7.23");
@@ -34,9 +34,9 @@ describe("Should deserialize floats", () => {
34
34
 
35
35
  expect(JSON.parse<f64>("0.000001").toString()).toBe("0.000001");
36
36
 
37
- // expect(JSON.parse<f64>("1e-7")).toBe(1e-7);
37
+ expect(JSON.parse<f64>("1e-7").toString()).toBe(1e-7.toString());
38
38
 
39
- // expect(JSON.parse<f64>("100000000000000000000.0").toString()).toBe(1e20);
39
+ expect(JSON.parse<f64>("100000000000000000000.0").toString()).toBe(1e20.toString());
40
40
 
41
- // expect(JSON.parse<f64>("1e+21")).toBe(1e21);
41
+ expect(JSON.parse<f64>("1e+21").toString()).toBe(1e21.toString());
42
42
  });
@@ -1,5 +1,5 @@
1
1
  import { JSON } from "..";
2
- import { describe, expect } from "../../modules/test/assembly";
2
+ import { describe, expect } from "./lib";
3
3
 
4
4
  describe("Should serialize integers", () => {
5
5
  expect(JSON.stringify(0)).toBe("0");
@@ -0,0 +1,7 @@
1
+ import { JSON } from "..";
2
+ import { describe, expect } from "./lib";
3
+
4
+ describe("Should deserialize complex objects", () => {
5
+ const input = '{"a":{"b":{"c":[{"d":"random value 1"},{"e":["value 2","value 3"]}],"f":{"g":{"h":[1,2,3],"i":{"j":"nested value"}}}},"k":"simple value"},"l":[{"m":"another value","n":{"o":"deep nested","p":[{"q":"even deeper"},"final value"]}}],"r":null}';
6
+ expect(JSON.stringify(JSON.parse<Map<string, JSON.Raw>>(input))).toBe(input);
7
+ })
@@ -1,5 +1,5 @@
1
1
  import { JSON } from "..";
2
- import { describe, expect } from "../../modules/test/assembly";
2
+ import { describe, expect } from "./lib";
3
3
 
4
4
  describe("Should serialize null", () => {
5
5
  expect(JSON.stringify(null)).toBe("null");
@@ -0,0 +1,23 @@
1
+ import { JSON } from "..";
2
+ import { describe, expect } from "./lib";
3
+
4
+ describe("Should serialize JSON.Raw", () => {
5
+ expect(JSON.stringify<JSON.Raw>(JSON.Raw.from('{"x":1.0,"y":2.0,"z":3.0}'))).toBe('{"x":1.0,"y":2.0,"z":3.0}');
6
+ });
7
+
8
+ describe("Should deserialize JSON.Raw", () => {
9
+ expect(JSON.parse<JSON.Raw>('{"x":1.0,"y":2.0,"z":3.0}').toString()).toBe('{"x":1.0,"y":2.0,"z":3.0}');
10
+ });
11
+
12
+ describe("Should serialize Map<string, JSON.Raw>", () => {
13
+ const m1 = new Map<string, JSON.Raw>();
14
+ m1.set("hello", new JSON.Raw("\"world\""));
15
+ m1.set("pos", new JSON.Raw("{\"x\":1.0,\"y\":2.0,\"z\":3.0}"));
16
+
17
+ expect(JSON.stringify(m1)).toBe('{"hello":"world","pos":{"x":1.0,"y":2.0,"z":3.0}}');
18
+ });
19
+
20
+ describe("Should deserialize Map<string, JSON.Raw>", () => {
21
+ const m1 = JSON.parse<Map<string, JSON.Raw>>('{"hello":"world","pos":{"x":1.0,"y":2.0,"z":3.0}}');
22
+ expect(JSON.stringify(m1)).toBe('{"hello":"world","pos":{"x":1.0,"y":2.0,"z":3.0}}');
23
+ });
@@ -1,5 +1,5 @@
1
1
  import { JSON } from "..";
2
- import { describe, expect } from "../../modules/test/assembly";
2
+ import { describe, expect } from "./lib";
3
3
 
4
4
  describe("Should serialize strings", () => {
5
5
  expect(JSON.stringify("abcdefg")).toBe('"abcdefg"');
@@ -1,7 +1,7 @@
1
1
  import { JSON } from "..";
2
- import { describe, expect } from "../../modules/test/assembly";
2
+ import { describe, expect } from "./lib";
3
3
 
4
- describe("Should serialize objects", () => {
4
+ describe("Should serialize structs", () => {
5
5
  expect(
6
6
  JSON.stringify<Vec3>({
7
7
  x: 3.4,
@@ -38,7 +38,7 @@ describe("Should serialize objects", () => {
38
38
  expect(JSON.stringify<ObjWithStrangeKey<string>>({ data: "foo" })).toBe('{"a\\\\\\t\\"\\u0002b`c":"foo"}');
39
39
  });
40
40
 
41
- describe("Should serialize objects with inheritance", () => {
41
+ describe("Should serialize structs with inheritance", () => {
42
42
  const obj = new DerivedObject("1", "2");
43
43
 
44
44
  expect(JSON.stringify(obj)).toBe('{"a":"1","b":"2"}');
@@ -52,6 +52,21 @@ describe("Should ignore properties decorated with @omit", () => {
52
52
  ).toBe('{"y":1,"x":1,"z":1}');
53
53
  });
54
54
 
55
+ describe("Should deserialize structs", () => {
56
+ expect(
57
+ JSON.stringify(JSON.parse<Vec3>('{"x":3.4,"y":1.2,"z":8.3}')),
58
+ ).toBe('{"x":3.4,"y":1.2,"z":8.3}');
59
+ });
60
+
61
+ describe("Should deserialize structs with whitespace", () => {
62
+ expect(
63
+ JSON.stringify(JSON.parse<Vec3>(' { "x" : 3.4 , "y" : 1.2 , "z" : 8.3 } ')),
64
+ ).toBe('{"x":3.4,"y":1.2,"z":8.3}');
65
+ });
66
+
67
+ // describe("Should serialize Suite struct", () => {
68
+
69
+ // });
55
70
 
56
71
  @json
57
72
  class BaseObject {
@@ -99,7 +114,6 @@ class ObjWithString {
99
114
 
100
115
  @json
101
116
  class ObjWithStrangeKey<T> {
102
-
103
117
  @alias('a\\\t"\x02b`c')
104
118
  data!: T;
105
119
  }
@@ -1,5 +1,5 @@
1
1
  import { JSON } from "../";
2
- import { describe, expect } from "../../modules/test/assembly/index";
2
+ import { describe, expect } from "./lib";
3
3
  import { DerivedObject, Null, ObjWithStrangeKey, ObjectWithFloat, OmitIf, Player, Vec3 } from "./types";
4
4
 
5
5
  // describe("Should serialize objects", () => {
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Central buffer namespace for managing memory operations.
3
+ */
4
+ declare namespace bs {
5
+ /** Current buffer pointer. */
6
+ export let buffer: ArrayBuffer;
7
+
8
+ /** Current offset within the buffer. */
9
+ export let offset: usize;
10
+
11
+ /** Proposed size of output. */
12
+ export let stackSize: usize;
13
+
14
+ /**
15
+ * Ensures the buffer size is at least the proposed size.
16
+ * If necessary, reallocates the buffer to the exact new size.
17
+ * @param size - The size to propose.
18
+ */
19
+ export function ensureSize(size: u32): void;
20
+
21
+ /**
22
+ * Proposes that the buffer size should be at least the given size.
23
+ * If necessary, reallocates the buffer to the exact new size.
24
+ * @param size - The size to propose.
25
+ */
26
+ export function proposeSize(size: u32): void;
27
+
28
+ /**
29
+ * Increases the proposed size by nextPowerOf2(n + 64) if necessary.
30
+ * If necessary, reallocates the buffer to the exact new size.
31
+ * @param size - The size to grow by.
32
+ */
33
+ export function growSize(size: u32): void;
34
+
35
+ /**
36
+ * Resizes the buffer to the specified size.
37
+ * @param newSize - The new buffer size.
38
+ */
39
+ export function resize(newSize: u32): void;
40
+
41
+ /**
42
+ * Copies the buffer's content to a new object of a specified type.
43
+ * @returns The new object containing the buffer's content.
44
+ */
45
+ export function out<T>(): T;
46
+
47
+ /**
48
+ * Copies the buffer's content to a given destination pointer.
49
+ * @param dst - The destination pointer.
50
+ * @returns The destination pointer cast to the specified type.
51
+ */
52
+ export function outTo<T>(dst: usize): T;
53
+ }
@@ -0,0 +1,26 @@
1
+ export function bench(description: string, routine: () => void, ops: u64 = 1_000_000): void {
2
+ console.log(" - Benchmarking " + description);
3
+ const start = Date.now();
4
+ let count = ops;
5
+ while (count != 0) {
6
+ routine();
7
+ count--;
8
+ }
9
+ const elapsed = Date.now() - start;
10
+
11
+ let opsPerSecond = (ops * 1000) / elapsed;
12
+
13
+ console.log(` Completed benchmark in ${formatNumber(elapsed)}ms at ${formatNumber(opsPerSecond)} ops/s\n`);
14
+ }
15
+
16
+ function formatNumber(n: u64): string {
17
+ let str = n.toString();
18
+ let len = str.length;
19
+ let result = "";
20
+ let commaOffset = len % 3;
21
+ for (let i = 0; i < len; i++) {
22
+ if (i > 0 && (i - commaOffset) % 3 == 0) result += ",";
23
+ result += str.charAt(i);
24
+ }
25
+ return result;
26
+ }
@@ -4,14 +4,15 @@ import { deserializeBoolean } from "./bool";
4
4
  import { deserializeFloat } from "./float";
5
5
  import { deserializeString } from "./string";
6
6
  import { deserializeObject } from "./object";
7
+ import { BRACE_LEFT, BRACKET_LEFT, QUOTE } from "../../custom/chars";
7
8
 
8
9
  export function deserializeArbitrary(srcStart: usize, srcEnd: usize, dst: usize): JSON.Value {
9
10
  const firstChar = load<u16>(srcStart);
10
- if (firstChar == 34) return JSON.Value.from(deserializeString(srcStart, srcEnd, dst));
11
- else if (firstChar == 123) return JSON.Value.from(deserializeObject(srcStart, srcEnd, dst));
11
+ if (firstChar == QUOTE) return JSON.Value.from(deserializeString(srcStart, srcEnd, 0));
12
+ else if (firstChar == BRACE_LEFT) return JSON.Value.from(deserializeObject(srcStart, srcEnd, 0));
12
13
  else if (firstChar - 48 <= 9 || firstChar == 45) return JSON.Value.from(deserializeFloat<f64>(srcStart, srcEnd));
13
- else if (firstChar == 91) {
14
- return JSON.Value.from(deserializeArray<JSON.Value[]>(srcStart, srcEnd, dst));
14
+ else if (firstChar == BRACKET_LEFT) {
15
+ return JSON.Value.from(deserializeArray<JSON.Value[]>(srcStart, srcEnd, 0));
15
16
  } else if (firstChar == 116 || firstChar == 102) return JSON.Value.from(deserializeBoolean(srcStart, srcEnd));
16
17
  return unreachable();
17
18
  }
@@ -1,10 +1,9 @@
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";
5
4
 
6
5
  export function deserializeArbitraryArray(srcStart: usize, srcEnd: usize, dst: usize): JSON.Value[] {
7
- const out = dst ? changetype<JSON.Value[]>(dst) : instantiate<JSON.Value[]>();
6
+ const out = changetype<JSON.Value[]>(dst || changetype<usize>(instantiate<JSON.Value[]>()));
8
7
  let lastIndex: usize = 0;
9
8
  let depth: u32 = 0;
10
9
  // if (load<u16>(srcStart) != BRACKET_LEFT)
@@ -2,15 +2,16 @@ import { BRACKET_LEFT, BRACKET_RIGHT } from "../../../custom/chars";
2
2
  import { JSON } from "../../../";
3
3
 
4
4
  export function deserializeArrayArray<T extends unknown[][]>(srcStart: usize, srcEnd: usize, dst: usize): T {
5
- const out = dst ? changetype<T>(dst) : instantiate<T>();
5
+ const out = changetype<nonnull<T>>(dst || changetype<usize>(instantiate<T>()));
6
6
  let lastIndex: usize = 0;
7
7
  let depth: u32 = 0;
8
- while (srcStart < srcEnd) {
8
+ srcStart += 2;
9
+ while (srcStart < srcEnd - 2) {
9
10
  const code = load<u16>(srcStart);
10
11
  if (code == BRACKET_LEFT && depth++ == 0) {
11
12
  lastIndex = srcStart;
12
13
  } else if (code == BRACKET_RIGHT && --depth == 0) {
13
- out.push(JSON.__deserialize<valueof<T>>(lastIndex, srcStart));
14
+ out.push(JSON.__deserialize<valueof<T>>(lastIndex, srcStart + 2));
14
15
  }
15
16
  srcStart += 2;
16
17
  }
@@ -1,17 +1,17 @@
1
- import { CHAR_E, CHAR_F, CHAR_T } from "../../../custom/chars";
2
-
3
1
  export function deserializeBooleanArray<T extends boolean[]>(srcStart: usize, srcEnd: usize, dst: usize): T {
4
- const out = dst ? changetype<T>(dst) : instantiate<T>();
2
+ const out = changetype<nonnull<T>>(dst || changetype<usize>(instantiate<T>()));
3
+ srcStart += 2; // skip [
5
4
  while (srcStart < srcEnd) {
6
- const code = load<u16>(srcStart);
7
- if (code == CHAR_T && load<u16>(srcStart, 8) == CHAR_E) {
5
+ const block = load<u64>(srcStart);
6
+ if (block == 28429475166421108) {
8
7
  out.push(true);
9
8
  srcStart += 10;
10
- } else if (code == CHAR_F && load<u16>(srcStart, 10) == CHAR_E) {
9
+ } else if (block == 32370086184550502 && load<u16>(srcStart, 8) == 101) {
11
10
  out.push(false);
12
11
  srcStart += 12;
12
+ } else {
13
+ srcStart += 2;
13
14
  }
14
- srcStart += 2;
15
15
  }
16
16
  return out;
17
17
  }
@@ -1,9 +1,9 @@
1
1
  import { isSpace } from "../../../util";
2
- import { COMMA, BRACE_RIGHT, BRACKET_RIGHT } from "../../../custom/chars";
2
+ import { COMMA, BRACKET_RIGHT } from "../../../custom/chars";
3
3
  import { JSON } from "../../..";
4
4
 
5
5
  export function deserializeFloatArray<T extends number[]>(srcStart: usize, srcEnd: usize, dst: usize): T {
6
- const out = dst ? changetype<T>(dst) : instantiate<T>();
6
+ const out = changetype<nonnull<T>>(dst || changetype<usize>(instantiate<T>()));
7
7
  let lastIndex: usize = 0;
8
8
  while (srcStart < srcEnd) {
9
9
  const code = load<u16>(srcStart);
@@ -2,7 +2,7 @@ import { atoi, isSpace } from "../../../util";
2
2
  import { COMMA, BRACKET_RIGHT } from "../../../custom/chars";
3
3
 
4
4
  export function deserializeIntegerArray<T extends number[]>(srcStart: usize, srcEnd: usize, dst: usize): T {
5
- const out: T = dst ? changetype<T>(dst) : instantiate<T>();
5
+ const out = changetype<nonnull<T>>(dst || changetype<usize>(instantiate<T>()));
6
6
  let lastIndex: usize = 0;
7
7
  while (srcStart < srcEnd) {
8
8
  const code = load<u16>(srcStart);
@@ -2,7 +2,7 @@ import { BRACE_LEFT, BRACE_RIGHT } from "../../../custom/chars";
2
2
  import { JSON } from "../../..";
3
3
 
4
4
  export function deserializeMapArray<T extends Map<any, any>[]>(srcStart: usize, srcEnd: usize, dst: usize): T {
5
- const out = dst ? changetype<T>(dst) : instantiate<T>();
5
+ const out = changetype<nonnull<T>>(dst || changetype<usize>(instantiate<T>()));
6
6
  let lastIndex: usize = 0;
7
7
  let depth: u32 = 0;
8
8
  while (srcStart < srcEnd) {
@@ -2,8 +2,8 @@ import { JSON } from "../../..";
2
2
  import { BACK_SLASH, QUOTE } from "../../../custom/chars";
3
3
 
4
4
  export function deserializeStringArray(srcStart: usize, srcEnd: usize, dst: usize): string[] {
5
- const out = dst ? changetype<string[]>(dst) : new Array<string>();
6
- let lastPos = 2;
5
+ const out = changetype<string[]>(dst || changetype<usize>(instantiate<string[]>()));
6
+ let lastPos: usize = 2;
7
7
  let inString = false;
8
8
  while (srcStart < srcEnd) {
9
9
  const code = load<u16>(srcStart);
@@ -12,7 +12,7 @@ export function deserializeStringArray(srcStart: usize, srcEnd: usize, dst: usiz
12
12
  inString = true;
13
13
  lastPos = srcStart;
14
14
  } else if (load<u16>(srcStart - 2) != BACK_SLASH) {
15
- out.push(JSON.__deserialize<string>(lastPos, srcStart));
15
+ out.push(JSON.__deserialize<string>(lastPos, srcStart + 2));
16
16
  inString = false;
17
17
  }
18
18
  }
@@ -1,16 +1,27 @@
1
- import { BRACE_LEFT, BRACE_RIGHT } from "../../../custom/chars";
1
+ import { BRACE_LEFT, BRACE_RIGHT, BRACKET_LEFT, BRACKET_RIGHT } from "../../../custom/chars";
2
2
  import { JSON } from "../../..";
3
+ import { isSpace } from "util/string";
3
4
 
4
5
  export function deserializeStructArray<T extends unknown[]>(srcStart: usize, srcEnd: usize, dst: usize): T {
5
- const out = dst ? changetype<T>(dst) : instantiate<T>();
6
+ const out = changetype<nonnull<T>>(dst || changetype<usize>(instantiate<T>()));
6
7
  let lastIndex: usize = 0;
7
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)
14
+ throw new Error("Input string had zero length or was all whitespace");
15
+
16
+ if (load<u16>(srcStart) != BRACKET_LEFT) throw new Error("Expected '[' at start of object at position " + (srcEnd - srcStart).toString());
17
+ if (load<u16>(srcEnd - 2) != BRACKET_RIGHT) throw new Error("Expected ']' at end of object at position " + (srcEnd - srcStart).toString());
18
+
8
19
  while (srcStart < srcEnd) {
9
20
  const code = load<u16>(srcStart);
10
21
  if (code == BRACE_LEFT && depth++ == 0) {
11
22
  lastIndex = srcStart;
12
23
  } else if (code == BRACE_RIGHT && --depth == 0) {
13
- out.push(JSON.__deserialize<valueof<T>>(lastIndex, srcStart));
24
+ out.push(JSON.__deserialize<valueof<T>>(lastIndex, srcStart += 2));
14
25
  }
15
26
  srcStart += 2;
16
27
  }
@@ -33,6 +33,9 @@ export function deserializeArray<T extends unknown[]>(srcStart: usize, srcEnd: u
33
33
  // @ts-ignore: type
34
34
  return deserializeMapArray<T>(srcStart, srcEnd, dst);
35
35
  // @ts-ignore: defined by transform
36
+ } else if (isDefined(type.__DESERIALIZE_CUSTOM)) {
37
+ return deserializeStructArray<T>(srcStart, srcEnd, dst);
38
+ // @ts-ignore: defined by transform
36
39
  } else if (isDefined(type.__DESERIALIZE)) {
37
40
  return deserializeStructArray<T>(srcStart, srcEnd, dst);
38
41
  }