json-as 1.0.6 → 1.0.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/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Change Log
2
2
 
3
+ ## 2025-05-21 - 1.0.8
4
+
5
+ - fix: inline warnings on layer-2 serialize and deserialize functions
6
+ - feat: fully support `JSON.Obj` and `JSON.Box` everywhere
7
+ - fix: temp disable SIMD
8
+ - feat: write fair benchmarks with `v8` using `jsvu`
9
+
10
+ ## 2025-05-14 - 1.0.7
11
+
12
+ - 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)
13
+
14
+ ## 2025-05-12 - 1.0.6
15
+
16
+ - fix: support zero-param serialization and make sure types are consistent
17
+ - fix: [#124](https://github.com/JairusSW/json-as/issues/124)
18
+
3
19
  ## 2025-05-11 - 1.0.5
4
20
 
5
21
  - feat: add sanity checks for badly formatted strings
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
  ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
7
7
  █████ ███████ ██████ ██ ████ ██ ██ ███████
8
8
  </span>
9
- AssemblyScript - v1.0.6
9
+ AssemblyScript - v1.0.8
10
10
  </pre>
11
11
  </h6>
12
12
 
@@ -57,7 +57,6 @@ 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
-
61
60
  @json
62
61
  class Vec3 {
63
62
  x: f32 = 0.0;
@@ -65,10 +64,8 @@ class Vec3 {
65
64
  z: f32 = 0.0;
66
65
  }
67
66
 
68
-
69
67
  @json
70
68
  class Player {
71
-
72
69
  @alias("first name")
73
70
  firstName!: string;
74
71
  lastName!: string;
@@ -76,8 +73,6 @@ class Player {
76
73
  // Drop in a code block, function, or expression that evaluates to a boolean
77
74
  @omitif((self: Player) => self.age < 18)
78
75
  age!: i32;
79
-
80
-
81
76
  @omitnull()
82
77
  pos!: Vec3 | null;
83
78
  isVerified!: boolean;
@@ -114,12 +109,9 @@ This library allows selective omission of fields during serialization using the
114
109
  This decorator excludes a field from serialization entirely.
115
110
 
116
111
  ```typescript
117
-
118
112
  @json
119
113
  class Example {
120
114
  name!: string;
121
-
122
-
123
115
  @omit
124
116
  SSN!: string;
125
117
  }
@@ -136,12 +128,9 @@ console.log(JSON.stringify(obj)); // { "name": "Jairus" }
136
128
  This decorator omits a field only if its value is null.
137
129
 
138
130
  ```typescript
139
-
140
131
  @json
141
132
  class Example {
142
133
  name!: string;
143
-
144
-
145
134
  @omitnull()
146
135
  optionalField!: string | null;
147
136
  }
@@ -158,12 +147,9 @@ console.log(JSON.stringify(obj)); // { "name": "Jairus" }
158
147
  This decorator omits a field based on a custom predicate function.
159
148
 
160
149
  ```typescript
161
-
162
150
  @json
163
151
  class Example {
164
152
  name!: string;
165
-
166
-
167
153
  @omitif((self: Example) => self.age <= 18)
168
154
  age!: number;
169
155
  }
@@ -188,7 +174,6 @@ AssemblyScript doesn't support using nullable primitive types, so instead, json-
188
174
  For example, this schema won't compile in AssemblyScript:
189
175
 
190
176
  ```typescript
191
-
192
177
  @json
193
178
  class Person {
194
179
  name!: string;
@@ -199,7 +184,6 @@ class Person {
199
184
  Instead, use `JSON.Box` to allow nullable primitives:
200
185
 
201
186
  ```typescript
202
-
203
187
  @json
204
188
  class Person {
205
189
  name: string;
@@ -262,7 +246,6 @@ More often, objects will be completely statically typed except for one or two va
262
246
  In such cases, `JSON.Value` can be used to handle fields that may hold different types at runtime.
263
247
 
264
248
  ```typescript
265
-
266
249
  @json
267
250
  class DynamicObj {
268
251
  id: i32 = 0;
@@ -319,7 +302,6 @@ Here's an example of creating a custom data type called `Point` which serializes
319
302
  ```typescript
320
303
  import { bytes } from "json-as/assembly/util";
321
304
 
322
-
323
305
  @json
324
306
  class Point {
325
307
  x: f64 = 0.0;
@@ -329,13 +311,11 @@ class Point {
329
311
  this.y = y;
330
312
  }
331
313
 
332
-
333
314
  @serializer
334
315
  serializer(self: Point): string {
335
316
  return `(${self.x},${self.y})`;
336
317
  }
337
318
 
338
-
339
319
  @deserializer
340
320
  deserializer(data: string): Point {
341
321
  const dataSize = bytes(data);
@@ -365,8 +345,8 @@ The deserializer function parses the string `(x,y)` back into a `Point` instance
365
345
  These functions are then wrapped before being consumed by the json-as library:
366
346
 
367
347
  ```typescript
368
- @inline __SERIALIZE_CUSTOM(ptr: usize): void {
369
- const data = this.serializer(changetype<Point>(ptr));
348
+ @inline __SERIALIZE_CUSTOM(): void {
349
+ const data = this.serializer(this);
370
350
  const dataSize = data.length << 1;
371
351
  memory.copy(bs.offset, changetype<usize>(data), dataSize);
372
352
  bs.offset += dataSize;
@@ -391,7 +371,7 @@ These benchmarks compare this library to JavaScript's native `JSON.stringify` an
391
371
 
392
372
  | Test Case | Size | Serialization (ops/s) | Deserialization (ops/s) | Serialization (MB/s) | Deserialization (MB/s) |
393
373
  | --------------- | ---------- | --------------------- | ----------------------- | -------------------- | ---------------------- |
394
- | Vector3 Object | 38 bytes | 35,714,285 ops/s | 35,435,552 ops/s | 1,357 MB/s | 1,348 MB/s |
374
+ | Vector3 Object | 38 bytes | 26,611,226 ops/s | 32,160,804 ops/s | 1,357 MB/s | 1,348 MB/s |
395
375
  | Alphabet String | 104 bytes | 13,617,021 ops/s | 18,390,804 ops/s | 1,416 MB/s | 1,986 MB/s |
396
376
  | Small Object | 88 bytes | 24,242,424 ops/s | 12,307,692 ops/s | 2,133 MB/s | 1,083 MB/s |
397
377
  | 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
@@ -63,7 +63,7 @@ bench(
63
63
  () => {
64
64
  JSON.stringify(v1);
65
65
  },
66
- 16_000_00,
66
+ 128_000_00,
67
67
  );
68
68
 
69
69
  bench(
@@ -71,5 +71,5 @@ bench(
71
71
  () => {
72
72
  JSON.parse<Vec3>(v2);
73
73
  },
74
- 16_000_00,
74
+ 128_000_00,
75
75
  );
@@ -32,6 +32,14 @@ class Point {
32
32
  }
33
33
  }
34
34
 
35
+ @json
36
+ export class ObjectWithCustom {
37
+ value: Point = new Point(0, 0)
38
+ constructor(value: Point) {
39
+ this.value = value
40
+ }
41
+ }
42
+
35
43
  describe("Should serialize using custom serializers", () => {
36
44
  expect(JSON.stringify<Point>(new Point(1, 2))).toBe("(1.0,2.0)");
37
45
  });
@@ -41,3 +49,7 @@ describe("Should deserialize using custom deserializers", () => {
41
49
  expect(p1.x.toString()).toBe("1.0");
42
50
  expect(p1.y.toString()).toBe("2.0");
43
51
  });
52
+
53
+ describe("Should serialize and deserialize using nested custom serializers", () => {
54
+ expect(JSON.stringify<ObjectWithCustom>(new ObjectWithCustom(new Point(1, 2)))).toBe(`{"value":(1.0,2.0)}`);
55
+ });
@@ -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,7 +31,13 @@ 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);
32
- } else if (type instanceof Map) {
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);
40
+ }else if (type instanceof Map) {
33
41
  // @ts-ignore: type
34
42
  return deserializeMapArray<T>(srcStart, srcEnd, dst);
35
43
  // @ts-ignore: defined by transform
package/assembly/index.ts CHANGED
@@ -15,7 +15,6 @@ import { deserializeInteger } from "./deserialize/simple/integer";
15
15
  import { deserializeString } from "./deserialize/simple/string";
16
16
  import { serializeArbitrary } from "./serialize/simple/arbitrary";
17
17
 
18
- import { Sink } from "./custom/sink";
19
18
  import { NULL_WORD, QUOTE } from "./custom/chars";
20
19
  import { dtoa_buffered, itoa_buffered } from "util/number";
21
20
  import { serializeBool } from "./serialize/simple/bool";
@@ -31,6 +30,7 @@ import { serializeRaw } from "./serialize/simple/raw";
31
30
  import { deserializeRaw } from "./deserialize/simple/raw";
32
31
  import { isSpace } from "util/string";
33
32
  import { deserializeString_SIMD } from "./deserialize/simd/string";
33
+ import { serializeString_SIMD } from "./serialize/simd/string";
34
34
 
35
35
  /**
36
36
  * Offset of the 'storage' property in the JSON.Value class.
@@ -116,7 +116,11 @@ export namespace JSON {
116
116
  // bs.setBuffer(oldBuf);
117
117
  // return changetype<string>(newBuf);
118
118
  // }
119
- serializeString(changetype<string>(data));
119
+ // if (ASC_FEATURE_SIMD) {
120
+ // serializeString_SIMD(data as string);
121
+ // } else {
122
+ serializeString(data as string);
123
+ // }
120
124
  return bs.out<string>();
121
125
  // @ts-ignore: Supplied by transform
122
126
  } else if (isDefined(data.__SERIALIZE_CUSTOM)) {
@@ -145,7 +149,7 @@ export namespace JSON {
145
149
  inline.always(serializeMap(changetype<nonnull<T>>(data)));
146
150
  return bs.out<string>();
147
151
  } else if (data instanceof JSON.Raw) {
148
- inline.always(serializeRaw(data));
152
+ serializeRaw(data);
149
153
  return bs.out<string>();
150
154
  } else if (data instanceof JSON.Value) {
151
155
  inline.always(serializeArbitrary(data));
@@ -404,18 +408,16 @@ export namespace JSON {
404
408
  case JSON.Types.Array: {
405
409
  const arr = this.get<JSON.Value[]>();
406
410
  if (!arr.length) return "[]";
407
- const out = Sink.fromStringLiteral("[");
411
+ let out = "["
408
412
  const end = arr.length - 1;
409
413
  for (let i = 0; i < end; i++) {
410
414
  const element = unchecked(arr[i]);
411
- out.write(element.toString());
412
- out.write(",");
415
+ out += element.toString() + ",";
413
416
  }
414
417
 
415
418
  const element = unchecked(arr[end]);
416
- out.write(element.toString());
419
+ out += element.toString() + "]";
417
420
 
418
- out.write("]");
419
421
  return out.toString();
420
422
  }
421
423
  case JSON.Types.Object: {
@@ -438,7 +440,7 @@ export namespace JSON {
438
440
  // @ts-ignore: type
439
441
  private storage: Map<string, JSON.Value> = new Map<string, JSON.Value>();
440
442
 
441
- constructor() {}
443
+ constructor() { }
442
444
 
443
445
  // @ts-ignore: decorator
444
446
  @inline get size(): i32 {
@@ -552,26 +554,26 @@ export namespace JSON {
552
554
  // @ts-ignore: Supplied by transform
553
555
  } else if (isDefined(src.__SERIALIZE_CUSTOM)) {
554
556
  // @ts-ignore
555
- return src.__SERIALIZE_CUSTOM(changetype<usize>(src));
557
+ return src.__SERIALIZE_CUSTOM();
556
558
  // @ts-ignore: Supplied by transform
557
559
  } else if (isDefined(src.__SERIALIZE)) {
558
560
  // @ts-ignore
559
- inline.always(serializeStruct(changetype<nonnull<T>>(src)));
561
+ serializeStruct(changetype<nonnull<T>>(src));
560
562
  } else if (src instanceof Date) {
561
563
  // @ts-ignore
562
564
  inline.always(serializeDate(changetype<nonnull<T>>(src)));
563
565
  } else if (src instanceof Array) {
564
566
  // @ts-ignore
565
- inline.always(serializeArray(changetype<nonnull<T>>(src)));
567
+ serializeArray(changetype<nonnull<T>>(src));
566
568
  } else if (src instanceof Map) {
567
569
  // @ts-ignore
568
- inline.always(serializeMap(changetype<nonnull<T>>(src)));
570
+ serializeMap(changetype<nonnull<T>>(src));
569
571
  } else if (src instanceof JSON.Raw) {
570
572
  serializeRaw(src);
571
573
  } else if (src instanceof JSON.Value) {
572
- inline.always(serializeArbitrary(src));
574
+ serializeArbitrary(src);
573
575
  } else if (src instanceof JSON.Obj) {
574
- inline.always(serializeObject(src));
576
+ serializeObject(src);
575
577
  } else if (src instanceof JSON.Box) {
576
578
  __serialize(src.value);
577
579
  } else {
@@ -596,7 +598,7 @@ export namespace JSON {
596
598
  return null;
597
599
  } else if (isArray<T>()) {
598
600
  // @ts-ignore: type
599
- return inline.always(deserializeArray<T>(srcStart, srcEnd, dst));
601
+ return deserializeArray<T>(srcStart, srcEnd, dst);
600
602
  } else {
601
603
  let type: nonnull<T> = changetype<nonnull<T>>(0);
602
604
  // @ts-ignore: Defined by transform
@@ -608,10 +610,10 @@ export namespace JSON {
608
610
  return changetype<nonnull<T>>(out).__DESERIALIZE_CUSTOM(ptrToStr(srcStart, srcEnd));
609
611
  // @ts-ignore: Defined by transform
610
612
  } else if (isDefined(type.__DESERIALIZE)) {
611
- return inline.always(deserializeStruct<T>(srcStart, srcEnd, dst));
613
+ return deserializeStruct<T>(srcStart, srcEnd, dst);
612
614
  } else if (type instanceof Map) {
613
615
  // @ts-ignore: type
614
- return inline.always(deserializeMap<T>(srcStart, srcEnd, dst));
616
+ return deserializeMap<T>(srcStart, srcEnd, dst);
615
617
  } else if (type instanceof Date) {
616
618
  // @ts-ignore: type
617
619
  return deserializeDate(srcStart, srcEnd);
@@ -620,7 +622,10 @@ export namespace JSON {
620
622
  return deserializeRaw(srcStart, srcEnd);
621
623
  } else if (type instanceof JSON.Value) {
622
624
  // @ts-ignore: type
623
- return inline.always(deserializeArbitrary(srcStart, srcEnd, 0));
625
+ return deserializeArbitrary(srcStart, srcEnd, 0);
626
+ }else if (type instanceof JSON.Obj) {
627
+ // @ts-ignore: type
628
+ return deserializeObject(srcStart, srcEnd, 0);
624
629
  } else if (type instanceof JSON.Box) {
625
630
  // @ts-ignore: type
626
631
  return new JSON.Box(deserializeBox(srcStart, srcEnd, dst, changetype<nonnull<T>>(0).value));
@@ -1,13 +1,7 @@
1
1
  import { bs } from "../../../lib/as-bs";
2
2
  import { BACK_SLASH } from "../../custom/chars";
3
3
  import { SERIALIZE_ESCAPE_TABLE } from "../../globals/tables";
4
- import { OBJECT, TOTAL_OVERHEAD } from "rt/common";
5
-
6
- const SPLAT_34 = i16x8.splat(34); /* " */
7
- const SPLAT_92 = i16x8.splat(92); /* \ */
8
-
9
- const SPLAT_32 = i16x8.splat(32); /* [ESC] */
10
- const SPLAT_0 = i16x8.splat(0); /* 0 */
4
+ import { bytes } from "../../util";
11
5
 
12
6
  /**
13
7
  * Serializes strings into their JSON counterparts using SIMD operations
@@ -15,16 +9,23 @@ const SPLAT_0 = i16x8.splat(0); /* 0 */
15
9
  * @param srcEnd pointer to end serialization at
16
10
  */
17
11
  export function serializeString_SIMD(src: string): void {
18
- const srcSize = changetype<OBJECT>(changetype<usize>(src) - TOTAL_OVERHEAD).rtSize;
12
+ const SPLAT_34 = i16x8.splat(34); /* " */
13
+ const SPLAT_92 = i16x8.splat(92); /* \ */
14
+
15
+ const SPLAT_32 = i16x8.splat(32); /* [ESC] */
16
+ const SPLAT_0 = i16x8.splat(0); /* 0 */
17
+
18
+ const srcSize = bytes(src);
19
19
  let srcStart = changetype<usize>(src);
20
20
  const srcEnd = srcStart + srcSize;
21
+ const srcEnd16 = srcEnd - 16;
22
+
21
23
  bs.proposeSize(srcSize + 4);
22
- const srcEnd16 = srcEnd - 15;
23
24
 
24
25
  store<u8>(changetype<usize>(bs.offset), 34); /* " */
25
26
  bs.offset += 2;
26
27
 
27
- while (srcStart < srcEnd16) {
28
+ while (srcStart <= srcEnd16) {
28
29
  const block = v128.load(srcStart);
29
30
  v128.store(bs.offset, block);
30
31
 
@@ -62,8 +63,7 @@ export function serializeString_SIMD(src: string): void {
62
63
  bs.offset += 16;
63
64
  }
64
65
 
65
- let rem = srcEnd - srcStart;
66
-
66
+ const rem = srcEnd - srcStart;
67
67
  if (rem & 8) {
68
68
  const block = v128.load64_zero(srcStart);
69
69
  v128.store64_lane(bs.offset, block, 0);