json-as 1.1.20 → 1.1.21

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,10 @@
1
1
  # Change Log
2
2
 
3
+ ## 2025-08-14 - 1.1.21
4
+
5
+ - fix: JSON.parse on classes with enums [#155](https://github.com/JairusSW/json-as/issues/155)
6
+ - fix: Resolve memory OOB issue within `serializeFloat` function [#153](https://github.com/JairusSW/json-as/issues/153)
7
+
3
8
  ## 2025-07-14 - 1.1.20
4
9
 
5
10
  - feat: enable SIMD string serialization
package/README.md CHANGED
@@ -1,34 +1,6 @@
1
- <h6 align="center">
2
- <pre>
3
- <span style="font-size: 0.8em;"> ██ ███████ ██████ ███ ██ █████ ███████
4
- ██ ██ ██ ██ ████ ██ ██ ██ ██
5
- ██ ███████ ██ ██ ██ ██ ██ █████ ███████ ███████
6
- ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
7
- █████ ███████ ██████ ██ ████ ██ ██ ███████
8
- </span>
9
- AssemblyScript - v1.1.20
10
- </pre>
11
- </h6>
12
-
13
- ## 📝 About
14
-
15
- 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.
16
-
17
- ## 📚 Contents
18
-
19
- - [Installation](#-installation)
20
- - [Usage](#-usage)
21
- - [Examples](#-examples)
22
- - [Omitting Fields](#️-omitting-fields)
23
- - [Nullable Primitives](#️-using-nullable-primitives)
24
- - [Unknown or Dynamic Data](#-working-with-unknown-or-dynamic-data)
25
- - [Using Raw JSON Strings](#️-using-raw-json-strings)
26
- - [Using Enums](#️-working-with-enums)
27
- - [Custom Serializers](#️-using-custom-serializers-or-deserializers)
28
- - [Performance](#-performance)
29
- - [Debugging](#-debugging)
30
- - [License](#-license)
31
- - [Contact](#-contact)
1
+ <h1 align="center"><pre> ╦╔═╗╔═╗╔╗╔ ╔═╗╔═╗
2
+ ║╚═╗║ ║║║║══╠═╣╚═╗
3
+ ╚╝╚═╝╚═╝╝╚╝ ╩ ╩╚═╝</pre></h1>
32
4
 
33
5
  ## 💾 Installation
34
6
 
@@ -297,7 +269,7 @@ console.log(JSON.stringify(map));
297
269
 
298
270
  ### 📝 Working with enums
299
271
 
300
- By default, enums arn't supported by `json-as`. However, you can use a workaround:
272
+ By default, enums with values other than `i32` arn't supported by AssemblyScript. However, you can use a workaround:
301
273
 
302
274
  ```typescript
303
275
  namespace Foo {
@@ -8,6 +8,22 @@ describe("Should serialize arbitrary types", () => {
8
8
  expect(JSON.stringify(JSON.Value.from(true))).toBe("true");
9
9
  expect(JSON.stringify(JSON.Value.from(new Vec3()))).toBe('{"x":1.0,"y":2.0,"z":3.0}');
10
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
+ const o = new JSON.Obj();
13
+ o.set("schema", "http://json-schema.org/draft-07/schema#");
14
+ o.set("additionalProperties", false);
15
+ o.set("properties", new JSON.Obj());
16
+ o.get("properties")!.as<JSON.Obj>().set("duration", new JSON.Obj());
17
+ o.get("properties")!.as<JSON.Obj>().get("duration")!.as<JSON.Obj>().set("default", 10.0);
18
+ o.get("properties")!.as<JSON.Obj>().get("duration")!.as<JSON.Obj>().set("description", "Duration of the operation in seconds");
19
+ o.get("properties")!.as<JSON.Obj>().get("duration")!.as<JSON.Obj>().set("type", "number");
20
+ o.get("properties")!.as<JSON.Obj>().set("steps", new JSON.Obj());
21
+ o.get("properties")!.as<JSON.Obj>().get("steps")!.as<JSON.Obj>().set("default", 5.0);
22
+ o.get("properties")!.as<JSON.Obj>().get("steps")!.as<JSON.Obj>().set("description", "Number of steps in the operation");
23
+ o.get("properties")!.as<JSON.Obj>().get("steps")!.as<JSON.Obj>().set("type", "number");
24
+ o.set("type", "object");
25
+
26
+ expect(o.toString()).toBe('{"schema":"http://json-schema.org/draft-07/schema#","additionalProperties":false,"properties":{"duration":{"default":10.0,"description":"Duration of the operation in seconds","type":"number"},"steps":{"default":5.0,"description":"Number of steps in the operation","type":"number"}},"type":"object"}');
11
27
  });
12
28
 
13
29
  describe("Should deserialize arbitrary types", () => {
@@ -0,0 +1,35 @@
1
+ import { JSON } from "..";
2
+ import { describe, expect } from "./lib";
3
+
4
+ enum Enum1 {
5
+ Zero = 0,
6
+ One = 1,
7
+ Two = 2,
8
+ Three = 3,
9
+ }
10
+
11
+
12
+ @json
13
+ class DataWithEnum {
14
+ v: Enum1 = Enum1.One;
15
+ constructor(v: Enum1) {
16
+ this.v = v;
17
+ }
18
+ }
19
+
20
+ describe("Should serialize enums", () => {
21
+ expect(JSON.stringify<Enum1>(Enum1.One)).toBe("1");
22
+ expect(JSON.stringify<Enum1>(Enum1.Zero)).toBe("0");
23
+ expect(JSON.stringify<DataWithEnum>(new DataWithEnum(Enum1.Two))).toBe('{"v":2}');
24
+ });
25
+
26
+ describe("Should deserialize enums", () => {
27
+ const date1 = JSON.parse<Enum1>("2");
28
+ expect(date1).toBe(Enum1.Two);
29
+
30
+ const date2 = JSON.parse<Enum1>("0");
31
+ expect(date2).toBe(Enum1.Zero);
32
+
33
+ const date3 = JSON.parse<DataWithEnum>('{"v":3}');
34
+ expect(date3.v).toBe(Enum1.Three);
35
+ });
@@ -10,14 +10,13 @@ import { DESERIALIZE_ESCAPE_TABLE, ESCAPE_HEX_TABLE } from "../../globals/tables
10
10
  // todo: optimize and stuff. it works, its not pretty. ideally, i'd like this to be (nearly) branchless
11
11
  export function deserializeString_SIMD(srcStart: usize, srcEnd: usize, dst: usize): usize {
12
12
  const SPLAT_92 = i16x8.splat(92); /* \ */
13
- let src_ptr = srcStart + 2;
13
+ srcStart += 2;
14
+ srcEnd -= 2;
14
15
  let dst_ptr = changetype<usize>(dst);
16
+ const src_end_15 = srcEnd - 15;
15
17
 
16
- const src_end = srcEnd - 2;
17
- const src_end_15 = src_end - 15;
18
-
19
- while (src_ptr < src_end_15) {
20
- const block = v128.load(src_ptr);
18
+ while (srcStart < src_end_15) {
19
+ const block = v128.load(srcStart);
21
20
  v128.store(dst_ptr, block);
22
21
 
23
22
  const backslash_indices = i16x8.eq(block, SPLAT_92);
@@ -26,7 +25,7 @@ export function deserializeString_SIMD(srcStart: usize, srcEnd: usize, dst: usiz
26
25
  while (mask != 0) {
27
26
  const lane_index = ctz(mask) << 1;
28
27
  const dst_offset = dst_ptr + lane_index;
29
- const src_offset = src_ptr + lane_index;
28
+ const src_offset = srcStart + lane_index;
30
29
  const code = load<u16>(src_offset, 2);
31
30
 
32
31
  mask &= mask - 1;
@@ -48,7 +47,7 @@ export function deserializeString_SIMD(srcStart: usize, srcEnd: usize, dst: usiz
48
47
  v128.store(dst_offset, v128.load(src_offset, 4), 2);
49
48
  if (lane_index >= 6) {
50
49
  const bytes_left = lane_index - 4;
51
- src_ptr += bytes_left;
50
+ srcStart += bytes_left;
52
51
  dst_ptr += bytes_left;
53
52
  // console.log(" e: " + (bytes_left).toString())
54
53
  }
@@ -59,25 +58,25 @@ export function deserializeString_SIMD(srcStart: usize, srcEnd: usize, dst: usiz
59
58
  v128.store(dst_offset, v128.load(src_offset, 4), 2);
60
59
  // console.log("Escaped:");
61
60
  if (lane_index == 14) {
62
- src_ptr += 2;
61
+ srcStart += 2;
63
62
  } else {
64
63
  dst_ptr -= 2;
65
64
  }
66
65
  }
67
66
  }
68
67
 
69
- src_ptr += 16;
68
+ srcStart += 16;
70
69
  dst_ptr += 16;
71
70
 
72
- // console.log("src: " + (src_ptr - changetype<usize>(src)).toString());
71
+ // console.log("src: " + (srcStart - changetype<usize>(src)).toString());
73
72
  // console.log("dst: " + (dst_ptr - dst).toString());
74
73
  }
75
- while (src_ptr < src_end) {
76
- let code = load<u16>(src_ptr);
74
+ while (srcStart < srcEnd) {
75
+ let code = load<u16>(srcStart);
77
76
  if (code == BACK_SLASH) {
78
- code = load<u16>(DESERIALIZE_ESCAPE_TABLE + load<u8>(src_ptr, 2));
79
- if (code == 117 && load<u32>(src_ptr, 4) == 3145776) {
80
- const block = load<u32>(src_ptr, 8);
77
+ code = load<u16>(DESERIALIZE_ESCAPE_TABLE + load<u8>(srcStart, 2));
78
+ if (code == 117 && load<u32>(srcStart, 4) == 3145776) {
79
+ const block = load<u32>(srcStart, 8);
81
80
  const codeA = block & 0xffff;
82
81
  const codeB = (block >> 16) & 0xffff;
83
82
  const escapedA = load<u8>(ESCAPE_HEX_TABLE + codeA);
@@ -85,16 +84,16 @@ export function deserializeString_SIMD(srcStart: usize, srcEnd: usize, dst: usiz
85
84
  const escaped = (escapedA << 4) + escapedB;
86
85
  store<u16>(dst_ptr, escaped);
87
86
  dst_ptr += 2;
88
- src_ptr += 12;
87
+ srcStart += 12;
89
88
  } else {
90
89
  store<u16>(dst_ptr, code);
91
90
  dst_ptr += 2;
92
- src_ptr += 4;
91
+ srcStart += 4;
93
92
  }
94
93
  } else {
95
94
  store<u16>(dst_ptr, code);
96
95
  dst_ptr += 2;
97
- src_ptr += 2;
96
+ srcStart += 2;
98
97
  }
99
98
  }
100
99
 
@@ -3,6 +3,10 @@ import { BACK_SLASH, COMMA, CHAR_F, BRACE_LEFT, BRACKET_LEFT, CHAR_N, QUOTE, BRA
3
3
  import { isSpace } from "../../util";
4
4
  import { ptrToStr } from "../../util/ptrToStr";
5
5
  import { deserializeArbitrary } from "./arbitrary";
6
+ import { deserializeArray } from "./array";
7
+ import { deserializeBoolean } from "./bool";
8
+ import { deserializeFloat } from "./float";
9
+ import { deserializeString } from "./string";
6
10
 
7
11
  export function deserializeObject(srcStart: usize, srcEnd: usize, dst: usize): JSON.Obj {
8
12
  const out = changetype<JSON.Obj>(dst || changetype<usize>(new JSON.Obj()));
@@ -48,8 +52,8 @@ export function deserializeObject(srcStart: usize, srcEnd: usize, dst: usize): J
48
52
  while (srcStart < srcEnd) {
49
53
  const code = load<u16>(srcStart);
50
54
  if (code == QUOTE && load<u16>(srcStart - 2) !== BACK_SLASH) {
51
- // console.log("Value (string): " + ptrToStr(lastIndex, srcStart + 2));
52
- out.set(ptrToStr(keyStart, keyEnd), deserializeArbitrary(lastIndex, srcStart + 2, dst));
55
+ // console.log("Value (string):-" + deserializeString(lastIndex, srcStart + 2, 0) + "-");
56
+ out.set(ptrToStr(keyStart, keyEnd), deserializeString(lastIndex, srcStart + 2, 0));
53
57
  // while (isSpace(load<u16>(srcStart))) srcStart += 2;
54
58
  srcStart += 4;
55
59
  // console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
@@ -65,7 +69,7 @@ export function deserializeObject(srcStart: usize, srcEnd: usize, dst: usize): J
65
69
  const code = load<u16>(srcStart);
66
70
  if (code == COMMA || code == BRACE_RIGHT || isSpace(code)) {
67
71
  // console.log("Value (number): " + ptrToStr(lastIndex, srcStart));
68
- out.set(ptrToStr(keyStart, keyEnd), deserializeArbitrary(lastIndex, srcStart, dst));
72
+ out.set(ptrToStr(keyStart, keyEnd), deserializeFloat<f64>(lastIndex, srcStart));
69
73
  // while (isSpace(load<u16>((srcStart += 2)))) {
70
74
  // /* empty */
71
75
  // }
@@ -88,7 +92,7 @@ export function deserializeObject(srcStart: usize, srcEnd: usize, dst: usize): J
88
92
  } else if (code == BRACE_RIGHT) {
89
93
  if (--depth == 0) {
90
94
  // console.log("Value (object): " + ptrToStr(lastIndex, srcStart + 2));
91
- out.set(ptrToStr(keyStart, keyEnd), deserializeArbitrary(lastIndex, (srcStart += 2), dst));
95
+ out.set(ptrToStr(keyStart, keyEnd), deserializeObject(lastIndex, (srcStart += 2), 0));
92
96
  // console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
93
97
  keyStart = 0;
94
98
  // while (isSpace(load<u16>(srcStart))) {
@@ -108,7 +112,7 @@ export function deserializeObject(srcStart: usize, srcEnd: usize, dst: usize): J
108
112
  if (code == BRACKET_RIGHT) {
109
113
  if (--depth == 0) {
110
114
  // console.log("Value (array): " + ptrToStr(lastIndex, srcStart + 2));
111
- out.set(ptrToStr(keyStart, keyEnd), deserializeArbitrary(lastIndex, (srcStart += 2), dst));
115
+ out.set(ptrToStr(keyStart, keyEnd), deserializeArray<JSON.Value[]>(lastIndex, (srcStart += 2), 0));
112
116
  // console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
113
117
  keyStart = 0;
114
118
  // while (isSpace(load<u16>((srcStart += 2)))) {
@@ -122,7 +126,8 @@ export function deserializeObject(srcStart: usize, srcEnd: usize, dst: usize): J
122
126
  } else if (code == CHAR_T) {
123
127
  if (load<u64>(srcStart) == 28429475166421108) {
124
128
  // console.log("Value (bool): " + ptrToStr(srcStart, srcStart + 8));
125
- out.set(ptrToStr(keyStart, keyEnd), deserializeArbitrary(srcStart, (srcStart += 8), dst));
129
+ out.set(ptrToStr(keyStart, keyEnd), true);
130
+ srcStart += 8;
126
131
  // while (isSpace(load<u16>((srcStart += 2)))) {
127
132
  // /* empty */
128
133
  // }
@@ -133,7 +138,8 @@ export function deserializeObject(srcStart: usize, srcEnd: usize, dst: usize): J
133
138
  } else if (code == CHAR_F) {
134
139
  if (load<u64>(srcStart, 2) == 28429466576093281) {
135
140
  // console.log("Value (bool): " + ptrToStr(srcStart, srcStart + 10));
136
- out.set(ptrToStr(keyStart, keyEnd), deserializeArbitrary(srcStart, (srcStart += 10), dst));
141
+ out.set(ptrToStr(keyStart, keyEnd), false);
142
+ srcStart += 10;
137
143
  // while (isSpace(load<u16>((srcStart += 2)))) {
138
144
  // /* empty */
139
145
  // }
@@ -144,7 +150,8 @@ export function deserializeObject(srcStart: usize, srcEnd: usize, dst: usize): J
144
150
  } else if (code == CHAR_N) {
145
151
  if (load<u64>(srcStart) == 30399761348886638) {
146
152
  // console.log("Value (null): " + ptrToStr(srcStart, srcStart + 8));
147
- out.set(ptrToStr(keyStart, keyEnd), deserializeArbitrary(srcStart, (srcStart += 8), dst));
153
+ out.set(ptrToStr(keyStart, keyEnd), JSON.Value.from<usize>(0));
154
+ srcStart += 8;
148
155
  // while (isSpace(load<u16>((srcStart += 2)))) {
149
156
  /* empty */
150
157
  // }
package/assembly/index.ts CHANGED
@@ -260,6 +260,8 @@ export namespace JSON {
260
260
  }
261
261
  }
262
262
 
263
+
264
+ @final
263
265
  export class Value {
264
266
  static METHODS: Map<u32, u32> = new Map<u32, u32>();
265
267
  public type: i32;
@@ -334,7 +336,7 @@ export namespace JSON {
334
336
  this.type = JSON.Types.Struct;
335
337
  store<T>(changetype<usize>(this), value, STORAGE);
336
338
  // @ts-ignore: supplied by transform
337
- } else if (isDefined(value.__SERIALIZE)) {
339
+ } else if (isDefined(value.__SERIALIZE) && isManaged<T>(value)) {
338
340
  this.type = idof<T>() + JSON.Types.Struct;
339
341
  // @ts-ignore
340
342
  if (!JSON.Value.METHODS.has(idof<T>())) JSON.Value.METHODS.set(idof<T>(), value.__SERIALIZE.index);
@@ -419,16 +421,20 @@ export namespace JSON {
419
421
  }
420
422
  }
421
423
  }
424
+
425
+
426
+ @unsafe private __visit(cookie: u32): void {
427
+ if (this.type >= JSON.Types.String) {
428
+ __visit(load<usize>(changetype<usize>(this), STORAGE), cookie);
429
+ }
430
+ }
422
431
  }
423
432
 
424
433
  export class Obj {
425
- // When accessing stackSize, subtract 2
426
- // @ts-ignore: type
427
- private stackSize: u32 = 6;
428
434
  // @ts-ignore: type
429
- private storage: Map<string, JSON.Value> = new Map<string, JSON.Value>();
435
+ storage: Map<string, JSON.Value> = new Map<string, JSON.Value>();
430
436
 
431
- constructor() { }
437
+ constructor() {}
432
438
 
433
439
  // @ts-ignore: decorator
434
440
  @inline get size(): i32 {
@@ -437,7 +443,7 @@ export namespace JSON {
437
443
 
438
444
  // @ts-ignore: decorator
439
445
  @inline set<T>(key: string, value: T): void {
440
- if (!this.storage.has(key)) this.stackSize += bytes(key) + 8;
446
+ // if (!this.storage.has(key)) this.stackSize += bytes(key) + 8;
441
447
  this.storage.set(key, JSON.Value.from<T>(value));
442
448
  }
443
449
 
@@ -475,7 +481,7 @@ export namespace JSON {
475
481
  // @ts-ignore: decorator
476
482
  @inline static from<T>(value: T): JSON.Obj {
477
483
  if (value instanceof JSON.Obj) return value;
478
- const out = changetype<JSON.Obj>(__new(offsetof<JSON.Obj>(), idof<JSON.Obj>()));
484
+ const out = new JSON.Obj();
479
485
 
480
486
  if (value instanceof Map) {
481
487
  }
@@ -3,14 +3,13 @@ import { BACK_SLASH } from "../../custom/chars";
3
3
  import { SERIALIZE_ESCAPE_TABLE } from "../../globals/tables";
4
4
  import { bytes } from "../../util";
5
5
 
6
- const U00_MARKER = 13511005048209500;
7
-
8
6
  /**
9
7
  * Serializes strings into their JSON counterparts using SIMD operations
10
8
  * @param srcStart pointer to begin serializing at
11
9
  * @param srcEnd pointer to end serialization at
12
10
  */
13
11
  export function serializeString_SIMD(src: string): void {
12
+ const U00_MARKER = 13511005048209500;
14
13
  const SPLAT_34 = i16x8.splat(34); /* " */
15
14
  const SPLAT_92 = i16x8.splat(92); /* \ */
16
15
 
@@ -21,7 +20,7 @@ export function serializeString_SIMD(src: string): void {
21
20
  const srcEnd = srcStart + srcSize;
22
21
  const srcEnd16 = srcEnd - 16;
23
22
 
24
- bs.proposeSize(srcSize + 40);
23
+ bs.proposeSize(srcSize + 4);
25
24
 
26
25
  store<u8>(changetype<usize>(bs.offset), 34); /* " */
27
26
  bs.offset += 2;
@@ -44,6 +44,7 @@ export function serializeArbitrary(src: JSON.Value): void {
44
44
  const fn = JSON.Value.METHODS.get(src.type - JSON.Types.Struct);
45
45
  const ptr = src.get<usize>();
46
46
  call_indirect<void>(fn, 0, ptr);
47
+ break;
47
48
  }
48
49
  }
49
50
  }
@@ -27,7 +27,7 @@ export function serializeArray<T extends any[]>(src: T): void {
27
27
 
28
28
  const lastBlock = unchecked(src[end]);
29
29
  JSON.__serialize<valueof<T>>(lastBlock);
30
- bs.growSize(2);
30
+ // bs.growSize(2);
31
31
  store<u16>(bs.offset, BRACKET_RIGHT);
32
32
  bs.offset += 2;
33
33
  }
@@ -5,7 +5,7 @@ import { bs } from "../../../lib/as-bs";
5
5
  * @returns void
6
6
  */
7
7
  export function serializeBool(data: bool): void {
8
- if (data == true) {
8
+ if (data === true) {
9
9
  bs.proposeSize(8);
10
10
  store<u64>(bs.offset, 28429475166421108);
11
11
  bs.offset += 8;
@@ -4,5 +4,7 @@ import { dtoa_buffered } from "util/number";
4
4
  // @ts-ignore: inline
5
5
  @inline export function serializeFloat<T extends number>(data: T): void {
6
6
  bs.ensureSize(64);
7
- bs.offset += dtoa_buffered(bs.offset, data) << 1;
7
+ const size = dtoa_buffered(bs.offset, data) << 1;
8
+ bs.stackSize += size;
9
+ bs.offset += size;
8
10
  }
@@ -5,8 +5,8 @@ import { itoa_buffered } from "util/number";
5
5
  @inline export function serializeInteger<T extends number>(data: T): void {
6
6
  bs.ensureSize(sizeof<T>() << 3);
7
7
  const bytesWritten = itoa_buffered(bs.offset, data) << 1;
8
- bs.offset += bytesWritten;
9
8
  bs.growSize(bytesWritten);
9
+ bs.offset += bytesWritten;
10
10
  }
11
11
 
12
12
  // 32 {"x":,"y":,"z"}
@@ -16,7 +16,7 @@ export function serializeMap<T extends Map<any, any>>(src: T): void {
16
16
  let keys = src.keys();
17
17
  let values = src.values();
18
18
 
19
- bs.proposeSize(srcSize << 3); // This needs to be predicted better
19
+ bs.proposeSize(4);
20
20
 
21
21
  store<u16>(bs.offset, BRACE_LEFT);
22
22
  bs.offset += 2;
@@ -37,7 +37,7 @@ export function serializeMap<T extends Map<any, any>>(src: T): void {
37
37
  store<u16>(bs.offset, COLON);
38
38
  bs.offset += 2;
39
39
  JSON.__serialize(unchecked(values[srcEnd]));
40
- bs.growSize(2);
40
+ // bs.growSize(2);
41
41
  store<u16>(bs.offset, BRACE_RIGHT);
42
42
  bs.offset += 2;
43
43
  }
@@ -1,44 +1,46 @@
1
1
  import { bs } from "../../../lib/as-bs";
2
2
  import { JSON } from "../..";
3
- import { BRACE_LEFT, BRACE_RIGHT, QUOTE } from "../../custom/chars";
4
- import { bytes } from "../../util";
3
+ import { BRACE_LEFT, BRACE_RIGHT, COLON, COMMA } from "../../custom/chars";
4
+ import { serializeArbitrary } from "./arbitrary";
5
+ import { serializeString } from "./string";
5
6
 
6
- export function serializeObject(data: JSON.Obj): void {
7
- if (!data.size) {
7
+ export function serializeObject(src: JSON.Obj): void {
8
+ const srcSize = src.size;
9
+ const srcEnd = srcSize - 1;
10
+
11
+ if (srcSize == 0) {
8
12
  bs.proposeSize(4);
9
13
  store<u32>(bs.offset, 8192123);
10
14
  bs.offset += 4;
11
15
  return;
12
16
  }
13
17
 
14
- bs.proposeSize(load<u32>(changetype<usize>(data), offsetof<JSON.Obj>("stackSize")) - 2);
15
- const keys = data.keys();
16
- const values = data.values();
17
-
18
- // console.log(" Keys " + keys.join(" "));
19
- // console.log(" Values " + values.map<string>(v => v.toString()).join(" "))
18
+ const keys = src.keys();
19
+ const values = src.values();
20
20
 
21
+ bs.growSize(2);
21
22
  store<u16>(bs.offset, BRACE_LEFT);
22
23
  bs.offset += 2;
23
24
 
24
- const firstKey = unchecked(keys[0]);
25
- const keySize = bytes(firstKey);
26
- store<u16>(bs.offset, QUOTE);
27
- memory.copy(bs.offset + 2, changetype<usize>(firstKey), keySize);
28
- store<u32>((bs.offset += keySize + 2), 3801122); // ":
29
- bs.offset += 4;
30
- JSON.__serialize(unchecked(values[0]));
31
-
32
- for (let i = 1; i < keys.length; i++) {
33
- const key = unchecked(keys[i]);
34
- const keySize = bytes(key);
35
- store<u32>(bs.offset, 2228268); // ,"
36
- memory.copy(bs.offset + 4, changetype<usize>(key), keySize);
37
- store<u32>((bs.offset += keySize + 4), 3801122); // ":
38
- bs.offset += 4;
39
- JSON.__serialize(unchecked(values[i]));
25
+ for (let i = 0; i < srcEnd; i++) {
26
+ serializeString(unchecked(keys[i]));
27
+ bs.growSize(2);
28
+ store<u16>(bs.offset, COLON);
29
+ bs.offset += 2;
30
+
31
+ serializeArbitrary(unchecked(values[i]));
32
+ bs.growSize(2);
33
+ store<u16>(bs.offset, COMMA);
34
+ bs.offset += 2;
40
35
  }
41
36
 
37
+ serializeString(unchecked(keys[srcEnd]));
38
+ bs.growSize(2);
39
+ store<u16>(bs.offset, COLON);
40
+ bs.offset += 2;
41
+ serializeArbitrary(unchecked(values[srcEnd]));
42
+
43
+ bs.growSize(2);
42
44
  store<u16>(bs.offset, BRACE_RIGHT);
43
45
  bs.offset += 2;
44
46
  }