json-as 0.5.32 → 0.5.34

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/asconfig.json CHANGED
@@ -12,6 +12,9 @@
12
12
  "options": {
13
13
  "transform": [
14
14
  "./transform"
15
- ]
16
- }
15
+ ],
16
+ "bindings": "esm",
17
+ "exportStart": "_start"
18
+ },
19
+ "extends": "./node_modules/@assemblyscript/wasi-shim/asconfig.json"
17
20
  }
@@ -1,6 +1,7 @@
1
1
  import { JSON } from "..";
2
2
  import { backSlashCode, quoteCode } from "../src/chars";
3
3
  import { atoi_fast, unsafeCharCodeAt } from "../src/util";
4
+ import { HASH } from "util/hash";
4
5
 
5
6
  @json
6
7
  class Vec3 {
@@ -23,28 +24,28 @@ class Vec3 {
23
24
  if (inStr === false && char === quoteCode) {
24
25
  if (key != null) {
25
26
  if (unsafeCharCodeAt(key, 0) == 120) {
26
- to.x = atoi_fast<i32>(data.slice(last, pos - 1))
27
+ to.x = atoi_fast<i32>(data.substring(last, pos - 1))
27
28
  } else if (unsafeCharCodeAt(key, 0) == 121) {
28
- to.y = atoi_fast<i32>(data.slice(last, pos - 1))
29
+ to.y = atoi_fast<i32>(data.substring(last, pos - 1))
29
30
  } else if (unsafeCharCodeAt(key, 0) == 122) {
30
- to.z = atoi_fast<i32>(data.slice(last, pos - 1))
31
+ to.z = atoi_fast<i32>(data.substring(last, pos - 1))
31
32
  }
32
33
  }
33
34
  last = ++pos;
34
35
  inStr = true;
35
36
  } else if (char === quoteCode && unsafeCharCodeAt(data, pos - 1) != backSlashCode) {
36
37
  inStr = false;
37
- key = data.slice(last, pos);
38
+ key = data.substring(last, pos);
38
39
  last = pos += 2;
39
40
  }
40
41
  }
41
42
  if (key != null) {
42
43
  if (unsafeCharCodeAt(key, 0) == 120) {
43
- to.x = atoi_fast<i32>(data.slice(last, pos - 1))
44
+ to.x = atoi_fast<i32>(data.substring(last, pos - 1))
44
45
  } else if (unsafeCharCodeAt(key, 0) == 121) {
45
- to.y = atoi_fast<i32>(data.slice(last, pos - 1))
46
+ to.y = atoi_fast<i32>(data.substring(last, pos - 1))
46
47
  } else if (unsafeCharCodeAt(key, 0) == 122) {
47
- to.z = atoi_fast<i32>(data.slice(last, pos - 1))
48
+ to.z = atoi_fast<i32>(data.substring(last, pos - 1))
48
49
  }
49
50
  }
50
51
  return to;
@@ -65,6 +66,9 @@ bench("Stringify Object (Vec3)", () => {
65
66
  blackbox<string>(vec.__JSON_Serialize(vec));
66
67
  });*/
67
68
 
69
+ bench("HASH String", () => {
70
+ blackbox<number>(HASH("Hello"));
71
+ })
68
72
  // TODO: Make this allocate without crashing
69
73
  bench("Parse Object (Vec3)", () => {
70
74
  blackbox<Vec3>(vec.__JSON_Deserialize('{"x":0,"y":0,"z":0}', vec));
package/assembly/test.ts CHANGED
@@ -2,69 +2,52 @@ import { backSlashCode, quoteCode } from "./src/chars";
2
2
  import { JSON } from "./src/json";
3
3
  import { atoi_fast, unsafeCharCodeAt } from "./src/util";
4
4
 
5
- // @json or @serializable work here
6
5
  @json
7
6
  class Vec3 {
8
7
  x!: f32;
9
8
  y!: f32;
10
9
  z!: f32;
10
+ }
11
11
 
12
- @inline
13
- __JSON_Serialize(): string {
14
- return `{"x":${this.x.toString()},"y":${this.y.toString()},"z":${this.z.toString()}}`;
15
- }
16
-
17
- @inline
18
- __JSON_Deserialize(data: string, to: Vec3): Vec3 {
19
- let last = 1;
20
- let char = 0;
21
- let inStr = false;
22
- let key: string | null = null;
23
- let pos = 0;
24
- for (; pos < data.length - 1; pos++) {
25
- char = unsafeCharCodeAt(data, pos);
26
- if (inStr === false && char === quoteCode) {
27
- if (key != null) {
28
- if (key == "x") {
29
- to.x = f32.parse(data.slice(last, pos - 1))
30
- } else if (key == "y") {
31
- to.y = f32.parse(data.slice(last, pos - 1))
32
- } else if (key == "z") {
33
- to.z = f32.parse(data.slice(last, pos - 1))
34
- }
35
- }
36
- last = ++pos;
37
- inStr = true;
38
- } else if (char === quoteCode && unsafeCharCodeAt(data, pos - 1) != backSlashCode) {
39
- inStr = false;
40
- key = data.slice(last, pos);
41
- last = pos += 2;
42
- }
43
- }
44
- if (key != null) {
45
- if (key == "x") {
46
- to.x = f32.parse(data.slice(last, pos - 1))
47
- } else if (key == "y") {
48
- to.y = f32.parse(data.slice(last, pos - 1))
49
- } else if (key == "z") {
50
- to.z = f32.parse(data.slice(last, pos - 1))
51
- }
52
- }
53
- return to;
54
- }
12
+ @json
13
+ class Player {
14
+ firstName!: string;
15
+ lastName!: string;
16
+ lastActive!: i32[];
17
+ age!: i32;
18
+ pos!: Vec3 | null;
19
+ isVerified!: boolean;
55
20
  }
56
21
 
22
+ const player: Player = {
23
+ firstName: "Emmet",
24
+ lastName: "West",
25
+ lastActive: [8, 27, 2022],
26
+ age: 23,
27
+ pos: {
28
+ x: 3.4,
29
+ y: 1.2,
30
+ z: 8.3
31
+ },
32
+ isVerified: true
33
+ };
34
+
57
35
  const vec: Vec3 = {
58
- x: 3.4,
59
- y: 1.2,
60
- z: 8.3
36
+ x: 3,
37
+ y: 1,
38
+ z: 8
61
39
  }
62
40
 
63
- const serializedVec3 = vec.__JSON_Serialize();
41
+ const serializedPlayer = JSON.stringify<Player>(player);
42
+ console.log(serializedPlayer);
43
+ const parsedPlayer = JSON.parse<Player>(serializedPlayer);
44
+ console.log(JSON.stringify(parsedPlayer));
45
+
46
+ const serializedVec3 = JSON.stringify(vec);
64
47
  console.log(serializedVec3);
65
48
 
66
- const parsedVec3 = vec.__JSON_Deserialize(serializedVec3, new Vec3());
67
- console.log(parsedVec3.__JSON_Serialize());
49
+ const parsedVec3 = JSON.parse<Vec3>(serializedVec3);
50
+ console.log(JSON.stringify(parsedVec3));
68
51
 
69
52
  console.log(`atoi_fast("429496729"): ${atoi_fast<i32>("429496729")}`);
70
53
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "json-as",
3
- "version": "0.5.32",
3
+ "version": "0.5.34",
4
4
  "description": "JSON encoder/decoder for AssemblyScript",
5
5
  "types": "assembly/index.ts",
6
6
  "author": "Jairus Tanaka",
@@ -0,0 +1,74 @@
1
+ // XXHash 32-bit as a starting point, see: https://cyan4973.github.io/xxHash
2
+ // primes
3
+ // @ts-ignore: decorator
4
+ const XXH32_P1 = 2654435761;
5
+ // @ts-ignore: decorator
6
+ const XXH32_P2 = 2246822519;
7
+ // @ts-ignore: decorator
8
+ const XXH32_P3 = 3266489917;
9
+ // @ts-ignore: decorator
10
+ const XXH32_P4 = 668265263;
11
+ // @ts-ignore: decorator
12
+ const XXH32_P5 = 374761393;
13
+ // @ts-ignore: decorator
14
+ const XXH32_SEED = 0;
15
+ function hash32(key, len = 4) {
16
+ let h = XXH32_SEED + XXH32_P5 + len;
17
+ h += key * XXH32_P3;
18
+ h = rotl(h, 17) * XXH32_P4;
19
+ h ^= h >> 15;
20
+ h *= XXH32_P2;
21
+ h ^= h >> 13;
22
+ h *= XXH32_P3;
23
+ h ^= h >> 16;
24
+ return h;
25
+ }
26
+ function rotl(x, r) {
27
+ return (x << r) | (x >>> (32 - r));
28
+ }
29
+ function mix(h, key) {
30
+ return rotl(h + key * XXH32_P2, 13) * XXH32_P1;
31
+ }
32
+ export function hashStr(key) {
33
+ if (key == null)
34
+ return XXH32_SEED;
35
+ let h = key.length;
36
+ let len = h;
37
+ let pos = 0;
38
+ if (len >= 16) {
39
+ let s1 = XXH32_SEED + XXH32_P1 + XXH32_P2;
40
+ let s2 = XXH32_SEED + XXH32_P2;
41
+ let s3 = XXH32_SEED;
42
+ let s4 = XXH32_SEED - XXH32_P1;
43
+ let end = len + pos - 16;
44
+ while (pos <= end) {
45
+ s1 = mix(s1, key.charCodeAt(pos));
46
+ s2 = mix(s2, key.charCodeAt(pos + 1));
47
+ s3 = mix(s3, key.charCodeAt(pos + 2));
48
+ s4 = mix(s4, load(pos, 12));
49
+ pos += 16;
50
+ }
51
+ h += rotl(s1, 1) + rotl(s2, 7) + rotl(s3, 12) + rotl(s4, 18);
52
+ }
53
+ else {
54
+ h += XXH32_SEED + XXH32_P5;
55
+ }
56
+ let end = changetype(key) + len - 4;
57
+ while (pos <= end) {
58
+ h += load(pos) * XXH32_P3;
59
+ h = rotl(h, 17) * XXH32_P4;
60
+ pos += 4;
61
+ }
62
+ end = changetype(key) + len;
63
+ while (pos < end) {
64
+ h += load(pos) * XXH32_P5;
65
+ h = rotl(h, 11) * XXH32_P1;
66
+ pos++;
67
+ }
68
+ h ^= h >> 15;
69
+ h *= XXH32_P2;
70
+ h ^= h >> 13;
71
+ h *= XXH32_P3;
72
+ h ^= h >> 16;
73
+ return h;
74
+ }
@@ -1,4 +1,4 @@
1
- import { getName, toString, isStdlib } from "visitor-as/dist/utils.js";
1
+ import { toString, isStdlib } from "visitor-as/dist/utils.js";
2
2
  import { BaseVisitor, SimpleParser } from "visitor-as/dist/index.js";
3
3
  import { Transform } from "assemblyscript/dist/transform.js";
4
4
  class SchemaData {
@@ -19,41 +19,6 @@ class AsJSONTransform extends BaseVisitor {
19
19
  this.sources = [];
20
20
  }
21
21
  visitMethodDeclaration() { }
22
- visitFieldDeclaration(node) {
23
- if (toString(node).startsWith("static"))
24
- return;
25
- const lineText = toString(node);
26
- if (lineText.startsWith("private"))
27
- return;
28
- const name = getName(node);
29
- if (!node.type) {
30
- throw new Error(`Field ${name} is missing a type declaration`);
31
- }
32
- let type = getName(node.type);
33
- // @ts-ignore
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
- }
40
- this.currentClass.keys.push(name);
41
- this.currentClass.types.push(type);
42
- // @ts-ignore
43
- //this.decodeStmts.push(
44
- // `${name}: JSON.parseObjectValue<${type}>(values.get("${name}")),\n`
45
- //);
46
- // @ts-ignore
47
- this.currentClass.setDataStmts.push(`if (key == "${name}") {
48
- this.${name} = JSON.parseObjectValue<${type}>(value);
49
- return;
50
- }
51
- `);
52
- // @ts-ignore
53
- //this.checkDecodeStmts.push(
54
- // ' if (!values.has("${name}")) throw new Error("Key "${name}" was not found. Cannot instantiate object.");\n'
55
- //);
56
- }
57
22
  visitClassDeclaration(node) {
58
23
  var _c;
59
24
  const className = node.name.text;
@@ -67,7 +32,7 @@ class AsJSONTransform extends BaseVisitor {
67
32
  }
68
33
  if (!foundDecorator)
69
34
  return;
70
- // Prevent from being triggered twice
35
+ // Prevent from being triggered twice.
71
36
  for (const member of node.members) {
72
37
  if (member.name.text == "__JSON_Serialize")
73
38
  return;
@@ -94,7 +59,35 @@ class AsJSONTransform extends BaseVisitor {
94
59
  }
95
60
  const parentSchema = this.schemasList.find((v) => v.name == this.currentClass.parent);
96
61
  const members = [...node.members, ...(parentSchema ? parentSchema.node.members : [])];
97
- this.visit(members);
62
+ for (const mem of members) {
63
+ if (mem.type && mem.type.name && mem.type.name.identifier.text) {
64
+ const member = mem;
65
+ if (toString(member).startsWith("static"))
66
+ return;
67
+ const lineText = toString(member);
68
+ if (lineText.startsWith("private"))
69
+ return;
70
+ // @ts-ignore
71
+ let type = toString(member.type);
72
+ const name = member.name.text;
73
+ this.currentClass.keys.push(name);
74
+ // @ts-ignore
75
+ this.currentClass.types.push(type);
76
+ // @ts-ignore
77
+ if (["u8", "i8", "u16", "i16", "u32", "i32", "f32", "u64", "i64", "f64"].includes(type.toLowerCase())) {
78
+ this.currentClass.encodeStmts.push(`"${name}":\${this.${name}.toString()},`);
79
+ }
80
+ else {
81
+ this.currentClass.encodeStmts.push(`"${name}":\${JSON.stringify<${type}>(this.${name})},`);
82
+ }
83
+ // @ts-ignore
84
+ this.currentClass.setDataStmts.push(`if (key == "${name}") {
85
+ this.${name} = JSON.parseObjectValue<${type}>(value);
86
+ return;
87
+ }
88
+ `);
89
+ }
90
+ }
98
91
  let serializeFunc = "";
99
92
  if (this.currentClass.encodeStmts.length > 0) {
100
93
  const stmt = this.currentClass.encodeStmts[this.currentClass.encodeStmts.length - 1];
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@json-as/transform",
3
- "version": "0.5.32",
3
+ "version": "0.5.34",
4
4
  "description": "JSON encoder/decoder for AssemblyScript",
5
5
  "main": "./lib/index.js",
6
6
  "author": "Jairus Tanaka",
@@ -10,7 +10,9 @@
10
10
  "Rom"
11
11
  ],
12
12
  "license": "MIT",
13
- "devDependencies": {},
13
+ "devDependencies": {
14
+ "assemblyscript": "^0.27.1"
15
+ },
14
16
  "dependencies": {},
15
17
  "repository": {
16
18
  "type": "git",
@@ -0,0 +1,83 @@
1
+ // XXHash 32-bit as a starting point, see: https://cyan4973.github.io/xxHash
2
+
3
+ // primes
4
+ // @ts-ignore: decorator
5
+ const XXH32_P1: number = 2654435761;
6
+ // @ts-ignore: decorator
7
+ const XXH32_P2: number = 2246822519;
8
+ // @ts-ignore: decorator
9
+ const XXH32_P3: number = 3266489917;
10
+ // @ts-ignore: decorator
11
+ const XXH32_P4: number = 668265263;
12
+ // @ts-ignore: decorator
13
+ const XXH32_P5: number = 374761393;
14
+ // @ts-ignore: decorator
15
+ const XXH32_SEED: number = 0;
16
+
17
+ function hash32(key: number, len: number = 4): number {
18
+ let h: number = XXH32_SEED + XXH32_P5 + len;
19
+ h += key * XXH32_P3;
20
+ h = rotl(h, 17) * XXH32_P4;
21
+ h ^= h >> 15;
22
+ h *= XXH32_P2;
23
+ h ^= h >> 13;
24
+ h *= XXH32_P3;
25
+ h ^= h >> 16;
26
+ return h;
27
+ }
28
+
29
+ function rotl(x: number, r: number): number {
30
+ return (x << r) | (x >>> (32 - r));
31
+ }
32
+
33
+ function mix(h: number, key: number): number {
34
+ return rotl(h + key * XXH32_P2, 13) * XXH32_P1;
35
+ }
36
+
37
+ export function hashStr(key: string): number {
38
+ if (key == null) return XXH32_SEED;
39
+
40
+ let h: number = key.length;
41
+ let len: number = h;
42
+ let pos = 0;
43
+
44
+ if (len >= 16) {
45
+ let s1 = XXH32_SEED + XXH32_P1 + XXH32_P2;
46
+ let s2 = XXH32_SEED + XXH32_P2;
47
+ let s3 = XXH32_SEED;
48
+ let s4 = XXH32_SEED - XXH32_P1;
49
+
50
+ let end = len + pos - 16;
51
+ while (pos <= end) {
52
+ s1 = mix(s1, key.charCodeAt(pos));
53
+ s2 = mix(s2, key.charCodeAt(pos + 1));
54
+ s3 = mix(s3, key.charCodeAt(pos + 2));
55
+ s4 = mix(s4, load<number>(pos, 12));
56
+ pos += 16;
57
+ }
58
+ h += rotl(s1, 1) + rotl(s2, 7) + rotl(s3, 12) + rotl(s4, 18);
59
+ } else {
60
+ h += XXH32_SEED + XXH32_P5;
61
+ }
62
+
63
+ let end = changetype<number>(key) + len - 4;
64
+ while (pos <= end) {
65
+ h += load<number>(pos) * XXH32_P3;
66
+ h = rotl(h, 17) * XXH32_P4;
67
+ pos += 4;
68
+ }
69
+
70
+ end = changetype<number>(key) + len;
71
+ while (pos < end) {
72
+ h += <number>load<u8>(pos) * XXH32_P5;
73
+ h = rotl(h, 11) * XXH32_P1;
74
+ pos++;
75
+ }
76
+
77
+ h ^= h >> 15;
78
+ h *= XXH32_P2;
79
+ h ^= h >> 13;
80
+ h *= XXH32_P3;
81
+ h ^= h >> 16;
82
+ return h;
83
+ }
@@ -4,7 +4,7 @@ import {
4
4
  Source,
5
5
  Parser
6
6
  } from "assemblyscript/dist/assemblyscript";
7
- import { getName, toString, isStdlib } from "visitor-as/dist/utils.js";
7
+ import { toString, isStdlib } from "visitor-as/dist/utils.js";
8
8
  import { BaseVisitor, SimpleParser } from "visitor-as/dist/index.js";
9
9
  import { Transform } from "assemblyscript/dist/transform.js";
10
10
 
@@ -24,48 +24,6 @@ class AsJSONTransform extends BaseVisitor {
24
24
  public sources: Source[] = [];
25
25
 
26
26
  visitMethodDeclaration(): void { }
27
- visitFieldDeclaration(node: FieldDeclaration): void {
28
- if (toString(node).startsWith("static")) return;
29
- const lineText = toString(node);
30
- if (lineText.startsWith("private")) return;
31
- const name = getName(node);
32
- if (!node.type) {
33
- throw new Error(`Field ${name} is missing a type declaration`);
34
- }
35
-
36
- let type = getName(node.type);
37
- // @ts-ignore
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
- }
47
-
48
- this.currentClass.keys.push(name);
49
- this.currentClass.types.push(type);
50
- // @ts-ignore
51
- //this.decodeStmts.push(
52
- // `${name}: JSON.parseObjectValue<${type}>(values.get("${name}")),\n`
53
- //);
54
-
55
- // @ts-ignore
56
- this.currentClass.setDataStmts.push(
57
- `if (key == "${name}") {
58
- this.${name} = JSON.parseObjectValue<${type}>(value);
59
- return;
60
- }
61
- `
62
- );
63
-
64
- // @ts-ignore
65
- //this.checkDecodeStmts.push(
66
- // ' if (!values.has("${name}")) throw new Error("Key "${name}" was not found. Cannot instantiate object.");\n'
67
- //);
68
- }
69
27
  visitClassDeclaration(node: ClassDeclaration): void {
70
28
  const className = node.name.text;
71
29
  if (!node.decorators?.length) return;
@@ -76,7 +34,7 @@ class AsJSONTransform extends BaseVisitor {
76
34
  }
77
35
  if (!foundDecorator) return;
78
36
 
79
- // Prevent from being triggered twice
37
+ // Prevent from being triggered twice.
80
38
  for (const member of node.members) {
81
39
  if (member.name.text == "__JSON_Serialize") return;
82
40
  }
@@ -104,7 +62,41 @@ class AsJSONTransform extends BaseVisitor {
104
62
 
105
63
  const parentSchema = this.schemasList.find((v) => v.name == this.currentClass.parent);
106
64
  const members = [...node.members, ...(parentSchema ? parentSchema.node.members : [])]
107
- this.visit(members);
65
+
66
+ for (const mem of members) {
67
+ if (mem.type && mem.type.name && mem.type.name.identifier.text) {
68
+ const member: FieldDeclaration = mem;
69
+ if (toString(member).startsWith("static")) return;
70
+ const lineText = toString(member);
71
+ if (lineText.startsWith("private")) return;
72
+
73
+ // @ts-ignore
74
+ let type = toString(member.type);
75
+
76
+ const name = member.name.text;
77
+ this.currentClass.keys.push(name);
78
+ // @ts-ignore
79
+ this.currentClass.types.push(type);
80
+ // @ts-ignore
81
+ if (["u8", "i8", "u16", "i16", "u32", "i32", "f32", "u64", "i64", "f64"].includes(type.toLowerCase())) {
82
+ this.currentClass.encodeStmts.push(
83
+ `"${name}":\${this.${name}.toString()},`
84
+ );
85
+ } else {
86
+ this.currentClass.encodeStmts.push(
87
+ `"${name}":\${JSON.stringify<${type}>(this.${name})},`
88
+ );
89
+ }
90
+ // @ts-ignore
91
+ this.currentClass.setDataStmts.push(
92
+ `if (key == "${name}") {
93
+ this.${name} = JSON.parseObjectValue<${type}>(value);
94
+ return;
95
+ }
96
+ `
97
+ );
98
+ }
99
+ }
108
100
 
109
101
  let serializeFunc = "";
110
102
 
@@ -138,7 +130,7 @@ class AsJSONTransform extends BaseVisitor {
138
130
  }
139
131
  }
140
132
  `
141
-
133
+
142
134
  const serializeMethod = SimpleParser.parseClassMember(serializeFunc, node);
143
135
  node.members.push(serializeMethod);
144
136
 
@@ -160,7 +152,7 @@ export default class Transformer extends Transform {
160
152
  afterParse(parser: Parser): void {
161
153
  // Create new transform
162
154
  const transformer = new AsJSONTransform();
163
-
155
+
164
156
  // Sort the sources so that user scripts are visited last
165
157
  const sources = parser.sources.filter(source => !isStdlib(source)).sort((_a, _b) => {
166
158
  const a = _a.internalPath
@@ -173,7 +165,7 @@ export default class Transformer extends Transform {
173
165
  return 0;
174
166
  }
175
167
  })
176
-
168
+
177
169
  // Loop over every source
178
170
  for (const source of sources) {
179
171
  // Ignore all lib and std. Visit everything else.