json-as 0.5.27 → 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
 
@@ -2,29 +2,32 @@ import { JSON } from "..";
2
2
 
3
3
  @json
4
4
  class Vec3 {
5
- x: f32;
6
- y: f32;
7
- z: f32;
5
+ x: i32;
6
+ y: i32;
7
+ z: i32;
8
8
  }
9
9
 
10
10
  const vec: Vec3 = blackbox<Vec3>({
11
- x: 0.0,
12
- y: 0.0,
13
- z: 0.0
11
+ x: 0,
12
+ y: 0,
13
+ z: 0
14
14
  });
15
15
 
16
16
  bench("Stringify Object (Vec3)", () => {
17
17
  blackbox(JSON.stringify(vec));
18
- });/*
18
+ });
19
19
 
20
20
  bench("Parse Object (Vec3)", () => {
21
- blackbox(JSON.parse<Vec3>(blackbox('{"x":0.0,"y":0.0,"z":0.0}')));
22
- });
21
+ blackbox(JSON.parse<Vec3>(blackbox('{"x":0,"y":0,"z":0}')));
22
+ });/*
23
23
 
24
24
  bench("Stringify Array", () => {
25
25
  blackbox(JSON.stringify(blackbox([1, 2, 3, 4, 5])));
26
26
  });
27
-
27
+ bench("Stringify String Array", () => {
28
+ blackbox(JSON.stringify(blackbox(["a", "b", "c", "d", "e"])));
29
+ });
30
+ /*
28
31
  bench("Parse Array", () => {
29
32
  blackbox(JSON.parse<i32[]>(blackbox("[1,2,3,4]")));
30
33
  });
@@ -41,8 +44,8 @@ bench("Stringify Nested Array", () => {
41
44
 
42
45
  bench("Parse Nested Array", () => {
43
46
  blackbox(JSON.parse<string[][]>(blackbox('[["a","b","c"]]')));
44
- });*/
45
-
47
+ });
48
+ */
46
49
  bench("Stringify String", () => {
47
50
  blackbox(JSON.stringify(blackbox("Hello \"World!")));
48
51
  });
@@ -40,65 +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
-
46
- let result = "\"";
47
-
48
- let char: i32 = 0;
49
- let last: i32 = 0;
50
- let found: boolean = false;
51
- // @ts-ignore
52
- for (let i = 0; i < data.length; i++) {
53
- char = unsafeCharCodeAt(<string>data, i);
54
- if (char === 34 || char === 92) {
55
- result += (<string>data).slice(last, i) + "\\";
56
- last = i;
57
- found = true;
58
- i++;
59
- } else if (char <= 13 && char >= 8) {
60
- result += (<string>data).slice(last, i);
61
- last = ++i;
62
- found = true;
63
- switch (char) {
64
- case 0x22: {
65
- result += "\\\"";
66
- break;
67
- }
68
- case 0x5C: {
69
- result += "\\\\";
70
- break;
71
- }
72
- case 0x08: {
73
- result += "\\b";
74
- break;
75
- }
76
- case 0x0A: {
77
- result += "\\n";
78
- break;
79
- }
80
- case 0x0D: {
81
- result += "\\r";
82
- break;
83
- }
84
- case 0x09: {
85
- result += "\\t";
86
- break;
87
- }
88
- case 0x0C: {
89
- result += "\\f";
90
- break;
91
- }
92
- case 0x0B: {
93
- result += "\\u000b";
94
- break;
95
- }
96
- }
97
- }
98
- }// 8 10 13 9 12
99
- if (!found) return "\"" + data + "\"";
100
- else result += (<string>data).slice(last);
101
- return result + "\"";
43
+ return serializeString(data);
102
44
  }
103
45
  // Boolean
104
46
  else if (isBoolean<T>()) {
@@ -124,19 +66,44 @@ export namespace JSON {
124
66
  }
125
67
  // ArrayLike
126
68
  else if (isArrayLike<T>()) {
127
- let result = new StringSink(leftBracketWord);
128
- // @ts-ignore
129
- if (data.length == 0) return emptyArrayWord;
130
69
  // @ts-ignore
131
- 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
+ }
132
102
  // @ts-ignore
133
- result.write(JSON.stringify(unchecked(data[i])));
134
- result.write(commaWord);
103
+ result.write(JSON.stringify(unchecked(data[data.length - 1])));
104
+ result.write(rightBracketWord);
105
+ return result.toString();
135
106
  }
136
- // @ts-ignore
137
- result.write(JSON.stringify(unchecked(data[data.length - 1])));
138
- result.write(rightBracketWord);
139
- return result.toString();
140
107
  } else if ((isManaged<T>() || isReference<T>()) && isBigNum<T>()) {
141
108
  // @ts-ignore
142
109
  return data.toString();
@@ -212,6 +179,94 @@ export namespace JSON {
212
179
  }
213
180
  }
214
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
+ }
215
270
  // @ts-ignore
216
271
  @inline
217
272
  // @ts-ignore
@@ -235,7 +290,47 @@ function parseBigNum<T>(data: string): T {
235
290
  // @ts-ignore
236
291
  @inline
237
292
  function parseString(data: string): string {
238
- 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;
239
334
  }
240
335
 
241
336
  // @ts-ignore
package/assembly/test.ts CHANGED
@@ -2,10 +2,11 @@ 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
10
  /*console.log(JSON.stringify([
10
11
  "abcdefg",
11
12
  'st"ring" w""ith quotes"',
@@ -13,6 +14,60 @@ const exp = `["abcdefg","st\\"ring\\" w\\"\\"ith quotes\\"","string \\t\\r\\"wit
13
14
  'string with colon : comma , brace [ ] bracket { } and quote " and other quote "',
14
15
  ]));*/
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
+
16
71
  console.log("abcdefg");
17
72
  console.log('st"ring" w""ith quotes"');
18
73
  console.log('string \t\r"with ran\tdom spa\nces and \nnewlines\n\n\n');
@@ -24,6 +79,8 @@ console.log(JSON.stringify('string \t\r"with ran\tdom spa\nces and \nnewlines\n\
24
79
  console.log(JSON.stringify('string with colon : comma , brace [ ] bracket { } and quote " and other quote "'));
25
80
 
26
81
  console.log(JSON.stringify("Hello W\"orld!"));
82
+
83
+ console.log("U000B: \u000b")
27
84
  // @ts-ignore
28
85
  @JSON
29
86
  class Vec3 {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "json-as",
3
- "version": "0.5.27",
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.27",
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);