json-as 0.5.37 → 0.5.38
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 +118 -116
- package/as-pect.asconfig.json +24 -24
- package/asconfig.json +18 -20
- package/assembly/__benches__/as-json.ts +30 -17
- package/assembly/__tests__/as-json.spec.ts +30 -22
- package/assembly/index.ts +1 -1
- package/assembly/src/chars.ts +1 -1
- package/assembly/src/json.ts +127 -103
- package/assembly/src/util.ts +40 -18
- package/assembly/test.ts +194 -13
- package/assembly/tsconfig.json +94 -1
- package/index.ts +1 -1
- package/package.json +1 -1
- package/transform/lib/hash.js +48 -50
- package/transform/lib/index.js +25 -7
- package/transform/lib/types.js +12 -12
- package/transform/package.json +36 -36
- package/transform/src/index.ts +54 -30
- package/transform/tsconfig.json +70 -70
- package/tsconfig.json +12 -12
- package/transform/src/hash.ts +0 -83
package/README.md
CHANGED
|
@@ -1,116 +1,118 @@
|
|
|
1
|
-
# AS-JSON
|
|
2
|
-
|
|
3
|
-

|
|
4
|
+

|
|
5
|
+
|
|
6
|
+
JSON for AssemblyScript focused on performance, low-overhead, and ease-of-use.
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install json-as
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Add the transform to your `asc` command (e.g. in package.json)
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
--transform json-as/transform
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Alternatively, add it to your `asconfig.json`
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
{
|
|
24
|
+
"options": {
|
|
25
|
+
"transform": ["json-as/transform"]
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Usage
|
|
31
|
+
|
|
32
|
+
```js
|
|
33
|
+
import { JSON } from "json-as/assembly";
|
|
34
|
+
|
|
35
|
+
// @json or @serializable work here
|
|
36
|
+
@json
|
|
37
|
+
class Vec3 {
|
|
38
|
+
x!: f32;
|
|
39
|
+
y!: f32;
|
|
40
|
+
z!: f32;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@json
|
|
44
|
+
class Player {
|
|
45
|
+
firstName!: string;
|
|
46
|
+
lastName!: string;
|
|
47
|
+
lastActive!: i32[];
|
|
48
|
+
age!: i32;
|
|
49
|
+
pos!: Vec3 | null;
|
|
50
|
+
isVerified!: boolean;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const player: Player = {
|
|
54
|
+
firstName: "Emmet",
|
|
55
|
+
lastName: "West",
|
|
56
|
+
lastActive: [8, 27, 2022],
|
|
57
|
+
age: 23,
|
|
58
|
+
pos: {
|
|
59
|
+
x: 3.4,
|
|
60
|
+
y: 1.2,
|
|
61
|
+
z: 8.3
|
|
62
|
+
},
|
|
63
|
+
isVerified: true
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const stringified = JSON.stringify<Player>(player);
|
|
67
|
+
|
|
68
|
+
const parsed = JSON.parse<Player>(stringified);
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Deviations from the spec
|
|
72
|
+
|
|
73
|
+
This implementation does not hold strongly to the JSON specification. Rather, design and behavior are inspired by the JSON implementation found in Google's v8 engine.
|
|
74
|
+
|
|
75
|
+
- No support for dynamic types
|
|
76
|
+
- Unsafe by design--parser assumes valid JSON
|
|
77
|
+
- Partial whitespace support--parser prefers speed over handling whitespace effectively. Users may use the `removeWhitespace` function provided by `json-as/src/util.ts`
|
|
78
|
+
- Is not based off of the official spec, but rather the behavior of the JSON C implementation found in google's v8 engine
|
|
79
|
+
- Support for scientific notation on integers. Float support coming soon.
|
|
80
|
+
|
|
81
|
+
## Implemented features
|
|
82
|
+
|
|
83
|
+
Fully supports:
|
|
84
|
+
|
|
85
|
+
- Strings
|
|
86
|
+
- Integers
|
|
87
|
+
- Floats (Scientific notation not implemented)
|
|
88
|
+
- Booleans
|
|
89
|
+
- Arrays
|
|
90
|
+
- Objects
|
|
91
|
+
- Date
|
|
92
|
+
- Null
|
|
93
|
+
|
|
94
|
+
## Performance
|
|
95
|
+
|
|
96
|
+
Number parsing speed has doubled over the last 5 versions due to the use of a `atoi_fast` function found in `assembly/util.ts`. This can be further optimized with SIMD.
|
|
97
|
+
|
|
98
|
+
String serialization has more than tripled in performance (+360%). The algorithm was rewritten for less if statements and more traps.
|
|
99
|
+
|
|
100
|
+
String deserialization was quadrupled from 3.4m ops to 14.8 ops (435%). It went from using `.replaceAll` to a specialized algorithm.
|
|
101
|
+
|
|
102
|
+
Schema (object) parsing is being optimized on GitHub and should be at least doubled if not tripled. (Current speed of barely-optimized version is 6.9m ops) This is due to taking advantage of the types with a type map and eliminating extra checking.
|
|
103
|
+
|
|
104
|
+
**Serialize Object (Vec3):** 6.7m ops/5s
|
|
105
|
+
|
|
106
|
+
**Deserialize Object (Vec3):** 5.1m ops/5s
|
|
107
|
+
|
|
108
|
+
**Serialize Array (int[]):** 6.6m ops/5s
|
|
109
|
+
|
|
110
|
+
**Deserialize Array (int[]):** 8.6m ops/5s
|
|
111
|
+
|
|
112
|
+
**Serialize String (5):** 5.9m ops/5s
|
|
113
|
+
|
|
114
|
+
**Deserialize String (5):** 16.3m ops/5s
|
|
115
|
+
|
|
116
|
+
## Issues
|
|
117
|
+
|
|
118
|
+
Please submit an issue to https://github.com/JairusSW/as-json/issues if you find anything wrong with this library
|
package/as-pect.asconfig.json
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
{
|
|
2
|
-
"targets": {
|
|
3
|
-
"coverage": {
|
|
4
|
-
"lib": ["@as-covers/assembly/index.ts"],
|
|
5
|
-
"transform": ["@as-covers/transform", "@as-pect/transform"]
|
|
6
|
-
},
|
|
7
|
-
"noCoverage": {
|
|
8
|
-
"transform": ["@as-pect/transform"]
|
|
9
|
-
}
|
|
10
|
-
},
|
|
11
|
-
"options": {
|
|
12
|
-
"exportMemory": true,
|
|
13
|
-
"outFile": "output.wasm",
|
|
14
|
-
"textFile": "output.wat",
|
|
15
|
-
"bindings": "raw",
|
|
16
|
-
"exportStart": "_start",
|
|
17
|
-
"exportRuntime": true,
|
|
18
|
-
"use": ["RTRACE=1"],
|
|
19
|
-
"debug": true,
|
|
20
|
-
"exportTable": true
|
|
21
|
-
},
|
|
22
|
-
"extends": "./asconfig.json",
|
|
23
|
-
"entries": ["./node_modules/@as-pect/assembly/assembly/index.ts"]
|
|
24
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"targets": {
|
|
3
|
+
"coverage": {
|
|
4
|
+
"lib": ["@as-covers/assembly/index.ts"],
|
|
5
|
+
"transform": ["@as-covers/transform", "@as-pect/transform"]
|
|
6
|
+
},
|
|
7
|
+
"noCoverage": {
|
|
8
|
+
"transform": ["@as-pect/transform"]
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
"options": {
|
|
12
|
+
"exportMemory": true,
|
|
13
|
+
"outFile": "output.wasm",
|
|
14
|
+
"textFile": "output.wat",
|
|
15
|
+
"bindings": "raw",
|
|
16
|
+
"exportStart": "_start",
|
|
17
|
+
"exportRuntime": true,
|
|
18
|
+
"use": ["RTRACE=1"],
|
|
19
|
+
"debug": true,
|
|
20
|
+
"exportTable": true
|
|
21
|
+
},
|
|
22
|
+
"extends": "./asconfig.json",
|
|
23
|
+
"entries": ["./node_modules/@as-pect/assembly/assembly/index.ts"]
|
|
24
|
+
}
|
package/asconfig.json
CHANGED
|
@@ -1,20 +1,18 @@
|
|
|
1
|
-
{
|
|
2
|
-
"targets": {
|
|
3
|
-
"test": {
|
|
4
|
-
"outFile": "build/test.wasm",
|
|
5
|
-
"sourceMap": false,
|
|
6
|
-
"optimizeLevel": 0,
|
|
7
|
-
"shrinkLevel": 0,
|
|
8
|
-
"converge": false,
|
|
9
|
-
"noAssert": false
|
|
10
|
-
}
|
|
11
|
-
},
|
|
12
|
-
"options": {
|
|
13
|
-
"transform": [
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
"extends": "./node_modules/@assemblyscript/wasi-shim/asconfig.json"
|
|
20
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"targets": {
|
|
3
|
+
"test": {
|
|
4
|
+
"outFile": "build/test.wasm",
|
|
5
|
+
"sourceMap": false,
|
|
6
|
+
"optimizeLevel": 0,
|
|
7
|
+
"shrinkLevel": 0,
|
|
8
|
+
"converge": false,
|
|
9
|
+
"noAssert": false
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"options": {
|
|
13
|
+
"transform": ["./transform"],
|
|
14
|
+
"bindings": "esm",
|
|
15
|
+
"exportStart": "_start"
|
|
16
|
+
},
|
|
17
|
+
"extends": "./node_modules/@assemblyscript/wasi-shim/asconfig.json"
|
|
18
|
+
}
|
|
@@ -8,11 +8,6 @@ class Vec3 {
|
|
|
8
8
|
x: i32;
|
|
9
9
|
y: i32;
|
|
10
10
|
z: i32;
|
|
11
|
-
|
|
12
|
-
/*@inline __JSON_Serialize(data: Vec3): string {
|
|
13
|
-
return `{"x":${data.x.toString()},"y":${data.y.toString()},"z":${data.z.toString()}}`;
|
|
14
|
-
}*/
|
|
15
|
-
|
|
16
11
|
@inline __JSON_Deserialize(data: string, to: Vec3): Vec3 {
|
|
17
12
|
let last = 1;
|
|
18
13
|
let char = 0;
|
|
@@ -55,20 +50,38 @@ class Vec3 {
|
|
|
55
50
|
const vec: Vec3 = {
|
|
56
51
|
x: 3,
|
|
57
52
|
y: 1,
|
|
58
|
-
z: 8
|
|
53
|
+
z: 8,
|
|
59
54
|
};
|
|
60
55
|
|
|
61
|
-
|
|
56
|
+
@inline function istr8<T extends number>(int: T): string {
|
|
57
|
+
if (int >= 100) {
|
|
58
|
+
const str = changetype<string>(__new(6, idof<String>()));
|
|
59
|
+
store<u16>(changetype<usize>(str), ((int / 100) % 10) + 48);
|
|
60
|
+
store<u16>(changetype<usize>(str), ((int / 10) % 10) + 48, 2);
|
|
61
|
+
store<u16>(changetype<usize>(str), (int % 10) + 48, 4);
|
|
62
|
+
return str;
|
|
63
|
+
} else if (int >= 10) {
|
|
64
|
+
const str = changetype<string>(__new(4, idof<String>()));
|
|
65
|
+
store<u16>(changetype<usize>(str), ((int / 10) % 10) + 48);
|
|
66
|
+
store<u16>(changetype<usize>(str), (int % 10) + 48, 2);
|
|
67
|
+
return str;
|
|
68
|
+
} else {
|
|
69
|
+
const str = changetype<string>(__new(2, idof<String>()));
|
|
70
|
+
store<u16>(changetype<usize>(str), (int % 10) + 48);
|
|
71
|
+
return str;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
62
74
|
|
|
63
|
-
|
|
64
|
-
|
|
75
|
+
bench("strint", () => {
|
|
76
|
+
blackbox<string>(istr8<i32>(123));
|
|
77
|
+
})
|
|
78
|
+
bench("tostr", () => {
|
|
79
|
+
blackbox<string>((<i32>123).toString());
|
|
80
|
+
})
|
|
65
81
|
bench("Stringify Object (Vec3)", () => {
|
|
66
82
|
blackbox<string>(vec.__JSON_Serialize());
|
|
67
83
|
});
|
|
68
84
|
|
|
69
|
-
bench("HASH String", () => {
|
|
70
|
-
blackbox<number>(HASH("Hello"));
|
|
71
|
-
})
|
|
72
85
|
// TODO: Make this allocate without crashing
|
|
73
86
|
bench("Parse Object (Vec3)", () => {
|
|
74
87
|
blackbox<Vec3>(vec.__JSON_Deserialize('{"x":0,"y":0,"z":0}', vec));
|
|
@@ -89,15 +102,15 @@ bench("Stringify Boolean Array", () => {
|
|
|
89
102
|
bench("Stringify String Array", () => {
|
|
90
103
|
blackbox(JSON.stringify<string[]>(["a", "b", "c"]));
|
|
91
104
|
});
|
|
92
|
-
|
|
105
|
+
|
|
93
106
|
bench("Stringify String", () => {
|
|
94
|
-
blackbox(JSON.stringify(blackbox(
|
|
107
|
+
blackbox(JSON.stringify(blackbox('Hello "World!')));
|
|
95
108
|
});
|
|
96
109
|
|
|
97
110
|
bench("Parse String", () => {
|
|
98
|
-
blackbox(JSON.parse<string>(blackbox('"Hello
|
|
111
|
+
blackbox(JSON.parse<string>(blackbox('"Hello "World!"')));
|
|
99
112
|
});
|
|
100
|
-
|
|
113
|
+
|
|
101
114
|
bench("Stringify Boolean", () => {
|
|
102
115
|
blackbox(JSON.stringify(blackbox(true)));
|
|
103
116
|
});
|
|
@@ -120,4 +133,4 @@ bench("Stringify Float", () => {
|
|
|
120
133
|
|
|
121
134
|
bench("Parse Float", () => {
|
|
122
135
|
blackbox(JSON.parse<f32>(blackbox("3.14")));
|
|
123
|
-
})
|
|
136
|
+
});
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { JSON } from "..";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
u128,
|
|
4
|
+
u128Safe,
|
|
5
|
+
u256,
|
|
6
|
+
u256Safe,
|
|
7
|
+
i128,
|
|
8
|
+
i128Safe,
|
|
9
|
+
i256Safe,
|
|
10
|
+
} from "as-bignum/assembly";
|
|
3
11
|
function canSerde<T>(data: T): void {
|
|
4
12
|
const serialized = JSON.stringify<T>(data);
|
|
5
13
|
const deserialized = JSON.stringify<T>(JSON.parse<T>(serialized));
|
|
@@ -41,11 +49,11 @@ describe("Ser/de Numbers", () => {
|
|
|
41
49
|
canSerde<i32>(-100);
|
|
42
50
|
canSerde<i64>(-101);
|
|
43
51
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
52
|
+
// canSerde<u128>(u128.from("0"))
|
|
53
|
+
// canSerde<u128>(u128.from("100"))
|
|
54
|
+
// canSerde<u128>(u128.from("101"))
|
|
47
55
|
|
|
48
|
-
|
|
56
|
+
/* canSerde<u128Safe>(u128Safe.from("0"))
|
|
49
57
|
canSerde<u128Safe>(u128Safe.from("100"))
|
|
50
58
|
canSerde<u128Safe>(u128Safe.from("101"))
|
|
51
59
|
|
|
@@ -102,7 +110,7 @@ describe("Ser/de Numbers", () => {
|
|
|
102
110
|
});
|
|
103
111
|
|
|
104
112
|
it("should ser/de BigInt objects", () => {
|
|
105
|
-
|
|
113
|
+
/* canSerde<i32>(0);
|
|
106
114
|
|
|
107
115
|
canSerde<u32>(100);
|
|
108
116
|
canSerde<u64>(101);
|
|
@@ -114,7 +122,7 @@ describe("Ser/de Numbers", () => {
|
|
|
114
122
|
canSerde<u128>(u128.from("-100"))
|
|
115
123
|
canSerde<u128>(u128.from("-101"))
|
|
116
124
|
*/
|
|
117
|
-
})
|
|
125
|
+
});
|
|
118
126
|
});
|
|
119
127
|
|
|
120
128
|
describe("Ser/de Array", () => {
|
|
@@ -178,19 +186,19 @@ describe("Ser/de Array", () => {
|
|
|
178
186
|
});
|
|
179
187
|
|
|
180
188
|
it("should ser/de object arrays", () => {
|
|
181
|
-
canSerde<Vec3[]>([
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
189
|
+
canSerde<Vec3[]>([
|
|
190
|
+
{
|
|
191
|
+
x: 3.4,
|
|
192
|
+
y: 1.2,
|
|
193
|
+
z: 8.3,
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
x: 3.4,
|
|
197
|
+
y: -2.1,
|
|
198
|
+
z: 9.3,
|
|
199
|
+
},
|
|
191
200
|
]);
|
|
192
|
-
|
|
193
|
-
})
|
|
201
|
+
});
|
|
194
202
|
});
|
|
195
203
|
|
|
196
204
|
describe("Ser/de Objects", () => {
|
|
@@ -198,7 +206,7 @@ describe("Ser/de Objects", () => {
|
|
|
198
206
|
canSerde<Vec3>({
|
|
199
207
|
x: 3.4,
|
|
200
208
|
y: 1.2,
|
|
201
|
-
z: 8.3
|
|
209
|
+
z: 8.3,
|
|
202
210
|
});
|
|
203
211
|
});
|
|
204
212
|
it("should ser/de deep objects", () => {
|
|
@@ -210,9 +218,9 @@ describe("Ser/de Objects", () => {
|
|
|
210
218
|
pos: {
|
|
211
219
|
x: 3.4,
|
|
212
220
|
y: 1.2,
|
|
213
|
-
z: 8.3
|
|
221
|
+
z: 8.3,
|
|
214
222
|
},
|
|
215
223
|
isVerified: true,
|
|
216
224
|
});
|
|
217
225
|
});
|
|
218
|
-
});
|
|
226
|
+
});
|
package/assembly/index.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { JSON } from "./src/json";
|
|
1
|
+
export { JSON } from "./src/json";
|
package/assembly/src/chars.ts
CHANGED