json-as 0.9.21 → 0.9.22
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/.prettierrc.json +4 -0
- package/CHANGELOG +1 -1
- package/README.md +2 -2
- package/assembly/__benches__/as-tral.d.ts +1 -0
- package/assembly/__benches__/bool.bench.ts +14 -0
- package/assembly/__benches__/simd.bench.ts +36 -0
- package/assembly/__benches__/string.bench.ts +21 -0
- package/assembly/__tests__/bool.spec.ts +7 -7
- package/assembly/__tests__/float.spec.ts +23 -23
- package/assembly/__tests__/integer.spec.ts +11 -11
- package/assembly/__tests__/obj.spec.ts +1 -2
- package/assembly/__tests__/string.spec.ts +17 -41
- package/assembly/__tests__/test.spec.ts +28 -130
- package/assembly/custom/bs.ts +57 -1
- package/assembly/custom/sink.ts +19 -75
- package/assembly/deserialize/array.ts +1 -5
- package/assembly/deserialize/string.ts +71 -1
- package/assembly/index.ts +16 -178
- package/assembly/serialize/bool.ts +13 -0
- package/assembly/serialize/object.ts +5 -0
- package/assembly/serialize/string.ts +218 -6
- package/assembly/test.ts +28 -8
- package/assembly/util/strings.ts +0 -0
- package/bench.js +1 -1
- package/package.json +8 -7
- package/transform/lib/index.js +177 -172
- package/transform/lib/visitor.js +448 -0
- package/transform/package.json +1 -1
- package/transform/src/index.ts +188 -229
- package/transform/tsconfig.json +2 -2
- package/bench/bench-node.js +0 -17
- package/bench/benchmark.ts +0 -77
- package/bench/benchmark.wasm +0 -0
- package/bench/tsconfig.json +0 -97
|
@@ -3,7 +3,20 @@
|
|
|
3
3
|
* @param data data to serialize
|
|
4
4
|
* @returns string
|
|
5
5
|
*/
|
|
6
|
+
|
|
7
|
+
import { bs } from "../custom/bs";
|
|
8
|
+
|
|
6
9
|
// @ts-ignore: Decorator valid here
|
|
7
10
|
@inline export function serializeBool(data: bool): string {
|
|
8
11
|
return data ? "true" : "false";
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
@inline export function serializeBool_BS(data: bool): void {
|
|
15
|
+
if (data === true) {
|
|
16
|
+
bs.write_64(28429475166421108); /* true */
|
|
17
|
+
} else {
|
|
18
|
+
//bs.write_128_n(i16x8(102, 97, 108, 115, 101, 0, 0, 0), 10);
|
|
19
|
+
bs.write_64(32370086184550502); /* fals */
|
|
20
|
+
bs.write_16(101); /* e */
|
|
21
|
+
}
|
|
9
22
|
}
|
|
@@ -5,4 +5,9 @@ interface GeneratedInterface {
|
|
|
5
5
|
// @ts-ignore: Decorator valid here
|
|
6
6
|
@inline export function serializeObject<T extends GeneratedInterface>(data: T): string {
|
|
7
7
|
return changetype<nonnull<T>>(data).__SERIALIZE();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// @ts-ignore: Decorator valid here
|
|
11
|
+
@inline export function serializeObject_Pretty<T extends GeneratedInterface>(data: T): string {
|
|
12
|
+
return changetype<nonnull<T>>(data).__SERIALIZE_PRETTY();
|
|
8
13
|
}
|
|
@@ -9,18 +9,225 @@ import {
|
|
|
9
9
|
} from "../custom/chars";
|
|
10
10
|
import { OBJECT, TOTAL_OVERHEAD } from "rt/common";
|
|
11
11
|
import { bs } from "../custom/bs";
|
|
12
|
-
import { _intTo16, intTo16 } from "../custom/util";
|
|
12
|
+
import { _intTo16, intTo16, unsafeCharCodeAt } from "../custom/util";
|
|
13
|
+
import { Sink } from "../custom/sink";
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
function needsEscaping(data: string): bool {
|
|
16
|
+
let len = data.length;
|
|
17
|
+
|
|
18
|
+
// if (len < 16) {
|
|
19
|
+
// while (len--) {
|
|
20
|
+
// const char = load<u16>(changetype<usize>(data) + len);
|
|
21
|
+
// if (char == 34 || char == 92 || char <= 31) {
|
|
22
|
+
// return true;
|
|
23
|
+
// }
|
|
24
|
+
// }
|
|
25
|
+
// return false;
|
|
26
|
+
// }
|
|
27
|
+
|
|
28
|
+
let running = v128.splat<i64>(0);
|
|
29
|
+
//let i = 0;
|
|
30
|
+
|
|
31
|
+
//while (i + 15 < len) {
|
|
32
|
+
let w = v128.load(changetype<usize>(data));
|
|
33
|
+
running = v128.or(running, v128.eq<i16>(w, i16x8.splat(34)));
|
|
34
|
+
running = v128.or(running, v128.eq<i16>(w, i16x8.splat(92)));
|
|
35
|
+
|
|
36
|
+
let subtracted = v128.sub<i16>(w, i8x16.splat(31));
|
|
37
|
+
running = v128.or(running, v128.eq<i16>(subtracted, v128.splat<i64>(0)));
|
|
38
|
+
//i += 16;
|
|
39
|
+
//}
|
|
40
|
+
|
|
41
|
+
return v128.any_true(running);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* A prototype SIMD implementation for string serialization which can only work in 128-byte (or 16 chars with wtf-16).
|
|
46
|
+
*
|
|
47
|
+
* A faster version could perhaps look like the following:
|
|
48
|
+
*/
|
|
49
|
+
// @ts-ignore: Decorator
|
|
50
|
+
@inline export function serialize_simd_v1(src: string, dst: usize): void {
|
|
51
|
+
let src_ptr = changetype<usize>(src);
|
|
52
|
+
let dst_ptr = changetype<usize>(dst) + 2;
|
|
53
|
+
|
|
54
|
+
store<u16>(changetype<usize>(dst), 34); /* " */
|
|
55
|
+
|
|
56
|
+
const src_end = src_ptr + u32(src.length << 1);
|
|
57
|
+
const src_end_15 = src_end - 15;
|
|
58
|
+
|
|
59
|
+
while (src_ptr < src_end_15) {
|
|
60
|
+
const currentBlock = v128.load(src_ptr);
|
|
61
|
+
const backslash_indices = i16x8.eq(currentBlock, i16x8.splat(92));
|
|
62
|
+
const quote_indices = i16x8.eq(currentBlock, i16x8.splat(34));
|
|
63
|
+
const concat_indices = v128.or(quote_indices, backslash_indices);
|
|
64
|
+
|
|
65
|
+
const escape_indices = i16x8.lt_u(currentBlock, i16x8.splat(32));
|
|
66
|
+
|
|
67
|
+
if (v128.any_true(v128.or(escape_indices, concat_indices))) {
|
|
68
|
+
const mask = i16x8.bitmask(concat_indices);
|
|
69
|
+
|
|
70
|
+
const anomalies = popcnt(mask);
|
|
71
|
+
const start_index = (clz(mask) & ~1) + 2 // This essentially floors to the nearest even integer
|
|
72
|
+
if (anomalies === 1) {
|
|
73
|
+
memory.copy(dst_ptr, src_ptr, start_index >> 1);
|
|
74
|
+
store<u16>(dst_ptr + start_index, 34);
|
|
75
|
+
memory.copy(dst_ptr + start_index + 2, src_ptr + start_index, (32 - start_index) >> 1)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (v128.any_true(escape_indices)) {
|
|
79
|
+
|
|
80
|
+
}
|
|
81
|
+
dst_ptr += 16;
|
|
82
|
+
src_ptr += 16;
|
|
83
|
+
} else {
|
|
84
|
+
v128.store(dst_ptr, currentBlock);
|
|
85
|
+
src_ptr += 16;
|
|
86
|
+
dst_ptr += 16;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const back_slash_reg = i16x8.splat(92); // "\"
|
|
92
|
+
const quote_reg = i16x8.splat(34); // "\""
|
|
93
|
+
|
|
94
|
+
// @ts-ignore: Decorator
|
|
95
|
+
@inline export function serialize_simd_v2(src: string, dst: usize): void {
|
|
96
|
+
let src_ptr = changetype<usize>(src);
|
|
97
|
+
let dst_ptr = changetype<usize>(dst);
|
|
98
|
+
|
|
99
|
+
let i = 0;
|
|
100
|
+
const len = src.length;
|
|
101
|
+
|
|
102
|
+
while (i < len) {
|
|
103
|
+
const block = v128.load16x4_u(src_ptr);
|
|
104
|
+
console.log("block: " + prt(block));
|
|
105
|
+
const backslash_mask = i16x8.eq(block, back_slash_reg);
|
|
106
|
+
const quote_mask = i16x8.eq(block, quote_reg);
|
|
107
|
+
const is_quote_or_backslash = v128.or(quote_mask, backslash_mask);
|
|
108
|
+
console.log("mask: " + prt10(is_quote_or_backslash))
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
// store<v128>(dst_ptr, expanded);
|
|
112
|
+
src_ptr += 8;
|
|
113
|
+
dst_ptr += 16;
|
|
114
|
+
i += 8;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function prt(obj: v128): string {
|
|
119
|
+
let out = "";
|
|
120
|
+
out += i16x8.extract_lane_u(obj, 0).toString() + " ";
|
|
121
|
+
out += i16x8.extract_lane_u(obj, 1).toString() + " ";
|
|
122
|
+
out += i16x8.extract_lane_u(obj, 2).toString() + " ";
|
|
123
|
+
out += i16x8.extract_lane_u(obj, 3).toString() + " ";
|
|
124
|
+
out += i16x8.extract_lane_u(obj, 4).toString() + " ";
|
|
125
|
+
out += i16x8.extract_lane_u(obj, 5).toString() + " ";
|
|
126
|
+
out += i16x8.extract_lane_u(obj, 6).toString() + " ";
|
|
127
|
+
out += i16x8.extract_lane_u(obj, 7).toString();
|
|
128
|
+
return out;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function prt10(obj: v128): string {
|
|
132
|
+
let out = "";
|
|
133
|
+
out += (i16x8.extract_lane_u(obj, 0) ? "1" : "0") + " ";
|
|
134
|
+
out += (i16x8.extract_lane_u(obj, 1) ? "1" : "0") + " ";
|
|
135
|
+
out += (i16x8.extract_lane_u(obj, 2) ? "1" : "0") + " ";
|
|
136
|
+
out += (i16x8.extract_lane_u(obj, 3) ? "1" : "0") + " ";
|
|
137
|
+
out += (i16x8.extract_lane_u(obj, 4) ? "1" : "0") + " ";
|
|
138
|
+
out += (i16x8.extract_lane_u(obj, 5) ? "1" : "0") + " ";
|
|
139
|
+
out += (i16x8.extract_lane_u(obj, 6) ? "1" : "0") + " ";
|
|
140
|
+
out += i16x8.extract_lane_u(obj, 7) ? "1" : "0";
|
|
141
|
+
return out;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function vis(src_ptr: usize, mask: i32): void {
|
|
145
|
+
let chars = "";
|
|
146
|
+
let bits = "";
|
|
147
|
+
for (let i = 0; i < 8; i++) {
|
|
148
|
+
const char = load<u16>(src_ptr + (i << 1));
|
|
149
|
+
const bit = (mask >> i) & 1;
|
|
150
|
+
chars += String.fromCharCode(char) + " ";
|
|
151
|
+
bits += bit.toString() + " ";
|
|
152
|
+
}
|
|
153
|
+
console.log(chars);
|
|
154
|
+
console.log(bits);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// @ts-ignore: Decorator
|
|
15
158
|
@inline export function serializeString(data: string): string {
|
|
159
|
+
if (!needsEscaping(data)) {
|
|
160
|
+
return "\"" + data + "\"";
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (data.length === 0) {
|
|
164
|
+
return "\"\"";
|
|
165
|
+
}
|
|
166
|
+
let result = Sink.fromString("\"");
|
|
167
|
+
|
|
168
|
+
let last: i32 = 0;
|
|
169
|
+
for (let i = 0; i < data.length; i++) {
|
|
170
|
+
const char = unsafeCharCodeAt(<string>data, i);
|
|
171
|
+
if (char === 34 || char === 92) {
|
|
172
|
+
result.write(<string>data, last, i);
|
|
173
|
+
result.writeCodePoint(92);
|
|
174
|
+
last = i;
|
|
175
|
+
} else if (char < 16) {
|
|
176
|
+
result.write(<string>data, last, i);
|
|
177
|
+
last = i + 1;
|
|
178
|
+
switch (char) {
|
|
179
|
+
case 8: {
|
|
180
|
+
result.write("\\b");
|
|
181
|
+
break;
|
|
182
|
+
}
|
|
183
|
+
case 9: {
|
|
184
|
+
result.write("\\t");
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
case 10: {
|
|
188
|
+
result.write("\\n");
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
case 12: {
|
|
192
|
+
result.write("\\f");
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
case 13: {
|
|
196
|
+
result.write("\\r");
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
199
|
+
default: {
|
|
200
|
+
// all chars 0-31 must be encoded as a four digit unicode escape sequence
|
|
201
|
+
// \u0000 to \u000f handled here
|
|
202
|
+
result.write("\\u000");
|
|
203
|
+
result.write(char.toString(16));
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
} else if (char < 32) {
|
|
208
|
+
result.write(<string>data, last, i);
|
|
209
|
+
last = i + 1;
|
|
210
|
+
// all chars 0-31 must be encoded as a four digit unicode escape sequence
|
|
211
|
+
// \u0010 to \u001f handled here
|
|
212
|
+
result.write("\\u00");
|
|
213
|
+
result.write(char.toString(16));
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
result.write(<string>data, last);
|
|
217
|
+
result.writeCodePoint(34);
|
|
218
|
+
return result.toString();
|
|
219
|
+
}
|
|
220
|
+
// @ts-ignore: Decorator valid here
|
|
221
|
+
@inline export function serializeString_BS(data: string): void {
|
|
16
222
|
const len = data.length << 1;
|
|
17
223
|
if (len === 0) {
|
|
18
224
|
bs.write_32(2228258); /* "" */
|
|
19
|
-
return
|
|
225
|
+
return;
|
|
20
226
|
}
|
|
21
227
|
|
|
22
228
|
bs.write_16(QUOTE);
|
|
23
229
|
|
|
230
|
+
|
|
24
231
|
let last: i32 = 0;
|
|
25
232
|
for (let i = 0; i < len; i += 2) {
|
|
26
233
|
const char = load<u16>(changetype<usize>(data) + i);
|
|
@@ -78,7 +285,12 @@ import { _intTo16, intTo16 } from "../custom/util";
|
|
|
78
285
|
last = i;
|
|
79
286
|
}
|
|
80
287
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
288
|
+
|
|
289
|
+
if (last === 0) {
|
|
290
|
+
bs.write_s(data);
|
|
291
|
+
bs.write_16(QUOTE)
|
|
292
|
+
} else {
|
|
293
|
+
bs.write_s_se(<string>data, last, changetype<OBJECT>(changetype<usize>(data) - TOTAL_OVERHEAD).rtSize);
|
|
294
|
+
bs.write_16(QUOTE);
|
|
295
|
+
}
|
|
84
296
|
}
|
package/assembly/test.ts
CHANGED
|
@@ -1,14 +1,34 @@
|
|
|
1
|
-
|
|
2
|
-
import { JSON } from ".";
|
|
1
|
+
import { JSON } from "."
|
|
3
2
|
|
|
4
3
|
@json
|
|
5
|
-
class
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
class Vec3<T> {
|
|
5
|
+
public x: i32 = 0;
|
|
6
|
+
public y: i32 = 0;
|
|
7
|
+
public z: T;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
@json
|
|
11
|
+
class Base {
|
|
12
|
+
public bam: string = "harekogkeorgke"
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@json
|
|
16
|
+
class Foo extends Base {
|
|
17
|
+
public bar: JSON.Raw = "\"this is ok\'"
|
|
18
|
+
public baz: i32 = 0;
|
|
19
|
+
public pos: Vec3<Vec3<i32>> = {
|
|
20
|
+
x: 1,
|
|
21
|
+
y: 2,
|
|
22
|
+
z: {
|
|
23
|
+
x: 1,
|
|
24
|
+
y: 2,
|
|
25
|
+
z: 3
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// ^ this is not okay
|
|
12
29
|
}
|
|
13
30
|
|
|
14
|
-
|
|
31
|
+
const serialized = JSON.stringify(new Foo());
|
|
32
|
+
console.log("Serialized: " + serialized);
|
|
33
|
+
const deserialized = JSON.parse<Foo>(serialized);
|
|
34
|
+
console.log("Deserialized: " + JSON.stringify(deserialized));
|
|
File without changes
|
package/bench.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "json-as",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.22",
|
|
4
4
|
"description": "The only JSON library you'll need for AssemblyScript. SIMD enabled",
|
|
5
5
|
"types": "assembly/index.ts",
|
|
6
6
|
"author": "Jairus Tanaka",
|
|
@@ -11,16 +11,15 @@
|
|
|
11
11
|
"Frankk Taylor",
|
|
12
12
|
"lekiano",
|
|
13
13
|
"Florian Guitton",
|
|
14
|
-
"Matt Johnson-Pint"
|
|
14
|
+
"Matt Johnson-Pint",
|
|
15
|
+
"Tomáš Hromada"
|
|
15
16
|
],
|
|
16
17
|
"license": "MIT",
|
|
17
18
|
"scripts": {
|
|
18
19
|
"test": "ast test && rm -rf ./build/",
|
|
19
20
|
"pretest": "rm -rf ./build/ && ast build",
|
|
20
|
-
"
|
|
21
|
-
"build:
|
|
22
|
-
"bench:wasmtime": "wasmtime ./bench/benchmark.wasm",
|
|
23
|
-
"bench:wasmer": "wasmer --llvm ./bench/benchmark.wasm",
|
|
21
|
+
"bench": "astral --enable simd --runtime stub",
|
|
22
|
+
"build:test": "rm -rf ./build/ && asc assembly/test.ts --transform ./transform -o ./build/test.wasm --enable simd --enable relaxed-simd",
|
|
24
23
|
"build:transform": "tsc -p ./transform",
|
|
25
24
|
"test:wasmtime": "wasmtime ./build/test.wasm",
|
|
26
25
|
"test:wavm": "wavm run ./build/test.wasm",
|
|
@@ -29,6 +28,7 @@
|
|
|
29
28
|
"prettier": "prettier -w ."
|
|
30
29
|
},
|
|
31
30
|
"devDependencies": {
|
|
31
|
+
"@as-tral/cli": "^3.0.2",
|
|
32
32
|
"@assemblyscript/wasi-shim": "^0.1.0",
|
|
33
33
|
"@types/node": "^20.14.12",
|
|
34
34
|
"as-bench": "^0.0.0-alpha",
|
|
@@ -44,7 +44,8 @@
|
|
|
44
44
|
"visitor-as": "^0.11.4"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"as-virtual": "^0.2.0"
|
|
47
|
+
"as-virtual": "^0.2.0",
|
|
48
|
+
"chalk": "^5.3.0"
|
|
48
49
|
},
|
|
49
50
|
"overrides": {
|
|
50
51
|
"assemblyscript": "$assemblyscript"
|