json-as 0.9.20 → 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.
@@ -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
- // @ts-ignore: Decorator valid here
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 bs.out<string>();
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
- bs.write_s_se_u(<string>data, last, changetype<OBJECT>(changetype<usize>(data) - TOTAL_OVERHEAD).rtSize);
82
- bs.write_16(QUOTE);
83
- return bs.out<string>();
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,29 +1,34 @@
1
- // import { JSON } from ".";
2
- import { JSON } from ".";
3
- @json
4
- class Message {
5
- @alias("raw_foo")
6
- public raw: JSON.Raw = "[1,2,3]";
7
- constructor(role: string, content: string) {
8
- this._role = role;
9
- this.content = content;
10
- }
1
+ import { JSON } from "."
11
2
 
12
- @alias("role")
13
- protected _role: string;
14
-
15
- get role(): string {
16
- return this._role;
17
- }
3
+ @json
4
+ class Vec3<T> {
5
+ public x: i32 = 0;
6
+ public y: i32 = 0;
7
+ public z: T;
8
+ }
18
9
 
19
- content: string;
10
+ @json
11
+ class Base {
12
+ public bam: string = "harekogkeorgke"
20
13
  }
21
14
 
22
15
  @json
23
- class UserMessage extends Message {
24
- constructor(content: string) {
25
- super("user", content);
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
+ }
26
27
  }
28
+ // ^ this is not okay
27
29
  }
28
- console.log(JSON.stringify(new Message("user", "foo")));
29
- console.log(JSON.stringify(new UserMessage("foo")));
30
+
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
@@ -67,7 +67,7 @@ const bench = new Bench({ time: 1000 })
67
67
  })
68
68
  */
69
69
  .add("Parse String", () => {
70
- data = JSON.parse("[[],[[]],[[],[[]]]]");
70
+ data = JSON.stringify('hello "world abc');
71
71
  })
72
72
  .todo("unimplemented .add");
73
73
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "json-as",
3
- "version": "0.9.20",
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
- "build:test": "rm -rf ./build/ && JSON_DEBUG=true asc assembly/test.ts --transform ./transform -o ./build/test.wasm",
21
- "build:bench": "asc bench/benchmark.ts -o bench/benchmark.wasm --transform ./transform --optimizeLevel 3 --shrinkLevel 0 --converge --noAssert --uncheckedBehavior always --runtime stub --enable simd",
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"