json-as 0.5.51 → 0.5.52
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/LICENSE +17 -17
- package/assembly/__benches__/as-json.ts +21 -5
- package/assembly/__tests__/as-json.spec.ts +10 -13
- package/assembly/src/json.ts +7 -11
- package/assembly/src/util.ts +171 -26
- package/assembly/test.ts +44 -234
- package/bench.js +1 -3
- package/package.json +7 -4
- package/transform/lib/index.js +77 -48
- package/transform/package.json +1 -1
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
MIT License
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Copyright (c) 2023 Jairus Tanaka <jairus.v.tanaka@outlook.com>
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { JSON } from "..";
|
|
2
2
|
import { backSlashCode, quoteCode } from "../src/chars";
|
|
3
|
-
import { atoi_fast, parseSciInteger, unsafeCharCodeAt } from "../src/util";
|
|
3
|
+
import { atoi_fast, parseSciInteger, snip_fast, unsafeCharCodeAt } from "../src/util";
|
|
4
4
|
import { HASH } from "util/hash";
|
|
5
5
|
|
|
6
6
|
|
|
@@ -66,15 +66,31 @@ const vec: Vec3 = {
|
|
|
66
66
|
y: 1,
|
|
67
67
|
z: 8,
|
|
68
68
|
}
|
|
69
|
-
|
|
69
|
+
|
|
70
|
+
bench("Parse Number SNIP", () => {
|
|
71
|
+
blackbox<i32>(snip_fast<i32>("12345"));
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
bench("Parse Number ATOI", () => {
|
|
75
|
+
blackbox<i32>(atoi_fast<i32>("12345"));
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
bench("Parse Number STDLIB", () => {
|
|
79
|
+
blackbox<i32>(i32.parse("12345"));
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
bench("Parse Number OLD", () => {
|
|
83
|
+
blackbox<i32>(parseSciInteger<i32>("12345"));
|
|
84
|
+
});
|
|
85
|
+
|
|
70
86
|
bench("Stringify Object (Vec3)", () => {
|
|
71
87
|
blackbox<string>(vec.__JSON_Serialize());
|
|
72
88
|
});
|
|
73
89
|
|
|
74
90
|
// TODO: Make this allocate without crashing
|
|
75
|
-
bench("Parse Object (Vec3)", () => {
|
|
91
|
+
/*bench("Parse Object (Vec3)", () => {
|
|
76
92
|
blackbox<Vec3>(vec.__JSON_Deserialize('{"x":0,"y":0,"z":0}', vec));
|
|
77
|
-
})
|
|
93
|
+
});*/
|
|
78
94
|
|
|
79
95
|
bench("Stringify Number Array", () => {
|
|
80
96
|
blackbox(JSON.stringify<i32[]>([1, 2, 3]));
|
|
@@ -87,7 +103,7 @@ bench("Parse Number Array", () => {
|
|
|
87
103
|
bench("Stringify String", () => {
|
|
88
104
|
blackbox(JSON.stringify(blackbox('Hello "World!')));
|
|
89
105
|
});
|
|
90
|
-
|
|
106
|
+
|
|
91
107
|
bench("Parse String", () => {
|
|
92
108
|
blackbox(JSON.parse<string>(blackbox('"Hello "World!"')));
|
|
93
109
|
});
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { JSON } from "..";
|
|
2
|
-
function canSerde<T>(data: T): void {
|
|
3
|
-
|
|
4
|
-
const deserialized = JSON.stringify<T>(JSON.parse<T>(
|
|
5
|
-
expect(
|
|
2
|
+
function canSerde<T>(data: T, toBe: string = ""): void {
|
|
3
|
+
if (!toBe) toBe = JSON.stringify<T>(data);
|
|
4
|
+
const deserialized = JSON.stringify<T>(JSON.parse<T>(JSON.stringify(data)));
|
|
5
|
+
expect(deserialized).toBe(toBe);
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
// @ts-ignore
|
|
@@ -53,16 +53,13 @@ describe("Ser/de Numbers", () => {
|
|
|
53
53
|
});
|
|
54
54
|
|
|
55
55
|
it("should ser/de floats", () => {
|
|
56
|
-
canSerde<f64>(7.23);
|
|
57
|
-
canSerde<f64>(10e2);
|
|
58
|
-
canSerde<f64>(10e2);
|
|
56
|
+
canSerde<f64>(7.23, "7.23");
|
|
57
|
+
canSerde<f64>(10e2, "1000.0");
|
|
59
58
|
|
|
60
|
-
canSerde<f64>(123456e-5);
|
|
59
|
+
canSerde<f64>(123456e-5, "1.23456");
|
|
61
60
|
|
|
62
|
-
canSerde<f64>(
|
|
63
|
-
|
|
64
|
-
canSerde<f64>(0.0);
|
|
65
|
-
canSerde<f64>(7.23);
|
|
61
|
+
canSerde<f64>(0.0, "0.0");
|
|
62
|
+
canSerde<f64>(7.23, "7.23");
|
|
66
63
|
});
|
|
67
64
|
|
|
68
65
|
it("should ser/de booleans", () => {
|
|
@@ -161,6 +158,6 @@ describe("Ser/de Objects", () => {
|
|
|
161
158
|
z: 8.3,
|
|
162
159
|
},
|
|
163
160
|
isVerified: true,
|
|
164
|
-
});
|
|
161
|
+
}, '{"firstName":"Emmet","lastName":"West","lastActive":[8,27,2022],"age":23,"pos":{"x":3.4,"y":1.2,"z":8.3},"isVerified":true}');
|
|
165
162
|
});
|
|
166
163
|
});
|
package/assembly/src/json.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { StringSink } from "as-string-sink/assembly";
|
|
2
|
-
import { isSpace
|
|
2
|
+
import { isSpace } from "util/string";
|
|
3
3
|
import {
|
|
4
4
|
backSlashCode,
|
|
5
5
|
commaCode,
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
uCode,
|
|
22
22
|
emptyArrayWord,
|
|
23
23
|
} from "./chars";
|
|
24
|
-
import {
|
|
24
|
+
import { snip_fast, unsafeCharCodeAt } from "./util";
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* JSON Encoder/Decoder for AssemblyScript
|
|
@@ -184,7 +184,7 @@ export namespace JSON {
|
|
|
184
184
|
} else if (
|
|
185
185
|
char === 117 &&
|
|
186
186
|
load<u64>(changetype<usize>(data) + <usize>((i + 1) << 1)) ===
|
|
187
|
-
|
|
187
|
+
27584753879220272
|
|
188
188
|
) {
|
|
189
189
|
result += "\u000b";
|
|
190
190
|
i += 4;
|
|
@@ -359,7 +359,7 @@ export namespace JSON {
|
|
|
359
359
|
if (
|
|
360
360
|
char === 117 &&
|
|
361
361
|
load<u64>(changetype<usize>(data) + <usize>((i + 1) << 1)) ===
|
|
362
|
-
|
|
362
|
+
27584753879220272
|
|
363
363
|
) {
|
|
364
364
|
result += "\u000b";
|
|
365
365
|
i += 4;
|
|
@@ -385,12 +385,10 @@ export namespace JSON {
|
|
|
385
385
|
}
|
|
386
386
|
|
|
387
387
|
// @ts-ignore
|
|
388
|
-
@inline export function parseNumber<
|
|
389
|
-
T
|
|
390
|
-
>(data: string): T {
|
|
388
|
+
@inline export function parseNumber<T>(data: string): T {
|
|
391
389
|
if (isInteger<T>()) {
|
|
392
390
|
// @ts-ignore
|
|
393
|
-
return
|
|
391
|
+
return snip_fast<T>(data);
|
|
394
392
|
}
|
|
395
393
|
// @ts-ignore
|
|
396
394
|
const type: T = 0;
|
|
@@ -401,9 +399,7 @@ export namespace JSON {
|
|
|
401
399
|
}
|
|
402
400
|
|
|
403
401
|
// @ts-ignore
|
|
404
|
-
@inline function parseObject<
|
|
405
|
-
T
|
|
406
|
-
>(data: string): T {
|
|
402
|
+
@inline function parseObject<T>(data: string): T {
|
|
407
403
|
let schema: nonnull<T> = changetype<nonnull<T>>(
|
|
408
404
|
__new(offsetof<nonnull<T>>(), idof<nonnull<T>>())
|
|
409
405
|
);
|
package/assembly/src/util.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { StringSink } from "as-string-sink/assembly";
|
|
2
|
-
import { isSpace } from "util/string";
|
|
2
|
+
import { CharCode, isSpace } from "util/string";
|
|
3
3
|
import { backSlashCode, quoteCode } from "./chars";
|
|
4
4
|
|
|
5
5
|
// @ts-ignore
|
|
@@ -79,6 +79,159 @@ export function getArrayDepth<T>(depth: i32 = 1): i32 {
|
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
+
// Scientific Notation Integer Parsing - SNIP
|
|
83
|
+
// This is absolutely the fastest algorithm I could think of while adding full support for Scientific Notation
|
|
84
|
+
// Loads 32 bits and retrieves the high/low bits
|
|
85
|
+
// Here are some benchmarks
|
|
86
|
+
// Parsing: "12345"
|
|
87
|
+
// Results are spread over 5000ms
|
|
88
|
+
// SNIP: 207M iterations
|
|
89
|
+
// ATOI: 222M iterations
|
|
90
|
+
// STD (parseInt): 162M iterations
|
|
91
|
+
export function snip_fast<T extends number>(str: string, offset: u32 = 0): T {
|
|
92
|
+
let ch: u32 = load<u32>(changetype<usize>(str));
|
|
93
|
+
const h = ch & 0xFFFF;
|
|
94
|
+
if (h === 48) return 0 as T;
|
|
95
|
+
const isNegative = h === 45; // Check if the number is negative
|
|
96
|
+
let val: T = 0 as T;
|
|
97
|
+
const len = u32(str.length << 1);
|
|
98
|
+
if (isNegative) {
|
|
99
|
+
if ((ch >> 16) === 48) return -0 as T;
|
|
100
|
+
offset += 2;
|
|
101
|
+
if (len >= 4) {
|
|
102
|
+
// 32-bit route
|
|
103
|
+
for (; offset < (len - 3); offset += 4) {
|
|
104
|
+
ch = load<u32>(changetype<usize>(str) + <usize>offset);
|
|
105
|
+
const low = ch & 0xFFFF;
|
|
106
|
+
const high = ch >> 16;
|
|
107
|
+
// 9 is 57. The highest group of two numbers is 114, so if a e or an E is included, this will fire.
|
|
108
|
+
if (low > 57) {
|
|
109
|
+
// The first char (f) is E or e
|
|
110
|
+
// We push the offset up by two and apply the notation.
|
|
111
|
+
offset += 2;
|
|
112
|
+
let exp: i32 = atoi_fast<i32>(str, offset);
|
|
113
|
+
if (exp < 0) {
|
|
114
|
+
for (let i = 0; i < exp; i++) {
|
|
115
|
+
val = (val / 10) as T;
|
|
116
|
+
}
|
|
117
|
+
} else {
|
|
118
|
+
for (let i = 0; i < exp; i++) {
|
|
119
|
+
val = (val * 10) as T;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return -val as T;
|
|
123
|
+
} else if (high > 57) {
|
|
124
|
+
// The first char (f) is E or e
|
|
125
|
+
// We push the offset up by two and apply the notation.
|
|
126
|
+
offset += 4;
|
|
127
|
+
let exp: i32 = atoi_fast<i32>(str, offset);
|
|
128
|
+
if (exp < 0) {
|
|
129
|
+
for (let i = 0; i < exp; i++) {
|
|
130
|
+
val = (val / 10) as T;
|
|
131
|
+
}
|
|
132
|
+
} else {
|
|
133
|
+
for (let i = 0; i < exp; i++) {
|
|
134
|
+
val = (val * 10) as T;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return -val as T;
|
|
138
|
+
} else {
|
|
139
|
+
val = (val * 100 + ((low - 48) * 10) + (high - 48)) as T;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// Finish up the remainder with 16 bits.
|
|
144
|
+
for (; offset < len; offset += 2) {
|
|
145
|
+
ch = load<u16>(changetype<usize>(str) + <usize>offset);
|
|
146
|
+
// 9 is 57. E and e are larger. Assumes valid JSON.
|
|
147
|
+
if (ch > 57) {
|
|
148
|
+
// The first char (f) is E or e
|
|
149
|
+
// We push the offset up by two and apply the notation.
|
|
150
|
+
offset += 2;
|
|
151
|
+
let exp: i32 = atoi_fast<i32>(str, offset);
|
|
152
|
+
if (exp < 0) {
|
|
153
|
+
for (let i = 0; i > exp; i--) {
|
|
154
|
+
val = (val / 10) as T;
|
|
155
|
+
}
|
|
156
|
+
} else {
|
|
157
|
+
for (let i = 0; i < exp; i++) {
|
|
158
|
+
val = (val * 10) as T;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return -val as T;
|
|
162
|
+
} else {
|
|
163
|
+
val = (val * 10) + (ch - 48) as T;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return -val as T;
|
|
167
|
+
} else {
|
|
168
|
+
if (len >= 4) {
|
|
169
|
+
// Duplet 16 bit lane load
|
|
170
|
+
for (; offset < (len - 3); offset += 4) {
|
|
171
|
+
ch = load<u32>(changetype<usize>(str) + <usize>offset);
|
|
172
|
+
const low = ch & 0xFFFF;
|
|
173
|
+
const high = ch >> 16;
|
|
174
|
+
// 9 is 57. The highest group of two numbers is 114, so if a e or an E is included, this will fire.
|
|
175
|
+
if (low > 57) {
|
|
176
|
+
// The first char (f) is E or e
|
|
177
|
+
// We push the offset up by two and apply the notation.
|
|
178
|
+
offset += 2;
|
|
179
|
+
let exp: i32 = atoi_fast<i32>(str, offset);
|
|
180
|
+
if (exp < 0) {
|
|
181
|
+
for (let i = 0; i < exp; i++) {
|
|
182
|
+
val = (val / 10) as T;
|
|
183
|
+
}
|
|
184
|
+
} else {
|
|
185
|
+
for (let i = 0; i < exp; i++) {
|
|
186
|
+
val = (val * 10) as T;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return val as T;
|
|
190
|
+
} else if (high > 57) {
|
|
191
|
+
offset += 4;
|
|
192
|
+
let exp: i32 = atoi_fast<i32>(str, offset);
|
|
193
|
+
if (exp < 0) {
|
|
194
|
+
for (let i = 0; i < exp; i++) {
|
|
195
|
+
val = (val / 10) as T;
|
|
196
|
+
}
|
|
197
|
+
} else {
|
|
198
|
+
for (let i = 0; i < exp; i++) {
|
|
199
|
+
val = (val * 10) as T;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return val as T;
|
|
203
|
+
} else {
|
|
204
|
+
// Optimized with multiplications and shifts.
|
|
205
|
+
val = (val * 100 + ((low - 48) * 10) + (high - 48)) as T;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
// Cover the remaining numbers with 16 bit loads.
|
|
210
|
+
for (; offset < len; offset += 2) {
|
|
211
|
+
ch = load<u16>(changetype<usize>(str) + <usize>offset);
|
|
212
|
+
// 0's char is 48 and 9 is 57. Anything above this range would signify an exponent (e or E).
|
|
213
|
+
// e is 101 and E is 69.
|
|
214
|
+
if (ch > 57) {
|
|
215
|
+
offset += 2;
|
|
216
|
+
let exp: i32 = atoi_fast<i32>(str, offset);
|
|
217
|
+
if (exp < 0) {
|
|
218
|
+
for (let i = 0; i > exp; i--) {
|
|
219
|
+
val = (val / 10) as T;
|
|
220
|
+
}
|
|
221
|
+
} else {
|
|
222
|
+
for (let i = 0; i < exp; i++) {
|
|
223
|
+
val = (val * 10) as T;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return val as T;
|
|
227
|
+
} else {
|
|
228
|
+
val = (val * 10) + (ch - 48) as T;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return val as T;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
82
235
|
/**
|
|
83
236
|
* Implementation of ATOI. Can be much much faster with SIMD.
|
|
84
237
|
* Benchmark: 40-46m ops/s
|
|
@@ -86,33 +239,25 @@ export function getArrayDepth<T>(depth: i32 = 1): i32 {
|
|
|
86
239
|
|
|
87
240
|
// @ts-ignore
|
|
88
241
|
@inline
|
|
89
|
-
export function atoi_fast<T extends number>(str: string, offset:
|
|
242
|
+
export function atoi_fast<T extends number>(str: string, offset: u32 = 0): T {
|
|
90
243
|
// @ts-ignore
|
|
91
244
|
let val: T = 0;
|
|
92
|
-
|
|
93
|
-
if (
|
|
245
|
+
const len = u32(str.length << 1);
|
|
246
|
+
if (load<u16>(changetype<usize>(str) + <usize>offset) === 45) {
|
|
94
247
|
offset += 2;
|
|
95
|
-
for (; offset <
|
|
248
|
+
for (; offset < len; offset += 2) {
|
|
96
249
|
// @ts-ignore
|
|
97
|
-
val =
|
|
98
|
-
(val << 1) +
|
|
99
|
-
(val << 3) +
|
|
100
|
-
(load<u16>(changetype<usize>(str) + <usize>offset) - 48);
|
|
101
|
-
// We use load because in this case, there is no need to have bounds-checking
|
|
250
|
+
val = (val << 1) + (val << 3) + (load<u16>(changetype<usize>(str) + <usize>offset) - 48);
|
|
102
251
|
}
|
|
103
252
|
// @ts-ignore
|
|
104
|
-
|
|
253
|
+
return -val;
|
|
105
254
|
} else {
|
|
106
|
-
for (; offset <
|
|
255
|
+
for (; offset < len; offset += 2) {
|
|
107
256
|
// @ts-ignore
|
|
108
|
-
val =
|
|
109
|
-
(val << 1) +
|
|
110
|
-
(val << 3) +
|
|
111
|
-
(load<u16>(changetype<usize>(str) + <usize>offset) - 48);
|
|
112
|
-
// We use load because in this case, there is no need to have bounds-checking
|
|
257
|
+
val = (val << 1) + (val << 3) + (load<u16>(changetype<usize>(str) + <usize>offset) - 48);
|
|
113
258
|
}
|
|
259
|
+
return val;
|
|
114
260
|
}
|
|
115
|
-
return val;
|
|
116
261
|
}
|
|
117
262
|
|
|
118
263
|
/**
|
|
@@ -164,15 +309,15 @@ export function parseSciInteger<T extends number>(str: string): T {
|
|
|
164
309
|
function sciNote<T extends number>(num: T): T {
|
|
165
310
|
let res = 1;
|
|
166
311
|
// @ts-ignore
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
}
|
|
171
|
-
} else {
|
|
172
|
-
for (let i: T = 0; i < num; i++) {
|
|
173
|
-
res /= 10;
|
|
174
|
-
}
|
|
312
|
+
if (num > 0) {
|
|
313
|
+
for (let i: T = 0; i < num; i++) {
|
|
314
|
+
res *= 10;
|
|
175
315
|
}
|
|
316
|
+
} else {
|
|
317
|
+
for (let i: T = 0; i < num; i++) {
|
|
318
|
+
res /= 10;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
176
321
|
// @ts-ignore
|
|
177
322
|
return res;
|
|
178
323
|
}
|
package/assembly/test.ts
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { atoi_fast, parseSciInteger } from "./src/util";
|
|
3
|
-
import * as a from "util/number";
|
|
4
|
-
// "st\"ring\" w\"\"ith quotes\""
|
|
1
|
+
import { snip_fast } from "./src/util";
|
|
5
2
|
|
|
3
|
+
import { JSON } from "./src/json";
|
|
6
4
|
@json
|
|
7
5
|
class Vec3 {
|
|
8
|
-
x!:
|
|
9
|
-
y!:
|
|
10
|
-
z!:
|
|
6
|
+
x!: f64;
|
|
7
|
+
y!: f64;
|
|
8
|
+
z!: f64;
|
|
11
9
|
}
|
|
12
10
|
|
|
13
11
|
@json
|
|
@@ -39,6 +37,29 @@ const vec: Vec3 = {
|
|
|
39
37
|
z: 8,
|
|
40
38
|
};
|
|
41
39
|
|
|
40
|
+
function canSerde<T>(data: T, toBe: string = ""): void {
|
|
41
|
+
if (!toBe) toBe = JSON.stringify<T>(data);
|
|
42
|
+
const deserialized = JSON.stringify<T>(JSON.parse<T>(JSON.stringify(data)));
|
|
43
|
+
if (deserialized != toBe) {
|
|
44
|
+
console.log("Expected: " + toBe);
|
|
45
|
+
console.log("Actual: " + deserialized);
|
|
46
|
+
} else {
|
|
47
|
+
console.log("Passed Test")
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
canSerde<Player>({
|
|
52
|
+
firstName: "Emmet",
|
|
53
|
+
lastName: "West",
|
|
54
|
+
lastActive: [8, 27, 2022],
|
|
55
|
+
age: 23,
|
|
56
|
+
pos: {
|
|
57
|
+
x: 3.4,
|
|
58
|
+
y: 1.2,
|
|
59
|
+
z: 8.3,
|
|
60
|
+
},
|
|
61
|
+
isVerified: true,
|
|
62
|
+
}, '{"firstName":"Emmet","lastName":"West","lastActive":[8,27,2022],"age":23,"pos":{"x":3.4,"y":1.2,"z":8.3},"isVerified":true}');
|
|
42
63
|
const serializedPlayer = JSON.stringify<Player>(player);
|
|
43
64
|
console.log(serializedPlayer);
|
|
44
65
|
const parsedPlayer = JSON.parse<Player>(serializedPlayer);
|
|
@@ -50,230 +71,19 @@ console.log(serializedVec3);
|
|
|
50
71
|
const parsedVec3 = JSON.parse<Vec3>(serializedVec3);
|
|
51
72
|
console.log(JSON.stringify(parsedVec3));
|
|
52
73
|
|
|
53
|
-
console.log("
|
|
54
|
-
console.log("
|
|
55
|
-
console.log("
|
|
56
|
-
console.log("
|
|
57
|
-
console.log("
|
|
58
|
-
console.log("
|
|
59
|
-
console.log(
|
|
60
|
-
console.log(
|
|
61
|
-
|
|
62
|
-
console.log(
|
|
63
|
-
console.log(
|
|
64
|
-
console.log(
|
|
65
|
-
console.log(
|
|
66
|
-
console.log(
|
|
67
|
-
console.log(
|
|
68
|
-
console.log(
|
|
69
|
-
console.log(JSON.stringify('string with colon : comma , brace [ ] bracket { } and quote " and other quote "'));
|
|
70
|
-
/*console.log(JSON.stringify(JSON.parse<string[]>(JSON.stringify([
|
|
71
|
-
"abcdefg",
|
|
72
|
-
'st"ring" w""ith quotes"',
|
|
73
|
-
'string \t\r"with ran\tdom spa\nces and \nnewlines\n\n\n',
|
|
74
|
-
'string with colon : comma , brace [ ] bracket { } and quote " and other quote "',
|
|
75
|
-
]))));
|
|
76
|
-
console.log('["abcdefg","st\"ring\" w\"\"ith quotes\"","string \t\r\"with ran\tdom spa\nces and \nnewlines\n\n\n","string with colon : comma , brace [ ] bracket { } and quote \" and other quote \""]');/*
|
|
77
|
-
console.log(
|
|
78
|
-
JSON.stringify(
|
|
79
|
-
JSON.parse<string[]>(
|
|
80
|
-
JSON.stringify([
|
|
81
|
-
"abcdefg",
|
|
82
|
-
'st"ring" w""ith quotes"',
|
|
83
|
-
'string \t\r"with ran\tdom spa\nces and \nnewlines\n\n\n',
|
|
84
|
-
'string with colon : comma , brace [ ] bracket { } and quote " and other quote "',
|
|
85
|
-
])
|
|
86
|
-
)
|
|
87
|
-
)
|
|
88
|
-
);
|
|
89
|
-
/*
|
|
90
|
-
const str = changetype<string>(new ArrayBuffer(6));
|
|
91
|
-
console.log("istr:");
|
|
92
|
-
console.log("123 - " + istr8(123));
|
|
93
|
-
console.log("32 - " + istr8(32));
|
|
94
|
-
console.log("3 - " + istr8(3));
|
|
95
|
-
|
|
96
|
-
console.log(Uint8Array.wrap(changetype<ArrayBuffer>(istr8(12))).join(" "));
|
|
97
|
-
console.log(load<u32>(changetype<usize>(istr8(12))).toString());
|
|
98
|
-
@inline function istr8<
|
|
99
|
-
T extends number
|
|
100
|
-
>(int: T): string {
|
|
101
|
-
if (int >= 100) {
|
|
102
|
-
const str = changetype<string>(__new(6, idof<String>()));
|
|
103
|
-
store<u16>(changetype<usize>(str), ((int / 100) % 10) + 48);
|
|
104
|
-
store<u16>(changetype<usize>(str), ((int / 10) % 10) + 48, 2);
|
|
105
|
-
store<u16>(changetype<usize>(str), (int % 10) + 48, 4);
|
|
106
|
-
return str;
|
|
107
|
-
} else if (int >= 10) {
|
|
108
|
-
const str = changetype<string>(__new(4, idof<String>()));
|
|
109
|
-
store<u16>(changetype<usize>(str), ((int / 10) % 10) + 48);
|
|
110
|
-
store<u16>(changetype<usize>(str), (int % 10) + 48, 2);
|
|
111
|
-
return str;
|
|
112
|
-
} else {
|
|
113
|
-
const str = changetype<string>(__new(2, idof<String>()));
|
|
114
|
-
store<u16>(changetype<usize>(str), (int % 10) + 48);
|
|
115
|
-
return str;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export function istr16<T extends number>(int: T): string {
|
|
120
|
-
if (int >= 10_000) {
|
|
121
|
-
const str = changetype<string>(__new(10, idof<String>()));
|
|
122
|
-
store<u16>(changetype<usize>(str), ((int / 10000) % 10) + 48);
|
|
123
|
-
store<u16>(changetype<usize>(str), ((int / 1000) % 10) + 48, 2);
|
|
124
|
-
store<u16>(changetype<usize>(str), ((int / 100) % 10) + 48, 4);
|
|
125
|
-
store<u16>(changetype<usize>(str), ((int / 10) % 10) + 48, 6);
|
|
126
|
-
store<u16>(changetype<usize>(str), (int % 10) + 48, 8);
|
|
127
|
-
return str;
|
|
128
|
-
} else if (int >= 1_000) {
|
|
129
|
-
const str = changetype<string>(__new(8, idof<String>()));
|
|
130
|
-
store<u16>(changetype<usize>(str), ((int / 1000) % 10) + 48);
|
|
131
|
-
store<u16>(changetype<usize>(str), ((int / 100) % 10) + 48, 2);
|
|
132
|
-
store<u16>(changetype<usize>(str), ((int / 10) % 10) + 48, 4);
|
|
133
|
-
store<u16>(changetype<usize>(str), (int % 10) + 48, 6);
|
|
134
|
-
return str;
|
|
135
|
-
} else if (int >= 100) {
|
|
136
|
-
const str = changetype<string>(__new(6, idof<String>()));
|
|
137
|
-
store<u16>(changetype<usize>(str), ((int / 100) % 10) + 48);
|
|
138
|
-
store<u16>(changetype<usize>(str), ((int / 10) % 10) + 48, 2);
|
|
139
|
-
store<u16>(changetype<usize>(str), (int % 10) + 48, 4);
|
|
140
|
-
return str;
|
|
141
|
-
} else if (int >= 10) {
|
|
142
|
-
const str = changetype<string>(__new(4, idof<String>()));
|
|
143
|
-
store<u16>(changetype<usize>(str), ((int / 10) % 10) + 48);
|
|
144
|
-
store<u16>(changetype<usize>(str), (int % 10) + 48, 2);
|
|
145
|
-
return str;
|
|
146
|
-
} else {
|
|
147
|
-
const str = changetype<string>(__new(2, idof<String>()));
|
|
148
|
-
store<u16>(changetype<usize>(str), (int % 10) + 48);
|
|
149
|
-
return str;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
export function istr32<T extends number>(int: T): string {
|
|
154
|
-
if (int >= 1_000_000_000) {
|
|
155
|
-
const str = changetype<string>(__new(22, idof<String>()));
|
|
156
|
-
store<u16>(changetype<usize>(str), ((int / 10000000000) % 10) + 48);
|
|
157
|
-
store<u16>(changetype<usize>(str), ((int / 1000000000) % 10) + 48, 2);
|
|
158
|
-
store<u16>(changetype<usize>(str), ((int / 100000000) % 10) + 48, 4);
|
|
159
|
-
store<u16>(changetype<usize>(str), ((int / 10000000) % 10) + 48, 6);
|
|
160
|
-
store<u16>(changetype<usize>(str), ((int / 1000000) % 10) + 48, 8);
|
|
161
|
-
store<u16>(changetype<usize>(str), ((int / 100000) % 10) + 48, 10);
|
|
162
|
-
store<u16>(changetype<usize>(str), ((int / 10000) % 10) + 48, 12);
|
|
163
|
-
store<u16>(changetype<usize>(str), ((int / 1000) % 10) + 48, 14);
|
|
164
|
-
store<u16>(changetype<usize>(str), ((int / 100) % 10) + 48, 16);
|
|
165
|
-
store<u16>(changetype<usize>(str), ((int / 10) % 10) + 48, 18);
|
|
166
|
-
store<u16>(changetype<usize>(str), (int % 10) + 48, 20);
|
|
167
|
-
return str;
|
|
168
|
-
} else if (int >= 100_000_000) {
|
|
169
|
-
const str = changetype<string>(__new(20, idof<String>()));
|
|
170
|
-
store<u16>(changetype<usize>(str), ((int / 1000000000) % 10) + 48);
|
|
171
|
-
store<u16>(changetype<usize>(str), ((int / 100000000) % 10) + 48, 2);
|
|
172
|
-
store<u16>(changetype<usize>(str), ((int / 10000000) % 10) + 48, 4);
|
|
173
|
-
store<u16>(changetype<usize>(str), ((int / 1000000) % 10) + 48, 6);
|
|
174
|
-
store<u16>(changetype<usize>(str), ((int / 100000) % 10) + 48, 8);
|
|
175
|
-
store<u16>(changetype<usize>(str), ((int / 10000) % 10) + 48, 10);
|
|
176
|
-
store<u16>(changetype<usize>(str), ((int / 1000) % 10) + 48, 12);
|
|
177
|
-
store<u16>(changetype<usize>(str), ((int / 100) % 10) + 48, 14);
|
|
178
|
-
store<u16>(changetype<usize>(str), ((int / 10) % 10) + 48, 16);
|
|
179
|
-
store<u16>(changetype<usize>(str), (int % 10) + 48, 18);
|
|
180
|
-
return str;
|
|
181
|
-
} else if (int >= 10_000_000) {
|
|
182
|
-
const str = changetype<string>(__new(18, idof<String>()));
|
|
183
|
-
store<u16>(changetype<usize>(str), ((int / 100000000) % 10) + 48);
|
|
184
|
-
store<u16>(changetype<usize>(str), ((int / 10000000) % 10) + 48, 2);
|
|
185
|
-
store<u16>(changetype<usize>(str), ((int / 1000000) % 10) + 48, 4);
|
|
186
|
-
store<u16>(changetype<usize>(str), ((int / 100000) % 10) + 48, 6);
|
|
187
|
-
store<u16>(changetype<usize>(str), ((int / 10000) % 10) + 48, 8);
|
|
188
|
-
store<u16>(changetype<usize>(str), ((int / 1000) % 10) + 48, 10);
|
|
189
|
-
store<u16>(changetype<usize>(str), ((int / 100) % 10) + 48, 12);
|
|
190
|
-
store<u16>(changetype<usize>(str), ((int / 10) % 10) + 48, 14);
|
|
191
|
-
store<u16>(changetype<usize>(str), (int % 10) + 48, 16);
|
|
192
|
-
return str;
|
|
193
|
-
} else if (int >= 10_000_000) {
|
|
194
|
-
const str = changetype<string>(__new(16, idof<String>()));
|
|
195
|
-
store<u16>(changetype<usize>(str), ((int / 10000000) % 10) + 48);
|
|
196
|
-
store<u16>(changetype<usize>(str), ((int / 1000000) % 10) + 48, 2);
|
|
197
|
-
store<u16>(changetype<usize>(str), ((int / 100000) % 10) + 48, 4);
|
|
198
|
-
store<u16>(changetype<usize>(str), ((int / 10000) % 10) + 48, 6);
|
|
199
|
-
store<u16>(changetype<usize>(str), ((int / 1000) % 10) + 48, 8);
|
|
200
|
-
store<u16>(changetype<usize>(str), ((int / 100) % 10) + 48, 10);
|
|
201
|
-
store<u16>(changetype<usize>(str), ((int / 10) % 10) + 48, 12);
|
|
202
|
-
store<u16>(changetype<usize>(str), (int % 10) + 48, 14);
|
|
203
|
-
return str;
|
|
204
|
-
} else if (int >= 1_000_000) {
|
|
205
|
-
const str = changetype<string>(__new(14, idof<String>()));
|
|
206
|
-
store<u16>(changetype<usize>(str), ((int / 1000000) % 10) + 48);
|
|
207
|
-
store<u16>(changetype<usize>(str), ((int / 100000) % 10) + 48, 2);
|
|
208
|
-
store<u16>(changetype<usize>(str), ((int / 10000) % 10) + 48, 4);
|
|
209
|
-
store<u16>(changetype<usize>(str), ((int / 1000) % 10) + 48, 6);
|
|
210
|
-
store<u16>(changetype<usize>(str), ((int / 100) % 10) + 48, 8);
|
|
211
|
-
store<u16>(changetype<usize>(str), ((int / 10) % 10) + 48, 10);
|
|
212
|
-
store<u16>(changetype<usize>(str), (int % 10) + 48, 12);
|
|
213
|
-
return str;
|
|
214
|
-
} else if (int >= 100_000) {
|
|
215
|
-
const str = changetype<string>(__new(12, idof<String>()));
|
|
216
|
-
store<u16>(changetype<usize>(str), ((int / 100000) % 10) + 48);
|
|
217
|
-
store<u16>(changetype<usize>(str), ((int / 10000) % 10) + 48, 2);
|
|
218
|
-
store<u16>(changetype<usize>(str), ((int / 1000) % 10) + 48, 4);
|
|
219
|
-
store<u16>(changetype<usize>(str), ((int / 100) % 10) + 48, 6);
|
|
220
|
-
store<u16>(changetype<usize>(str), ((int / 10) % 10) + 48, 8);
|
|
221
|
-
store<u16>(changetype<usize>(str), (int % 10) + 48, 10);
|
|
222
|
-
return str;
|
|
223
|
-
} else if (int >= 10_000) {
|
|
224
|
-
const str = changetype<string>(__new(10, idof<String>()));
|
|
225
|
-
store<u16>(changetype<usize>(str), ((int / 10000) % 10) + 48);
|
|
226
|
-
store<u16>(changetype<usize>(str), ((int / 1000) % 10) + 48, 2);
|
|
227
|
-
store<u16>(changetype<usize>(str), ((int / 100) % 10) + 48, 4);
|
|
228
|
-
store<u16>(changetype<usize>(str), ((int / 10) % 10) + 48, 6);
|
|
229
|
-
store<u16>(changetype<usize>(str), (int % 10) + 48, 8);
|
|
230
|
-
return str;
|
|
231
|
-
} else if (int >= 1_000) {
|
|
232
|
-
const str = changetype<string>(__new(8, idof<String>()));
|
|
233
|
-
store<u16>(changetype<usize>(str), ((int / 1000) % 10) + 48);
|
|
234
|
-
store<u16>(changetype<usize>(str), ((int / 100) % 10) + 48, 2);
|
|
235
|
-
store<u16>(changetype<usize>(str), ((int / 10) % 10) + 48, 4);
|
|
236
|
-
store<u16>(changetype<usize>(str), (int % 10) + 48, 6);
|
|
237
|
-
return str;
|
|
238
|
-
} else if (int >= 100) {
|
|
239
|
-
const str = changetype<string>(__new(6, idof<String>()));
|
|
240
|
-
store<u16>(changetype<usize>(str), ((int / 100) % 10) + 48);
|
|
241
|
-
store<u16>(changetype<usize>(str), ((int / 10) % 10) + 48, 2);
|
|
242
|
-
store<u16>(changetype<usize>(str), (int % 10) + 48, 4);
|
|
243
|
-
return str;
|
|
244
|
-
} else if (int >= 10) {
|
|
245
|
-
const str = changetype<string>(__new(4, idof<String>()));
|
|
246
|
-
store<u16>(changetype<usize>(str), ((int / 10) % 10) + 48);
|
|
247
|
-
store<u16>(changetype<usize>(str), (int % 10) + 48, 2);
|
|
248
|
-
return str;
|
|
249
|
-
} else {
|
|
250
|
-
const str = changetype<string>(__new(2, idof<String>()));
|
|
251
|
-
store<u16>(changetype<usize>(str), (int % 10) + 48);
|
|
252
|
-
return str;
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
export function istr64<T extends number>(int: T): string {
|
|
257
|
-
const val = new ArrayBuffer(6);
|
|
258
|
-
store<u16>(changetype<usize>(val), (int % 10) + 48, 4);
|
|
259
|
-
if ((int = (int / 10) as T) > 0)
|
|
260
|
-
store<u16>(changetype<usize>(val), (int % 10) + 48, 2);
|
|
261
|
-
else return changetype<string>(val);
|
|
262
|
-
if ((int = (int / 10) as T) > 0)
|
|
263
|
-
store<u16>(changetype<usize>(val), (int % 10) + 48);
|
|
264
|
-
return changetype<string>(val);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
// 0 = 48
|
|
268
|
-
// 1 = 49
|
|
269
|
-
// 2 = 50
|
|
270
|
-
// 3 = 51
|
|
271
|
-
// 4 = 52
|
|
272
|
-
// 5 = 53
|
|
273
|
-
// 6 = 54
|
|
274
|
-
// 7 = 55
|
|
275
|
-
// 8 = 56
|
|
276
|
-
// 9 = 57
|
|
277
|
-
|
|
278
|
-
console.log(JSON.stringify("h\\i from gray\bson"));
|
|
279
|
-
*/
|
|
74
|
+
console.log("snip:");
|
|
75
|
+
console.log("1234 <-> " + snip_fast<i32>("1234").toString());
|
|
76
|
+
console.log("-1234 <-> " + snip_fast<i32>("-1234").toString());
|
|
77
|
+
console.log("12340 <-> " + snip_fast<i32>("1234e1").toString());
|
|
78
|
+
console.log("123400 <-> " + snip_fast<i32>("1234e2").toString());
|
|
79
|
+
console.log("1234000 <-> " + snip_fast<i32>("1234e3").toString());
|
|
80
|
+
console.log("12 <-> " + snip_fast<i32>("123e-1").toString());
|
|
81
|
+
console.log("123 <-> " + snip_fast<i32>("123").toString());
|
|
82
|
+
console.log("-12340 <-> " + snip_fast<i32>("-1234e1").toString());
|
|
83
|
+
console.log("-1234500 <-> " + snip_fast<i32>("-12345e2").toString());
|
|
84
|
+
console.log("-123456000 <-> " + snip_fast<i32>("-123456e3").toString());
|
|
85
|
+
console.log("-12 <-> " + snip_fast<i32>("-123e-1").toString());
|
|
86
|
+
console.log("-123 <-> " + snip_fast<i32>("-123").toString());
|
|
87
|
+
console.log(snip_fast<i32>("1000").toString());
|
|
88
|
+
console.log(snip_fast<i32>("-1000").toString());
|
|
89
|
+
console.log(JSON.stringify([[1, 2, 3, 4, 5], [5, 4, 3, 2, 1]]));
|
package/bench.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { Bench } from "tinybench";
|
|
2
2
|
// Trying a new benchmarking lib.
|
|
3
|
-
// It seems to not warmup long at all, so its probably bad.
|
|
4
|
-
// benchmark will probably be best here
|
|
5
3
|
|
|
6
4
|
// JavaScript Results
|
|
7
5
|
// ┌─────────┬───────────────────────────┬─────────────┬────────────────────┬──────────┬─────────┐
|
|
@@ -35,7 +33,7 @@ const vec = {
|
|
|
35
33
|
|
|
36
34
|
let data;
|
|
37
35
|
|
|
38
|
-
const bench = new Bench({ time:
|
|
36
|
+
const bench = new Bench({ time: 1000 })
|
|
39
37
|
|
|
40
38
|
.add("Stringify Object (Vec3)", () => {
|
|
41
39
|
data = JSON.stringify(vec);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "json-as",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.52",
|
|
4
4
|
"description": "JSON encoder/decoder for AssemblyScript",
|
|
5
5
|
"types": "assembly/index.ts",
|
|
6
6
|
"author": "Jairus Tanaka",
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"scripts": {
|
|
16
16
|
"aspect": "asp",
|
|
17
|
-
"bench:astral": "astral -Ospeed --noAssert --uncheckedBehavior always --runtime
|
|
18
|
-
"build:test": "asc assembly/test.ts --target test
|
|
17
|
+
"bench:astral": "astral -Ospeed --noAssert --uncheckedBehavior always --runtime stub",
|
|
18
|
+
"build:test": "asc assembly/test.ts --target test",
|
|
19
19
|
"build:transform": "tsc -p ./transform",
|
|
20
20
|
"test:wasmtime": "wasmtime ./build/test.wasm",
|
|
21
21
|
"test:lunatic": "lunatic ./build/test.wasm",
|
|
@@ -26,8 +26,11 @@
|
|
|
26
26
|
"@as-pect/cli": "^8.0.1",
|
|
27
27
|
"@as-tral/cli": "^2.0.0",
|
|
28
28
|
"@assemblyscript/wasi-shim": "^0.1.0",
|
|
29
|
-
"assemblyscript": "^0.27.
|
|
29
|
+
"assemblyscript": "^0.27.8",
|
|
30
30
|
"assemblyscript-prettier": "^1.0.7",
|
|
31
|
+
"benchmark": "^2.1.4",
|
|
32
|
+
"kati": "^0.6.2",
|
|
33
|
+
"microtime": "^3.1.1",
|
|
31
34
|
"prettier": "^2.8.4",
|
|
32
35
|
"tinybench": "^2.5.0",
|
|
33
36
|
"typescript": "^4.9.5",
|
package/transform/lib/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { toString, isStdlib } from "visitor-as/dist/utils.js";
|
|
2
2
|
import { BaseVisitor, SimpleParser } from "visitor-as/dist/index.js";
|
|
3
3
|
import { Transform } from "assemblyscript/dist/transform.js";
|
|
4
4
|
class SchemaData {
|
|
@@ -19,48 +19,23 @@ class AsJSONTransform extends BaseVisitor {
|
|
|
19
19
|
this.sources = [];
|
|
20
20
|
}
|
|
21
21
|
visitMethodDeclaration() { }
|
|
22
|
-
visitFieldDeclaration(node) {
|
|
23
|
-
if (toString(node).startsWith("static"))
|
|
24
|
-
return;
|
|
25
|
-
const lineText = toString(node);
|
|
26
|
-
if (lineText.startsWith("private"))
|
|
27
|
-
return;
|
|
28
|
-
const name = getName(node);
|
|
29
|
-
if (!node.type) {
|
|
30
|
-
throw new Error(`Field ${name} is missing a type declaration`);
|
|
31
|
-
}
|
|
32
|
-
let type = getName(node.type);
|
|
33
|
-
// @ts-ignore
|
|
34
|
-
this.currentClass.encodeStmts.push(`"${name}":\${JSON.stringify<${type}>(this.${name})},`);
|
|
35
|
-
// @ts-ignore
|
|
36
|
-
//this.decodeStmts.push(
|
|
37
|
-
// `${name}: JSON.parseObjectValue<${type}>(values.get("${name}")),\n`
|
|
38
|
-
//);
|
|
39
|
-
// @ts-ignore
|
|
40
|
-
this.currentClass.setDataStmts.push(`if (key.length === ${name.length} && (memory.compare(changetype<usize>("${name}"), changetype<usize>(key), ${name.length}) == 0)) {
|
|
41
|
-
this.${name} = JSON.parseObjectValue<${type}>(value);
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
`);
|
|
45
|
-
// @ts-ignore
|
|
46
|
-
//this.checkDecodeStmts.push(
|
|
47
|
-
// ' if (!values.has("${name}")) throw new Error("Key "${name}" was not found. Cannot instantiate object.");\n'
|
|
48
|
-
//);
|
|
49
|
-
}
|
|
50
22
|
visitClassDeclaration(node) {
|
|
51
|
-
var
|
|
23
|
+
var _c;
|
|
52
24
|
const className = node.name.text;
|
|
53
|
-
if (!((
|
|
25
|
+
if (!((_c = node.decorators) === null || _c === void 0 ? void 0 : _c.length))
|
|
54
26
|
return;
|
|
55
27
|
let foundDecorator = false;
|
|
56
28
|
for (const decorator of node.decorators) {
|
|
29
|
+
if (
|
|
57
30
|
// @ts-ignore
|
|
58
|
-
|
|
31
|
+
decorator.name.text.toLowerCase() == "json" ||
|
|
32
|
+
// @ts-ignore
|
|
33
|
+
decorator.name.text.toLowerCase() == "serializable")
|
|
59
34
|
foundDecorator = true;
|
|
60
35
|
}
|
|
61
36
|
if (!foundDecorator)
|
|
62
37
|
return;
|
|
63
|
-
// Prevent from being triggered twice
|
|
38
|
+
// Prevent from being triggered twice.
|
|
64
39
|
for (const member of node.members) {
|
|
65
40
|
if (member.name.text == "__JSON_Serialize")
|
|
66
41
|
return;
|
|
@@ -73,7 +48,7 @@ class AsJSONTransform extends BaseVisitor {
|
|
|
73
48
|
parent: node.extendsType ? toString(node.extendsType) : "",
|
|
74
49
|
node: node,
|
|
75
50
|
encodeStmts: [],
|
|
76
|
-
setDataStmts: []
|
|
51
|
+
setDataStmts: [],
|
|
77
52
|
};
|
|
78
53
|
if (this.currentClass.parent.length > 0) {
|
|
79
54
|
const parentSchema = this.schemasList.find((v) => v.name == this.currentClass.parent);
|
|
@@ -82,17 +57,64 @@ class AsJSONTransform extends BaseVisitor {
|
|
|
82
57
|
this.currentClass.encodeStmts.push(...parentSchema === null || parentSchema === void 0 ? void 0 : parentSchema.encodeStmts);
|
|
83
58
|
}
|
|
84
59
|
else {
|
|
85
|
-
console.error("Class extends " +
|
|
60
|
+
console.error("Class extends " +
|
|
61
|
+
this.currentClass.parent +
|
|
62
|
+
", but parent class not found. Maybe add the @json decorator over parent class?");
|
|
86
63
|
}
|
|
87
64
|
}
|
|
88
65
|
const parentSchema = this.schemasList.find((v) => v.name == this.currentClass.parent);
|
|
89
|
-
const members = [
|
|
90
|
-
|
|
66
|
+
const members = [
|
|
67
|
+
...node.members,
|
|
68
|
+
...(parentSchema ? parentSchema.node.members : []),
|
|
69
|
+
];
|
|
70
|
+
for (const mem of members) {
|
|
71
|
+
// @ts-ignore
|
|
72
|
+
if (mem.type && mem.type.name && mem.type.name.identifier.text) {
|
|
73
|
+
const member = mem;
|
|
74
|
+
if (toString(member).startsWith("static"))
|
|
75
|
+
return;
|
|
76
|
+
const lineText = toString(member);
|
|
77
|
+
if (lineText.startsWith("private"))
|
|
78
|
+
return;
|
|
79
|
+
// @ts-ignore
|
|
80
|
+
let type = toString(member.type);
|
|
81
|
+
const name = member.name.text;
|
|
82
|
+
this.currentClass.keys.push(name);
|
|
83
|
+
// @ts-ignore
|
|
84
|
+
this.currentClass.types.push(type);
|
|
85
|
+
// @ts-ignore
|
|
86
|
+
if ([
|
|
87
|
+
"u8",
|
|
88
|
+
"i8",
|
|
89
|
+
"u16",
|
|
90
|
+
"i16",
|
|
91
|
+
"u32",
|
|
92
|
+
"i32",
|
|
93
|
+
"f32",
|
|
94
|
+
"u64",
|
|
95
|
+
"i64",
|
|
96
|
+
"f64",
|
|
97
|
+
].includes(type.toLowerCase())) {
|
|
98
|
+
this.currentClass.encodeStmts.push(`"${name}":\${this.${name}.toString()},`);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
this.currentClass.encodeStmts.push(`"${name}":\${JSON.stringify<${type}>(this.${name})},`);
|
|
102
|
+
}
|
|
103
|
+
// @ts-ignore
|
|
104
|
+
this.currentClass.setDataStmts.push(`if (key == "${name}") {
|
|
105
|
+
this.${name} = JSON.parseObjectValue<${type}>(value);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
91
111
|
let serializeFunc = "";
|
|
92
112
|
if (this.currentClass.encodeStmts.length > 0) {
|
|
93
113
|
const stmt = this.currentClass.encodeStmts[this.currentClass.encodeStmts.length - 1];
|
|
94
|
-
this.currentClass.encodeStmts[this.currentClass.encodeStmts.length - 1] =
|
|
114
|
+
this.currentClass.encodeStmts[this.currentClass.encodeStmts.length - 1] =
|
|
115
|
+
stmt.slice(0, stmt.length - 1);
|
|
95
116
|
serializeFunc = `
|
|
117
|
+
@inline
|
|
96
118
|
__JSON_Serialize(): string {
|
|
97
119
|
return \`{${this.currentClass.encodeStmts.join("")}}\`;
|
|
98
120
|
}
|
|
@@ -100,16 +122,18 @@ class AsJSONTransform extends BaseVisitor {
|
|
|
100
122
|
}
|
|
101
123
|
else {
|
|
102
124
|
serializeFunc = `
|
|
125
|
+
@inline
|
|
103
126
|
__JSON_Serialize(): string {
|
|
104
127
|
return "{}";
|
|
105
128
|
}
|
|
106
129
|
`;
|
|
107
130
|
}
|
|
108
131
|
const setKeyFunc = `
|
|
132
|
+
@inline
|
|
109
133
|
__JSON_Set_Key(key: string, value: string): void {
|
|
110
134
|
${
|
|
111
|
-
|
|
112
|
-
|
|
135
|
+
// @ts-ignore
|
|
136
|
+
this.currentClass.setDataStmts.join("")}
|
|
113
137
|
}
|
|
114
138
|
`;
|
|
115
139
|
const serializeMethod = SimpleParser.parseClassMember(serializeFunc, node);
|
|
@@ -127,18 +151,23 @@ export default class Transformer extends Transform {
|
|
|
127
151
|
afterParse(parser) {
|
|
128
152
|
// Create new transform
|
|
129
153
|
const transformer = new AsJSONTransform();
|
|
130
|
-
//
|
|
131
|
-
const sources = parser.sources
|
|
132
|
-
|
|
133
|
-
|
|
154
|
+
// Sort the sources so that user scripts are visited last
|
|
155
|
+
const sources = parser.sources
|
|
156
|
+
.filter((source) => !isStdlib(source))
|
|
157
|
+
.sort((_a, _b) => {
|
|
158
|
+
const a = _a.internalPath;
|
|
159
|
+
const b = _b.internalPath;
|
|
134
160
|
if (a[0] === "~" && b[0] !== "~") {
|
|
135
161
|
return -1;
|
|
136
|
-
}
|
|
162
|
+
}
|
|
163
|
+
else if (a[0] !== "~" && b[0] === "~") {
|
|
137
164
|
return 1;
|
|
138
|
-
}
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
139
167
|
return 0;
|
|
140
168
|
}
|
|
141
|
-
})
|
|
169
|
+
});
|
|
170
|
+
// Loop over every source
|
|
142
171
|
for (const source of sources) {
|
|
143
172
|
// Ignore all lib and std. Visit everything else.
|
|
144
173
|
if (!isStdlib(source)) {
|
|
@@ -146,4 +175,4 @@ export default class Transformer extends Transform {
|
|
|
146
175
|
}
|
|
147
176
|
}
|
|
148
177
|
}
|
|
149
|
-
}
|
|
178
|
+
}
|