json-as 0.5.26 → 0.5.28

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 CHANGED
@@ -79,13 +79,13 @@ Performance is nearly equal to the JavaScript JSON implementation which is in C+
79
79
 
80
80
  ## Performance
81
81
 
82
- **Serialize Object (Vec2):** ~7.20m ops/s
82
+ **Serialize Object (Vec3):** ~11.1m ops/s
83
83
 
84
- **Deserialize Object (Vec2):** ~2.2m ops/s
84
+ **Deserialize Object (Vec3):** ~3.2m ops/s
85
85
 
86
- **Serialize Array (int[4]):** ~1.4m ops/s
86
+ **Serialize Array (int[]):** ~1.4m ops/s
87
87
 
88
- **Deserialize Array (int[4]):** ~2.8m ops/s
88
+ **Deserialize Array (int[]):** ~2.8m ops/s
89
89
 
90
90
  **Serialize String (5):** ~5.2m ops/sw
91
91
 
package/asconfig.json CHANGED
@@ -12,9 +12,6 @@
12
12
  "options": {
13
13
  "transform": [
14
14
  "./transform"
15
- ],
16
- "bindings": "esm",
17
- "exportStart": "_start"
18
- },
19
- "extends": "./node_modules/@assemblyscript/wasi-shim/asconfig.json"
15
+ ]
16
+ }
20
17
  }
@@ -1,28 +1,33 @@
1
1
  import { JSON } from "..";
2
2
 
3
3
  @json
4
- class Vec2 {
5
- x: f32;
6
- y: f32;
4
+ class Vec3 {
5
+ x: i32;
6
+ y: i32;
7
+ z: i32;
7
8
  }
8
9
 
9
- const vec: Vec2 = blackbox<Vec2>({
10
- x: 0.0,
11
- y: 0.0,
10
+ const vec: Vec3 = blackbox<Vec3>({
11
+ x: 0,
12
+ y: 0,
13
+ z: 0
12
14
  });
13
15
 
14
- bench("Stringify Object (Vec2)", () => {
16
+ bench("Stringify Object (Vec3)", () => {
15
17
  blackbox(JSON.stringify(vec));
16
18
  });
17
19
 
18
- bench("Parse Object (Vec2)", () => {
19
- blackbox(JSON.parse<Vec2>(blackbox('{"x":0.0,"y":0.0}')));
20
- });
20
+ bench("Parse Object (Vec3)", () => {
21
+ blackbox(JSON.parse<Vec3>(blackbox('{"x":0,"y":0,"z":0}')));
22
+ });/*
21
23
 
22
24
  bench("Stringify Array", () => {
23
25
  blackbox(JSON.stringify(blackbox([1, 2, 3, 4, 5])));
24
26
  });
25
-
27
+ bench("Stringify String Array", () => {
28
+ blackbox(JSON.stringify(blackbox(["a", "b", "c", "d", "e"])));
29
+ });
30
+ /*
26
31
  bench("Parse Array", () => {
27
32
  blackbox(JSON.parse<i32[]>(blackbox("[1,2,3,4]")));
28
33
  });
@@ -40,13 +45,13 @@ bench("Stringify Nested Array", () => {
40
45
  bench("Parse Nested Array", () => {
41
46
  blackbox(JSON.parse<string[][]>(blackbox('[["a","b","c"]]')));
42
47
  });
43
-
48
+ */
44
49
  bench("Stringify String", () => {
45
- blackbox(JSON.stringify(blackbox("Hello")));
50
+ blackbox(JSON.stringify(blackbox("Hello \"World!")));
46
51
  });
47
52
 
48
53
  bench("Parse String", () => {
49
- blackbox(JSON.parse<string>(blackbox('"Hello"')));
54
+ blackbox(JSON.parse<string>(blackbox('"Hello \"World!"')));
50
55
  });
51
56
  /*
52
57
  bench("Stringify Boolean", () => {
@@ -40,54 +40,7 @@ export namespace JSON {
40
40
  export function stringify<T>(data: T): string {
41
41
  // String
42
42
  if (isString<T>() && data != null) {
43
- // @ts-ignore
44
- if (data.length === 0) return "\"\"";
45
- let result = new StringSink("\"");
46
- // @ts-ignore
47
- for (let i = 0; i < data.length; i++) {
48
- // @ts-ignore
49
- switch (unsafeCharCodeAt(data, i)) {
50
- case 0x22: {
51
- result.write("\\\"");
52
- break;
53
- }
54
- case 0x5C: {
55
- result.write("\\\\");
56
- break;
57
- }
58
- case 0x08: {
59
- result.write("\\b");
60
- break;
61
- }
62
- case 0x0A: {
63
- result.write("\\n");
64
- break;
65
- }
66
- case 0x0D: {
67
- result.write("\\r");
68
- break;
69
- }
70
- case 0x09: {
71
- result.write("\\t");
72
- break;
73
- }
74
- case 0x0C: {
75
- result.write("\\f");
76
- break;
77
- }
78
- case 0x0B: {
79
- result.write("\\u000b");
80
- break;
81
- }
82
- default: {
83
- // @ts-ignore
84
- result.write(data.charAt(i));
85
- break;
86
- }
87
- }
88
- }
89
- result.write("\"");
90
- return result.toString();
43
+ return serializeString(data);
91
44
  }
92
45
  // Boolean
93
46
  else if (isBoolean<T>()) {
@@ -113,19 +66,44 @@ export namespace JSON {
113
66
  }
114
67
  // ArrayLike
115
68
  else if (isArrayLike<T>()) {
116
- let result = new StringSink(leftBracketWord);
117
- // @ts-ignore
118
- if (data.length == 0) return emptyArrayWord;
119
69
  // @ts-ignore
120
- for (let i = 0; i < data.length - 1; i++) {
70
+ if (data.length == 0) {
71
+ return emptyArrayWord;
72
+ } else if (isString<valueof<T>>()) {
73
+ let result = "[";
74
+ for (let i = 0; i < data.length - 1; i++) {
75
+ // @ts-ignore
76
+ result += serializeString(unchecked(data[i]));
77
+ result += commaWord;
78
+ }
79
+ result += serializeString(unchecked(data[data.length - 1]));
80
+ result += rightBracketWord;
81
+ return result;
82
+ } else if (isFloat<valueof<T>>() || isInteger<valueof<T>>()) {
83
+ let result = new StringSink(leftBracketWord);
84
+ // @ts-ignore
85
+ for (let i = 0; i < data.length - 1; i++) {
86
+ // @ts-ignore
87
+ result.write(JSON.stringify(unchecked(data[i])));
88
+ result.write(commaWord);
89
+ }
90
+ // @ts-ignore
91
+ result.write(JSON.stringify(unchecked(data[data.length - 1])));
92
+ result.write(rightBracketWord);
93
+ return result.toString();
94
+ } else {
95
+ let result = new StringSink(leftBracketWord);
96
+ // @ts-ignore
97
+ for (let i = 0; i < data.length - 1; i++) {
98
+ // @ts-ignore
99
+ result.write(JSON.stringify(unchecked(data[i])));
100
+ result.write(commaWord);
101
+ }
121
102
  // @ts-ignore
122
- result.write(JSON.stringify(unchecked(data[i])));
123
- result.write(commaWord);
103
+ result.write(JSON.stringify(unchecked(data[data.length - 1])));
104
+ result.write(rightBracketWord);
105
+ return result.toString();
124
106
  }
125
- // @ts-ignore
126
- result.write(JSON.stringify(unchecked(data[data.length - 1])));
127
- result.write(rightBracketWord);
128
- return result.toString();
129
107
  } else if ((isManaged<T>() || isReference<T>()) && isBigNum<T>()) {
130
108
  // @ts-ignore
131
109
  return data.toString();
@@ -201,30 +179,158 @@ export namespace JSON {
201
179
  }
202
180
  }
203
181
 
182
+ // @ts-ignore
183
+ @inline
184
+ // @ts-ignore
185
+ function serializeString(data: string): string {
186
+ // @ts-ignore
187
+ if (data.length === 0) return "\"\"";
188
+ // Fast path for Vectors (3)
189
+ let char: i32 = 0;
190
+ if (data.length === 1) {
191
+ char === unsafeCharCodeAt(data, 0);
192
+ if (char === 34) {
193
+ return "\\\"";
194
+ } else if (char === 92) {
195
+ return "\\n";
196
+ } else if (char <= 13 && char >= 8) {
197
+ switch (char) {
198
+ case 0x5C: {
199
+ return "\\\\";
200
+ }
201
+ case 0x08: {
202
+ return "\\b";
203
+ }
204
+ case 0x0D: {
205
+ return "\\r";
206
+ }
207
+ case 0x09: {
208
+ return "\\t";
209
+ }
210
+ case 0x0C: {
211
+ return "\\f";
212
+ }
213
+ case 0x0B: {
214
+ return "\\u000b";
215
+ }
216
+ }
217
+ } else {
218
+ return data;
219
+ }
220
+ }
221
+
222
+ let result = "\"";
223
+
224
+ let last: i32 = 0;
225
+ let found: boolean = false;
226
+ // @ts-ignore
227
+ for (let i = 0; i < data.length; i++) {
228
+ char = unsafeCharCodeAt(<string>data, i);
229
+ if (char === 34 || char === 92) {
230
+ result += (<string>data).slice(last, i) + "\\";
231
+ last = i;
232
+ found = true;
233
+ i++;
234
+ } else if (char <= 13 && char >= 8) {
235
+ result += (<string>data).slice(last, i);
236
+ last = ++i;
237
+ found = true;
238
+ switch (char) {
239
+ case 0x5C: {
240
+ result += "\\\\";
241
+ break;
242
+ }
243
+ case 0x08: {
244
+ result += "\\b";
245
+ break;
246
+ }
247
+ case 0x0D: {
248
+ result += "\\r";
249
+ break;
250
+ }
251
+ case 0x09: {
252
+ result += "\\t";
253
+ break;
254
+ }
255
+ case 0x0C: {
256
+ result += "\\f";
257
+ break;
258
+ }
259
+ case 0x0B: {
260
+ result += "\\u000b";
261
+ break;
262
+ }
263
+ }
264
+ }
265
+ }// 8 10 13 9 12
266
+ if (!found) return "\"" + data + "\"";
267
+ else result += (<string>data).slice(last);
268
+ return result + "\"";
269
+ }
204
270
  // @ts-ignore
205
271
  @inline
206
272
  // @ts-ignore
207
273
  function parseBigNum<T>(data: string): T {
208
274
  // @ts-ignore
209
275
  if (idof<T>() == idof<u128>()) return u128.fromString(data);
210
- // @ts-ignore
276
+ // @ts-ignore
211
277
  if (idof<T>() == idof<u128Safe>()) return u128Safe.fromString(data);
212
- // @ts-ignore
278
+ // @ts-ignore
213
279
  if (idof<T>() == idof<u256>()) return u128Safe.fromString(data);
214
- // @ts-ignore
280
+ // @ts-ignore
215
281
  if (idof<T>() == idof<u256Safe>()) return u256Safe.fromString(data);
216
- // @ts-ignore
282
+ // @ts-ignore
217
283
  if (idof<T>() == idof<i128>()) return i128.fromString(data);
218
- // @ts-ignore
284
+ // @ts-ignore
219
285
  if (idof<T>() == idof<i128Safe>()) return i128Safe.fromString(data);
220
- // @ts-ignore
286
+ // @ts-ignore
221
287
  //if (idof<T>() == idof<i256Safe>()) return data.
222
288
  }
223
289
 
224
290
  // @ts-ignore
225
291
  @inline
226
292
  function parseString(data: string): string {
227
- return data.slice(1, data.length - 1).replaceAll('\\"', '"');
293
+ let result = "";
294
+ let last = 1;
295
+ let char = 0;
296
+ for (let i = 1; i < data.length - 1; i++) {
297
+ // \\"
298
+ if (unsafeCharCodeAt(data, i) === backSlashCode) {
299
+ char = unsafeCharCodeAt(data, ++i);
300
+ result += data.slice(last, i - 1)
301
+ if (char === 34) {
302
+ result += "\"";
303
+ last = ++i;
304
+ } else if (char === 110) {
305
+ result += "\n";
306
+ last = ++i;
307
+ // 92 98 114 116 102 117
308
+ } else if (char >= 92 && char <= 117) {
309
+ if (char === 92) {
310
+ result += "\\";
311
+ last = ++i;
312
+ } else if (char === 98) {
313
+ result += "\b";
314
+ last = ++i;
315
+ } else if (char === 102) {
316
+ result += "\f";
317
+ last = ++i;
318
+ } else if (char === 114) {
319
+ result += "\r";
320
+ last = ++i;
321
+ } else if (char === 116) {
322
+ result += "\t";
323
+ last = ++i;
324
+ } else if (char === 117 && load<u64>(changetype<usize>(data) + <usize>((i + 1) << 1)) === 27584753879220272) {
325
+ result += "\u000b";
326
+ i += 4;
327
+ last = ++i;
328
+ }
329
+ }
330
+ }
331
+ }
332
+ result += data.slice(last, data.length - 1);
333
+ return result;
228
334
  }
229
335
 
230
336
  // @ts-ignore
@@ -396,7 +502,7 @@ function parseArray<T extends unknown[]>(data: string): T {
396
502
  return parseArrayArray<T>(data);
397
503
  // @ts-ignore
398
504
  } else if (isManaged<valueof<T>>() || isReference<valueof<T>>()) {
399
- const type = changetype<nonnull<valueof<T>>>(__new(offsetof<nonnull<valueof<T>>>(), idof <nonnull<valueof<T>>>()));
505
+ const type = changetype<nonnull<valueof<T>>>(__new(offsetof<nonnull<valueof<T>>>(), idof<nonnull<valueof<T>>>()));
400
506
  // @ts-ignore
401
507
  if (isDefined(type.__JSON_Set_Key)) {
402
508
  // @ts-ignore
package/assembly/test.ts CHANGED
@@ -2,16 +2,85 @@ import { u128 } from "as-bignum/assembly";
2
2
  import {
3
3
  JSON
4
4
  } from ".";
5
+ import { unsafeCharCodeAt } from "./src/util";
6
+ import { backSlashCode, quoteCode } from "./src/chars";
5
7
 
6
8
  const exp = `["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 \\""]`;
7
9
 
8
- console.log(exp);
9
- console.log(JSON.stringify([
10
+ /*console.log(JSON.stringify([
10
11
  "abcdefg",
11
12
  'st"ring" w""ith quotes"',
12
13
  'string \t\r"with ran\tdom spa\nces and \nnewlines\n\n\n',
13
14
  'string with colon : comma , brace [ ] bracket { } and quote " and other quote "',
14
- ]))
15
+ ]));*/
16
+
17
+ const str = "\\\""
18
+
19
+ function parseString(data: string): string {
20
+ let result = "";
21
+ let last = 1;
22
+ let char = 0;
23
+ for (let i = 1; i < data.length - 1; i++) {
24
+ // \\"
25
+ if (unsafeCharCodeAt(data, i) === backSlashCode) {
26
+ char = unsafeCharCodeAt(data, ++i);
27
+ result += data.slice(last, i - 1)
28
+ if (char === 34) {
29
+ result += "\"";
30
+ last = ++i;
31
+ } else if (char === 110) {
32
+ result += "\n";
33
+ last = ++i;
34
+ // 92 98 114 116 102 117
35
+ } else if (char >= 92 && char <= 117) {
36
+ if (char === 92) {
37
+ result += "\\";
38
+ last = ++i;
39
+ } else if (char === 98) {
40
+ result += "\b";
41
+ last = ++i;
42
+ } else if (char === 102) {
43
+ result += "\f";
44
+ last = ++i;
45
+ } else if (char === 114) {
46
+ result += "\r";
47
+ last = ++i;
48
+ } else if (char === 116) {
49
+ result += "\t";
50
+ last = ++i;
51
+ } else if (char === 117 && load<u64>(changetype<usize>(data) + <usize>((i + 1) << 1)) === 27584753879220272) {
52
+ result += "\u000b";
53
+ i += 4;
54
+ last = ++i;
55
+ }
56
+ }
57
+ }
58
+ }
59
+ result += data.slice(last, data.length - 1);
60
+ return result;
61
+ }
62
+
63
+ console.log(parseString("\"Hello W\\\"orld!\""));
64
+ console.log(parseString("\"Hello New \\nWorld!\""));
65
+ console.log(parseString("\"\\t TAB Hello World!\""));
66
+ console.log(JSON.stringify(parseString("\"U000B \\u000b Hello World!\"")));
67
+ console.log(load<u32>(changetype<usize>(str)).toString());
68
+ console.log(load<u8>(changetype<usize>(str)).toString());
69
+ console.log(load<u8>(changetype<usize>(str) + <usize>2).toString());
70
+
71
+ console.log("abcdefg");
72
+ console.log('st"ring" w""ith quotes"');
73
+ console.log('string \t\r"with ran\tdom spa\nces and \nnewlines\n\n\n');
74
+ console.log('string with colon : comma , brace [ ] bracket { } and quote " and other quote "');
75
+
76
+ console.log(JSON.stringify("abcdefg"));
77
+ console.log(JSON.stringify('st"ring" w""ith quotes"'));
78
+ console.log(JSON.stringify('string \t\r"with ran\tdom spa\nces and \nnewlines\n\n\n'));
79
+ console.log(JSON.stringify('string with colon : comma , brace [ ] bracket { } and quote " and other quote "'));
80
+
81
+ console.log(JSON.stringify("Hello W\"orld!"));
82
+
83
+ console.log("U000B: \u000b")
15
84
  // @ts-ignore
16
85
  @JSON
17
86
  class Vec3 {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "json-as",
3
- "version": "0.5.26",
3
+ "version": "0.5.28",
4
4
  "description": "JSON encoder/decoder for AssemblyScript",
5
5
  "types": "assembly/index.ts",
6
6
  "author": "Jairus Tanaka",
@@ -31,13 +31,18 @@ class AsJSONTransform extends BaseVisitor {
31
31
  }
32
32
  let type = getName(node.type);
33
33
  // @ts-ignore
34
- this.currentClass.encodeStmts.push(`"${name}":\${JSON.stringify<${type}>(this.${name})},`);
34
+ if (["u8", "i8", "u16", "i16", "u32", "i32", "f32", "u64", "i64", "f64"].includes(type.toLowerCase())) {
35
+ this.currentClass.encodeStmts.push(`"${name}":\${this.${name}.toString()},`);
36
+ }
37
+ else {
38
+ this.currentClass.encodeStmts.push(`"${name}":\${JSON.stringify<${type}>(this.${name})},`);
39
+ }
35
40
  // @ts-ignore
36
41
  //this.decodeStmts.push(
37
42
  // `${name}: JSON.parseObjectValue<${type}>(values.get("${name}")),\n`
38
43
  //);
39
44
  // @ts-ignore
40
- this.currentClass.setDataStmts.push(`if (key.length === ${name.length} && (memory.compare(changetype<usize>("${name}"), changetype<usize>(key), ${name.length}) == 0)) {
45
+ this.currentClass.setDataStmts.push(`if (key == "${name}") {
41
46
  this.${name} = JSON.parseObjectValue<${type}>(value);
42
47
  return;
43
48
  }
@@ -93,6 +98,7 @@ class AsJSONTransform extends BaseVisitor {
93
98
  const stmt = this.currentClass.encodeStmts[this.currentClass.encodeStmts.length - 1];
94
99
  this.currentClass.encodeStmts[this.currentClass.encodeStmts.length - 1] = stmt.slice(0, stmt.length - 1);
95
100
  serializeFunc = `
101
+ @inline
96
102
  __JSON_Serialize(): string {
97
103
  return \`{${this.currentClass.encodeStmts.join("")}}\`;
98
104
  }
@@ -100,12 +106,14 @@ class AsJSONTransform extends BaseVisitor {
100
106
  }
101
107
  else {
102
108
  serializeFunc = `
109
+ @inline
103
110
  __JSON_Serialize(): string {
104
111
  return "{}";
105
112
  }
106
113
  `;
107
114
  }
108
115
  const setKeyFunc = `
116
+ @inline
109
117
  __JSON_Set_Key(key: string, value: string): void {
110
118
  ${
111
119
  // @ts-ignore
@@ -117,6 +125,8 @@ class AsJSONTransform extends BaseVisitor {
117
125
  const setDataMethod = SimpleParser.parseClassMember(setKeyFunc, node);
118
126
  node.members.push(setDataMethod);
119
127
  this.schemasList.push(this.currentClass);
128
+ console.log(serializeFunc);
129
+ console.log(setKeyFunc);
120
130
  }
121
131
  visitSource(node) {
122
132
  super.visitSource(node);
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@json-as/transform",
3
- "version": "0.5.26",
3
+ "version": "0.5.28",
4
4
  "description": "JSON encoder/decoder for AssemblyScript",
5
5
  "main": "./lib/index.js",
6
6
  "author": "Jairus Tanaka",
@@ -35,9 +35,15 @@ class AsJSONTransform extends BaseVisitor {
35
35
 
36
36
  let type = getName(node.type);
37
37
  // @ts-ignore
38
- this.currentClass.encodeStmts.push(
39
- `"${name}":\${JSON.stringify<${type}>(this.${name})},`
40
- );
38
+ if (["u8", "i8", "u16", "i16", "u32", "i32", "f32", "u64", "i64", "f64"].includes(type.toLowerCase())) {
39
+ this.currentClass.encodeStmts.push(
40
+ `"${name}":\${this.${name}.toString()},`
41
+ );
42
+ } else {
43
+ this.currentClass.encodeStmts.push(
44
+ `"${name}":\${JSON.stringify<${type}>(this.${name})},`
45
+ );
46
+ }
41
47
 
42
48
  // @ts-ignore
43
49
  //this.decodeStmts.push(
@@ -46,7 +52,7 @@ class AsJSONTransform extends BaseVisitor {
46
52
 
47
53
  // @ts-ignore
48
54
  this.currentClass.setDataStmts.push(
49
- `if (key.length === ${name.length} && (memory.compare(changetype<usize>("${name}"), changetype<usize>(key), ${name.length}) == 0)) {
55
+ `if (key == "${name}") {
50
56
  this.${name} = JSON.parseObjectValue<${type}>(value);
51
57
  return;
52
58
  }
@@ -107,12 +113,14 @@ class AsJSONTransform extends BaseVisitor {
107
113
  stmt.length - 1
108
114
  );
109
115
  serializeFunc = `
116
+ @inline
110
117
  __JSON_Serialize(): string {
111
118
  return \`{${this.currentClass.encodeStmts.join("")}}\`;
112
119
  }
113
120
  `;
114
121
  } else {
115
122
  serializeFunc = `
123
+ @inline
116
124
  __JSON_Serialize(): string {
117
125
  return "{}";
118
126
  }
@@ -120,6 +128,7 @@ class AsJSONTransform extends BaseVisitor {
120
128
  }
121
129
 
122
130
  const setKeyFunc = `
131
+ @inline
123
132
  __JSON_Set_Key(key: string, value: string): void {
124
133
  ${
125
134
  // @ts-ignore
@@ -138,6 +147,9 @@ class AsJSONTransform extends BaseVisitor {
138
147
  node.members.push(setDataMethod);
139
148
 
140
149
  this.schemasList.push(this.currentClass);
150
+
151
+ console.log(serializeFunc);
152
+ console.log(setKeyFunc);
141
153
  }
142
154
  visitSource(node: Source): void {
143
155
  super.visitSource(node);