json-as 1.0.0-alpha.3 → 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/CHANGELOG +14 -0
- package/README.md +76 -59
- 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__/box.spec.ts +37 -0
- package/assembly/__tests__/date.spec.ts +38 -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/bool.ts +4 -7
- package/assembly/deserialize/simple/date.ts +2 -2
- package/assembly/deserialize/simple/integer.ts +2 -1
- package/assembly/deserialize/simple/map.ts +1 -1
- package/assembly/deserialize/simple/object.ts +13 -17
- package/assembly/deserialize/simple/struct.ts +158 -0
- package/assembly/index.ts +143 -24
- package/assembly/serialize/simd/string.ts +11 -11
- package/assembly/serialize/simple/arbitrary.ts +15 -2
- package/assembly/serialize/simple/array.ts +4 -3
- package/assembly/serialize/simple/float.ts +1 -1
- package/assembly/serialize/simple/integer.ts +7 -2
- package/assembly/serialize/simple/object.ts +43 -6
- package/assembly/serialize/simple/struct.ts +7 -0
- package/assembly/test.ts +84 -4
- package/assembly/util/atoi.ts +1 -1
- package/assembly/util/snp.ts +2 -2
- package/bench.js +11 -2
- package/modules/as-bs/assembly/index.ts +63 -32
- package/modules/as-bs/assembly/state.ts +8 -0
- package/package.json +7 -6
- package/transform/lib/builder.js +1340 -1262
- package/transform/lib/index.js +577 -512
- package/transform/lib/index.js.map +1 -1
- package/transform/lib/linker.js +12 -10
- package/transform/lib/types.js +19 -19
- package/transform/lib/util.js +34 -34
- package/transform/lib/visitor.js +529 -526
- package/transform/src/index.ts +25 -23
|
@@ -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));
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import { JSON } from "../..";
|
|
1
2
|
import { BACK_SLASH, COMMA, CHAR_F, BRACE_LEFT, BRACKET_LEFT, CHAR_N, QUOTE, BRACE_RIGHT, BRACKET_RIGHT, CHAR_T } from "../../custom/chars";
|
|
2
3
|
import { isSpace } from "../../util";
|
|
4
|
+
import { ptrToStr } from "../../util/ptrToStr";
|
|
5
|
+
import { deserializeArbitrary } from "./arbitrary";
|
|
3
6
|
|
|
4
|
-
export function deserializeObject
|
|
5
|
-
const out =
|
|
7
|
+
export function deserializeObject(srcStart: usize, srcEnd: usize, dst: usize): JSON.Obj {
|
|
8
|
+
const out = new JSON.Obj();
|
|
6
9
|
|
|
7
10
|
let keyStart: usize = 0;
|
|
8
11
|
let keyEnd: usize = 0;
|
|
@@ -20,7 +23,7 @@ export function deserializeObject<T>(srcStart: usize, srcEnd: usize, dst: usize)
|
|
|
20
23
|
if (isKey) {
|
|
21
24
|
keyStart = lastIndex;
|
|
22
25
|
keyEnd = srcStart;
|
|
23
|
-
// console.log("Key: " + ptrToStr(
|
|
26
|
+
// console.log("Key: " + ptrToStr(keyStart, keyEnd));
|
|
24
27
|
// console.log("Next: " + String.fromCharCode(load<u16>(srcStart + 2)));
|
|
25
28
|
srcStart += 2;
|
|
26
29
|
// while (isSpace((code = load<u16>((srcStart += 2))))) {
|
|
@@ -44,8 +47,7 @@ export function deserializeObject<T>(srcStart: usize, srcEnd: usize, dst: usize)
|
|
|
44
47
|
const code = load<u16>(srcStart);
|
|
45
48
|
if (code == QUOTE && load<u16>(srcStart - 2) !== BACK_SLASH) {
|
|
46
49
|
// console.log("Value (string): " + ptrToStr(lastIndex, srcStart + 2));
|
|
47
|
-
|
|
48
|
-
out.__DESERIALIZE(keyStart, keyEnd, lastIndex, srcStart + 2, dst);
|
|
50
|
+
out.set(ptrToStr(keyStart, keyEnd), deserializeArbitrary(lastIndex, srcStart + 2, dst));
|
|
49
51
|
// while (isSpace(load<u16>(srcStart))) srcStart += 2;
|
|
50
52
|
srcStart += 4;
|
|
51
53
|
// console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
|
|
@@ -60,9 +62,8 @@ export function deserializeObject<T>(srcStart: usize, srcEnd: usize, dst: usize)
|
|
|
60
62
|
while (srcStart < srcEnd) {
|
|
61
63
|
const code = load<u16>(srcStart);
|
|
62
64
|
if (code == COMMA || code == BRACE_RIGHT || isSpace(code)) {
|
|
63
|
-
// @ts-ignore: exists
|
|
64
|
-
out.__DESERIALIZE(keyStart, keyEnd, lastIndex, srcStart, dst);
|
|
65
65
|
// console.log("Value (number): " + ptrToStr(lastIndex, srcStart));
|
|
66
|
+
out.set(ptrToStr(keyStart, keyEnd), deserializeArbitrary(lastIndex, srcStart, dst));
|
|
66
67
|
// while (isSpace(load<u16>((srcStart += 2)))) {
|
|
67
68
|
// /* empty */
|
|
68
69
|
// }
|
|
@@ -82,8 +83,7 @@ export function deserializeObject<T>(srcStart: usize, srcEnd: usize, dst: usize)
|
|
|
82
83
|
if (code == BRACE_RIGHT) {
|
|
83
84
|
if (--depth == 0) {
|
|
84
85
|
// console.log("Value (object): " + ptrToStr(lastIndex, srcStart + 2));
|
|
85
|
-
|
|
86
|
-
out.__DESERIALIZE(keyStart, keyEnd, lastIndex, (srcStart += 2), dst);
|
|
86
|
+
out.set(ptrToStr(keyStart, keyEnd), deserializeArbitrary(lastIndex, srcStart += 2, dst));
|
|
87
87
|
// console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
|
|
88
88
|
keyStart = 0;
|
|
89
89
|
// while (isSpace(load<u16>(srcStart))) {
|
|
@@ -103,8 +103,7 @@ export function deserializeObject<T>(srcStart: usize, srcEnd: usize, dst: usize)
|
|
|
103
103
|
if (code == BRACKET_RIGHT) {
|
|
104
104
|
if (--depth == 0) {
|
|
105
105
|
// console.log("Value (array): " + ptrToStr(lastIndex, srcStart + 2));
|
|
106
|
-
|
|
107
|
-
out.__DESERIALIZE(keyStart, keyEnd, lastIndex, (srcStart += 2), dst);
|
|
106
|
+
out.set(ptrToStr(keyStart, keyEnd), deserializeArbitrary(lastIndex, srcStart += 2, dst));
|
|
108
107
|
// console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
|
|
109
108
|
keyStart = 0;
|
|
110
109
|
// while (isSpace(load<u16>((srcStart += 2)))) {
|
|
@@ -118,8 +117,7 @@ export function deserializeObject<T>(srcStart: usize, srcEnd: usize, dst: usize)
|
|
|
118
117
|
} else if (code == CHAR_T) {
|
|
119
118
|
if (load<u64>(srcStart) == 28429475166421108) {
|
|
120
119
|
// console.log("Value (bool): " + ptrToStr(srcStart, srcStart + 8));
|
|
121
|
-
|
|
122
|
-
out.__DESERIALIZE(keyStart, keyEnd, srcStart, (srcStart += 8), dst);
|
|
120
|
+
out.set(ptrToStr(keyStart, keyEnd), deserializeArbitrary(lastIndex, srcStart += 8, dst));
|
|
123
121
|
// while (isSpace(load<u16>((srcStart += 2)))) {
|
|
124
122
|
// /* empty */
|
|
125
123
|
// }
|
|
@@ -130,8 +128,7 @@ export function deserializeObject<T>(srcStart: usize, srcEnd: usize, dst: usize)
|
|
|
130
128
|
} else if (code == CHAR_F) {
|
|
131
129
|
if (load<u64>(srcStart, 2) == 28429466576093281) {
|
|
132
130
|
// console.log("Value (bool): " + ptrToStr(srcStart, srcStart + 10));
|
|
133
|
-
|
|
134
|
-
out.__DESERIALIZE(keyStart, keyEnd, srcStart, (srcStart += 10), dst);
|
|
131
|
+
out.set(ptrToStr(keyStart, keyEnd), deserializeArbitrary(lastIndex, srcStart += 10, dst));
|
|
135
132
|
// while (isSpace(load<u16>((srcStart += 2)))) {
|
|
136
133
|
// /* empty */
|
|
137
134
|
// }
|
|
@@ -142,8 +139,7 @@ export function deserializeObject<T>(srcStart: usize, srcEnd: usize, dst: usize)
|
|
|
142
139
|
} else if (code == CHAR_N) {
|
|
143
140
|
if (load<u64>(srcStart) == 30399761348886638) {
|
|
144
141
|
// console.log("Value (null): " + ptrToStr(srcStart, srcStart + 8));
|
|
145
|
-
|
|
146
|
-
out.__DESERIALIZE(keyStart, keyEnd, srcStart, (srcStart += 8), dst);
|
|
142
|
+
out.set(ptrToStr(keyStart, keyEnd), deserializeArbitrary(lastIndex, srcStart += 8, dst));
|
|
147
143
|
// while (isSpace(load<u16>((srcStart += 2)))) {
|
|
148
144
|
/* empty */
|
|
149
145
|
// }
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { BACK_SLASH, COMMA, CHAR_F, BRACE_LEFT, BRACKET_LEFT, CHAR_N, QUOTE, BRACE_RIGHT, BRACKET_RIGHT, CHAR_T } from "../../custom/chars";
|
|
2
|
+
import { isSpace } from "../../util";
|
|
3
|
+
|
|
4
|
+
export function deserializeStruct<T>(srcStart: usize, srcEnd: usize, dst: usize): T {
|
|
5
|
+
const out = changetype<nonnull<T>>(dst || __new(offsetof<T>(), idof<T>()));
|
|
6
|
+
|
|
7
|
+
let keyStart: usize = 0;
|
|
8
|
+
let keyEnd: usize = 0;
|
|
9
|
+
let isKey = false;
|
|
10
|
+
let depth = 0;
|
|
11
|
+
let lastIndex: usize = 0;
|
|
12
|
+
|
|
13
|
+
// while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
|
|
14
|
+
// while (srcEnd > srcStart && isSpace(load<u16>(srcEnd))) srcEnd -= 2;
|
|
15
|
+
srcStart += 2;
|
|
16
|
+
while (srcStart < srcEnd) {
|
|
17
|
+
let code = load<u16>(srcStart); // while (isSpace(code)) code = load<u16>(srcStart += 2);
|
|
18
|
+
if (keyStart == 0) {
|
|
19
|
+
if (code == QUOTE && load<u16>(srcStart - 2) !== BACK_SLASH) {
|
|
20
|
+
if (isKey) {
|
|
21
|
+
keyStart = lastIndex;
|
|
22
|
+
keyEnd = srcStart;
|
|
23
|
+
// console.log("Key: " + ptrToStr(lastIndex, srcStart));
|
|
24
|
+
// console.log("Next: " + String.fromCharCode(load<u16>(srcStart + 2)));
|
|
25
|
+
srcStart += 2;
|
|
26
|
+
// while (isSpace((code = load<u16>((srcStart += 2))))) {
|
|
27
|
+
// /* empty */
|
|
28
|
+
// }
|
|
29
|
+
// if (code !== COLON) throw new Error("Expected ':' after key at position " + (srcStart - srcPtr).toString());
|
|
30
|
+
isKey = false;
|
|
31
|
+
} else {
|
|
32
|
+
// console.log("Got key start");
|
|
33
|
+
isKey = true; // i don't like this
|
|
34
|
+
lastIndex = srcStart + 2;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// isKey = !isKey;
|
|
38
|
+
srcStart += 2;
|
|
39
|
+
} else {
|
|
40
|
+
if (code == QUOTE) {
|
|
41
|
+
lastIndex = srcStart;
|
|
42
|
+
srcStart += 2;
|
|
43
|
+
while (srcStart < srcEnd) {
|
|
44
|
+
const code = load<u16>(srcStart);
|
|
45
|
+
if (code == QUOTE && load<u16>(srcStart - 2) !== BACK_SLASH) {
|
|
46
|
+
// console.log("Value (string): " + ptrToStr(lastIndex, srcStart + 2));
|
|
47
|
+
// @ts-ignore: exists
|
|
48
|
+
out.__DESERIALIZE(keyStart, keyEnd, lastIndex, srcStart + 2, dst);
|
|
49
|
+
// while (isSpace(load<u16>(srcStart))) srcStart += 2;
|
|
50
|
+
srcStart += 4;
|
|
51
|
+
// console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
|
|
52
|
+
keyStart = 0;
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
srcStart += 2;
|
|
56
|
+
}
|
|
57
|
+
} else if (code - 48 <= 9 || code == 45) {
|
|
58
|
+
lastIndex = srcStart;
|
|
59
|
+
srcStart += 2;
|
|
60
|
+
while (srcStart < srcEnd) {
|
|
61
|
+
const code = load<u16>(srcStart);
|
|
62
|
+
if (code == COMMA || code == BRACE_RIGHT || isSpace(code)) {
|
|
63
|
+
// console.log("Value (number): " + ptrToStr(lastIndex, srcStart));
|
|
64
|
+
// @ts-ignore: exists
|
|
65
|
+
out.__DESERIALIZE(keyStart, keyEnd, lastIndex, srcStart, dst);
|
|
66
|
+
// while (isSpace(load<u16>((srcStart += 2)))) {
|
|
67
|
+
// /* empty */
|
|
68
|
+
// }
|
|
69
|
+
srcStart += 2;
|
|
70
|
+
// console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
|
|
71
|
+
keyStart = 0;
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
srcStart += 2;
|
|
75
|
+
}
|
|
76
|
+
} else if (code == BRACE_LEFT) {
|
|
77
|
+
lastIndex = srcStart;
|
|
78
|
+
depth++;
|
|
79
|
+
srcStart += 2;
|
|
80
|
+
while (srcStart < srcEnd) {
|
|
81
|
+
const code = load<u16>(srcStart);
|
|
82
|
+
if (code == BRACE_RIGHT) {
|
|
83
|
+
if (--depth == 0) {
|
|
84
|
+
// console.log("Value (object): " + ptrToStr(lastIndex, srcStart + 2));
|
|
85
|
+
// @ts-ignore: exists
|
|
86
|
+
out.__DESERIALIZE(keyStart, keyEnd, lastIndex, (srcStart += 2), dst);
|
|
87
|
+
// console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
|
|
88
|
+
keyStart = 0;
|
|
89
|
+
// while (isSpace(load<u16>(srcStart))) {
|
|
90
|
+
// /* empty */
|
|
91
|
+
// }
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
} else if (code == BRACE_LEFT) depth++;
|
|
95
|
+
srcStart += 2;
|
|
96
|
+
}
|
|
97
|
+
} else if (code == BRACKET_LEFT) {
|
|
98
|
+
lastIndex = srcStart;
|
|
99
|
+
depth++;
|
|
100
|
+
srcStart += 2;
|
|
101
|
+
while (srcStart < srcEnd) {
|
|
102
|
+
const code = load<u16>(srcStart);
|
|
103
|
+
if (code == BRACKET_RIGHT) {
|
|
104
|
+
if (--depth == 0) {
|
|
105
|
+
// console.log("Value (array): " + ptrToStr(lastIndex, srcStart + 2));
|
|
106
|
+
// @ts-ignore: exists
|
|
107
|
+
out.__DESERIALIZE(keyStart, keyEnd, lastIndex, (srcStart += 2), dst);
|
|
108
|
+
// console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
|
|
109
|
+
keyStart = 0;
|
|
110
|
+
// while (isSpace(load<u16>((srcStart += 2)))) {
|
|
111
|
+
// /* empty */
|
|
112
|
+
// }
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
} else if (code == BRACKET_LEFT) depth++;
|
|
116
|
+
srcStart += 2;
|
|
117
|
+
}
|
|
118
|
+
} else if (code == CHAR_T) {
|
|
119
|
+
if (load<u64>(srcStart) == 28429475166421108) {
|
|
120
|
+
// console.log("Value (bool): " + ptrToStr(srcStart, srcStart + 8));
|
|
121
|
+
// @ts-ignore: exists
|
|
122
|
+
out.__DESERIALIZE(keyStart, keyEnd, srcStart, (srcStart += 8), dst);
|
|
123
|
+
// while (isSpace(load<u16>((srcStart += 2)))) {
|
|
124
|
+
// /* empty */
|
|
125
|
+
// }
|
|
126
|
+
srcStart += 2;
|
|
127
|
+
// console.log("Next: " + String.fromCharCode(load<u16>(srcStart)) + " " + (srcStart < srcEnd).toString());
|
|
128
|
+
keyStart = 0;
|
|
129
|
+
}
|
|
130
|
+
} else if (code == CHAR_F) {
|
|
131
|
+
if (load<u64>(srcStart, 2) == 28429466576093281) {
|
|
132
|
+
// console.log("Value (bool): " + ptrToStr(srcStart, srcStart + 10));
|
|
133
|
+
// @ts-ignore: exists
|
|
134
|
+
out.__DESERIALIZE(keyStart, keyEnd, srcStart, (srcStart += 10), dst);
|
|
135
|
+
// while (isSpace(load<u16>((srcStart += 2)))) {
|
|
136
|
+
// /* empty */
|
|
137
|
+
// }
|
|
138
|
+
srcStart += 2;
|
|
139
|
+
// console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
|
|
140
|
+
keyStart = 0;
|
|
141
|
+
}
|
|
142
|
+
} else if (code == CHAR_N) {
|
|
143
|
+
if (load<u64>(srcStart) == 30399761348886638) {
|
|
144
|
+
// console.log("Value (null): " + ptrToStr(srcStart, srcStart + 8));
|
|
145
|
+
// @ts-ignore: exists
|
|
146
|
+
out.__DESERIALIZE(keyStart, keyEnd, srcStart, (srcStart += 8), dst);
|
|
147
|
+
// while (isSpace(load<u16>((srcStart += 2)))) {
|
|
148
|
+
/* empty */
|
|
149
|
+
// }
|
|
150
|
+
srcStart += 2;
|
|
151
|
+
// console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
|
|
152
|
+
keyStart = 0;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return out;
|
|
158
|
+
}
|
package/assembly/index.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { serializeMap } from "./serialize/simple/map";
|
|
|
7
7
|
import { deserializeBoolean } from "./deserialize/simple/bool";
|
|
8
8
|
import { deserializeArray } from "./deserialize/simple/array";
|
|
9
9
|
import { deserializeFloat } from "./deserialize/simple/float";
|
|
10
|
-
import {
|
|
10
|
+
import { deserializeStruct } from "./deserialize/simple/struct";
|
|
11
11
|
import { deserializeMap } from "./deserialize/simple/map";
|
|
12
12
|
import { deserializeDate } from "./deserialize/simple/date";
|
|
13
13
|
import { deserializeInteger } from "./deserialize/simple/integer";
|
|
@@ -20,9 +20,13 @@ import { dtoa_buffered, itoa_buffered } from "util/number";
|
|
|
20
20
|
import { serializeBool } from "./serialize/simple/bool";
|
|
21
21
|
import { serializeInteger } from "./serialize/simple/integer";
|
|
22
22
|
import { serializeFloat } from "./serialize/simple/float";
|
|
23
|
-
import {
|
|
23
|
+
import { serializeStruct } from "./serialize/simple/struct";
|
|
24
24
|
import { ptrToStr } from "./util/ptrToStr";
|
|
25
|
-
import { bytes } from "./util";
|
|
25
|
+
import { atoi, bytes } from "./util";
|
|
26
|
+
import { deserializeArbitrary } from "./deserialize/simple/arbitrary";
|
|
27
|
+
import { SERIALIZE_ESCAPE_TABLE } from "./globals/tables";
|
|
28
|
+
import { serializeObject } from "./serialize/simple/object";
|
|
29
|
+
import { deserializeObject } from "./deserialize/simple/object";
|
|
26
30
|
|
|
27
31
|
export type Raw = string;
|
|
28
32
|
|
|
@@ -36,6 +40,11 @@ export type Raw = string;
|
|
|
36
40
|
* JSON Encoder/Decoder for AssemblyScript
|
|
37
41
|
*/
|
|
38
42
|
export namespace JSON {
|
|
43
|
+
export namespace Memory {
|
|
44
|
+
export function shrink(): void {
|
|
45
|
+
bs.resize(64);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
39
48
|
/**
|
|
40
49
|
* Serializes valid JSON data
|
|
41
50
|
* ```js
|
|
@@ -44,7 +53,8 @@ export namespace JSON {
|
|
|
44
53
|
* @param data T
|
|
45
54
|
* @returns string
|
|
46
55
|
*/
|
|
47
|
-
|
|
56
|
+
// @ts-ignore: inline
|
|
57
|
+
@inline export function stringify<T>(data: T, out: string | null = null): string {
|
|
48
58
|
if (isBoolean<T>()) {
|
|
49
59
|
if (out) {
|
|
50
60
|
if (<bool>data == true) {
|
|
@@ -107,9 +117,7 @@ export namespace JSON {
|
|
|
107
117
|
serializeString(changetype<string>(data));
|
|
108
118
|
return bs.out<string>();
|
|
109
119
|
// @ts-ignore: Supplied by transform
|
|
110
|
-
} else if (isDefined(data.__SERIALIZE)
|
|
111
|
-
// @ts-ignore
|
|
112
|
-
// data.__ALLOCATE();
|
|
120
|
+
} else if (isDefined(data.__SERIALIZE)) {
|
|
113
121
|
// @ts-ignore
|
|
114
122
|
data.__SERIALIZE(changetype<usize>(data));
|
|
115
123
|
return bs.out<string>();
|
|
@@ -119,8 +127,8 @@ export namespace JSON {
|
|
|
119
127
|
|
|
120
128
|
store<u16>(changetype<usize>(out), QUOTE);
|
|
121
129
|
memory.copy(changetype<usize>(out) + 2, changetype<usize>(data.toISOString()), 48);
|
|
122
|
-
store<u16>(changetype<usize>(out), 50);
|
|
123
|
-
return out;
|
|
130
|
+
store<u16>(changetype<usize>(out), QUOTE, 50);
|
|
131
|
+
return changetype<string>(out);
|
|
124
132
|
} else if (data instanceof Array) {
|
|
125
133
|
// @ts-ignore
|
|
126
134
|
serializeArray(changetype<nonnull<T>>(data));
|
|
@@ -132,6 +140,9 @@ export namespace JSON {
|
|
|
132
140
|
} else if (data instanceof JSON.Value) {
|
|
133
141
|
serializeArbitrary(data);
|
|
134
142
|
return bs.out<string>();
|
|
143
|
+
} else if (data instanceof JSON.Obj) {
|
|
144
|
+
serializeObject(data);
|
|
145
|
+
return bs.out<string>();
|
|
135
146
|
} else if (data instanceof JSON.Box) {
|
|
136
147
|
return JSON.stringify(data.value);
|
|
137
148
|
} else {
|
|
@@ -147,7 +158,8 @@ export namespace JSON {
|
|
|
147
158
|
* @param data string
|
|
148
159
|
* @returns T
|
|
149
160
|
*/
|
|
150
|
-
|
|
161
|
+
// @ts-ignore: inline
|
|
162
|
+
@inline export function parse<T>(data: string): T {
|
|
151
163
|
const dataSize = bytes(data);
|
|
152
164
|
const dataPtr = changetype<usize>(data);
|
|
153
165
|
if (isBoolean<T>()) {
|
|
@@ -156,7 +168,7 @@ export namespace JSON {
|
|
|
156
168
|
return deserializeInteger<T>(dataPtr, dataPtr + dataSize);
|
|
157
169
|
} else if (isFloat<T>()) {
|
|
158
170
|
return deserializeFloat<T>(dataPtr, dataPtr + dataSize);
|
|
159
|
-
} else if (isNullable<T>() &&
|
|
171
|
+
} else if (isNullable<T>() && dataSize == 8 && load<u64>(dataPtr) == 30399761348886638) {
|
|
160
172
|
// @ts-ignore
|
|
161
173
|
return null;
|
|
162
174
|
} else if (isString<T>()) {
|
|
@@ -168,21 +180,27 @@ export namespace JSON {
|
|
|
168
180
|
}
|
|
169
181
|
let type: nonnull<T> = changetype<nonnull<T>>(0);
|
|
170
182
|
// @ts-ignore: Defined by transform
|
|
171
|
-
if (isDefined(type.__DESERIALIZE)
|
|
183
|
+
if (isDefined(type.__DESERIALIZE)) {
|
|
172
184
|
const out = __new(offsetof<nonnull<T>>(), idof<nonnull<T>>());
|
|
185
|
+
// @ts-ignore: Defined by transform
|
|
186
|
+
if (isDefined(type.__INITIALIZE)) changetype<nonnull<T>>(out).__INITIALIZE();
|
|
173
187
|
// @ts-ignore
|
|
174
|
-
|
|
175
|
-
// @ts-ignore
|
|
176
|
-
return deserializeObject<nonnull<T>>(dataPtr, dataPtr + dataSize, out);
|
|
188
|
+
return deserializeStruct<nonnull<T>>(dataPtr, dataPtr + dataSize, out);
|
|
177
189
|
} else if (type instanceof Map) {
|
|
178
190
|
// @ts-ignore
|
|
179
191
|
return deserializeMap<nonnull<T>>(dataPtr, dataPtr + dataSize);
|
|
180
192
|
} else if (type instanceof Date) {
|
|
181
193
|
// @ts-ignore
|
|
182
194
|
return deserializeDate(dataPtr, dataPtr + dataSize);
|
|
195
|
+
} else if (type instanceof JSON.Value) {
|
|
196
|
+
// @ts-ignore
|
|
197
|
+
return deserializeArbitrary(dataPtr, dataPtr + dataSize, 0);
|
|
198
|
+
} else if (type instanceof JSON.Obj) {
|
|
199
|
+
// @ts-ignore
|
|
200
|
+
return deserializeObject(dataPtr, dataPtr + dataSize, 0);
|
|
183
201
|
} else if (type instanceof JSON.Box) {
|
|
184
202
|
// @ts-ignore
|
|
185
|
-
return new JSON.Box(
|
|
203
|
+
return new JSON.Box(parseBox(data, changetype<nonnull<T>>(0).value));
|
|
186
204
|
} else {
|
|
187
205
|
throw new Error(`Could not deserialize data ${data} to type ${nameof<T>()}. Make sure to add the correct decorators to classes.`);
|
|
188
206
|
}
|
|
@@ -254,7 +272,7 @@ export namespace JSON {
|
|
|
254
272
|
this.type = JSON.Types.U64;
|
|
255
273
|
store<T>(changetype<usize>(this), value, STORAGE);
|
|
256
274
|
} else if (value instanceof f32) {
|
|
257
|
-
this.type = JSON.Types.
|
|
275
|
+
this.type = JSON.Types.F32;
|
|
258
276
|
store<T>(changetype<usize>(this), value, STORAGE);
|
|
259
277
|
} else if (value instanceof f64) {
|
|
260
278
|
this.type = JSON.Types.F64;
|
|
@@ -274,6 +292,9 @@ export namespace JSON {
|
|
|
274
292
|
// @ts-ignore
|
|
275
293
|
if (!JSON.Value.METHODS.has(idof<T>())) JSON.Value.METHODS.set(idof<T>(), value.__SERIALIZE.index);
|
|
276
294
|
// @ts-ignore
|
|
295
|
+
store<usize>(changetype<usize>(this), changetype<usize>(value), STORAGE);
|
|
296
|
+
} else if (value instanceof JSON.Obj) {
|
|
297
|
+
this.type = JSON.Types.Object;
|
|
277
298
|
store<T>(changetype<usize>(this), value, STORAGE);
|
|
278
299
|
// @ts-ignore
|
|
279
300
|
} else if (isArray<T>() && idof<valueof<T>>() == idof<JSON.Value>()) {
|
|
@@ -305,6 +326,10 @@ export namespace JSON {
|
|
|
305
326
|
return this.get<u32>().toString();
|
|
306
327
|
case JSON.Types.U64:
|
|
307
328
|
return this.get<u64>().toString();
|
|
329
|
+
case JSON.Types.F32:
|
|
330
|
+
return this.get<f32>().toString();
|
|
331
|
+
case JSON.Types.F64:
|
|
332
|
+
return this.get<f64>().toString();
|
|
308
333
|
case JSON.Types.String:
|
|
309
334
|
return '"' + this.get<string>() + '"';
|
|
310
335
|
case JSON.Types.Bool:
|
|
@@ -326,20 +351,88 @@ export namespace JSON {
|
|
|
326
351
|
out.write("]");
|
|
327
352
|
return out.toString();
|
|
328
353
|
}
|
|
354
|
+
case JSON.Types.Object: {
|
|
355
|
+
return JSON.stringify(this.get<JSON.Obj>());
|
|
356
|
+
}
|
|
329
357
|
default: {
|
|
330
358
|
const fn = JSON.Value.METHODS.get(this.type - JSON.Types.Struct);
|
|
331
359
|
const value = this.get<usize>();
|
|
332
|
-
|
|
360
|
+
call_indirect<void>(fn, 0, value);
|
|
361
|
+
return bs.out<string>();
|
|
333
362
|
}
|
|
334
363
|
}
|
|
335
364
|
}
|
|
336
365
|
}
|
|
337
366
|
|
|
367
|
+
export class Obj {
|
|
368
|
+
// When accessing stackSize, subtract 2
|
|
369
|
+
// @ts-ignore: type
|
|
370
|
+
private stackSize: u32 = 6;
|
|
371
|
+
// @ts-ignore: type
|
|
372
|
+
private storage: Map<string, JSON.Value> = new Map<string, JSON.Value>();
|
|
373
|
+
|
|
374
|
+
constructor() { }
|
|
375
|
+
|
|
376
|
+
// @ts-ignore: decorator
|
|
377
|
+
@inline get size(): i32 {
|
|
378
|
+
return this.storage.size;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// @ts-ignore: decorator
|
|
382
|
+
@inline set<T>(key: string, value: T): void {
|
|
383
|
+
if (!this.storage.has(key)) this.stackSize += bytes(key) + 8;
|
|
384
|
+
this.storage.set(key, JSON.Value.from<T>(value));
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// @ts-ignore: decorator
|
|
388
|
+
@inline get(key: string): JSON.Value | null {
|
|
389
|
+
if (!this.storage.has(key)) return null;
|
|
390
|
+
return this.storage.get(key);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// @ts-ignore: decorator
|
|
394
|
+
@inline has(key: string): bool {
|
|
395
|
+
return this.storage.has(key);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// @ts-ignore: decorator
|
|
399
|
+
@inline delete(key: string): bool {
|
|
400
|
+
return this.storage.delete(key);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// @ts-ignore: decorator
|
|
404
|
+
@inline keys(): string[] {
|
|
405
|
+
return this.storage.keys();
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// @ts-ignore: decorator
|
|
409
|
+
@inline values(): JSON.Value[] {
|
|
410
|
+
return this.storage.values();
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// @ts-ignore: decorator
|
|
414
|
+
@inline toString(): string {
|
|
415
|
+
return JSON.stringify(this);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// @ts-ignore: decorator
|
|
419
|
+
@inline static from<T>(value: T): JSON.Obj {
|
|
420
|
+
if (value instanceof JSON.Obj) return value;
|
|
421
|
+
const out = changetype<JSON.Obj>(__new(offsetof<JSON.Obj>(), idof<JSON.Obj>()));
|
|
422
|
+
|
|
423
|
+
if (value instanceof Map) {
|
|
424
|
+
|
|
425
|
+
}
|
|
426
|
+
return out;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
338
429
|
/**
|
|
339
430
|
* Box for primitive types
|
|
340
431
|
*/
|
|
341
432
|
export class Box<T> {
|
|
342
|
-
constructor(public value: T) {
|
|
433
|
+
constructor(public value: T) {
|
|
434
|
+
if (!isInteger<T>() && !isFloat<T>()) ERROR("JSON.Box should only hold primitive types!");
|
|
435
|
+
}
|
|
343
436
|
/**
|
|
344
437
|
* Creates a reference to a primitive type
|
|
345
438
|
* This means that it can create a nullable primitive
|
|
@@ -353,9 +446,16 @@ export namespace JSON {
|
|
|
353
446
|
@inline static from<T>(value: T): Box<T> {
|
|
354
447
|
return new Box(value);
|
|
355
448
|
}
|
|
449
|
+
toString(): string {
|
|
450
|
+
if (isNullable<this>() && changetype<usize>(this) == null) return "null";
|
|
451
|
+
// @ts-ignore: type
|
|
452
|
+
if (isDefined(this.value.toString)) return this.value.toString();
|
|
453
|
+
return "null";
|
|
454
|
+
}
|
|
356
455
|
}
|
|
357
456
|
|
|
358
|
-
|
|
457
|
+
// @ts-ignore: inline
|
|
458
|
+
@inline export function __serialize<T>(src: T): void {
|
|
359
459
|
if (isBoolean<T>()) {
|
|
360
460
|
serializeBool(src as bool);
|
|
361
461
|
} else if (isInteger<T>() && nameof<T>() == "usize" && src == 0) {
|
|
@@ -378,7 +478,7 @@ export namespace JSON {
|
|
|
378
478
|
// @ts-ignore: Supplied by transform
|
|
379
479
|
} else if (isDefined(src.__SERIALIZE)) {
|
|
380
480
|
// @ts-ignore
|
|
381
|
-
|
|
481
|
+
serializeStruct(changetype<nonnull<T>>(src));
|
|
382
482
|
} else if (src instanceof Date) {
|
|
383
483
|
// @ts-ignore
|
|
384
484
|
serializeDate(changetype<nonnull<T>>(src));
|
|
@@ -390,18 +490,22 @@ export namespace JSON {
|
|
|
390
490
|
serializeMap(changetype<nonnull<T>>(src));
|
|
391
491
|
} else if (src instanceof JSON.Value) {
|
|
392
492
|
serializeArbitrary(src);
|
|
493
|
+
} else if (src instanceof JSON.Obj) {
|
|
494
|
+
serializeObject(src);
|
|
393
495
|
} else if (src instanceof JSON.Box) {
|
|
394
496
|
__serialize(src.value);
|
|
395
497
|
} else {
|
|
396
498
|
throw new Error(`Could not serialize provided data. Make sure to add the correct decorators to classes.`);
|
|
397
499
|
}
|
|
398
500
|
}
|
|
399
|
-
|
|
501
|
+
|
|
502
|
+
// @ts-ignore: inline
|
|
503
|
+
@inline export function __deserialize<T>(srcStart: usize, srcEnd: usize, dst: usize = 0): T {
|
|
400
504
|
if (isBoolean<T>()) {
|
|
401
505
|
// @ts-ignore: type
|
|
402
506
|
return deserializeBoolean(srcStart, srcEnd);
|
|
403
507
|
} else if (isInteger<T>()) {
|
|
404
|
-
return
|
|
508
|
+
return atoi<T>(srcStart, srcEnd);
|
|
405
509
|
} else if (isFloat<T>()) {
|
|
406
510
|
return deserializeFloat<T>(srcStart, srcEnd);
|
|
407
511
|
} else if (isString<T>()) {
|
|
@@ -414,15 +518,30 @@ export namespace JSON {
|
|
|
414
518
|
let type: nonnull<T> = changetype<nonnull<T>>(0);
|
|
415
519
|
// @ts-ignore: declared by transform
|
|
416
520
|
if (isDefined(type.__DESERIALIZE)) {
|
|
417
|
-
return
|
|
521
|
+
return deserializeStruct<T>(srcStart, srcEnd, dst);
|
|
418
522
|
} else if (type instanceof Map) {
|
|
419
523
|
// @ts-ignore: type
|
|
420
524
|
return deserializeMap<T>(srcStart, srcEnd, dst);
|
|
421
525
|
} else if (type instanceof Date) {
|
|
422
526
|
// @ts-ignore: type
|
|
423
527
|
return deserializeDate(srcStart, srcEnd);
|
|
528
|
+
} else if (type instanceof JSON.Value) {
|
|
529
|
+
// @ts-ignore: type
|
|
530
|
+
return deserializeArbitrary(srcStart, srcEnd, 0);
|
|
531
|
+
} else if (type instanceof JSON.Box) {
|
|
532
|
+
// @ts-ignore: type
|
|
533
|
+
return new JSON.Box(deserializeBox(srcStart, srcEnd, dst, changetype<nonnull<T>>(0).value));
|
|
424
534
|
}
|
|
425
535
|
}
|
|
426
536
|
throw new Error(`Could not deserialize data '${ptrToStr(srcStart, srcEnd).slice(0, 100)}' to type. Make sure to add the correct decorators to classes.`);
|
|
427
537
|
}
|
|
428
538
|
}
|
|
539
|
+
|
|
540
|
+
// @ts-ignore: decorator
|
|
541
|
+
@inline function parseBox<T>(data: string, ty: T): T {
|
|
542
|
+
return JSON.parse<T>(data);
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
function deserializeBox<T>(srcStart: usize, srcEnd: usize, dst: usize, ty: T): T {
|
|
546
|
+
return JSON.__deserialize<T>(srcStart, srcEnd, dst);
|
|
547
|
+
}
|
|
@@ -18,7 +18,7 @@ export function serializeString_SIMD(src: string): void {
|
|
|
18
18
|
const srcSize = changetype<OBJECT>(changetype<usize>(src) - TOTAL_OVERHEAD).rtSize;
|
|
19
19
|
let srcStart = changetype<usize>(src);
|
|
20
20
|
const srcEnd = srcStart + srcSize;
|
|
21
|
-
bs.
|
|
21
|
+
bs.proposeSize(srcSize + 4);
|
|
22
22
|
const srcEnd16 = srcEnd - 15;
|
|
23
23
|
|
|
24
24
|
store<u8>(changetype<usize>(bs.offset), 34); /* " */
|
|
@@ -45,13 +45,13 @@ export function serializeString_SIMD(src: string): void {
|
|
|
45
45
|
mask &= mask - 1;
|
|
46
46
|
|
|
47
47
|
if ((escaped & 0xffff) != BACK_SLASH) {
|
|
48
|
-
bs.
|
|
48
|
+
bs.growSize(10);
|
|
49
49
|
store<u64>(dst_offset, 13511005048209500);
|
|
50
50
|
store<u32>(dst_offset, escaped, 8);
|
|
51
51
|
v128.store(dst_offset, v128.load(src_offset, 2), 12);
|
|
52
52
|
bs.offset += 10;
|
|
53
53
|
} else {
|
|
54
|
-
bs.
|
|
54
|
+
bs.growSize(2);
|
|
55
55
|
store<u32>(dst_offset, escaped);
|
|
56
56
|
v128.store(dst_offset, v128.load(src_offset, 2), 4);
|
|
57
57
|
bs.offset += 2;
|
|
@@ -84,7 +84,7 @@ export function serializeString_SIMD(src: string): void {
|
|
|
84
84
|
mask &= mask - 1;
|
|
85
85
|
|
|
86
86
|
if ((escaped & 0xffff) != BACK_SLASH) {
|
|
87
|
-
bs.
|
|
87
|
+
bs.growSize(10);
|
|
88
88
|
store<u64>(dst_offset, 13511005048209500);
|
|
89
89
|
store<u32>(dst_offset, escaped, 8);
|
|
90
90
|
while (lane_index < 6) {
|
|
@@ -93,7 +93,7 @@ export function serializeString_SIMD(src: string): void {
|
|
|
93
93
|
}
|
|
94
94
|
bs.offset += 10;
|
|
95
95
|
} else {
|
|
96
|
-
bs.
|
|
96
|
+
bs.growSize(2);
|
|
97
97
|
store<u32>(dst_offset, escaped);
|
|
98
98
|
|
|
99
99
|
while (lane_index < 6) {
|
|
@@ -116,12 +116,12 @@ export function serializeString_SIMD(src: string): void {
|
|
|
116
116
|
const escaped = load<u32>(SERIALIZE_ESCAPE_TABLE + (codeA << 2));
|
|
117
117
|
|
|
118
118
|
if ((escaped & 0xffff) != BACK_SLASH) {
|
|
119
|
-
bs.
|
|
119
|
+
bs.growSize(10);
|
|
120
120
|
store<u64>(bs.offset, 13511005048209500);
|
|
121
121
|
store<u32>(bs.offset, escaped, 8);
|
|
122
122
|
bs.offset += 12;
|
|
123
123
|
} else {
|
|
124
|
-
bs.
|
|
124
|
+
bs.growSize(2);
|
|
125
125
|
store<u32>(bs.offset, escaped);
|
|
126
126
|
bs.offset += 4;
|
|
127
127
|
}
|
|
@@ -134,12 +134,12 @@ export function serializeString_SIMD(src: string): void {
|
|
|
134
134
|
const escaped = load<u32>(SERIALIZE_ESCAPE_TABLE + (codeB << 2));
|
|
135
135
|
|
|
136
136
|
if ((escaped & 0xffff) != BACK_SLASH) {
|
|
137
|
-
bs.
|
|
137
|
+
bs.growSize(10);
|
|
138
138
|
store<u64>(bs.offset, 13511005048209500);
|
|
139
139
|
store<u32>(bs.offset, escaped, 8);
|
|
140
140
|
bs.offset += 12;
|
|
141
141
|
} else {
|
|
142
|
-
bs.
|
|
142
|
+
bs.growSize(2);
|
|
143
143
|
store<u32>(bs.offset, escaped);
|
|
144
144
|
bs.offset += 4;
|
|
145
145
|
}
|
|
@@ -156,12 +156,12 @@ export function serializeString_SIMD(src: string): void {
|
|
|
156
156
|
const escaped = load<u32>(SERIALIZE_ESCAPE_TABLE + (code << 2));
|
|
157
157
|
|
|
158
158
|
if ((escaped & 0xffff) != BACK_SLASH) {
|
|
159
|
-
bs.
|
|
159
|
+
bs.growSize(10);
|
|
160
160
|
store<u64>(bs.offset, 13511005048209500);
|
|
161
161
|
store<u32>(bs.offset, escaped, 8);
|
|
162
162
|
bs.offset += 12;
|
|
163
163
|
} else {
|
|
164
|
-
bs.
|
|
164
|
+
bs.growSize(2);
|
|
165
165
|
store<u32>(bs.offset, escaped);
|
|
166
166
|
bs.offset += 4;
|
|
167
167
|
}
|