json-as 1.0.0-alpha.4 → 1.0.0-beta.2
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/.trunk/configs/.markdownlint.yaml +2 -0
- package/.trunk/configs/.shellcheckrc +7 -0
- package/.trunk/configs/.yamllint.yaml +7 -0
- package/.trunk/trunk.yaml +36 -0
- package/CHANGELOG +23 -0
- package/README.md +59 -57
- package/assembly/__benches__/misc.bench.ts +48 -0
- package/assembly/__benches__/schemas.ts +25 -0
- package/assembly/__benches__/string.bench.ts +24 -0
- package/assembly/__benches__/struct.bench.ts +22 -0
- package/assembly/__tests__/arbitrary.spec.ts +19 -0
- package/assembly/__tests__/custom.spec.ts +42 -0
- package/assembly/__tests__/types.ts +3 -3
- package/assembly/custom/bench.ts +26 -0
- 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.d.ts +15 -1
- package/assembly/index.ts +144 -18
- 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 +61 -3
- package/assembly/util/atoi.ts +1 -1
- package/bench/bench.ts +15 -0
- package/bench/schemas.ts +5 -0
- package/bench/string.bench.ts +16 -0
- 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 +59 -9
- package/transform/lib/index.js.map +1 -1
- package/transform/src/index.ts +75 -9
|
@@ -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
|
// }
|
|
@@ -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.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Class decorator that enables the class to be recognized as JSON.
|
|
3
3
|
*/
|
|
4
|
+
// @ts-ignore: type
|
|
4
5
|
declare function json(..._): void;
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Class decorator that enables the class to be recognized as JSON.
|
|
8
9
|
*/
|
|
10
|
+
// @ts-ignore: type
|
|
9
11
|
declare function serializable(..._): void;
|
|
10
12
|
|
|
11
13
|
/**
|
|
@@ -16,6 +18,7 @@ declare function alias(newName: string): Function;
|
|
|
16
18
|
/**
|
|
17
19
|
* Property decorator that allows omits a field, making it be ignored.
|
|
18
20
|
*/
|
|
21
|
+
// @ts-ignore: type
|
|
19
22
|
declare function omit(..._): void;
|
|
20
23
|
|
|
21
24
|
/**
|
|
@@ -26,6 +29,17 @@ declare function omitif(condition: string | ((value: any) => boolean)): Function
|
|
|
26
29
|
/**
|
|
27
30
|
* Property decorator that allows a field to be omitted when a property is null.
|
|
28
31
|
*/
|
|
32
|
+
// @ts-ignore: type
|
|
29
33
|
declare function omitnull(..._): Function;
|
|
30
34
|
|
|
31
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Method decorator that denotes a function to handle that schema's serialization.
|
|
37
|
+
*/
|
|
38
|
+
// @ts-ignore: type
|
|
39
|
+
declare function serializer(..._): any;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Method decorator that denotes a function to handle that schema's deserialization.
|
|
43
|
+
*/
|
|
44
|
+
// @ts-ignore: type
|
|
45
|
+
declare function deserializer(..._): any;
|
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
|
|
|
@@ -49,7 +53,8 @@ export namespace JSON {
|
|
|
49
53
|
* @param data T
|
|
50
54
|
* @returns string
|
|
51
55
|
*/
|
|
52
|
-
|
|
56
|
+
// @ts-ignore: inline
|
|
57
|
+
@inline export function stringify<T>(data: T, out: string | null = null): string {
|
|
53
58
|
if (isBoolean<T>()) {
|
|
54
59
|
if (out) {
|
|
55
60
|
if (<bool>data == true) {
|
|
@@ -112,6 +117,11 @@ export namespace JSON {
|
|
|
112
117
|
serializeString(changetype<string>(data));
|
|
113
118
|
return bs.out<string>();
|
|
114
119
|
// @ts-ignore: Supplied by transform
|
|
120
|
+
} else if (isDefined(data.__SERIALIZE_CUSTOM)) {
|
|
121
|
+
// @ts-ignore
|
|
122
|
+
data.__SERIALIZE_CUSTOM(changetype<usize>(data));
|
|
123
|
+
return bs.out<string>();
|
|
124
|
+
// @ts-ignore: Supplied by transform
|
|
115
125
|
} else if (isDefined(data.__SERIALIZE)) {
|
|
116
126
|
// @ts-ignore
|
|
117
127
|
data.__SERIALIZE(changetype<usize>(data));
|
|
@@ -135,6 +145,9 @@ export namespace JSON {
|
|
|
135
145
|
} else if (data instanceof JSON.Value) {
|
|
136
146
|
serializeArbitrary(data);
|
|
137
147
|
return bs.out<string>();
|
|
148
|
+
} else if (data instanceof JSON.Obj) {
|
|
149
|
+
serializeObject(data);
|
|
150
|
+
return bs.out<string>();
|
|
138
151
|
} else if (data instanceof JSON.Box) {
|
|
139
152
|
return JSON.stringify(data.value);
|
|
140
153
|
} else {
|
|
@@ -150,7 +163,8 @@ export namespace JSON {
|
|
|
150
163
|
* @param data string
|
|
151
164
|
* @returns T
|
|
152
165
|
*/
|
|
153
|
-
|
|
166
|
+
// @ts-ignore: inline
|
|
167
|
+
@inline export function parse<T>(data: string): T {
|
|
154
168
|
const dataSize = bytes(data);
|
|
155
169
|
const dataPtr = changetype<usize>(data);
|
|
156
170
|
if (isBoolean<T>()) {
|
|
@@ -171,18 +185,31 @@ export namespace JSON {
|
|
|
171
185
|
}
|
|
172
186
|
let type: nonnull<T> = changetype<nonnull<T>>(0);
|
|
173
187
|
// @ts-ignore: Defined by transform
|
|
174
|
-
if (isDefined(type.
|
|
175
|
-
const out =
|
|
188
|
+
if (isDefined(type.__DESERIALIZE_CUSTOM)) {
|
|
189
|
+
const out = changetype<nonnull<T>>(0);
|
|
190
|
+
// @ts-ignore: Defined by transform
|
|
191
|
+
if (isDefined(type.__INITIALIZE)) out.__INITIALIZE();
|
|
176
192
|
// @ts-ignore
|
|
177
|
-
|
|
193
|
+
return out.__DESERIALIZE_CUSTOM(ptrToStr(dataPtr, dataPtr + dataSize));
|
|
194
|
+
// @ts-ignore: Defined by transform
|
|
195
|
+
} else if (isDefined(type.__DESERIALIZE)) {
|
|
196
|
+
const out = __new(offsetof<nonnull<T>>(), idof<nonnull<T>>());
|
|
197
|
+
// @ts-ignore: Defined by transform
|
|
198
|
+
if (isDefined(type.__INITIALIZE)) changetype<nonnull<T>>(out).__INITIALIZE();
|
|
178
199
|
// @ts-ignore
|
|
179
|
-
return
|
|
200
|
+
return deserializeStruct<nonnull<T>>(dataPtr, dataPtr + dataSize, out);
|
|
180
201
|
} else if (type instanceof Map) {
|
|
181
202
|
// @ts-ignore
|
|
182
203
|
return deserializeMap<nonnull<T>>(dataPtr, dataPtr + dataSize);
|
|
183
204
|
} else if (type instanceof Date) {
|
|
184
205
|
// @ts-ignore
|
|
185
206
|
return deserializeDate(dataPtr, dataPtr + dataSize);
|
|
207
|
+
} else if (type instanceof JSON.Value) {
|
|
208
|
+
// @ts-ignore
|
|
209
|
+
return deserializeArbitrary(dataPtr, dataPtr + dataSize, 0);
|
|
210
|
+
} else if (type instanceof JSON.Obj) {
|
|
211
|
+
// @ts-ignore
|
|
212
|
+
return deserializeObject(dataPtr, dataPtr + dataSize, 0);
|
|
186
213
|
} else if (type instanceof JSON.Box) {
|
|
187
214
|
// @ts-ignore
|
|
188
215
|
return new JSON.Box(parseBox(data, changetype<nonnull<T>>(0).value));
|
|
@@ -257,7 +284,7 @@ export namespace JSON {
|
|
|
257
284
|
this.type = JSON.Types.U64;
|
|
258
285
|
store<T>(changetype<usize>(this), value, STORAGE);
|
|
259
286
|
} else if (value instanceof f32) {
|
|
260
|
-
this.type = JSON.Types.
|
|
287
|
+
this.type = JSON.Types.F32;
|
|
261
288
|
store<T>(changetype<usize>(this), value, STORAGE);
|
|
262
289
|
} else if (value instanceof f64) {
|
|
263
290
|
this.type = JSON.Types.F64;
|
|
@@ -271,12 +298,22 @@ export namespace JSON {
|
|
|
271
298
|
}
|
|
272
299
|
this.type = JSON.Types.Struct;
|
|
273
300
|
store<T>(changetype<usize>(this), value, STORAGE);
|
|
301
|
+
// @ts-ignore: supplied by transform
|
|
302
|
+
}else if (isDefined(value.__SERIALIZE_CUSTOM)) {
|
|
303
|
+
this.type = idof<T>() + JSON.Types.Struct;
|
|
304
|
+
// @ts-ignore
|
|
305
|
+
if (!JSON.Value.METHODS.has(idof<T>())) JSON.Value.METHODS.set(idof<T>(), value.__SERIALIZE_CUSTOM.index);
|
|
274
306
|
// @ts-ignore
|
|
307
|
+
store<usize>(changetype<usize>(this), changetype<usize>(value), STORAGE);
|
|
308
|
+
// @ts-ignore: supplied by transform
|
|
275
309
|
} else if (isDefined(value.__SERIALIZE)) {
|
|
276
310
|
this.type = idof<T>() + JSON.Types.Struct;
|
|
277
311
|
// @ts-ignore
|
|
278
312
|
if (!JSON.Value.METHODS.has(idof<T>())) JSON.Value.METHODS.set(idof<T>(), value.__SERIALIZE.index);
|
|
279
313
|
// @ts-ignore
|
|
314
|
+
store<usize>(changetype<usize>(this), changetype<usize>(value), STORAGE);
|
|
315
|
+
} else if (value instanceof JSON.Obj) {
|
|
316
|
+
this.type = JSON.Types.Object;
|
|
280
317
|
store<T>(changetype<usize>(this), value, STORAGE);
|
|
281
318
|
// @ts-ignore
|
|
282
319
|
} else if (isArray<T>() && idof<valueof<T>>() == idof<JSON.Value>()) {
|
|
@@ -308,6 +345,10 @@ export namespace JSON {
|
|
|
308
345
|
return this.get<u32>().toString();
|
|
309
346
|
case JSON.Types.U64:
|
|
310
347
|
return this.get<u64>().toString();
|
|
348
|
+
case JSON.Types.F32:
|
|
349
|
+
return this.get<f32>().toString();
|
|
350
|
+
case JSON.Types.F64:
|
|
351
|
+
return this.get<f64>().toString();
|
|
311
352
|
case JSON.Types.String:
|
|
312
353
|
return '"' + this.get<string>() + '"';
|
|
313
354
|
case JSON.Types.Bool:
|
|
@@ -329,15 +370,81 @@ export namespace JSON {
|
|
|
329
370
|
out.write("]");
|
|
330
371
|
return out.toString();
|
|
331
372
|
}
|
|
373
|
+
case JSON.Types.Object: {
|
|
374
|
+
return JSON.stringify(this.get<JSON.Obj>());
|
|
375
|
+
}
|
|
332
376
|
default: {
|
|
333
377
|
const fn = JSON.Value.METHODS.get(this.type - JSON.Types.Struct);
|
|
334
378
|
const value = this.get<usize>();
|
|
335
|
-
|
|
379
|
+
call_indirect<void>(fn, 0, value);
|
|
380
|
+
return bs.out<string>();
|
|
336
381
|
}
|
|
337
382
|
}
|
|
338
383
|
}
|
|
339
384
|
}
|
|
340
385
|
|
|
386
|
+
export class Obj {
|
|
387
|
+
// When accessing stackSize, subtract 2
|
|
388
|
+
// @ts-ignore: type
|
|
389
|
+
private stackSize: u32 = 6;
|
|
390
|
+
// @ts-ignore: type
|
|
391
|
+
private storage: Map<string, JSON.Value> = new Map<string, JSON.Value>();
|
|
392
|
+
|
|
393
|
+
constructor() { }
|
|
394
|
+
|
|
395
|
+
// @ts-ignore: decorator
|
|
396
|
+
@inline get size(): i32 {
|
|
397
|
+
return this.storage.size;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// @ts-ignore: decorator
|
|
401
|
+
@inline set<T>(key: string, value: T): void {
|
|
402
|
+
if (!this.storage.has(key)) this.stackSize += bytes(key) + 8;
|
|
403
|
+
this.storage.set(key, JSON.Value.from<T>(value));
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// @ts-ignore: decorator
|
|
407
|
+
@inline get(key: string): JSON.Value | null {
|
|
408
|
+
if (!this.storage.has(key)) return null;
|
|
409
|
+
return this.storage.get(key);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
// @ts-ignore: decorator
|
|
413
|
+
@inline has(key: string): bool {
|
|
414
|
+
return this.storage.has(key);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// @ts-ignore: decorator
|
|
418
|
+
@inline delete(key: string): bool {
|
|
419
|
+
return this.storage.delete(key);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// @ts-ignore: decorator
|
|
423
|
+
@inline keys(): string[] {
|
|
424
|
+
return this.storage.keys();
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// @ts-ignore: decorator
|
|
428
|
+
@inline values(): JSON.Value[] {
|
|
429
|
+
return this.storage.values();
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// @ts-ignore: decorator
|
|
433
|
+
@inline toString(): string {
|
|
434
|
+
return JSON.stringify(this);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// @ts-ignore: decorator
|
|
438
|
+
@inline static from<T>(value: T): JSON.Obj {
|
|
439
|
+
if (value instanceof JSON.Obj) return value;
|
|
440
|
+
const out = changetype<JSON.Obj>(__new(offsetof<JSON.Obj>(), idof<JSON.Obj>()));
|
|
441
|
+
|
|
442
|
+
if (value instanceof Map) {
|
|
443
|
+
|
|
444
|
+
}
|
|
445
|
+
return out;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
341
448
|
/**
|
|
342
449
|
* Box for primitive types
|
|
343
450
|
*/
|
|
@@ -366,7 +473,8 @@ export namespace JSON {
|
|
|
366
473
|
}
|
|
367
474
|
}
|
|
368
475
|
|
|
369
|
-
|
|
476
|
+
// @ts-ignore: inline
|
|
477
|
+
@inline export function __serialize<T>(src: T): void {
|
|
370
478
|
if (isBoolean<T>()) {
|
|
371
479
|
serializeBool(src as bool);
|
|
372
480
|
} else if (isInteger<T>() && nameof<T>() == "usize" && src == 0) {
|
|
@@ -387,9 +495,13 @@ export namespace JSON {
|
|
|
387
495
|
} else if (isString<nonnull<T>>()) {
|
|
388
496
|
serializeString(src as string);
|
|
389
497
|
// @ts-ignore: Supplied by transform
|
|
498
|
+
} else if (isDefined(src.__SERIALIZE_CUSTOM)) {
|
|
499
|
+
// @ts-ignore
|
|
500
|
+
return src.__SERIALIZE_CUSTOM(changetype<nonnull<T>>(src));
|
|
501
|
+
// @ts-ignore: Supplied by transform
|
|
390
502
|
} else if (isDefined(src.__SERIALIZE)) {
|
|
391
503
|
// @ts-ignore
|
|
392
|
-
|
|
504
|
+
serializeStruct(changetype<nonnull<T>>(src));
|
|
393
505
|
} else if (src instanceof Date) {
|
|
394
506
|
// @ts-ignore
|
|
395
507
|
serializeDate(changetype<nonnull<T>>(src));
|
|
@@ -401,18 +513,22 @@ export namespace JSON {
|
|
|
401
513
|
serializeMap(changetype<nonnull<T>>(src));
|
|
402
514
|
} else if (src instanceof JSON.Value) {
|
|
403
515
|
serializeArbitrary(src);
|
|
516
|
+
} else if (src instanceof JSON.Obj) {
|
|
517
|
+
serializeObject(src);
|
|
404
518
|
} else if (src instanceof JSON.Box) {
|
|
405
519
|
__serialize(src.value);
|
|
406
520
|
} else {
|
|
407
521
|
throw new Error(`Could not serialize provided data. Make sure to add the correct decorators to classes.`);
|
|
408
522
|
}
|
|
409
523
|
}
|
|
410
|
-
|
|
524
|
+
|
|
525
|
+
// @ts-ignore: inline
|
|
526
|
+
@inline export function __deserialize<T>(srcStart: usize, srcEnd: usize, dst: usize = 0): T {
|
|
411
527
|
if (isBoolean<T>()) {
|
|
412
528
|
// @ts-ignore: type
|
|
413
529
|
return deserializeBoolean(srcStart, srcEnd);
|
|
414
530
|
} else if (isInteger<T>()) {
|
|
415
|
-
return
|
|
531
|
+
return atoi<T>(srcStart, srcEnd);
|
|
416
532
|
} else if (isFloat<T>()) {
|
|
417
533
|
return deserializeFloat<T>(srcStart, srcEnd);
|
|
418
534
|
} else if (isString<T>()) {
|
|
@@ -423,15 +539,25 @@ export namespace JSON {
|
|
|
423
539
|
return deserializeArray<T>(srcStart, srcEnd, dst);
|
|
424
540
|
} else {
|
|
425
541
|
let type: nonnull<T> = changetype<nonnull<T>>(0);
|
|
426
|
-
// @ts-ignore:
|
|
427
|
-
if (isDefined(type.
|
|
428
|
-
|
|
542
|
+
// @ts-ignore: Defined by transform
|
|
543
|
+
if (isDefined(type.__DESERIALIZE_CUSTOM)) {
|
|
544
|
+
const out = __new(offsetof<nonnull<T>>(), idof<nonnull<T>>());
|
|
545
|
+
// @ts-ignore: Defined by transform
|
|
546
|
+
if (isDefined(type.__INITIALIZE)) changetype<nonnull<T>>(out).__INITIALIZE();
|
|
547
|
+
// @ts-ignore
|
|
548
|
+
return changetype<nonnull<T>>(out).__DESERIALIZE_CUSTOM(ptrToStr(dataPtr, dataPtr + dataSize));
|
|
549
|
+
// @ts-ignore: Defined by transform
|
|
550
|
+
} else if (isDefined(type.__DESERIALIZE)) {
|
|
551
|
+
return deserializeStruct<T>(srcStart, srcEnd, dst);
|
|
429
552
|
} else if (type instanceof Map) {
|
|
430
553
|
// @ts-ignore: type
|
|
431
554
|
return deserializeMap<T>(srcStart, srcEnd, dst);
|
|
432
555
|
} else if (type instanceof Date) {
|
|
433
556
|
// @ts-ignore: type
|
|
434
557
|
return deserializeDate(srcStart, srcEnd);
|
|
558
|
+
} else if (type instanceof JSON.Value) {
|
|
559
|
+
// @ts-ignore: type
|
|
560
|
+
return deserializeArbitrary(srcStart, srcEnd, 0);
|
|
435
561
|
} else if (type instanceof JSON.Box) {
|
|
436
562
|
// @ts-ignore: type
|
|
437
563
|
return new JSON.Box(deserializeBox(srcStart, srcEnd, dst, changetype<nonnull<T>>(0).value));
|