json-as 1.0.0-beta.9 → 1.0.1

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.
Files changed (60) hide show
  1. package/.github/workflows/{nodejs.yml → tests.yml} +1 -1
  2. package/{CHANGELOG → CHANGELOG.md} +45 -0
  3. package/README.md +147 -93
  4. package/assembly/__benches__/abc.bench.ts +21 -0
  5. package/assembly/__benches__/large.bench.ts +174 -0
  6. package/assembly/__benches__/lib/index.ts +26 -0
  7. package/assembly/__benches__/medium.bench.ts +46 -0
  8. package/assembly/__benches__/small.bench.ts +33 -0
  9. package/assembly/__benches__/vec3.bench.ts +72 -0
  10. package/assembly/__tests__/array.spec.ts +42 -0
  11. package/assembly/__tests__/float.spec.ts +3 -3
  12. package/assembly/__tests__/map.spec.ts +7 -0
  13. package/assembly/__tests__/raw.spec.ts +4 -5
  14. package/assembly/__tests__/struct.spec.ts +2 -2
  15. package/assembly/deserialize/simple/arbitrary.ts +8 -4
  16. package/assembly/deserialize/simple/array/arbitrary.ts +6 -6
  17. package/assembly/deserialize/simple/array/array.ts +4 -3
  18. package/assembly/deserialize/simple/array/bool.ts +7 -7
  19. package/assembly/deserialize/simple/array/float.ts +2 -2
  20. package/assembly/deserialize/simple/array/integer.ts +1 -1
  21. package/assembly/deserialize/simple/array/map.ts +1 -1
  22. package/assembly/deserialize/simple/array/string.ts +3 -3
  23. package/assembly/deserialize/simple/array/struct.ts +14 -3
  24. package/assembly/deserialize/simple/array.ts +3 -0
  25. package/assembly/deserialize/simple/map.ts +93 -75
  26. package/assembly/deserialize/simple/object.ts +26 -16
  27. package/assembly/deserialize/simple/struct.ts +31 -19
  28. package/assembly/index.ts +14 -11
  29. package/assembly/serialize/simple/array.ts +1 -0
  30. package/assembly/serialize/simple/bool.ts +1 -0
  31. package/assembly/serialize/simple/date.ts +1 -0
  32. package/assembly/serialize/simple/float.ts +1 -0
  33. package/assembly/serialize/simple/integer.ts +1 -0
  34. package/assembly/serialize/simple/map.ts +1 -0
  35. package/assembly/serialize/simple/object.ts +1 -0
  36. package/assembly/serialize/simple/raw.ts +1 -0
  37. package/assembly/serialize/simple/string.ts +1 -0
  38. package/assembly/test.ts +18 -0
  39. package/bench/abc.bench.ts +20 -0
  40. package/bench/large.bench.ts +126 -0
  41. package/bench/medium.bench.ts +43 -0
  42. package/bench/small.bench.ts +30 -0
  43. package/bench/vec3.bench.ts +26 -0
  44. package/index.ts +1 -1
  45. package/package.json +24 -26
  46. package/run-bench.as.sh +27 -0
  47. package/run-bench.js.sh +12 -0
  48. package/run-tests.sh +14 -2
  49. package/transform/lib/index.js +29 -69
  50. package/transform/lib/index.js.map +1 -1
  51. package/transform/src/index.ts +55 -71
  52. package/.gitmodules +0 -0
  53. package/assembly/__benches__/misc.bench.ts +0 -47
  54. package/assembly/__benches__/schemas.ts +0 -25
  55. package/assembly/__benches__/string.bench.ts +0 -23
  56. package/assembly/__benches__/struct.bench.ts +0 -21
  57. package/assembly/as-bs.d.ts +0 -53
  58. package/bench/schemas.ts +0 -5
  59. package/bench/string.bench.ts +0 -16
  60. /package/bench/{bench.ts → lib/bench.ts} +0 -0
@@ -1,154 +1,172 @@
1
1
  import { JSON } from "../..";
2
2
  import { BACK_SLASH, COMMA, CHAR_F, BRACE_LEFT, BRACKET_LEFT, CHAR_N, QUOTE, BRACE_RIGHT, BRACKET_RIGHT, CHAR_T, COLON } from "../../custom/chars";
3
3
  import { isSpace } from "../../util";
4
+ import { ptrToStr } from "../../util/ptrToStr";
4
5
 
5
6
  export function deserializeMap<T extends Map<any, any>>(srcStart: usize, srcEnd: usize, dst: usize): T {
6
- const out = changetype<T>(dst || __new(offsetof<T>(), idof<T>()));
7
+ const out = changetype<nonnull<T>>(dst || changetype<usize>(instantiate<T>()));
7
8
  // @ts-ignore: type
8
9
  if (!isString<indexof<T>>() && !isInteger<indexof<T>>() && !isFloat<indexof<T>>()) throw new Error("Map key must also be a valid JSON key!");
9
10
 
10
- const srcPtr = srcStart;
11
- let key: string | null = null;
11
+ let keyStart: usize = 0;
12
+ let keyEnd: usize = 0;
12
13
  let isKey = false;
13
14
  let depth = 0;
14
- let lastIndex = 0;
15
+ let lastIndex: usize = 0;
15
16
 
16
- // while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
17
- // while (srcEnd > srcStart && isSpace(load<u16>(srcEnd))) srcEnd -= 2;
17
+ while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
18
+ while (srcEnd > srcStart && isSpace(load<u16>(srcEnd - 2))) srcEnd -= 2; // would like to optimize this later
18
19
 
20
+ if (srcStart - srcEnd == 0)
21
+ throw new Error("Input string had zero length or was all whitespace");
22
+ if (load<u16>(srcStart) != BRACE_LEFT) throw new Error("Expected '{' at start of object at position " + (srcEnd - srcStart).toString());
23
+ if (load<u16>(srcEnd - 2) != BRACE_RIGHT) throw new Error("Expected '}' at end of object at position " + (srcEnd - srcStart).toString());
24
+
25
+ srcStart += 2;
19
26
  while (srcStart < srcEnd) {
20
27
  let code = load<u16>(srcStart); // while (isSpace(code)) code = load<u16>(srcStart += 2);
21
- if (key == null) {
28
+ if (keyStart == 0) {
22
29
  if (code == QUOTE && load<u16>(srcStart - 2) !== BACK_SLASH) {
23
30
  if (isKey) {
24
- key = sliceTo(lastIndex, srcStart);
25
- while (isSpace((code = load<u16>((srcStart += 2))))) {
26
- /* empty */
27
- }
28
- if (code !== COLON) throw new Error("Expected ':' after key at position " + (srcStart - srcPtr).toString());
31
+ keyStart = lastIndex;
32
+ keyEnd = srcStart;
33
+ // console.log("Key: " + ptrToStr(lastIndex, srcStart));
34
+ // console.log("Next: " + String.fromCharCode(load<u16>(srcStart + 2)));
35
+ while (isSpace((code = load<u16>((srcStart += 2))))) { }
36
+ if (code !== COLON) throw new Error("Expected ':' after key at position " + (srcEnd - srcStart).toString());
29
37
  isKey = false;
30
38
  } else {
31
- isKey = true;
39
+ // console.log("Got key start");
40
+ isKey = true; // i don't like this
32
41
  lastIndex = srcStart + 2;
33
42
  }
34
43
  }
35
44
  // isKey = !isKey;
36
45
  srcStart += 2;
37
46
  } else {
38
- // @ts-ignore: type
39
- if (isString<valueof<T>>() && code == QUOTE) {
47
+ if (code == QUOTE) {
40
48
  lastIndex = srcStart;
41
49
  srcStart += 2;
42
50
  while (srcStart < srcEnd) {
43
51
  const code = load<u16>(srcStart);
44
52
  if (code == QUOTE && load<u16>(srcStart - 2) !== BACK_SLASH) {
45
- while (isSpace(load<u16>((srcStart += 2)))) {
46
- /* empty */
47
- }
53
+ // console.log("Value (string): " + ptrToStr(lastIndex, srcStart + 2));
48
54
  // @ts-ignore: type
49
- out.set(key, JSON.__deserialize<valueof<T>>(lastIndex, srcStart));
50
- key = null;
55
+ out.set(ptrToStr(keyStart, keyEnd), JSON.__deserialize<valueof<T>>(lastIndex, srcStart + 2));
56
+ // while (isSpace(load<u16>(srcStart))) srcStart += 2;
57
+ srcStart += 4;
58
+ // console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
59
+ keyStart = 0;
51
60
  break;
52
61
  }
53
62
  srcStart += 2;
54
63
  }
55
- // @ts-ignore: type
56
- } else if ((!isBoolean<valueof<T>>() && isInteger<valueof<T>>() && code - 48 <= 9) || code == 45) {
64
+ } else if (code - 48 <= 9 || code == 45) {
57
65
  lastIndex = srcStart;
58
66
  srcStart += 2;
59
67
  while (srcStart < srcEnd) {
60
68
  const code = load<u16>(srcStart);
61
- if (code == COMMA || isSpace(code) || code == BRACE_RIGHT) {
69
+ if (code == COMMA || code == BRACE_RIGHT || isSpace(code)) {
70
+ // console.log("Value (number): " + ptrToStr(lastIndex, srcStart));
62
71
  // @ts-ignore: type
63
- out.set(key, JSON.__deserialize<valueof<T>>(lastIndex, srcStart));
64
- while (isSpace(load<u16>((srcStart += 2)))) {
65
- /* empty */
66
- }
67
- key = null;
72
+ out.set(ptrToStr(keyStart, keyEnd), JSON.__deserialize<valueof<T>>(lastIndex, srcStart));
73
+ // while (isSpace(load<u16>((srcStart += 2)))) {
74
+ // /* empty */
75
+ // }
76
+ srcStart += 2;
77
+ // console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
78
+ keyStart = 0;
68
79
  break;
69
80
  }
70
81
  srcStart += 2;
71
82
  }
72
- // @ts-ignore: type
73
- } else if (isArray<valueof<T>>() && code == BRACKET_LEFT) {
83
+ } else if (code == BRACE_LEFT) {
74
84
  lastIndex = srcStart;
75
85
  depth++;
76
86
  srcStart += 2;
77
87
  while (srcStart < srcEnd) {
78
88
  const code = load<u16>(srcStart);
79
- if (code == BRACKET_RIGHT) {
89
+ if (code == QUOTE) {
90
+ srcStart += 2;
91
+ while (!(load<u16>(srcStart) == QUOTE && load<u16>(srcStart - 2) != BACK_SLASH)) srcStart += 2;
92
+ } else if (code == BRACE_RIGHT) {
80
93
  if (--depth == 0) {
94
+ // console.log("Value (object): " + ptrToStr(lastIndex, srcStart + 2));
81
95
  // @ts-ignore: type
82
- out.set(key, JSON.__deserialize<valueof<T>>(lastIndex, srcStart));
83
- while (isSpace(load<u16>((srcStart += 2)))) {
84
- /* empty */
85
- }
86
- key = null;
96
+ out.set(ptrToStr(keyStart, keyEnd), JSON.__deserialize<valueof<T>>(lastIndex, (srcStart += 2)));
97
+ // console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
98
+ keyStart = 0;
99
+ // while (isSpace(load<u16>(srcStart))) {
100
+ // /* empty */
101
+ // }
87
102
  break;
88
103
  }
89
- } else if (code == BRACKET_LEFT) depth++;
104
+ } else if (code == BRACE_LEFT) depth++;
90
105
  srcStart += 2;
91
106
  }
92
- // @ts-ignore: type
93
- } else if (isDefined(changetype<nonnull<valueof<T>>>(0).__DESERIALIZE) && code == BRACE_LEFT) {
107
+ } else if (code == BRACKET_LEFT) {
94
108
  lastIndex = srcStart;
95
109
  depth++;
96
110
  srcStart += 2;
97
111
  while (srcStart < srcEnd) {
98
112
  const code = load<u16>(srcStart);
99
- if (code == BRACE_RIGHT) {
113
+ if (code == BRACKET_RIGHT) {
100
114
  if (--depth == 0) {
115
+ // console.log("Value (array): " + ptrToStr(lastIndex, srcStart + 2));
101
116
  // @ts-ignore: type
102
- out.set(key, JSON.__deserialize<valueof<T>>(lastIndex, srcStart));
103
- while (isSpace(load<u16>((srcStart += 2)))) {
104
- /* empty */
105
- }
106
- key = null;
117
+ out.set(ptrToStr(keyStart, keyEnd), JSON.__deserialize<valueof<T>>(lastIndex, (srcStart += 2)));
118
+ // console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
119
+ keyStart = 0;
120
+ // while (isSpace(load<u16>((srcStart += 2)))) {
121
+ // /* empty */
122
+ // }
107
123
  break;
108
124
  }
109
- } else if (code == BRACE_LEFT) depth++;
125
+ } else if (code == BRACKET_LEFT) depth++;
110
126
  srcStart += 2;
111
127
  }
112
- // @ts-ignore: type
113
- } else if (isBoolean<valueof<T>>() && code == CHAR_T) {
128
+ } else if (code == CHAR_T) {
114
129
  if (load<u64>(srcStart) == 28429475166421108) {
130
+ // console.log("Value (bool): " + ptrToStr(srcStart, srcStart + 8));
115
131
  // @ts-ignore: type
116
- out.set(key, JSON.__deserialize<valueof<T>>(srcStart, (srcStart += 8)));
117
- while (isSpace(load<u16>((srcStart += 2)))) {
118
- /* empty */
119
- }
120
- key = null;
132
+ out.set(ptrToStr(keyStart, keyEnd), JSON.__deserialize<valueof<T>>(srcStart, (srcStart += 8)));
133
+ // while (isSpace(load<u16>((srcStart += 2)))) {
134
+ // /* empty */
135
+ // }
136
+ srcStart += 2;
137
+ // console.log("Next: " + String.fromCharCode(load<u16>(srcStart)) + " " + (srcStart < srcEnd).toString());
138
+ keyStart = 0;
121
139
  }
122
- // @ts-ignore: type
123
- } else if (isBoolean<valueof<T>>() && code == CHAR_F) {
140
+ } else if (code == CHAR_F) {
124
141
  if (load<u64>(srcStart, 2) == 28429466576093281) {
142
+ // console.log("Value (bool): " + ptrToStr(srcStart, srcStart + 10));
125
143
  // @ts-ignore: type
126
- out.set(key, JSON.__deserialize<valueof<T>>(srcStart, (srcStart += 10)));
127
- while (isSpace(load<u16>((srcStart += 2)))) {
128
- /* empty */
129
- }
130
- key = null;
144
+ out.set(ptrToStr(keyStart, keyEnd), JSON.__deserialize<valueof<T>>(srcStart, (srcStart += 10)));
145
+ // while (isSpace(load<u16>((srcStart += 2)))) {
146
+ // /* empty */
147
+ // }
148
+ srcStart += 2;
149
+ // console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
150
+ keyStart = 0;
131
151
  }
132
- } else if ((isNullable<T>() || nameof<T>() == "usize") && code == CHAR_N) {
152
+ } else if (code == CHAR_N) {
133
153
  if (load<u64>(srcStart) == 30399761348886638) {
154
+ // console.log("Value (null): " + ptrToStr(srcStart, srcStart + 8));
134
155
  // @ts-ignore: type
135
- out.set(key, JSON.__deserialize<valueof<T>>(srcStart, (srcStart += 8)));
136
- while (isSpace(load<u16>((srcStart += 2)))) {
137
- /* empty */
138
- }
156
+ out.set(ptrToStr(keyStart, keyEnd), JSON.__deserialize<valueof<T>>(srcStart, (srcStart += 8)));
157
+ // while (isSpace(load<u16>((srcStart += 2)))) {
158
+ /* empty */
159
+ // }
160
+ srcStart += 2;
161
+ // console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
162
+ keyStart = 0;
139
163
  }
164
+ } else if (isSpace(code)) {
165
+ srcStart += 2;
140
166
  } else {
141
- // @ts-ignore: type
142
- throw new Error("Unexpected character " + String.fromCharCode(code) + " or type " + nameof<valueof<T>>() + " does not match found type!");
167
+ throw new Error("Unexpected character in JSON object '" + String.fromCharCode(code) + "' at position " + (srcEnd - srcStart).toString());
143
168
  }
144
169
  }
145
170
  }
146
171
  return out;
147
- }
148
-
149
- function sliceTo(srcStart: usize, srcEnd: usize): string {
150
- const dstSize = srcEnd - srcStart;
151
- const dst = __new(dstSize, idof<string>());
152
- memory.copy(dst, srcStart, dstSize);
153
- return changetype<string>(dst);
154
- }
172
+ }
@@ -1,11 +1,11 @@
1
1
  import { JSON } from "../..";
2
- import { BACK_SLASH, COMMA, CHAR_F, BRACE_LEFT, BRACKET_LEFT, CHAR_N, QUOTE, BRACE_RIGHT, BRACKET_RIGHT, CHAR_T } from "../../custom/chars";
2
+ import { BACK_SLASH, COMMA, CHAR_F, BRACE_LEFT, BRACKET_LEFT, CHAR_N, QUOTE, BRACE_RIGHT, BRACKET_RIGHT, CHAR_T, COLON } from "../../custom/chars";
3
3
  import { isSpace } from "../../util";
4
4
  import { ptrToStr } from "../../util/ptrToStr";
5
5
  import { deserializeArbitrary } from "./arbitrary";
6
6
 
7
7
  export function deserializeObject(srcStart: usize, srcEnd: usize, dst: usize): JSON.Obj {
8
- const out = new JSON.Obj();
8
+ const out = changetype<JSON.Obj>(dst || changetype<usize>(new JSON.Obj()));
9
9
 
10
10
  let keyStart: usize = 0;
11
11
  let keyEnd: usize = 0;
@@ -13,8 +13,14 @@ export function deserializeObject(srcStart: usize, srcEnd: usize, dst: usize): J
13
13
  let depth = 0;
14
14
  let lastIndex: usize = 0;
15
15
 
16
- // while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
17
- // while (srcEnd > srcStart && isSpace(load<u16>(srcEnd))) srcEnd -= 2;
16
+ while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
17
+ while (srcEnd > srcStart && isSpace(load<u16>(srcEnd - 2))) srcEnd -= 2; // would like to optimize this later
18
+
19
+ if (srcStart - srcEnd == 0)
20
+ throw new Error("Input string had zero length or was all whitespace");
21
+ if (load<u16>(srcStart) != BRACE_LEFT) throw new Error("Expected '{' at start of object at position " + (srcEnd - srcStart).toString());
22
+ if (load<u16>(srcEnd - 2) != BRACE_RIGHT) throw new Error("Expected '}' at end of object at position " + (srcEnd - srcStart).toString());
23
+
18
24
  srcStart += 2;
19
25
  while (srcStart < srcEnd) {
20
26
  let code = load<u16>(srcStart); // while (isSpace(code)) code = load<u16>(srcStart += 2);
@@ -23,13 +29,10 @@ export function deserializeObject(srcStart: usize, srcEnd: usize, dst: usize): J
23
29
  if (isKey) {
24
30
  keyStart = lastIndex;
25
31
  keyEnd = srcStart;
26
- // console.log("Key: " + ptrToStr(keyStart, keyEnd));
32
+ // console.log("Key: " + ptrToStr(lastIndex, srcStart));
27
33
  // console.log("Next: " + String.fromCharCode(load<u16>(srcStart + 2)));
28
- srcStart += 2;
29
- // while (isSpace((code = load<u16>((srcStart += 2))))) {
30
- // /* empty */
31
- // }
32
- // if (code !== COLON) throw new Error("Expected ':' after key at position " + (srcStart - srcPtr).toString());
34
+ while (isSpace((code = load<u16>((srcStart += 2))))) { }
35
+ if (code !== COLON) throw new Error("Expected ':' after key at position " + (srcEnd - srcStart).toString());
33
36
  isKey = false;
34
37
  } else {
35
38
  // console.log("Got key start");
@@ -80,10 +83,13 @@ export function deserializeObject(srcStart: usize, srcEnd: usize, dst: usize): J
80
83
  srcStart += 2;
81
84
  while (srcStart < srcEnd) {
82
85
  const code = load<u16>(srcStart);
83
- if (code == BRACE_RIGHT) {
86
+ if (code == QUOTE) {
87
+ srcStart += 2;
88
+ while (!(load<u16>(srcStart) == QUOTE && load<u16>(srcStart - 2) != BACK_SLASH)) srcStart += 2;
89
+ } else if (code == BRACE_RIGHT) {
84
90
  if (--depth == 0) {
85
91
  // console.log("Value (object): " + ptrToStr(lastIndex, srcStart + 2));
86
- out.set(ptrToStr(keyStart, keyEnd), deserializeArbitrary(lastIndex, srcStart += 2, dst));
92
+ out.set(ptrToStr(keyStart, keyEnd), deserializeArbitrary(lastIndex, (srcStart += 2), dst));
87
93
  // console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
88
94
  keyStart = 0;
89
95
  // while (isSpace(load<u16>(srcStart))) {
@@ -103,7 +109,7 @@ export function deserializeObject(srcStart: usize, srcEnd: usize, dst: usize): J
103
109
  if (code == BRACKET_RIGHT) {
104
110
  if (--depth == 0) {
105
111
  // console.log("Value (array): " + ptrToStr(lastIndex, srcStart + 2));
106
- out.set(ptrToStr(keyStart, keyEnd), deserializeArbitrary(lastIndex, srcStart += 2, dst));
112
+ out.set(ptrToStr(keyStart, keyEnd), deserializeArbitrary(lastIndex, (srcStart += 2), dst));
107
113
  // console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
108
114
  keyStart = 0;
109
115
  // while (isSpace(load<u16>((srcStart += 2)))) {
@@ -117,7 +123,7 @@ export function deserializeObject(srcStart: usize, srcEnd: usize, dst: usize): J
117
123
  } else if (code == CHAR_T) {
118
124
  if (load<u64>(srcStart) == 28429475166421108) {
119
125
  // console.log("Value (bool): " + ptrToStr(srcStart, srcStart + 8));
120
- out.set(ptrToStr(keyStart, keyEnd), deserializeArbitrary(lastIndex, srcStart += 8, dst));
126
+ out.set(ptrToStr(keyStart, keyEnd), deserializeArbitrary(srcStart, (srcStart += 8), dst));
121
127
  // while (isSpace(load<u16>((srcStart += 2)))) {
122
128
  // /* empty */
123
129
  // }
@@ -128,7 +134,7 @@ export function deserializeObject(srcStart: usize, srcEnd: usize, dst: usize): J
128
134
  } else if (code == CHAR_F) {
129
135
  if (load<u64>(srcStart, 2) == 28429466576093281) {
130
136
  // console.log("Value (bool): " + ptrToStr(srcStart, srcStart + 10));
131
- out.set(ptrToStr(keyStart, keyEnd), deserializeArbitrary(lastIndex, srcStart += 10, dst));
137
+ out.set(ptrToStr(keyStart, keyEnd), deserializeArbitrary(srcStart, (srcStart += 10), dst));
132
138
  // while (isSpace(load<u16>((srcStart += 2)))) {
133
139
  // /* empty */
134
140
  // }
@@ -139,7 +145,7 @@ export function deserializeObject(srcStart: usize, srcEnd: usize, dst: usize): J
139
145
  } else if (code == CHAR_N) {
140
146
  if (load<u64>(srcStart) == 30399761348886638) {
141
147
  // console.log("Value (null): " + ptrToStr(srcStart, srcStart + 8));
142
- out.set(ptrToStr(keyStart, keyEnd), deserializeArbitrary(lastIndex, srcStart += 8, dst));
148
+ out.set(ptrToStr(keyStart, keyEnd), deserializeArbitrary(srcStart, (srcStart += 8), dst));
143
149
  // while (isSpace(load<u16>((srcStart += 2)))) {
144
150
  /* empty */
145
151
  // }
@@ -147,6 +153,10 @@ export function deserializeObject(srcStart: usize, srcEnd: usize, dst: usize): J
147
153
  // console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
148
154
  keyStart = 0;
149
155
  }
156
+ } else if (isSpace(code)) {
157
+ srcStart += 2;
158
+ } else {
159
+ throw new Error("Unexpected character in JSON object '" + String.fromCharCode(code) + "' at position " + (srcEnd - srcStart).toString());
150
160
  }
151
161
  }
152
162
  }
@@ -1,23 +1,29 @@
1
1
  import { BACK_SLASH, COMMA, CHAR_F, BRACE_LEFT, BRACKET_LEFT, CHAR_N, QUOTE, BRACE_RIGHT, BRACKET_RIGHT, CHAR_T, COLON } from "../../custom/chars";
2
2
  import { isSpace } from "../../util";
3
+ import { ptrToStr } from "../../util/ptrToStr";
3
4
 
4
5
  export function deserializeStruct<T>(srcStart: usize, srcEnd: usize, dst: usize): T {
5
6
  const out = changetype<nonnull<T>>(dst || __new(offsetof<T>(), idof<T>()));
6
7
 
8
+ // @ts-ignore: supplied by transform
9
+ if (isDefined(out.__INITIALIZE)) out.__INITIALIZE();
10
+
7
11
  let keyStart: usize = 0;
8
12
  let keyEnd: usize = 0;
9
13
  let isKey = false;
10
14
  let depth = 0;
11
15
  let lastIndex: usize = 0;
12
16
 
13
- while (isSpace(load<u16>(srcStart))) srcStart += 2;
14
- while (isSpace(load<u16>(srcEnd -= 2))) {};
17
+ while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
18
+ while (srcEnd > srcStart && isSpace(load<u16>(srcEnd - 2))) srcEnd -= 2; // would like to optimize this later
15
19
 
20
+ if (srcStart - srcEnd == 0)
21
+ throw new Error("Input string had zero length or was all whitespace");
16
22
  if (load<u16>(srcStart) != BRACE_LEFT) throw new Error("Expected '{' at start of object at position " + (srcEnd - srcStart).toString());
17
- if (load<u16>(srcEnd) != BRACE_RIGHT) throw new Error("Expected '}' at end of object at position " + (srcEnd - srcStart).toString());
23
+ if (load<u16>(srcEnd - 2) != BRACE_RIGHT) throw new Error("Expected '}' at end of object at position " + (srcEnd - srcStart).toString());
18
24
 
19
25
  srcStart += 2;
20
- while (srcStart <= srcEnd) {
26
+ while (srcStart < srcEnd) {
21
27
  let code = load<u16>(srcStart); // while (isSpace(code)) code = load<u16>(srcStart += 2);
22
28
  if (keyStart == 0) {
23
29
  if (code == QUOTE && load<u16>(srcStart - 2) !== BACK_SLASH) {
@@ -26,7 +32,7 @@ export function deserializeStruct<T>(srcStart: usize, srcEnd: usize, dst: usize)
26
32
  keyEnd = srcStart;
27
33
  // console.log("Key: " + ptrToStr(lastIndex, srcStart));
28
34
  // console.log("Next: " + String.fromCharCode(load<u16>(srcStart + 2)));
29
- while (isSpace((code = load<u16>((srcStart += 2))))) {}
35
+ while (isSpace((code = load<u16>((srcStart += 2))))) { }
30
36
  if (code !== COLON) throw new Error("Expected ':' after key at position " + (srcEnd - srcStart).toString());
31
37
  isKey = false;
32
38
  } else {
@@ -41,12 +47,12 @@ export function deserializeStruct<T>(srcStart: usize, srcEnd: usize, dst: usize)
41
47
  if (code == QUOTE) {
42
48
  lastIndex = srcStart;
43
49
  srcStart += 2;
44
- while (srcStart <= srcEnd) {
50
+ while (srcStart < srcEnd) {
45
51
  const code = load<u16>(srcStart);
46
52
  if (code == QUOTE && load<u16>(srcStart - 2) !== BACK_SLASH) {
47
53
  // console.log("Value (string): " + ptrToStr(lastIndex, srcStart + 2));
48
54
  // @ts-ignore: exists
49
- out.__DESERIALIZE(keyStart, keyEnd, lastIndex, srcStart + 2, dst);
55
+ out.__DESERIALIZE(keyStart, keyEnd, lastIndex, srcStart + 2, changetype<usize>(out));
50
56
  // while (isSpace(load<u16>(srcStart))) srcStart += 2;
51
57
  srcStart += 4;
52
58
  // console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
@@ -58,12 +64,12 @@ export function deserializeStruct<T>(srcStart: usize, srcEnd: usize, dst: usize)
58
64
  } else if (code - 48 <= 9 || code == 45) {
59
65
  lastIndex = srcStart;
60
66
  srcStart += 2;
61
- while (srcStart <= srcEnd) {
67
+ while (srcStart < srcEnd) {
62
68
  const code = load<u16>(srcStart);
63
69
  if (code == COMMA || code == BRACE_RIGHT || isSpace(code)) {
64
70
  // console.log("Value (number): " + ptrToStr(lastIndex, srcStart));
65
71
  // @ts-ignore: exists
66
- out.__DESERIALIZE(keyStart, keyEnd, lastIndex, srcStart, dst);
72
+ out.__DESERIALIZE(keyStart, keyEnd, lastIndex, srcStart, changetype<usize>(out));
67
73
  // while (isSpace(load<u16>((srcStart += 2)))) {
68
74
  // /* empty */
69
75
  // }
@@ -78,13 +84,16 @@ export function deserializeStruct<T>(srcStart: usize, srcEnd: usize, dst: usize)
78
84
  lastIndex = srcStart;
79
85
  depth++;
80
86
  srcStart += 2;
81
- while (srcStart <= srcEnd) {
87
+ while (srcStart < srcEnd) {
82
88
  const code = load<u16>(srcStart);
83
- if (code == BRACE_RIGHT) {
89
+ if (code == QUOTE) {
90
+ srcStart += 2;
91
+ while (!(load<u16>(srcStart) == QUOTE && load<u16>(srcStart - 2) != BACK_SLASH)) srcStart += 2;
92
+ } else if (code == BRACE_RIGHT) {
84
93
  if (--depth == 0) {
85
94
  // console.log("Value (object): " + ptrToStr(lastIndex, srcStart + 2));
86
95
  // @ts-ignore: exists
87
- out.__DESERIALIZE(keyStart, keyEnd, lastIndex, (srcStart += 2), dst);
96
+ out.__DESERIALIZE(keyStart, keyEnd, lastIndex, (srcStart += 2), changetype<usize>(out));
88
97
  // console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
89
98
  keyStart = 0;
90
99
  // while (isSpace(load<u16>(srcStart))) {
@@ -99,13 +108,16 @@ export function deserializeStruct<T>(srcStart: usize, srcEnd: usize, dst: usize)
99
108
  lastIndex = srcStart;
100
109
  depth++;
101
110
  srcStart += 2;
102
- while (srcStart <= srcEnd) {
111
+ while (srcStart < srcEnd) {
103
112
  const code = load<u16>(srcStart);
104
- if (code == BRACKET_RIGHT) {
113
+ if (code == QUOTE) {
114
+ srcStart += 2;
115
+ while (!(load<u16>(srcStart) == QUOTE && load<u16>(srcStart - 2) != BACK_SLASH)) srcStart += 2;
116
+ } else if (code == BRACKET_RIGHT) {
105
117
  if (--depth == 0) {
106
118
  // console.log("Value (array): " + ptrToStr(lastIndex, srcStart + 2));
107
119
  // @ts-ignore: exists
108
- out.__DESERIALIZE(keyStart, keyEnd, lastIndex, (srcStart += 2), dst);
120
+ out.__DESERIALIZE(keyStart, keyEnd, lastIndex, (srcStart += 2), changetype<usize>(out));
109
121
  // console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
110
122
  keyStart = 0;
111
123
  // while (isSpace(load<u16>((srcStart += 2)))) {
@@ -120,19 +132,19 @@ export function deserializeStruct<T>(srcStart: usize, srcEnd: usize, dst: usize)
120
132
  if (load<u64>(srcStart) == 28429475166421108) {
121
133
  // console.log("Value (bool): " + ptrToStr(srcStart, srcStart + 8));
122
134
  // @ts-ignore: exists
123
- out.__DESERIALIZE(keyStart, keyEnd, srcStart, (srcStart += 8), dst);
135
+ out.__DESERIALIZE(keyStart, keyEnd, srcStart, (srcStart += 8), changetype<usize>(out));
124
136
  // while (isSpace(load<u16>((srcStart += 2)))) {
125
137
  // /* empty */
126
138
  // }
127
139
  srcStart += 2;
128
- // console.log("Next: " + String.fromCharCode(load<u16>(srcStart)) + " " + (srcStart <= srcEnd).toString());
140
+ // console.log("Next: " + String.fromCharCode(load<u16>(srcStart)) + " " + (srcStart < srcEnd).toString());
129
141
  keyStart = 0;
130
142
  }
131
143
  } else if (code == CHAR_F) {
132
144
  if (load<u64>(srcStart, 2) == 28429466576093281) {
133
145
  // console.log("Value (bool): " + ptrToStr(srcStart, srcStart + 10));
134
146
  // @ts-ignore: exists
135
- out.__DESERIALIZE(keyStart, keyEnd, srcStart, (srcStart += 10), dst);
147
+ out.__DESERIALIZE(keyStart, keyEnd, srcStart, (srcStart += 10), changetype<usize>(out));
136
148
  // while (isSpace(load<u16>((srcStart += 2)))) {
137
149
  // /* empty */
138
150
  // }
@@ -144,7 +156,7 @@ export function deserializeStruct<T>(srcStart: usize, srcEnd: usize, dst: usize)
144
156
  if (load<u64>(srcStart) == 30399761348886638) {
145
157
  // console.log("Value (null): " + ptrToStr(srcStart, srcStart + 8));
146
158
  // @ts-ignore: exists
147
- out.__DESERIALIZE(keyStart, keyEnd, srcStart, (srcStart += 8), dst);
159
+ out.__DESERIALIZE(keyStart, keyEnd, srcStart, (srcStart += 8), changetype<usize>(out));
148
160
  // while (isSpace(load<u16>((srcStart += 2)))) {
149
161
  /* empty */
150
162
  // }
package/assembly/index.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  /// <reference path="./index.d.ts" />
2
2
 
3
+ import { bs } from "../lib/as-bs";
3
4
  import { serializeString } from "./serialize/simple/string";
4
5
  import { serializeArray } from "./serialize/simple/array";
5
6
  import { serializeMap } from "./serialize/simple/map";
@@ -66,7 +67,7 @@ export namespace JSON {
66
67
  return out;
67
68
  }
68
69
  return data ? "true" : "false";
69
- } else if (isInteger<T>() && nameof<T>() == "usize" && data == 0) {
70
+ } else if (isInteger<T>() && !isSigned<T>() && nameof<T>() == "usize" && data == 0) {
70
71
  if (out) {
71
72
  out = changetype<string>(__renew(changetype<usize>(out), 8));
72
73
  store<u64>(changetype<usize>(out), 30399761348886638);
@@ -233,11 +234,12 @@ export namespace JSON {
233
234
  U64 = 4,
234
235
  F32 = 5,
235
236
  F64 = 6,
236
- Bool = 7,
237
- String = 8,
238
- Object = 9,
239
- Array = 10,
240
- Struct = 11,
237
+ Null = 7,
238
+ Bool = 8,
239
+ String = 9,
240
+ Object = 10,
241
+ Array = 12,
242
+ Struct = 13,
241
243
  }
242
244
 
243
245
  export class Raw {
@@ -297,6 +299,9 @@ export namespace JSON {
297
299
  if (isBoolean<T>()) {
298
300
  this.type = JSON.Types.Bool;
299
301
  store<T>(changetype<usize>(this), value, STORAGE);
302
+ } else if (isInteger<T>() && !isSigned<T>() && changetype<usize>(value) == 0 && nameof<T>() == "usize") {
303
+ this.type = JSON.Types.Null;
304
+ store<usize>(changetype<usize>(this), 0, STORAGE);
300
305
  } else if (value instanceof u8 || value instanceof i8) {
301
306
  this.type = JSON.Types.U8;
302
307
  store<T>(changetype<usize>(this), value, STORAGE);
@@ -514,8 +519,7 @@ export namespace JSON {
514
519
  }
515
520
  }
516
521
 
517
- // @ts-ignore: inline
518
- @inline export function __serialize<T>(src: T): void {
522
+ export function __serialize<T>(src: T): void {
519
523
  if (isBoolean<T>()) {
520
524
  serializeBool(src as bool);
521
525
  } else if (isInteger<T>() && nameof<T>() == "usize" && src == 0) {
@@ -565,8 +569,7 @@ export namespace JSON {
565
569
  }
566
570
  }
567
571
 
568
- // @ts-ignore: inline
569
- @inline export function __deserialize<T>(srcStart: usize, srcEnd: usize, dst: usize = 0): T {
572
+ export function __deserialize<T>(srcStart: usize, srcEnd: usize, dst: usize = 0): T {
570
573
  if (isBoolean<T>()) {
571
574
  // @ts-ignore: type
572
575
  return deserializeBoolean(srcStart, srcEnd);
@@ -588,7 +591,7 @@ export namespace JSON {
588
591
  // @ts-ignore: Defined by transform
589
592
  if (isDefined(type.__INITIALIZE)) changetype<nonnull<T>>(out).__INITIALIZE();
590
593
  // @ts-ignore
591
- return changetype<nonnull<T>>(out).__DESERIALIZE_CUSTOM(ptrToStr(dataPtr, dataPtr + dataSize));
594
+ return changetype<nonnull<T>>(out).__DESERIALIZE_CUSTOM(ptrToStr(srcStart, srcEnd));
592
595
  // @ts-ignore: Defined by transform
593
596
  } else if (isDefined(type.__DESERIALIZE)) {
594
597
  return deserializeStruct<T>(srcStart, srcEnd, dst);
@@ -1,3 +1,4 @@
1
+ import { bs } from "../../../lib/as-bs";
1
2
  import { COMMA, BRACKET_RIGHT, BRACKET_LEFT } from "../../custom/chars";
2
3
  import { JSON } from "../..";
3
4
 
@@ -1,3 +1,4 @@
1
+ import { bs } from "../../../lib/as-bs";
1
2
  /**
2
3
  * Serialize a bool to type string
3
4
  * @param data data to serialize
@@ -1,3 +1,4 @@
1
+ import { bs } from "../../../lib/as-bs";
1
2
  import { QUOTE } from "../../custom/chars";
2
3
  import { bytes } from "../../util/bytes";
3
4
 
@@ -1,3 +1,4 @@
1
+ import { bs } from "../../../lib/as-bs";
1
2
  import { dtoa_buffered } from "util/number";
2
3
 
3
4
  export function serializeFloat<T extends number>(data: T): void {
@@ -1,3 +1,4 @@
1
+ import { bs } from "../../../lib/as-bs";
1
2
  import { itoa_buffered } from "util/number";
2
3
 
3
4
  export function serializeInteger<T extends number>(data: T): void {
@@ -1,3 +1,4 @@
1
+ import { bs } from "../../../lib/as-bs";
1
2
  import { JSON } from "../..";
2
3
  import { BRACE_LEFT, BRACE_RIGHT, COLON, COMMA } from "../../custom/chars";
3
4
 
@@ -1,3 +1,4 @@
1
+ import { bs } from "../../../lib/as-bs";
1
2
  import { JSON } from "../..";
2
3
  import { BRACE_LEFT, BRACE_RIGHT, QUOTE } from "../../custom/chars";
3
4
  import { bytes } from "../../util";
@@ -1,3 +1,4 @@
1
+ import { bs } from "../../../lib/as-bs";
1
2
  import { JSON } from "../..";
2
3
  import { bytes } from "../../util";
3
4
 
@@ -1,3 +1,4 @@
1
+ import { bs } from "../../../lib/as-bs";
1
2
  import { _intTo16 } from "../../custom/util";
2
3
  import { bytes } from "../../util/bytes";
3
4
  import { BACK_SLASH, QUOTE } from "../../custom/chars";