json-as 1.0.0-alpha.4 → 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.
- package/README.md +60 -55
- package/assembly/__benches__/misc.bench.ts +48 -0
- package/assembly/__benches__/schemas.ts +25 -0
- package/assembly/__tests__/arbitrary.spec.ts +19 -0
- package/assembly/__tests__/types.ts +3 -3
- package/assembly/deserialize/simd/string.ts +1 -1
- package/assembly/deserialize/simple/arbitrary.ts +1 -1
- package/assembly/deserialize/simple/array/arbitrary.ts +47 -24
- package/assembly/deserialize/simple/array/{object.ts → struct.ts} +1 -1
- package/assembly/deserialize/simple/array.ts +4 -9
- package/assembly/deserialize/simple/integer.ts +2 -1
- package/assembly/deserialize/simple/map.ts +1 -1
- package/assembly/deserialize/simple/object.ts +11 -17
- package/assembly/deserialize/simple/struct.ts +158 -0
- package/assembly/index.ts +112 -16
- package/assembly/serialize/simple/arbitrary.ts +15 -2
- package/assembly/serialize/simple/object.ts +43 -6
- package/assembly/serialize/simple/struct.ts +7 -0
- package/assembly/test.ts +29 -3
- package/assembly/util/atoi.ts +1 -1
- package/bench.js +11 -2
- package/modules/as-bs/assembly/index.ts +3 -3
- package/modules/as-bs/assembly/state.ts +8 -0
- package/package.json +3 -2
- package/transform/lib/index.js +4 -9
- package/transform/lib/index.js.map +1 -1
- package/transform/src/index.ts +4 -8
package/README.md
CHANGED
|
@@ -1,41 +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-
|
|
9
|
+
AssemblyScript - v1.0.0-beta.1
|
|
10
10
|
</pre>
|
|
11
11
|
</h5>
|
|
12
12
|
|
|
13
|
-
## Contents
|
|
14
|
-
- [About](#about)
|
|
15
|
-
- [Installation](#installation)
|
|
16
|
-
- [Usage](#usage)
|
|
17
|
-
- [Examples](#examples)
|
|
18
|
-
- [Performance](#performance)
|
|
19
|
-
- [License](#license)
|
|
20
|
-
- [Contact](#contact)
|
|
13
|
+
## 📚 Contents
|
|
21
14
|
|
|
22
|
-
|
|
15
|
+
- [About](#-about)
|
|
16
|
+
- [Installation](#-installation)
|
|
17
|
+
- [Usage](#-usage)
|
|
18
|
+
- [Examples](#examples)
|
|
19
|
+
- [Performance](#-performance)
|
|
20
|
+
- [License](#-license)
|
|
21
|
+
- [Contact](#-contact)
|
|
23
22
|
|
|
24
|
-
##
|
|
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
|
|
25
28
|
|
|
26
29
|
```bash
|
|
27
|
-
npm install json-as@1.0.0-
|
|
30
|
+
npm install json-as@1.0.0-beta.1
|
|
28
31
|
```
|
|
29
32
|
|
|
30
33
|
Add the `--transform` to your `asc` command (e.g. in package.json)
|
|
31
34
|
|
|
32
35
|
```bash
|
|
33
|
-
--transform json-as
|
|
36
|
+
--transform json-as/transform
|
|
34
37
|
```
|
|
35
38
|
|
|
36
39
|
Alternatively, add it to your `asconfig.json`
|
|
37
40
|
|
|
38
|
-
```
|
|
41
|
+
```json
|
|
39
42
|
{
|
|
40
43
|
// ...
|
|
41
44
|
"options": {
|
|
@@ -46,7 +49,7 @@ Alternatively, add it to your `asconfig.json`
|
|
|
46
49
|
|
|
47
50
|
If you'd like to see the code that the transform generates, run with `JSON_DEBUG=true`
|
|
48
51
|
|
|
49
|
-
## Usage
|
|
52
|
+
## 🪄 Usage
|
|
50
53
|
|
|
51
54
|
```js
|
|
52
55
|
import { JSON } from "json-as";
|
|
@@ -75,7 +78,7 @@ class Player {
|
|
|
75
78
|
const player: Player = {
|
|
76
79
|
firstName: "Jairus",
|
|
77
80
|
lastName: "Tanaka",
|
|
78
|
-
lastActive: [2,
|
|
81
|
+
lastActive: [2, 13, 2025],
|
|
79
82
|
age: 18,
|
|
80
83
|
pos: {
|
|
81
84
|
x: 3.4,
|
|
@@ -86,56 +89,58 @@ const player: Player = {
|
|
|
86
89
|
};
|
|
87
90
|
|
|
88
91
|
const serialized = JSON.stringify<Player>(player);
|
|
89
|
-
const
|
|
92
|
+
const deserialized = JSON.parse<Player>(serialized);
|
|
90
93
|
|
|
91
|
-
console.log("Serialized
|
|
92
|
-
console.log("
|
|
94
|
+
console.log("Serialized " + serialized);
|
|
95
|
+
console.log("Deserialized " + JSON.stringify(deserialized));
|
|
93
96
|
```
|
|
94
97
|
|
|
95
98
|
## Examples
|
|
96
99
|
|
|
97
|
-
|
|
100
|
+
## ⚡ Performance
|
|
98
101
|
|
|
99
|
-
|
|
100
|
-
@json
|
|
101
|
-
class Base {}
|
|
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
|
-
|
|
104
|
-
class Vec1 extends Base {
|
|
105
|
-
x: f32 = 1.0;
|
|
106
|
-
}
|
|
107
|
-
@json
|
|
108
|
-
class Vec2 extends Vec1 {
|
|
109
|
-
y: f32 = 2.0;
|
|
110
|
-
}
|
|
111
|
-
@json
|
|
112
|
-
class Vec3 extends Vec2 {
|
|
113
|
-
z: f32 = 3.0;
|
|
114
|
-
}
|
|
104
|
+
### Raw Performance
|
|
115
105
|
|
|
116
|
-
|
|
117
|
-
new Vec1(),
|
|
118
|
-
new Vec2(),
|
|
119
|
-
new Vec3()
|
|
120
|
-
];
|
|
106
|
+
Simple
|
|
121
107
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
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] |
|
|
126
115
|
|
|
127
|
-
|
|
116
|
+
SIMD
|
|
128
117
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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
|
|
137
|
+
|
|
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] |
|
|
137
143
|
|
|
138
|
-
If you use this project in your codebase, consider dropping a [star](https://github.com/JairusSW/as-json). I would really appreciate it!
|
|
139
144
|
|
|
140
145
|
## 📃 License
|
|
141
146
|
|
|
@@ -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
|
+
});
|
|
@@ -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(
|
|
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
|
|
6
|
-
const out = dst ? changetype<
|
|
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
|
-
|
|
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 ==
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
|
|
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<
|
|
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 ==
|
|
55
|
+
if (code == COMMA || code == BRACKET_RIGHT || isSpace(code)) {
|
|
33
56
|
// @ts-ignore: type
|
|
34
|
-
out.push(JSON.__deserialize<
|
|
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<
|
|
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<
|
|
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<
|
|
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
|
-
|
|
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<
|
|
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
|
-
|
|
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<
|
|
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
|
|
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 {
|
|
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
|
|
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
|
|
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
|
+
}
|
|
@@ -76,7 +76,7 @@ export function deserializeMap<T extends Map<any, any>>(srcStart: usize, srcEnd:
|
|
|
76
76
|
srcStart += 2;
|
|
77
77
|
while (srcStart < srcEnd) {
|
|
78
78
|
const code = load<u16>(srcStart);
|
|
79
|
-
if (
|
|
79
|
+
if (code == BRACKET_RIGHT) {
|
|
80
80
|
if (--depth == 0) {
|
|
81
81
|
// @ts-ignore: type
|
|
82
82
|
out.set(key, JSON.__deserialize<valueof<T>>(lastIndex, srcStart));
|
|
@@ -2,9 +2,10 @@ import { JSON } from "../..";
|
|
|
2
2
|
import { BACK_SLASH, COMMA, CHAR_F, BRACE_LEFT, BRACKET_LEFT, CHAR_N, QUOTE, BRACE_RIGHT, BRACKET_RIGHT, CHAR_T } from "../../custom/chars";
|
|
3
3
|
import { isSpace } from "../../util";
|
|
4
4
|
import { ptrToStr } from "../../util/ptrToStr";
|
|
5
|
+
import { deserializeArbitrary } from "./arbitrary";
|
|
5
6
|
|
|
6
|
-
export function deserializeObject
|
|
7
|
-
const out =
|
|
7
|
+
export function deserializeObject(srcStart: usize, srcEnd: usize, dst: usize): JSON.Obj {
|
|
8
|
+
const out = new JSON.Obj();
|
|
8
9
|
|
|
9
10
|
let keyStart: usize = 0;
|
|
10
11
|
let keyEnd: usize = 0;
|
|
@@ -22,7 +23,7 @@ export function deserializeObject<T>(srcStart: usize, srcEnd: usize, dst: usize)
|
|
|
22
23
|
if (isKey) {
|
|
23
24
|
keyStart = lastIndex;
|
|
24
25
|
keyEnd = srcStart;
|
|
25
|
-
// console.log("Key: " + ptrToStr(
|
|
26
|
+
// console.log("Key: " + ptrToStr(keyStart, keyEnd));
|
|
26
27
|
// console.log("Next: " + String.fromCharCode(load<u16>(srcStart + 2)));
|
|
27
28
|
srcStart += 2;
|
|
28
29
|
// while (isSpace((code = load<u16>((srcStart += 2))))) {
|
|
@@ -46,8 +47,7 @@ export function deserializeObject<T>(srcStart: usize, srcEnd: usize, dst: usize)
|
|
|
46
47
|
const code = load<u16>(srcStart);
|
|
47
48
|
if (code == QUOTE && load<u16>(srcStart - 2) !== BACK_SLASH) {
|
|
48
49
|
// console.log("Value (string): " + ptrToStr(lastIndex, srcStart + 2));
|
|
49
|
-
|
|
50
|
-
out.__DESERIALIZE(keyStart, keyEnd, lastIndex, srcStart + 2, dst);
|
|
50
|
+
out.set(ptrToStr(keyStart, keyEnd), deserializeArbitrary(lastIndex, srcStart + 2, dst));
|
|
51
51
|
// while (isSpace(load<u16>(srcStart))) srcStart += 2;
|
|
52
52
|
srcStart += 4;
|
|
53
53
|
// console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
|
|
@@ -63,8 +63,7 @@ export function deserializeObject<T>(srcStart: usize, srcEnd: usize, dst: usize)
|
|
|
63
63
|
const code = load<u16>(srcStart);
|
|
64
64
|
if (code == COMMA || code == BRACE_RIGHT || isSpace(code)) {
|
|
65
65
|
// console.log("Value (number): " + ptrToStr(lastIndex, srcStart));
|
|
66
|
-
|
|
67
|
-
out.__DESERIALIZE(keyStart, keyEnd, lastIndex, srcStart, dst);
|
|
66
|
+
out.set(ptrToStr(keyStart, keyEnd), deserializeArbitrary(lastIndex, srcStart, dst));
|
|
68
67
|
// while (isSpace(load<u16>((srcStart += 2)))) {
|
|
69
68
|
// /* empty */
|
|
70
69
|
// }
|
|
@@ -84,8 +83,7 @@ export function deserializeObject<T>(srcStart: usize, srcEnd: usize, dst: usize)
|
|
|
84
83
|
if (code == BRACE_RIGHT) {
|
|
85
84
|
if (--depth == 0) {
|
|
86
85
|
// console.log("Value (object): " + ptrToStr(lastIndex, srcStart + 2));
|
|
87
|
-
|
|
88
|
-
out.__DESERIALIZE(keyStart, keyEnd, lastIndex, (srcStart += 2), dst);
|
|
86
|
+
out.set(ptrToStr(keyStart, keyEnd), deserializeArbitrary(lastIndex, srcStart += 2, dst));
|
|
89
87
|
// console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
|
|
90
88
|
keyStart = 0;
|
|
91
89
|
// while (isSpace(load<u16>(srcStart))) {
|
|
@@ -105,8 +103,7 @@ export function deserializeObject<T>(srcStart: usize, srcEnd: usize, dst: usize)
|
|
|
105
103
|
if (code == BRACKET_RIGHT) {
|
|
106
104
|
if (--depth == 0) {
|
|
107
105
|
// console.log("Value (array): " + ptrToStr(lastIndex, srcStart + 2));
|
|
108
|
-
|
|
109
|
-
out.__DESERIALIZE(keyStart, keyEnd, lastIndex, (srcStart += 2), dst);
|
|
106
|
+
out.set(ptrToStr(keyStart, keyEnd), deserializeArbitrary(lastIndex, srcStart += 2, dst));
|
|
110
107
|
// console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
|
|
111
108
|
keyStart = 0;
|
|
112
109
|
// while (isSpace(load<u16>((srcStart += 2)))) {
|
|
@@ -120,8 +117,7 @@ export function deserializeObject<T>(srcStart: usize, srcEnd: usize, dst: usize)
|
|
|
120
117
|
} else if (code == CHAR_T) {
|
|
121
118
|
if (load<u64>(srcStart) == 28429475166421108) {
|
|
122
119
|
// console.log("Value (bool): " + ptrToStr(srcStart, srcStart + 8));
|
|
123
|
-
|
|
124
|
-
out.__DESERIALIZE(keyStart, keyEnd, srcStart, (srcStart += 8), dst);
|
|
120
|
+
out.set(ptrToStr(keyStart, keyEnd), deserializeArbitrary(lastIndex, srcStart += 8, dst));
|
|
125
121
|
// while (isSpace(load<u16>((srcStart += 2)))) {
|
|
126
122
|
// /* empty */
|
|
127
123
|
// }
|
|
@@ -132,8 +128,7 @@ export function deserializeObject<T>(srcStart: usize, srcEnd: usize, dst: usize)
|
|
|
132
128
|
} else if (code == CHAR_F) {
|
|
133
129
|
if (load<u64>(srcStart, 2) == 28429466576093281) {
|
|
134
130
|
// console.log("Value (bool): " + ptrToStr(srcStart, srcStart + 10));
|
|
135
|
-
|
|
136
|
-
out.__DESERIALIZE(keyStart, keyEnd, srcStart, (srcStart += 10), dst);
|
|
131
|
+
out.set(ptrToStr(keyStart, keyEnd), deserializeArbitrary(lastIndex, srcStart += 10, dst));
|
|
137
132
|
// while (isSpace(load<u16>((srcStart += 2)))) {
|
|
138
133
|
// /* empty */
|
|
139
134
|
// }
|
|
@@ -144,8 +139,7 @@ export function deserializeObject<T>(srcStart: usize, srcEnd: usize, dst: usize)
|
|
|
144
139
|
} else if (code == CHAR_N) {
|
|
145
140
|
if (load<u64>(srcStart) == 30399761348886638) {
|
|
146
141
|
// console.log("Value (null): " + ptrToStr(srcStart, srcStart + 8));
|
|
147
|
-
|
|
148
|
-
out.__DESERIALIZE(keyStart, keyEnd, srcStart, (srcStart += 8), dst);
|
|
142
|
+
out.set(ptrToStr(keyStart, keyEnd), deserializeArbitrary(lastIndex, srcStart += 8, dst));
|
|
149
143
|
// while (isSpace(load<u16>((srcStart += 2)))) {
|
|
150
144
|
/* empty */
|
|
151
145
|
// }
|