json-as 0.5.6 → 0.5.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -4
- package/asconfig.json +1 -1
- package/assembly/__tests__/as-json.spec.ts +5 -5
- package/assembly/src/json.ts +32 -27
- package/assembly/test.ts +59 -9
- package/assembly/tsconfig.json +5 -8
- package/build/.gitignore +2 -0
- package/index.html +10 -0
- package/package.json +18 -6
- package/transform/lib/index.js +52 -40
- package/transform/package.json +2 -2
- package/transform/src/index.ts +57 -48
- package/assembly/json.ts +0 -451
package/README.md
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
# AS-JSON
|
|
2
2
|

|
|
3
3
|

|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
Full
|
|
8
4
|
## Installation
|
|
9
5
|
|
|
10
6
|
```bash
|
|
@@ -90,6 +86,19 @@ const stringified = JSON.stringify<Player>(data);
|
|
|
90
86
|
const parsed = JSON.parse<Player>(stringified);
|
|
91
87
|
```
|
|
92
88
|
|
|
89
|
+
# FAQ
|
|
90
|
+
|
|
91
|
+
**Does it support the JSON specification?**
|
|
92
|
+
Yes, it does. However, dynamic objects and arrays are not supported, but planned in the near future.
|
|
93
|
+
|
|
94
|
+
**Is it fast?**
|
|
95
|
+
Look below
|
|
96
|
+
|
|
97
|
+
**How does it compare to other librarys?**
|
|
98
|
+
Its pretty much the same as the other libraries out there (near/assemblyscript-json and @serial-as/json), but it focuses highly on performance
|
|
99
|
+
|
|
100
|
+
**Will it catch invalid JSON?**
|
|
101
|
+
No, it does not check for invalid JSON, but gives its best shot at parsing instead. Will probably throw an error.
|
|
93
102
|
|
|
94
103
|
## Performance
|
|
95
104
|
|
package/asconfig.json
CHANGED
|
@@ -40,16 +40,16 @@ describe("Ser/de Numbers", () => {
|
|
|
40
40
|
canSerde<u64>(101);
|
|
41
41
|
canSerde<i32>(-100);
|
|
42
42
|
canSerde<i64>(-101);
|
|
43
|
-
|
|
43
|
+
/*
|
|
44
44
|
canSerde<u128>(u128.from("0"))
|
|
45
45
|
canSerde<u128>(u128.from("100"))
|
|
46
46
|
canSerde<u128>(u128.from("101"))
|
|
47
|
-
|
|
47
|
+
`
|
|
48
48
|
canSerde<u128Safe>(u128Safe.from("0"))
|
|
49
49
|
canSerde<u128Safe>(u128Safe.from("100"))
|
|
50
50
|
canSerde<u128Safe>(u128Safe.from("101"))
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
canSerde<u256>(u256.fromU128(u128.from("0")))
|
|
53
53
|
canSerde<u256>(u256.fromU128(u128.from("100")))
|
|
54
54
|
canSerde<u256>(u256.fromU128(u128.from("101")))
|
|
55
55
|
|
|
@@ -65,9 +65,9 @@ describe("Ser/de Numbers", () => {
|
|
|
65
65
|
canSerde<i128Safe>(i128Safe.from("100"))
|
|
66
66
|
canSerde<i128Safe>(i128Safe.from("101"))
|
|
67
67
|
canSerde<i128Safe>(i128Safe.from("-100"))
|
|
68
|
-
canSerde<i128Safe>(i128Safe.from("-101"))
|
|
68
|
+
canSerde<i128Safe>(i128Safe.from("-101"))*/
|
|
69
69
|
|
|
70
|
-
canSerde<i256Safe>(new i256Safe(10, 11, 500, 501))
|
|
70
|
+
//canSerde<i256Safe>(new i256Safe(10, 11, 500, 501))
|
|
71
71
|
});
|
|
72
72
|
|
|
73
73
|
it("should ser/de floats", () => {
|
package/assembly/src/json.ts
CHANGED
|
@@ -81,6 +81,8 @@ export namespace JSON {
|
|
|
81
81
|
} else if ((isManaged<T>() || isReference<T>()) && isBigNum<T>()) {
|
|
82
82
|
// @ts-ignore
|
|
83
83
|
return data.toString();
|
|
84
|
+
} else if (data instanceof Date) {
|
|
85
|
+
return data.toISOString();
|
|
84
86
|
} else {
|
|
85
87
|
throw new Error(`Could not serialize data of type ${nameof<T>()}. Invalid data provided.`);
|
|
86
88
|
}
|
|
@@ -152,21 +154,17 @@ export namespace JSON {
|
|
|
152
154
|
throw new Error(`Could not deserialize data ${data} to type ${nameof<T>()}. Invalide data provided.`)
|
|
153
155
|
}
|
|
154
156
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
at<T>(index: i32): T {
|
|
161
|
-
return this.data.at(index).get<T>();
|
|
162
|
-
}
|
|
163
|
-
}*/
|
|
157
|
+
// @ts-ignore
|
|
158
|
+
@unsafe
|
|
159
|
+
export function createObjectUnsafe<T>(): T {
|
|
160
|
+
return changetype<nonnull<T>>(__new(offsetof<nonnull<T>>(), idof<nonnull<T>>()))
|
|
161
|
+
}
|
|
164
162
|
}
|
|
165
163
|
|
|
166
164
|
// @ts-ignore
|
|
167
165
|
@inline
|
|
168
|
-
|
|
169
|
-
|
|
166
|
+
// @ts-ignore
|
|
167
|
+
function parseBigNum<T>(data: string): T {
|
|
170
168
|
// @ts-ignore
|
|
171
169
|
if (idof<T>() == idof<u128>()) return u128.fromString(data);
|
|
172
170
|
// @ts-ignore
|
|
@@ -180,18 +178,18 @@ export namespace JSON {
|
|
|
180
178
|
// @ts-ignore
|
|
181
179
|
if (idof<T>() == idof<i128Safe>()) return i128Safe.fromString(data);
|
|
182
180
|
// @ts-ignore
|
|
183
|
-
if (idof<T>() == idof<i256Safe>()) return
|
|
181
|
+
//if (idof<T>() == idof<i256Safe>()) return data.
|
|
184
182
|
}
|
|
185
183
|
|
|
186
184
|
// @ts-ignore
|
|
187
185
|
@inline
|
|
188
|
-
|
|
186
|
+
function parseString(data: string): string {
|
|
189
187
|
return data.slice(1, data.length - 1).replaceAll('\\"', '"');
|
|
190
188
|
}
|
|
191
189
|
|
|
192
190
|
// @ts-ignore
|
|
193
191
|
@inline
|
|
194
|
-
|
|
192
|
+
function parseBoolean<T extends boolean>(data: string): T {
|
|
195
193
|
if (data.length > 3 && data.startsWith("true")) return <T>true;
|
|
196
194
|
else if (data.length > 4 && data.startsWith("false")) return <T>false;
|
|
197
195
|
else throw new Error(`JSON: Cannot parse "${data}" as boolean`);
|
|
@@ -199,7 +197,7 @@ export namespace JSON {
|
|
|
199
197
|
|
|
200
198
|
// @ts-ignore
|
|
201
199
|
@inline
|
|
202
|
-
|
|
200
|
+
function parseNumber<T>(data: string): T {
|
|
203
201
|
let type: T;
|
|
204
202
|
// @ts-ignore
|
|
205
203
|
if (type instanceof f64) return F64.parseFloat(data);
|
|
@@ -221,15 +219,15 @@ export namespace JSON {
|
|
|
221
219
|
else if (type instanceof i16) return I16.parseInt(data);
|
|
222
220
|
// @ts-ignore
|
|
223
221
|
else if (type instanceof i8) return I8.parseInt(data);
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
222
|
+
|
|
223
|
+
throw new Error(
|
|
224
|
+
`JSON: Cannot parse invalid data into a number. Either "${data}" is not a valid number, or <${nameof<T>()}> is an invald number type.`
|
|
225
|
+
);
|
|
228
226
|
}
|
|
229
227
|
|
|
230
228
|
// @ts-ignore
|
|
231
229
|
@inline
|
|
232
|
-
|
|
230
|
+
export function parseObject<T>(data: string): T {
|
|
233
231
|
let schema: nonnull<T> = changetype<nonnull<T>>(__new(offsetof<nonnull<T>>(), idof<nonnull<T>>()));
|
|
234
232
|
let key = "";
|
|
235
233
|
let isKey = false;
|
|
@@ -251,6 +249,7 @@ export namespace JSON {
|
|
|
251
249
|
depth = depth >> 1;
|
|
252
250
|
if (depth === 1) {
|
|
253
251
|
++arrayValueIndex;
|
|
252
|
+
// @ts-ignore
|
|
254
253
|
schema.__JSON_Set_Key(key, data.slice(outerLoopIndex, arrayValueIndex));
|
|
255
254
|
outerLoopIndex = arrayValueIndex;
|
|
256
255
|
isKey = false;
|
|
@@ -271,6 +270,7 @@ export namespace JSON {
|
|
|
271
270
|
depth = depth >> 1;
|
|
272
271
|
if (depth === 1) {
|
|
273
272
|
++objectValueIndex;
|
|
273
|
+
// @ts-ignore
|
|
274
274
|
schema.__JSON_Set_Key(key, data.slice(outerLoopIndex, objectValueIndex));
|
|
275
275
|
outerLoopIndex = objectValueIndex;
|
|
276
276
|
isKey = false;
|
|
@@ -293,6 +293,7 @@ export namespace JSON {
|
|
|
293
293
|
key = data.slice(outerLoopIndex, stringValueIndex);
|
|
294
294
|
isKey = true;
|
|
295
295
|
} else {
|
|
296
|
+
// @ts-ignore
|
|
296
297
|
schema.__JSON_Set_Key(key, data.slice(outerLoopIndex, stringValueIndex));
|
|
297
298
|
isKey = false;
|
|
298
299
|
}
|
|
@@ -301,6 +302,7 @@ export namespace JSON {
|
|
|
301
302
|
}
|
|
302
303
|
}
|
|
303
304
|
} else if (char == nCode) {
|
|
305
|
+
// @ts-ignore
|
|
304
306
|
schema.__JSON_Set_Key(key, nullWord);
|
|
305
307
|
isKey = false;
|
|
306
308
|
} else if (
|
|
@@ -309,6 +311,7 @@ export namespace JSON {
|
|
|
309
311
|
unsafeCharCodeAt(data, ++outerLoopIndex) === uCode &&
|
|
310
312
|
unsafeCharCodeAt(data, ++outerLoopIndex) === eCode
|
|
311
313
|
) {
|
|
314
|
+
// @ts-ignore
|
|
312
315
|
schema.__JSON_Set_Key(key, trueWord);
|
|
313
316
|
isKey = false;
|
|
314
317
|
} else if (
|
|
@@ -318,6 +321,7 @@ export namespace JSON {
|
|
|
318
321
|
unsafeCharCodeAt(data, ++outerLoopIndex) === "s".charCodeAt(0) &&
|
|
319
322
|
unsafeCharCodeAt(data, ++outerLoopIndex) === eCode
|
|
320
323
|
) {
|
|
324
|
+
// @ts-ignore
|
|
321
325
|
schema.__JSON_Set_Key(key, "false");
|
|
322
326
|
isKey = false;
|
|
323
327
|
} else if ((char >= 48 && char <= 57) || char === 45) {
|
|
@@ -325,6 +329,7 @@ export namespace JSON {
|
|
|
325
329
|
for (; numberValueIndex < data.length; numberValueIndex++) {
|
|
326
330
|
char = unsafeCharCodeAt(data, numberValueIndex);
|
|
327
331
|
if (char === commaCode || char === rightBraceCode || isSpace(char)) {
|
|
332
|
+
// @ts-ignore
|
|
328
333
|
schema.__JSON_Set_Key(key, data.slice(outerLoopIndex - 1, numberValueIndex));
|
|
329
334
|
outerLoopIndex = numberValueIndex;
|
|
330
335
|
isKey = false;
|
|
@@ -338,8 +343,8 @@ export namespace JSON {
|
|
|
338
343
|
|
|
339
344
|
// @ts-ignore
|
|
340
345
|
@inline
|
|
341
|
-
|
|
342
|
-
|
|
346
|
+
// @ts-ignore
|
|
347
|
+
export function parseArray<T extends unknown[]>(data: string): T {
|
|
343
348
|
let type!: valueof<T>;
|
|
344
349
|
if (type instanceof String) {
|
|
345
350
|
return <T>parseStringArray(data);
|
|
@@ -361,7 +366,7 @@ export namespace JSON {
|
|
|
361
366
|
|
|
362
367
|
// @ts-ignore
|
|
363
368
|
@inline
|
|
364
|
-
|
|
369
|
+
export function parseStringArray(data: string): string[] {
|
|
365
370
|
const result: string[] = [];
|
|
366
371
|
let lastPos = 0;
|
|
367
372
|
let instr = false;
|
|
@@ -381,7 +386,7 @@ export namespace JSON {
|
|
|
381
386
|
|
|
382
387
|
// @ts-ignore
|
|
383
388
|
@inline
|
|
384
|
-
|
|
389
|
+
export function parseBooleanArray<T extends boolean[]>(data: string): T {
|
|
385
390
|
const result = instantiate<T>();
|
|
386
391
|
let lastPos = 1;
|
|
387
392
|
let char = 0;
|
|
@@ -409,7 +414,7 @@ export namespace JSON {
|
|
|
409
414
|
|
|
410
415
|
// @ts-ignore
|
|
411
416
|
@inline
|
|
412
|
-
|
|
417
|
+
export function parseNumberArray<T extends number[]>(data: string): T {
|
|
413
418
|
const result = instantiate<T>();
|
|
414
419
|
let lastPos = 0;
|
|
415
420
|
let char = 0;
|
|
@@ -435,7 +440,7 @@ export namespace JSON {
|
|
|
435
440
|
|
|
436
441
|
// @ts-ignore
|
|
437
442
|
@inline
|
|
438
|
-
|
|
443
|
+
export function parseArrayArray<T extends unknown[][]>(data: string): T {
|
|
439
444
|
const result = instantiate<T>();
|
|
440
445
|
let char = 0;
|
|
441
446
|
let lastPos = 0;
|
|
@@ -465,7 +470,7 @@ export namespace JSON {
|
|
|
465
470
|
|
|
466
471
|
// @ts-ignore
|
|
467
472
|
@inline
|
|
468
|
-
|
|
473
|
+
export function parseObjectArray<T extends unknown[][]>(data: string): T {
|
|
469
474
|
const result = instantiate<T>();
|
|
470
475
|
let char = 0;
|
|
471
476
|
let lastPos = 1;
|
package/assembly/test.ts
CHANGED
|
@@ -1,15 +1,50 @@
|
|
|
1
|
-
import "wasi";
|
|
2
|
-
import { u128 } from "as-bignum/assembly";
|
|
1
|
+
import { wasi_console } from "@assemblyscript/wasi-shim/assembly/wasi_console";
|
|
3
2
|
import {
|
|
4
3
|
JSON
|
|
5
4
|
} from ".";
|
|
5
|
+
@json
|
|
6
|
+
class Player {
|
|
7
|
+
firstName: string;
|
|
8
|
+
lastName: string;
|
|
9
|
+
lastActive: i32[];
|
|
10
|
+
age: i32;
|
|
11
|
+
pos: Vec3 | null;
|
|
12
|
+
isVerified: boolean;
|
|
13
|
+
stats: Stats
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
@json
|
|
17
|
+
class Contacts {
|
|
18
|
+
type: string
|
|
19
|
+
player: string
|
|
20
|
+
}
|
|
6
21
|
|
|
22
|
+
const player = JSON.createObjectUnsafe<Player>()
|
|
23
|
+
|
|
24
|
+
player.firstName = "John";
|
|
25
|
+
player.lastName = "West";
|
|
26
|
+
player.age = 23;
|
|
27
|
+
|
|
28
|
+
const contact: Contacts = {
|
|
29
|
+
player: JSON.stringify(player),
|
|
30
|
+
type: "friends"
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
let stringifiedContact = JSON.stringify(contact);
|
|
34
|
+
console.log("Input (Should see backslashes logged): " + stringifiedContact);
|
|
35
|
+
const contacts = JSON.parse<Contacts>(stringifiedContact)
|
|
36
|
+
console.log("Player: " + contacts.player);
|
|
37
|
+
console.log("Type: " + contacts.type);
|
|
38
|
+
const parsedPlayer = JSON.parse<Player>(contacts.player);
|
|
39
|
+
console.log("Final Player: " + JSON.stringify(parsedPlayer));
|
|
40
|
+
console.log("Final Result (Contacts): " + JSON.stringify(contacts));/*
|
|
41
|
+
/*
|
|
7
42
|
// @ts-ignore
|
|
8
43
|
@json
|
|
9
44
|
class Stats {
|
|
10
45
|
wins: u128
|
|
11
46
|
loss: u128
|
|
12
|
-
}
|
|
47
|
+
}*/
|
|
13
48
|
// @ts-ignore
|
|
14
49
|
@json
|
|
15
50
|
class Vec3 {
|
|
@@ -17,7 +52,20 @@ class Vec3 {
|
|
|
17
52
|
y: f32;
|
|
18
53
|
z: f32;
|
|
19
54
|
}
|
|
20
|
-
|
|
55
|
+
// @ts-ignore
|
|
56
|
+
@json
|
|
57
|
+
class Test {
|
|
58
|
+
data: string
|
|
59
|
+
}
|
|
60
|
+
const vec: Vec3 = {
|
|
61
|
+
x: 3.4,
|
|
62
|
+
y: 1.2,
|
|
63
|
+
z: 8.3
|
|
64
|
+
}
|
|
65
|
+
const test: Test = {
|
|
66
|
+
data: JSON.stringify(vec)
|
|
67
|
+
}
|
|
68
|
+
/*
|
|
21
69
|
// @ts-ignore
|
|
22
70
|
@json
|
|
23
71
|
class Player {
|
|
@@ -46,8 +94,10 @@ const player: Player = {
|
|
|
46
94
|
loss: u128.fromString("693")
|
|
47
95
|
}
|
|
48
96
|
};
|
|
49
|
-
|
|
50
|
-
const serializedPlayer = JSON.stringify<
|
|
51
|
-
|
|
52
|
-
const deserializedPlayer = JSON.parse<
|
|
53
|
-
|
|
97
|
+
*//*
|
|
98
|
+
const serializedPlayer = JSON.stringify<Test>(test);
|
|
99
|
+
wasi_console.log("Serialized Player: " + serializedPlayer);
|
|
100
|
+
const deserializedPlayer = JSON.parse<Test>(serializedPlayer);
|
|
101
|
+
wasi_console.log("Deserialized Player: " + JSON.stringify(deserializedPlayer));
|
|
102
|
+
wasi_console.log("Deserialize Vec3: " + JSON.stringify(JSON.parse<Vec3>(deserializedPlayer.data)))
|
|
103
|
+
*/
|
package/assembly/tsconfig.json
CHANGED
package/build/.gitignore
ADDED
package/index.html
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "json-as",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.8",
|
|
4
4
|
"description": "JSON encoder/decoder for AssemblyScript",
|
|
5
5
|
"types": "assembly/index.ts",
|
|
6
6
|
"author": "Jairus Tanaka",
|
|
@@ -16,14 +16,20 @@
|
|
|
16
16
|
"test:wasmtime": "wasmtime ./build/test.wasm",
|
|
17
17
|
"test:lunatic": "lunatic ./build/test.wasm",
|
|
18
18
|
"test:wasm3": "wasm3 ./build/test.wasm",
|
|
19
|
-
"prettier": "as-prettier -w ."
|
|
19
|
+
"prettier": "as-prettier -w .",
|
|
20
|
+
"asbuild:debug": "asc assembly/index.ts --target debug",
|
|
21
|
+
"asbuild:release": "asc assembly/index.ts --target release",
|
|
22
|
+
"asbuild": "yarn asbuild:debug && yarn asbuild:release",
|
|
23
|
+
"test": "node tests",
|
|
24
|
+
"start": "npx serve ."
|
|
20
25
|
},
|
|
21
26
|
"devDependencies": {
|
|
22
27
|
"@as-pect/cli": "^7.0.7",
|
|
23
|
-
"@as-tral/cli": "^1.
|
|
28
|
+
"@as-tral/cli": "^1.2.0",
|
|
24
29
|
"@assemblyscript/loader": "^0.21.3",
|
|
25
|
-
"@
|
|
26
|
-
"
|
|
30
|
+
"@assemblyscript/wasi-shim": "^0.1.0",
|
|
31
|
+
"as-bignum": "^0.2.23",
|
|
32
|
+
"assemblyscript": "^0.24.1",
|
|
27
33
|
"assemblyscript-prettier": "^1.0.2",
|
|
28
34
|
"prettier": "^2.7.1",
|
|
29
35
|
"typescript": "^4.7.2"
|
|
@@ -48,5 +54,11 @@
|
|
|
48
54
|
"url": "https://github.com/JairusSW/as-json/issues"
|
|
49
55
|
},
|
|
50
56
|
"homepage": "https://github.com/JairusSW/as-json#readme",
|
|
51
|
-
"type": "module"
|
|
57
|
+
"type": "module",
|
|
58
|
+
"exports": {
|
|
59
|
+
".": {
|
|
60
|
+
"import": "./build/release.js",
|
|
61
|
+
"types": "./build/release.d.ts"
|
|
62
|
+
}
|
|
63
|
+
}
|
|
52
64
|
}
|
package/transform/lib/index.js
CHANGED
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
import { ClassDecorator, registerDecorator, } from "visitor-as/dist/decorator.js";
|
|
2
2
|
import { getName, toString } from "visitor-as/dist/utils.js";
|
|
3
3
|
import { SimpleParser } from "visitor-as/dist/index.js";
|
|
4
|
+
class SchemaData {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.keys = [];
|
|
7
|
+
this.values = [];
|
|
8
|
+
this.types = [];
|
|
9
|
+
this.name = "";
|
|
10
|
+
this.parent = "";
|
|
11
|
+
this.encodeStmts = [];
|
|
12
|
+
this.setDataStmts = [];
|
|
13
|
+
}
|
|
14
|
+
}
|
|
4
15
|
class AsJSONTransform extends ClassDecorator {
|
|
5
16
|
constructor() {
|
|
6
17
|
super(...arguments);
|
|
18
|
+
this.schemasList = [];
|
|
7
19
|
this.sources = [];
|
|
8
|
-
this.encodeStmts = [];
|
|
9
|
-
//public decodeStmts: string[] = [];
|
|
10
|
-
this.setDataStmts = [];
|
|
11
20
|
}
|
|
12
|
-
//public checkDecodeStmts: string[] = [];
|
|
13
21
|
visitMethodDeclaration() { }
|
|
14
22
|
visitFieldDeclaration(node) {
|
|
15
23
|
const lineText = toString(node);
|
|
@@ -21,13 +29,13 @@ class AsJSONTransform extends ClassDecorator {
|
|
|
21
29
|
}
|
|
22
30
|
let type = getName(node.type);
|
|
23
31
|
// @ts-ignore
|
|
24
|
-
this.encodeStmts.push(`"${name}":\${JSON.stringify<${type}>(this.${name})},`);
|
|
32
|
+
this.currentClass.encodeStmts.push(`"${name}":\${JSON.stringify<${type}>(this.${name})},`);
|
|
25
33
|
// @ts-ignore
|
|
26
34
|
//this.decodeStmts.push(
|
|
27
35
|
// `${name}: JSON.parseObjectValue<${type}>(values.get("${name}")),\n`
|
|
28
36
|
//);
|
|
29
37
|
// @ts-ignore
|
|
30
|
-
this.setDataStmts.push(`if (key.length === ${name.length} && (memory.compare(changetype<usize>("${name}"), changetype<usize>(key), ${name.length}) == 0)) {
|
|
38
|
+
this.currentClass.setDataStmts.push(`if (key.length === ${name.length} && (memory.compare(changetype<usize>("${name}"), changetype<usize>(key), ${name.length}) == 0)) {
|
|
31
39
|
this.${name} = JSON.parseObjectValue<${type}>(value);
|
|
32
40
|
return;
|
|
33
41
|
}
|
|
@@ -38,19 +46,43 @@ class AsJSONTransform extends ClassDecorator {
|
|
|
38
46
|
//);
|
|
39
47
|
}
|
|
40
48
|
visitClassDeclaration(node) {
|
|
49
|
+
var _a, _b, _c;
|
|
41
50
|
if (!node.members) {
|
|
42
51
|
return;
|
|
43
52
|
}
|
|
44
|
-
this.currentClass =
|
|
53
|
+
this.currentClass = {
|
|
54
|
+
name: toString(node.name),
|
|
55
|
+
keys: [],
|
|
56
|
+
values: [],
|
|
57
|
+
types: [],
|
|
58
|
+
parent: node.extendsType ? toString(node.extendsType) : "",
|
|
59
|
+
node: node,
|
|
60
|
+
encodeStmts: [],
|
|
61
|
+
setDataStmts: []
|
|
62
|
+
};
|
|
63
|
+
if (this.currentClass.parent.length > 0) {
|
|
64
|
+
const parentSchema = this.schemasList.map((v) => {
|
|
65
|
+
if (v.name == this.currentClass.parent) {
|
|
66
|
+
return v;
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
if (parentSchema.length > 0) {
|
|
70
|
+
(_a = parentSchema[0]) === null || _a === void 0 ? void 0 : _a.encodeStmts.push(((_b = parentSchema[0]) === null || _b === void 0 ? void 0 : _b.encodeStmts.pop()) + ",");
|
|
71
|
+
this.currentClass.encodeStmts.push(...(_c = parentSchema[0]) === null || _c === void 0 ? void 0 : _c.encodeStmts);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
//console.log("Class extends " + this.currentClass.parent + ", but parent class not found. Maybe add the @json decorator over parent class?")
|
|
75
|
+
}
|
|
76
|
+
}
|
|
45
77
|
this.visit(node.members);
|
|
46
|
-
const serializedProp = '__JSON_Serialized: string = "";';
|
|
78
|
+
// const serializedProp = '__JSON_Serialized: string = "";';
|
|
47
79
|
let serializeFunc = "";
|
|
48
|
-
if (this.encodeStmts.length > 0) {
|
|
49
|
-
const stmt = this.encodeStmts[this.encodeStmts.length - 1];
|
|
50
|
-
this.encodeStmts[this.encodeStmts.length - 1] = stmt.slice(0, stmt.length - 1);
|
|
80
|
+
if (this.currentClass.encodeStmts.length > 0) {
|
|
81
|
+
const stmt = this.currentClass.encodeStmts[this.currentClass.encodeStmts.length - 1];
|
|
82
|
+
this.currentClass.encodeStmts[this.currentClass.encodeStmts.length - 1] = stmt.slice(0, stmt.length - 1);
|
|
51
83
|
serializeFunc = `
|
|
52
84
|
__JSON_Serialize(): string {
|
|
53
|
-
return \`{${this.encodeStmts.join("")}}\`;
|
|
85
|
+
return \`{${this.currentClass.encodeStmts.join("")}}\`;
|
|
54
86
|
}
|
|
55
87
|
`;
|
|
56
88
|
}
|
|
@@ -61,44 +93,24 @@ class AsJSONTransform extends ClassDecorator {
|
|
|
61
93
|
}
|
|
62
94
|
`;
|
|
63
95
|
}
|
|
64
|
-
/*const deserializeFunc = `
|
|
65
|
-
__JSON_Deserialize<T>(values: Map<string, string>): T {
|
|
66
|
-
${
|
|
67
|
-
process.argv.includes("--debugJSON")
|
|
68
|
-
? this.checkDecodeStmts.join("else")
|
|
69
|
-
: ""
|
|
70
|
-
}
|
|
71
|
-
return {
|
|
72
|
-
${
|
|
73
|
-
// @ts-ignore
|
|
74
|
-
this.decodeStmts.join("")
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
`;*/
|
|
79
96
|
const setKeyFunc = `
|
|
80
97
|
__JSON_Set_Key(key: string, value: string): void {
|
|
81
98
|
${
|
|
82
99
|
// @ts-ignore
|
|
83
|
-
this.setDataStmts.join("")}
|
|
100
|
+
this.currentClass.setDataStmts.join("")}
|
|
84
101
|
}
|
|
85
102
|
`;
|
|
86
|
-
//console.log(
|
|
87
|
-
|
|
88
|
-
//
|
|
89
|
-
this.setDataStmts = [];
|
|
90
|
-
//this.checkDecodeStmts = [];
|
|
91
|
-
const serializedProperty = SimpleParser.parseClassMember(serializedProp, node);
|
|
92
|
-
node.members.push(serializedProperty);
|
|
93
|
-
const serializeMethod = SimpleParser.parseClassMember(serializeFunc, node);
|
|
94
|
-
node.members.push(serializeMethod);
|
|
95
|
-
//const deserializeMethod = SimpleParser.parseClassMember(
|
|
96
|
-
// deserializeFunc,
|
|
103
|
+
//console.log(serializeFunc)
|
|
104
|
+
//const serializedProperty = SimpleParser.parseClassMember(
|
|
105
|
+
// serializedProp,
|
|
97
106
|
// node
|
|
98
107
|
//);
|
|
99
|
-
//node.members.push(
|
|
108
|
+
//node.members.push(serializedProperty);
|
|
109
|
+
const serializeMethod = SimpleParser.parseClassMember(serializeFunc, node);
|
|
110
|
+
node.members.push(serializeMethod);
|
|
100
111
|
const setDataMethod = SimpleParser.parseClassMember(setKeyFunc, node);
|
|
101
112
|
node.members.push(setDataMethod);
|
|
113
|
+
this.schemasList.push(this.currentClass);
|
|
102
114
|
}
|
|
103
115
|
get name() {
|
|
104
116
|
return "json";
|
package/transform/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@json-as/transform",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.8",
|
|
4
4
|
"description": "JSON encoder/decoder for AssemblyScript",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"author": "Jairus Tanaka",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"devDependencies": {},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"visitor-as": "^0.
|
|
13
|
+
"visitor-as": "^0.11.3"
|
|
14
14
|
},
|
|
15
15
|
"repository": {
|
|
16
16
|
"type": "git",
|
package/transform/src/index.ts
CHANGED
|
@@ -10,15 +10,22 @@ import {
|
|
|
10
10
|
import { getName, toString } from "visitor-as/dist/utils.js";
|
|
11
11
|
import { SimpleParser } from "visitor-as/dist/index.js";
|
|
12
12
|
|
|
13
|
-
class
|
|
14
|
-
public
|
|
15
|
-
public
|
|
13
|
+
class SchemaData {
|
|
14
|
+
public keys: string[] = [];
|
|
15
|
+
public values: string[] = [];
|
|
16
|
+
public types: string[] = [];
|
|
17
|
+
public name: string = "";
|
|
18
|
+
public parent: string = "";
|
|
19
|
+
public node!: ClassDeclaration;
|
|
16
20
|
public encodeStmts: string[] = [];
|
|
17
|
-
//public decodeStmts: string[] = [];
|
|
18
21
|
public setDataStmts: string[] = [];
|
|
19
|
-
|
|
22
|
+
}
|
|
23
|
+
class AsJSONTransform extends ClassDecorator {
|
|
24
|
+
public schemasList: SchemaData[] = [];
|
|
25
|
+
public currentClass!: SchemaData;
|
|
26
|
+
public sources: Source[] = [];
|
|
20
27
|
|
|
21
|
-
visitMethodDeclaration(): void {}
|
|
28
|
+
visitMethodDeclaration(): void { }
|
|
22
29
|
visitFieldDeclaration(node: FieldDeclaration): void {
|
|
23
30
|
const lineText = toString(node);
|
|
24
31
|
if (lineText.startsWith("private")) return;
|
|
@@ -29,17 +36,17 @@ class AsJSONTransform extends ClassDecorator {
|
|
|
29
36
|
|
|
30
37
|
let type = getName(node.type);
|
|
31
38
|
// @ts-ignore
|
|
32
|
-
this.encodeStmts.push(
|
|
39
|
+
this.currentClass.encodeStmts.push(
|
|
33
40
|
`"${name}":\${JSON.stringify<${type}>(this.${name})},`
|
|
34
41
|
);
|
|
35
42
|
|
|
36
43
|
// @ts-ignore
|
|
37
44
|
//this.decodeStmts.push(
|
|
38
|
-
|
|
45
|
+
// `${name}: JSON.parseObjectValue<${type}>(values.get("${name}")),\n`
|
|
39
46
|
//);
|
|
40
47
|
|
|
41
48
|
// @ts-ignore
|
|
42
|
-
this.setDataStmts.push(
|
|
49
|
+
this.currentClass.setDataStmts.push(
|
|
43
50
|
`if (key.length === ${name.length} && (memory.compare(changetype<usize>("${name}"), changetype<usize>(key), ${name.length}) == 0)) {
|
|
44
51
|
this.${name} = JSON.parseObjectValue<${type}>(value);
|
|
45
52
|
return;
|
|
@@ -57,23 +64,46 @@ class AsJSONTransform extends ClassDecorator {
|
|
|
57
64
|
return;
|
|
58
65
|
}
|
|
59
66
|
|
|
60
|
-
this.currentClass =
|
|
67
|
+
this.currentClass = {
|
|
68
|
+
name: toString(node.name),
|
|
69
|
+
keys: [],
|
|
70
|
+
values: [],
|
|
71
|
+
types: [],
|
|
72
|
+
parent: node.extendsType ? toString(node.extendsType) : "",
|
|
73
|
+
node: node,
|
|
74
|
+
encodeStmts: [],
|
|
75
|
+
setDataStmts: []
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (this.currentClass.parent.length > 0) {
|
|
79
|
+
const parentSchema = this.schemasList.map((v) => {
|
|
80
|
+
if (v.name == this.currentClass.parent) {
|
|
81
|
+
return v;
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
if (parentSchema.length > 0) {
|
|
85
|
+
parentSchema[0]?.encodeStmts.push(parentSchema[0]?.encodeStmts.pop() + ",")
|
|
86
|
+
this.currentClass.encodeStmts.push(...parentSchema[0]?.encodeStmts)
|
|
87
|
+
} else {
|
|
88
|
+
//console.log("Class extends " + this.currentClass.parent + ", but parent class not found. Maybe add the @json decorator over parent class?")
|
|
89
|
+
}
|
|
90
|
+
}
|
|
61
91
|
|
|
62
92
|
this.visit(node.members);
|
|
63
93
|
|
|
64
|
-
|
|
94
|
+
// const serializedProp = '__JSON_Serialized: string = "";';
|
|
65
95
|
|
|
66
96
|
let serializeFunc = "";
|
|
67
97
|
|
|
68
|
-
if (this.encodeStmts.length > 0) {
|
|
69
|
-
const stmt = this.encodeStmts[this.encodeStmts.length - 1]!;
|
|
70
|
-
this.encodeStmts[this.encodeStmts.length - 1] = stmt!.slice(
|
|
98
|
+
if (this.currentClass.encodeStmts.length > 0) {
|
|
99
|
+
const stmt = this.currentClass.encodeStmts[this.currentClass.encodeStmts.length - 1]!;
|
|
100
|
+
this.currentClass.encodeStmts[this.currentClass.encodeStmts.length - 1] = stmt!.slice(
|
|
71
101
|
0,
|
|
72
102
|
stmt.length - 1
|
|
73
103
|
);
|
|
74
104
|
serializeFunc = `
|
|
75
105
|
__JSON_Serialize(): string {
|
|
76
|
-
return \`{${this.encodeStmts.join("")}}\`;
|
|
106
|
+
return \`{${this.currentClass.encodeStmts.join("")}}\`;
|
|
77
107
|
}
|
|
78
108
|
`;
|
|
79
109
|
} else {
|
|
@@ -83,53 +113,32 @@ class AsJSONTransform extends ClassDecorator {
|
|
|
83
113
|
}
|
|
84
114
|
`;
|
|
85
115
|
}
|
|
86
|
-
|
|
87
|
-
__JSON_Deserialize<T>(values: Map<string, string>): T {
|
|
88
|
-
${
|
|
89
|
-
process.argv.includes("--debugJSON")
|
|
90
|
-
? this.checkDecodeStmts.join("else")
|
|
91
|
-
: ""
|
|
92
|
-
}
|
|
93
|
-
return {
|
|
94
|
-
${
|
|
95
|
-
// @ts-ignore
|
|
96
|
-
this.decodeStmts.join("")
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
`;*/
|
|
116
|
+
|
|
101
117
|
const setKeyFunc = `
|
|
102
118
|
__JSON_Set_Key(key: string, value: string): void {
|
|
103
119
|
${
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
120
|
+
// @ts-ignore
|
|
121
|
+
this.currentClass.setDataStmts.join("")
|
|
122
|
+
}
|
|
107
123
|
}
|
|
108
124
|
`
|
|
109
|
-
//console.log(
|
|
110
|
-
|
|
111
|
-
//
|
|
112
|
-
|
|
113
|
-
//
|
|
114
|
-
|
|
115
|
-
serializedProp,
|
|
116
|
-
node
|
|
117
|
-
);
|
|
118
|
-
node.members.push(serializedProperty);
|
|
125
|
+
//console.log(serializeFunc)
|
|
126
|
+
//const serializedProperty = SimpleParser.parseClassMember(
|
|
127
|
+
// serializedProp,
|
|
128
|
+
// node
|
|
129
|
+
//);
|
|
130
|
+
//node.members.push(serializedProperty);
|
|
119
131
|
|
|
120
132
|
const serializeMethod = SimpleParser.parseClassMember(serializeFunc, node);
|
|
121
133
|
node.members.push(serializeMethod);
|
|
122
134
|
|
|
123
|
-
//const deserializeMethod = SimpleParser.parseClassMember(
|
|
124
|
-
// deserializeFunc,
|
|
125
|
-
// node
|
|
126
|
-
//);
|
|
127
|
-
//node.members.push(deserializeMethod);
|
|
128
135
|
const setDataMethod = SimpleParser.parseClassMember(
|
|
129
136
|
setKeyFunc,
|
|
130
137
|
node
|
|
131
138
|
);
|
|
132
139
|
node.members.push(setDataMethod);
|
|
140
|
+
|
|
141
|
+
this.schemasList.push(this.currentClass);
|
|
133
142
|
}
|
|
134
143
|
get name(): string {
|
|
135
144
|
return "json";
|
package/assembly/json.ts
DELETED
|
@@ -1,451 +0,0 @@
|
|
|
1
|
-
import { StringSink } from "as-string-sink/assembly";
|
|
2
|
-
import { isSpace } from "util/string";
|
|
3
|
-
import {
|
|
4
|
-
backSlashCode,
|
|
5
|
-
commaCode,
|
|
6
|
-
eCode,
|
|
7
|
-
fCode,
|
|
8
|
-
leftBraceCode,
|
|
9
|
-
leftBracketCode,
|
|
10
|
-
nCode,
|
|
11
|
-
quoteCode,
|
|
12
|
-
rightBraceCode,
|
|
13
|
-
rightBracketCode,
|
|
14
|
-
tCode,
|
|
15
|
-
} from "./chars";
|
|
16
|
-
import { unsafeCharCodeAt } from "./util";
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* JSON Encoder/Decoder for AssemblyScript
|
|
20
|
-
*/
|
|
21
|
-
export class JSON {
|
|
22
|
-
/**
|
|
23
|
-
* Stringifies valid JSON data.
|
|
24
|
-
* ```js
|
|
25
|
-
* JSON.stringify<T>(data)
|
|
26
|
-
* ```
|
|
27
|
-
* @param data T
|
|
28
|
-
* @returns string
|
|
29
|
-
*/
|
|
30
|
-
static stringify<T>(data: T): string {
|
|
31
|
-
// String
|
|
32
|
-
if (isString<T>()) {
|
|
33
|
-
return '"' + (<string>data).replaceAll('"', '\\"') + '"';
|
|
34
|
-
}
|
|
35
|
-
// Boolean
|
|
36
|
-
else if (isBoolean<T>()) {
|
|
37
|
-
return data ? "true" : "false";
|
|
38
|
-
}
|
|
39
|
-
// Nullable
|
|
40
|
-
else if (isNullable<T>() && data == null) {
|
|
41
|
-
return "null";
|
|
42
|
-
}
|
|
43
|
-
// Integers/Floats
|
|
44
|
-
// @ts-ignore
|
|
45
|
-
else if ((isInteger<T>() || isFloat<T>()) && isFinite(data)) {
|
|
46
|
-
// @ts-ignore
|
|
47
|
-
return data.toString();
|
|
48
|
-
}
|
|
49
|
-
// Class-Based serialization
|
|
50
|
-
// @ts-ignore
|
|
51
|
-
else if (isDefined(data.__JSON_Serialize)) {
|
|
52
|
-
// @ts-ignore
|
|
53
|
-
//if (isNullable<T>()) return "null";
|
|
54
|
-
// @ts-ignore
|
|
55
|
-
return data.__JSON_Serialize();
|
|
56
|
-
}
|
|
57
|
-
// ArrayLike
|
|
58
|
-
else if (isArrayLike<T>()) {
|
|
59
|
-
let result = new StringSink("[");
|
|
60
|
-
// @ts-ignore
|
|
61
|
-
if (data.length == 0) return "[]";
|
|
62
|
-
// @ts-ignore
|
|
63
|
-
for (let i = 0; i < data.length - 1; i++) {
|
|
64
|
-
// @ts-ignore
|
|
65
|
-
result.write(JSON.stringify(unchecked(data[i])) + ",");
|
|
66
|
-
}
|
|
67
|
-
// @ts-ignore
|
|
68
|
-
result.write(JSON.stringify(unchecked(data[data.length - 1])));
|
|
69
|
-
result.write("]");
|
|
70
|
-
return result.toString();
|
|
71
|
-
} else {
|
|
72
|
-
return "null";
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Parses valid JSON strings into their original format.
|
|
77
|
-
* ```js
|
|
78
|
-
* JSON.parse<T>(data)
|
|
79
|
-
* ```
|
|
80
|
-
* @param data string
|
|
81
|
-
* @returns T
|
|
82
|
-
*/
|
|
83
|
-
static parse<T>(data: string): T {
|
|
84
|
-
let type!: T;
|
|
85
|
-
if (isString<T>()) {
|
|
86
|
-
// @ts-ignore
|
|
87
|
-
return parseString(data);
|
|
88
|
-
} else if (isBoolean<T>()) {
|
|
89
|
-
// @ts-ignore
|
|
90
|
-
return parseBoolean<T>(data);
|
|
91
|
-
} else if (isFloat<T>() || isInteger<T>()) {
|
|
92
|
-
return parseNumber<T>(data);
|
|
93
|
-
} else if (isArrayLike<T>()) {
|
|
94
|
-
// @ts-ignore
|
|
95
|
-
return parseArray<T>(data.trimStart());
|
|
96
|
-
// @ts-ignore
|
|
97
|
-
} else if (isNullable<T>() && data == "null") {
|
|
98
|
-
// @ts-ignore
|
|
99
|
-
return null;
|
|
100
|
-
// @ts-ignore
|
|
101
|
-
} else if (isDefined(type.__JSON_Deserialize)) {
|
|
102
|
-
return parseObject<T>(data.trimStart());
|
|
103
|
-
} else {
|
|
104
|
-
// @ts-ignore
|
|
105
|
-
return null;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
private static parseObjectValue<T>(data: string): T {
|
|
109
|
-
let type!: T;
|
|
110
|
-
if (isString<T>()) {
|
|
111
|
-
// @ts-ignore
|
|
112
|
-
return data.replaceAll('\\"', '"');
|
|
113
|
-
} else if (isBoolean<T>()) {
|
|
114
|
-
// @ts-ignore
|
|
115
|
-
return parseBoolean<T>(data);
|
|
116
|
-
} else if (isFloat<T>() || isInteger<T>()) {
|
|
117
|
-
return parseNumber<T>(data);
|
|
118
|
-
} else if (isArrayLike<T>()) {
|
|
119
|
-
// @ts-ignore
|
|
120
|
-
return parseArray<T>(data);
|
|
121
|
-
// @ts-ignore
|
|
122
|
-
} else if (isNullable<T>() && data == "null") {
|
|
123
|
-
// @ts-ignore
|
|
124
|
-
return null;
|
|
125
|
-
// @ts-ignore
|
|
126
|
-
} else if (isDefined(type.__JSON_Deserialize)) {
|
|
127
|
-
// @ts-ignore
|
|
128
|
-
//if (isNullable<T>()) return null;
|
|
129
|
-
return parseObject<T>(data);
|
|
130
|
-
} else {
|
|
131
|
-
// @ts-ignore
|
|
132
|
-
//return null;
|
|
133
|
-
throw new Error(`Could not parse value: ${data}`);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// @ts-ignore
|
|
139
|
-
@inline
|
|
140
|
-
function parseString(data: string): string {
|
|
141
|
-
return data.slice(1, data.length - 1).replaceAll('\\"', '"');
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// @ts-ignore
|
|
145
|
-
@inline
|
|
146
|
-
function parseBoolean<T extends boolean>(data: string): T {
|
|
147
|
-
if (data.length > 3 && data.startsWith("true")) return <T>true;
|
|
148
|
-
else if (data.length > 4 && data.startsWith("false")) return <T>false;
|
|
149
|
-
else throw new Error(`JSON: Cannot parse "${data}" as boolean`);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// @ts-ignore
|
|
153
|
-
@inline
|
|
154
|
-
function parseNumber<T>(data: string): T {
|
|
155
|
-
let type: T;
|
|
156
|
-
// @ts-ignore
|
|
157
|
-
if (type instanceof f64) return F64.parseFloat(data);
|
|
158
|
-
// @ts-ignore
|
|
159
|
-
else if (type instanceof f32) return F32.parseFloat(data);
|
|
160
|
-
// @ts-ignore
|
|
161
|
-
else if (type instanceof u64) return U64.parseInt(data);
|
|
162
|
-
// @ts-ignore
|
|
163
|
-
else if (type instanceof u32) return U32.parseInt(data);
|
|
164
|
-
// @ts-ignore
|
|
165
|
-
else if (type instanceof u8) return U8.parseInt(data);
|
|
166
|
-
// @ts-ignore
|
|
167
|
-
else if (type instanceof u16) return U16.parseInt(data);
|
|
168
|
-
// @ts-ignore
|
|
169
|
-
else if (type instanceof i64) return I64.parseInt(data);
|
|
170
|
-
// @ts-ignore
|
|
171
|
-
else if (type instanceof i32) return I32.parseInt(data);
|
|
172
|
-
// @ts-ignore
|
|
173
|
-
else if (type instanceof i16) return I16.parseInt(data);
|
|
174
|
-
// @ts-ignore
|
|
175
|
-
else if (type instanceof i8) return I8.parseInt(data);
|
|
176
|
-
else
|
|
177
|
-
throw new Error(
|
|
178
|
-
`JSON: Cannot parse invalid data into a number. Either "${data}" is not a valid number, or <${nameof<T>()}> is an invald number type.`
|
|
179
|
-
);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// @ts-ignore
|
|
183
|
-
@inline
|
|
184
|
-
export function parseObject<T>(data: string): T {
|
|
185
|
-
let schema: T = changetype<T>(__new(offsetof<T>(), idof<T>()));
|
|
186
|
-
const result = new Map<string, string>();
|
|
187
|
-
let key = "";
|
|
188
|
-
let isKey = false;
|
|
189
|
-
let depth = 1;
|
|
190
|
-
let char = 0;
|
|
191
|
-
let outerLoopIndex = 1;
|
|
192
|
-
for (; outerLoopIndex < data.length - 1; outerLoopIndex++) {
|
|
193
|
-
char = unsafeCharCodeAt(data, outerLoopIndex);
|
|
194
|
-
if (char === leftBracketCode) {
|
|
195
|
-
for (
|
|
196
|
-
let arrayValueIndex = outerLoopIndex;
|
|
197
|
-
arrayValueIndex < data.length - 1;
|
|
198
|
-
arrayValueIndex++
|
|
199
|
-
) {
|
|
200
|
-
char = unsafeCharCodeAt(data, arrayValueIndex);
|
|
201
|
-
if (char === leftBracketCode) {
|
|
202
|
-
depth = depth << 1;
|
|
203
|
-
} else if (char === rightBracketCode) {
|
|
204
|
-
depth = depth >> 1;
|
|
205
|
-
if (depth === 1) {
|
|
206
|
-
++arrayValueIndex;
|
|
207
|
-
result.set(key, data.slice(outerLoopIndex, arrayValueIndex));
|
|
208
|
-
outerLoopIndex = arrayValueIndex;
|
|
209
|
-
isKey = false;
|
|
210
|
-
break;
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
} else if (char === leftBraceCode) {
|
|
215
|
-
for (
|
|
216
|
-
let objectValueIndex = outerLoopIndex;
|
|
217
|
-
objectValueIndex < data.length - 1;
|
|
218
|
-
objectValueIndex++
|
|
219
|
-
) {
|
|
220
|
-
char = unsafeCharCodeAt(data, objectValueIndex);
|
|
221
|
-
if (char === leftBraceCode) {
|
|
222
|
-
depth = depth << 1;
|
|
223
|
-
} else if (char === rightBraceCode) {
|
|
224
|
-
depth = depth >> 1;
|
|
225
|
-
if (depth === 1) {
|
|
226
|
-
++objectValueIndex;
|
|
227
|
-
result.set(key, data.slice(outerLoopIndex, objectValueIndex));
|
|
228
|
-
outerLoopIndex = objectValueIndex;
|
|
229
|
-
isKey = false;
|
|
230
|
-
break;
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
} else if (char === quoteCode) {
|
|
235
|
-
for (
|
|
236
|
-
let stringValueIndex = ++outerLoopIndex;
|
|
237
|
-
stringValueIndex < data.length - 1;
|
|
238
|
-
stringValueIndex++
|
|
239
|
-
) {
|
|
240
|
-
char = unsafeCharCodeAt(data, stringValueIndex);
|
|
241
|
-
if (
|
|
242
|
-
char === quoteCode &&
|
|
243
|
-
unsafeCharCodeAt(data, stringValueIndex - 1) !== backSlashCode
|
|
244
|
-
) {
|
|
245
|
-
if (isKey === false) {
|
|
246
|
-
key = data.slice(outerLoopIndex, stringValueIndex);
|
|
247
|
-
isKey = true;
|
|
248
|
-
} else {
|
|
249
|
-
result.set(key, data.slice(outerLoopIndex, stringValueIndex));
|
|
250
|
-
isKey = false;
|
|
251
|
-
}
|
|
252
|
-
outerLoopIndex = ++stringValueIndex;
|
|
253
|
-
break;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
} else if (char == nCode) {
|
|
257
|
-
result.set(key, "null");
|
|
258
|
-
isKey = false;
|
|
259
|
-
} else if (
|
|
260
|
-
char === tCode &&
|
|
261
|
-
unsafeCharCodeAt(data, ++outerLoopIndex) === "r".charCodeAt(0) &&
|
|
262
|
-
unsafeCharCodeAt(data, ++outerLoopIndex) === "u".charCodeAt(0) &&
|
|
263
|
-
unsafeCharCodeAt(data, ++outerLoopIndex) === eCode
|
|
264
|
-
) {
|
|
265
|
-
result.set(key, "true");
|
|
266
|
-
isKey = false;
|
|
267
|
-
} else if (
|
|
268
|
-
char === fCode &&
|
|
269
|
-
unsafeCharCodeAt(data, ++outerLoopIndex) === "a".charCodeAt(0) &&
|
|
270
|
-
unsafeCharCodeAt(data, ++outerLoopIndex) === "l".charCodeAt(0) &&
|
|
271
|
-
unsafeCharCodeAt(data, ++outerLoopIndex) === "s".charCodeAt(0) &&
|
|
272
|
-
unsafeCharCodeAt(data, ++outerLoopIndex) === eCode
|
|
273
|
-
) {
|
|
274
|
-
result.set(key, "false");
|
|
275
|
-
isKey = false;
|
|
276
|
-
} else if ((char >= 48 && char <= 57) || char === 45) {
|
|
277
|
-
let numberValueIndex = ++outerLoopIndex;
|
|
278
|
-
for (; numberValueIndex < data.length; numberValueIndex++) {
|
|
279
|
-
char = unsafeCharCodeAt(data, numberValueIndex);
|
|
280
|
-
if (char === commaCode || char === rightBraceCode || isSpace(char)) {
|
|
281
|
-
result.set(key, data.slice(outerLoopIndex - 1, numberValueIndex));
|
|
282
|
-
outerLoopIndex = numberValueIndex;
|
|
283
|
-
isKey = false;
|
|
284
|
-
break;
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
// @ts-ignore
|
|
290
|
-
//const deserialized =
|
|
291
|
-
//changetype<nonnull<T>>(schema).__JSON_Deserialize<T>(result);
|
|
292
|
-
//heap.free(changetype<usize>(schema));
|
|
293
|
-
return changetype<nonnull<T>>(schema).__JSON_Deserialize<T>(result);
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
// @ts-ignore
|
|
297
|
-
@inline
|
|
298
|
-
// @ts-ignore
|
|
299
|
-
export function parseArray<T extends unknown[]>(data: string): T {
|
|
300
|
-
let type!: valueof<T>;
|
|
301
|
-
if (type instanceof String) {
|
|
302
|
-
return <T>parseStringArray(data);
|
|
303
|
-
} else if (isBoolean<valueof<T>>()) {
|
|
304
|
-
// @ts-ignore
|
|
305
|
-
return parseBooleanArray<T>(data);
|
|
306
|
-
} else if (isFloat<valueof<T>>() || isInteger<valueof<T>>()) {
|
|
307
|
-
// @ts-ignore
|
|
308
|
-
return parseNumberArray<T>(data);
|
|
309
|
-
} else if (isArrayLike<valueof<T>>()) {
|
|
310
|
-
// @ts-ignore
|
|
311
|
-
return parseArrayArray<T>(data);
|
|
312
|
-
// @ts-ignore
|
|
313
|
-
} else if (isDefined(type.__JSON_Deserialize)) {
|
|
314
|
-
// @ts-ignore
|
|
315
|
-
return parseObjectArray<T>(data);
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
// @ts-ignore
|
|
320
|
-
@inline
|
|
321
|
-
export function parseStringArray(data: string): string[] {
|
|
322
|
-
const result: string[] = [];
|
|
323
|
-
let lastPos = 0;
|
|
324
|
-
let instr = false;
|
|
325
|
-
for (let i = 1; i < data.length - 1; i++) {
|
|
326
|
-
if (unsafeCharCodeAt(data, i) === quoteCode) {
|
|
327
|
-
if (instr === false) {
|
|
328
|
-
instr = true;
|
|
329
|
-
lastPos = i;
|
|
330
|
-
} else if (unsafeCharCodeAt(data, i - 1) !== backSlashCode) {
|
|
331
|
-
instr = false;
|
|
332
|
-
result.push(data.slice(lastPos + 1, i).replaceAll('\\"', '"'));
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
return result;
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
// @ts-ignore
|
|
340
|
-
@inline
|
|
341
|
-
export function parseBooleanArray<T extends boolean[]>(data: string): T {
|
|
342
|
-
const result = instantiate<T>();
|
|
343
|
-
let lastPos = 1;
|
|
344
|
-
let char = 0;
|
|
345
|
-
for (let i = 1; i < data.length - 1; i++) {
|
|
346
|
-
char = unsafeCharCodeAt(data, i);
|
|
347
|
-
/*// if char == "t" && i+3 == "e"
|
|
348
|
-
if (char === tCode && data.charCodeAt(i + 3) === eCode) {
|
|
349
|
-
//i += 3;
|
|
350
|
-
result.push(parseBoolean<valueof<T>>(data.slice(lastPos, i+2)));
|
|
351
|
-
//i++;
|
|
352
|
-
} else if (char === fCode && data.charCodeAt(i + 4) === eCode) {
|
|
353
|
-
//i += 4;
|
|
354
|
-
result.push(parseBoolean<valueof<T>>(data.slice(lastPos, i+3)));
|
|
355
|
-
//i++;
|
|
356
|
-
}*/
|
|
357
|
-
if (char === tCode || char === fCode) {
|
|
358
|
-
lastPos = i;
|
|
359
|
-
} else if (char === eCode) {
|
|
360
|
-
i++;
|
|
361
|
-
result.push(parseBoolean<valueof<T>>(data.slice(lastPos, i)));
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
return result;
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
// @ts-ignore
|
|
368
|
-
@inline
|
|
369
|
-
export function parseNumberArray<T extends number[]>(data: string): T {
|
|
370
|
-
const result = instantiate<T>();
|
|
371
|
-
let lastPos = 0;
|
|
372
|
-
let char = 0;
|
|
373
|
-
let i = 1;
|
|
374
|
-
for (; i < data.length - 1; i++) {
|
|
375
|
-
char = unsafeCharCodeAt(data, i);
|
|
376
|
-
if ((lastPos === 0 && char >= 48 && char <= 57) || char === 45) {
|
|
377
|
-
lastPos = i;
|
|
378
|
-
} else if ((isSpace(char) || char == commaCode) && lastPos > 0) {
|
|
379
|
-
result.push(parseNumber<valueof<T>>(data.slice(lastPos, i)));
|
|
380
|
-
lastPos = 0;
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
for (; i > lastPos - 1; i--) {
|
|
384
|
-
char = unsafeCharCodeAt(data, i);
|
|
385
|
-
if (char !== rightBracketCode) {
|
|
386
|
-
result.push(parseNumber<valueof<T>>(data.slice(lastPos, i + 1)));
|
|
387
|
-
break;
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
return result;
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
// @ts-ignore
|
|
394
|
-
@inline
|
|
395
|
-
export function parseArrayArray<T extends unknown[][]>(data: string): T {
|
|
396
|
-
const result = instantiate<T>();
|
|
397
|
-
let char = 0;
|
|
398
|
-
let lastPos = 0;
|
|
399
|
-
let depth = 1;
|
|
400
|
-
let i = 1;
|
|
401
|
-
// Find start of bracket
|
|
402
|
-
//for (; unsafeCharCodeAt(data, i) !== leftBracketCode; i++) {}
|
|
403
|
-
//i++;
|
|
404
|
-
for (; i < data.length - 1; i++) {
|
|
405
|
-
char = unsafeCharCodeAt(data, i);
|
|
406
|
-
if (char === leftBracketCode) {
|
|
407
|
-
if (depth === 1) {
|
|
408
|
-
lastPos = i;
|
|
409
|
-
}
|
|
410
|
-
// Shifting is 6% faster than incrementing
|
|
411
|
-
depth = depth << 1;
|
|
412
|
-
} else if (char === rightBracketCode) {
|
|
413
|
-
depth = depth >> 1;
|
|
414
|
-
if (depth === 1) {
|
|
415
|
-
i++;
|
|
416
|
-
result.push(JSON.parse<valueof<T>>(data.slice(lastPos, i)));
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
return result;
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
// @ts-ignore
|
|
424
|
-
@inline
|
|
425
|
-
export function parseObjectArray<T extends unknown[][]>(data: string): T {
|
|
426
|
-
const result = instantiate<T>();
|
|
427
|
-
let char = 0;
|
|
428
|
-
let lastPos = 1;
|
|
429
|
-
let depth = 1;
|
|
430
|
-
let i = 1;
|
|
431
|
-
// Find start of bracket
|
|
432
|
-
//for (; unsafeCharCodeAt(data, i) !== leftBracketCode; i++) { }
|
|
433
|
-
//i++;
|
|
434
|
-
for (; i < data.length - 1; i++) {
|
|
435
|
-
char = unsafeCharCodeAt(data, i);
|
|
436
|
-
if (char === leftBraceCode) {
|
|
437
|
-
if (depth === 1) {
|
|
438
|
-
lastPos = i;
|
|
439
|
-
}
|
|
440
|
-
// Shifting is 6% faster than incrementing
|
|
441
|
-
depth = depth << 1;
|
|
442
|
-
} else if (char === rightBraceCode) {
|
|
443
|
-
depth = depth >> 1;
|
|
444
|
-
if (depth === 1) {
|
|
445
|
-
i++;
|
|
446
|
-
result.push(JSON.parse<valueof<T>>(data.slice(lastPos, i)));
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
return result;
|
|
451
|
-
}
|