json-as 1.3.1 → 1.3.3

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 (55) hide show
  1. package/CHANGELOG.md +9 -26
  2. package/README.md +43 -19
  3. package/assembly/deserialize/index/arbitrary.ts +1 -1
  4. package/assembly/deserialize/index/array.ts +6 -1
  5. package/assembly/deserialize/index/float.ts +1 -1
  6. package/assembly/deserialize/index/integer.ts +1 -1
  7. package/assembly/deserialize/index/unsigned.ts +1 -1
  8. package/assembly/deserialize/simd/string.ts +17 -13
  9. package/assembly/deserialize/simple/arbitrary.ts +1 -1
  10. package/assembly/deserialize/simple/array/generic.ts +42 -0
  11. package/assembly/deserialize/simple/array.ts +8 -1
  12. package/assembly/deserialize/{float.ts → simple/float.ts} +22 -2
  13. package/assembly/deserialize/{integer.ts → simple/integer.ts} +3 -2
  14. package/assembly/deserialize/simple/map.ts +62 -12
  15. package/assembly/deserialize/simple/object.ts +1 -1
  16. package/assembly/deserialize/simple/set.ts +119 -134
  17. package/assembly/deserialize/simple/staticarray.ts +13 -1
  18. package/assembly/deserialize/simple/string.ts +15 -10
  19. package/assembly/deserialize/simple/struct.ts +9 -157
  20. package/assembly/deserialize/simple/typedarray.ts +1 -1
  21. package/assembly/deserialize/{unsigned.ts → simple/unsigned.ts} +3 -2
  22. package/assembly/deserialize/swar/array/array.ts +42 -7
  23. package/assembly/deserialize/swar/array/bool.ts +6 -2
  24. package/assembly/deserialize/swar/array/float.ts +7 -3
  25. package/assembly/deserialize/swar/array/generic.ts +41 -0
  26. package/assembly/deserialize/swar/array/integer.ts +8 -4
  27. package/assembly/deserialize/swar/array/object.ts +21 -4
  28. package/assembly/deserialize/swar/array/shared.ts +19 -4
  29. package/assembly/deserialize/swar/array/string.ts +6 -2
  30. package/assembly/deserialize/swar/array/struct.ts +21 -4
  31. package/assembly/deserialize/swar/array.ts +57 -2
  32. package/assembly/deserialize/swar/string.ts +248 -372
  33. package/assembly/index.d.ts +1 -0
  34. package/assembly/index.ts +77 -19
  35. package/assembly/serialize/index/arbitrary.ts +3 -3
  36. package/assembly/serialize/index/float.ts +1 -1
  37. package/assembly/serialize/index/object.ts +1 -5
  38. package/assembly/serialize/simd/string.ts +4 -5
  39. package/assembly/serialize/simple/arbitrary.ts +3 -3
  40. package/assembly/serialize/simple/array.ts +18 -6
  41. package/assembly/serialize/simple/float.ts +20 -4
  42. package/assembly/serialize/simple/map.ts +10 -27
  43. package/assembly/serialize/simple/object.ts +1 -5
  44. package/assembly/serialize/simple/set.ts +3 -4
  45. package/assembly/serialize/simple/staticarray.ts +4 -3
  46. package/assembly/serialize/simple/typedarray.ts +9 -7
  47. package/assembly/serialize/swar/string.ts +0 -1
  48. package/assembly/tsconfig.json +1 -0
  49. package/assembly/util/dragonbox-cache.ts +4 -0
  50. package/assembly/util/dragonbox.ts +624 -0
  51. package/lib/as-bs.ts +35 -24
  52. package/package.json +26 -18
  53. package/transform/lib/index.d.ts.map +1 -1
  54. package/transform/lib/index.js +508 -148
  55. package/transform/lib/index.js.map +1 -1
@@ -1,39 +1,66 @@
1
1
  import { JSON } from "../..";
2
- import { BACK_SLASH, BRACKET_LEFT, BRACKET_RIGHT, BRACE_LEFT, BRACE_RIGHT, CHAR_F, CHAR_N, CHAR_T, COMMA, QUOTE } from "../../custom/chars";
3
- import { isSpace, atoi, isUnescapedQuote, scanStringEnd } from "../../util";
2
+ import { BRACKET_LEFT, BRACKET_RIGHT, BRACE_LEFT, BRACE_RIGHT, CHAR_F, CHAR_T, COMMA, QUOTE } from "../../custom/chars";
3
+ import { isSpace, atoi, scanStringEnd } from "../../util";
4
4
 
5
- export function deserializeSet<T extends Set<any>>(srcStart: usize, srcEnd: usize, dst: usize): T {
6
- const out = changetype<nonnull<T>>(dst || changetype<usize>(instantiate<T>()));
5
+ // @ts-expect-error: Decorator valid here
6
+ @inline function scanSetElementEnd(srcStart: usize, srcEnd: usize): usize {
7
+ const first = load<u16>(srcStart);
7
8
 
8
- while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
9
- while (srcEnd > srcStart && isSpace(load<u16>(srcEnd - 2))) srcEnd -= 2;
9
+ if (first == QUOTE) {
10
+ const end = scanStringEnd(srcStart, srcEnd);
11
+ return end < srcEnd ? end + 2 : 0;
12
+ }
10
13
 
11
- if (srcStart >= srcEnd) throw new Error("Input string had zero length or was all whitespace");
12
- if (load<u16>(srcStart) != BRACKET_LEFT) throw new Error("Expected '[' at start of set");
13
- if (load<u16>(srcEnd - 2) != BRACKET_RIGHT) throw new Error("Expected ']' at end of set");
14
+ if (first == BRACE_LEFT || first == BRACKET_LEFT) {
15
+ let depth: i32 = 1;
16
+ let ptr = srcStart + 2;
17
+
18
+ while (ptr < srcEnd) {
19
+ const code = load<u16>(ptr);
20
+ if (code == QUOTE) {
21
+ ptr = scanStringEnd(ptr, srcEnd);
22
+ if (ptr >= srcEnd) return 0;
23
+ } else if (code == BRACE_LEFT || code == BRACKET_LEFT) {
24
+ depth++;
25
+ } else if (code == BRACE_RIGHT || code == BRACKET_RIGHT) {
26
+ if (--depth == 0) return ptr + 2;
27
+ }
28
+ ptr += 2;
29
+ }
30
+
31
+ return 0;
32
+ }
33
+
34
+ let ptr = srcStart;
35
+ while (ptr < srcEnd) {
36
+ const code = load<u16>(ptr);
37
+ if (code == COMMA || code == BRACKET_RIGHT) return ptr;
38
+ ptr += 2;
39
+ }
40
+
41
+ return 0;
42
+ }
43
+
44
+ function deserializeSetDirect<T extends Set<any>>(srcStart: usize, srcEnd: usize, out: nonnull<T>, allowWhitespace: bool = false): usize {
45
+ if (srcStart >= srcEnd || load<u16>(srcStart) != BRACKET_LEFT) throw new Error("Expected '[' at start of set");
14
46
 
15
47
  srcStart += 2;
48
+ if (allowWhitespace) while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
49
+ if (srcStart >= srcEnd) throw new Error("Unterminated set");
50
+ if (load<u16>(srcStart) == BRACKET_RIGHT) return srcStart + 2;
16
51
 
17
- while (srcStart < srcEnd - 2) {
18
- let code = load<u16>(srcStart);
19
- while (isSpace(code)) code = load<u16>((srcStart += 2));
52
+ while (srcStart < srcEnd) {
53
+ if (allowWhitespace) while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
54
+ const code = load<u16>(srcStart);
20
55
 
21
56
  // @ts-ignore: type
22
57
  if (isString<indexof<T>>()) {
23
- if (code == QUOTE) {
24
- const lastIndex = srcStart;
25
- srcStart += 2;
26
- while (srcStart < srcEnd) {
27
- const c = load<u16>(srcStart);
28
- if (c == QUOTE && isUnescapedQuote(srcStart)) {
29
- // @ts-ignore: type
30
- out.add(JSON.__deserialize<indexof<T>>(lastIndex, srcStart + 2));
31
- srcStart += 2;
32
- break;
33
- }
34
- srcStart += 2;
35
- }
36
- }
58
+ if (code != QUOTE) break;
59
+ const end = scanStringEnd(srcStart, srcEnd);
60
+ if (end >= srcEnd) break;
61
+ // @ts-ignore: type
62
+ out.add(JSON.__deserialize<indexof<T>>(srcStart, end + 2));
63
+ srcStart = end + 2;
37
64
  // @ts-ignore: type
38
65
  } else if (isBoolean<indexof<T>>()) {
39
66
  if (code == CHAR_T) {
@@ -44,126 +71,84 @@ export function deserializeSet<T extends Set<any>>(srcStart: usize, srcEnd: usiz
44
71
  // @ts-ignore: type
45
72
  out.add(<indexof<T>>false);
46
73
  srcStart += 10;
74
+ } else {
75
+ break;
47
76
  }
48
77
  // @ts-ignore: type
49
78
  } else if (isInteger<indexof<T>>()) {
50
- if (code - 48 <= 9 || code == 45) {
51
- const lastIndex = srcStart;
52
- srcStart += 2;
53
- while (srcStart < srcEnd) {
54
- const c = load<u16>(srcStart);
55
- if (c == COMMA || c == BRACKET_RIGHT || isSpace(c)) {
56
- // @ts-ignore: type
57
- out.add(atoi<indexof<T>>(lastIndex, srcStart));
58
- break;
59
- }
60
- srcStart += 2;
61
- }
79
+ if (code - 48 > 9 && code != 45) break;
80
+ let ptr = srcStart + 2;
81
+ while (ptr < srcEnd) {
82
+ const next = load<u16>(ptr);
83
+ if (next == COMMA || next == BRACKET_RIGHT || (allowWhitespace && isSpace(next))) break;
84
+ ptr += 2;
62
85
  }
63
86
  // @ts-ignore: type
87
+ out.add(atoi<indexof<T>>(srcStart, ptr));
88
+ srcStart = ptr;
89
+ // @ts-ignore: type
64
90
  } else if (isFloat<indexof<T>>()) {
65
- if (code - 48 <= 9 || code == 45) {
66
- const lastIndex = srcStart;
67
- srcStart += 2;
68
- while (srcStart < srcEnd) {
69
- const c = load<u16>(srcStart);
70
- if (c == COMMA || c == BRACKET_RIGHT || isSpace(c)) {
71
- // @ts-ignore: type
72
- out.add(JSON.__deserialize<indexof<T>>(lastIndex, srcStart));
73
- break;
74
- }
75
- srcStart += 2;
76
- }
91
+ if (code - 48 > 9 && code != 45) break;
92
+ let ptr = srcStart + 2;
93
+ while (ptr < srcEnd) {
94
+ const next = load<u16>(ptr);
95
+ if (next == COMMA || next == BRACKET_RIGHT || (allowWhitespace && isSpace(next))) break;
96
+ ptr += 2;
77
97
  }
78
98
  // @ts-ignore: type
99
+ out.add(JSON.__deserialize<indexof<T>>(srcStart, ptr));
100
+ srcStart = ptr;
101
+ // @ts-ignore: type
79
102
  } else if (isManaged<indexof<T>>() || isReference<indexof<T>>()) {
103
+ const end = scanSetElementEnd(srcStart, srcEnd);
104
+ if (!end) break;
80
105
  // @ts-ignore: type
81
- const type = changetype<nonnull<indexof<T>>>(0);
82
- if (code == BRACE_LEFT) {
83
- // Object
84
- const lastIndex = srcStart;
85
- let depth: u32 = 1;
86
- srcStart += 2;
87
- while (srcStart < srcEnd) {
88
- const c = load<u16>(srcStart);
89
- if (c == QUOTE) {
90
- srcStart = scanStringEnd(srcStart, srcEnd);
91
- if (srcStart >= srcEnd) throw new Error("Unterminated string in JSON set");
92
- } else if (c == BRACE_RIGHT) {
93
- if (--depth == 0) {
94
- srcStart += 2;
95
- // @ts-ignore: type
96
- out.add(JSON.__deserialize<indexof<T>>(lastIndex, srcStart));
97
- break;
98
- }
99
- } else if (c == BRACE_LEFT) {
100
- depth++;
101
- }
102
- srcStart += 2;
103
- }
104
- } else if (code == BRACKET_LEFT) {
105
- // Nested array/set
106
- const lastIndex = srcStart;
107
- let depth: u32 = 1;
108
- srcStart += 2;
109
- while (srcStart < srcEnd) {
110
- const c = load<u16>(srcStart);
111
- if (c == BRACKET_RIGHT) {
112
- if (--depth == 0) {
113
- srcStart += 2;
114
- // @ts-ignore: type
115
- out.add(JSON.__deserialize<indexof<T>>(lastIndex, srcStart));
116
- break;
117
- }
118
- } else if (c == BRACKET_LEFT) {
119
- depth++;
120
- }
121
- srcStart += 2;
122
- }
123
- } else if (type instanceof JSON.Raw) {
124
- // Handle JSON.Raw
125
- if (code == QUOTE) {
126
- const lastIndex = srcStart;
127
- srcStart += 2;
128
- while (srcStart < srcEnd) {
129
- const c = load<u16>(srcStart);
130
- if (c == QUOTE && isUnescapedQuote(srcStart)) {
131
- // @ts-ignore: type
132
- out.add(JSON.__deserialize<indexof<T>>(lastIndex, srcStart + 2));
133
- srcStart += 2;
134
- break;
135
- }
136
- srcStart += 2;
137
- }
138
- } else if (code - 48 <= 9 || code == 45) {
139
- const lastIndex = srcStart;
140
- srcStart += 2;
141
- while (srcStart < srcEnd) {
142
- const c = load<u16>(srcStart);
143
- if (c == COMMA || c == BRACKET_RIGHT || isSpace(c)) {
144
- // @ts-ignore: type
145
- out.add(JSON.__deserialize<indexof<T>>(lastIndex, srcStart));
146
- break;
147
- }
148
- srcStart += 2;
149
- }
150
- } else if (code == CHAR_T) {
151
- // @ts-ignore: type
152
- out.add(JSON.__deserialize<indexof<T>>(srcStart, srcStart + 8));
153
- srcStart += 8;
154
- } else if (code == CHAR_F) {
155
- // @ts-ignore: type
156
- out.add(JSON.__deserialize<indexof<T>>(srcStart, srcStart + 10));
157
- srcStart += 10;
158
- } else if (code == CHAR_N) {
159
- // @ts-ignore: type
160
- out.add(JSON.__deserialize<indexof<T>>(srcStart, srcStart + 8));
161
- srcStart += 8;
162
- }
163
- }
106
+ out.add(JSON.__deserialize<indexof<T>>(srcStart, end));
107
+ srcStart = end;
108
+ } else {
109
+ break;
110
+ }
111
+
112
+ if (allowWhitespace) while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
113
+ if (srcStart >= srcEnd) break;
114
+ const next = load<u16>(srcStart);
115
+ if (next == COMMA) {
116
+ srcStart += 2;
117
+ if (allowWhitespace) while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
118
+ continue;
164
119
  }
165
- srcStart += 2;
120
+ if (next == BRACKET_RIGHT) return srcStart + 2;
121
+ break;
166
122
  }
167
123
 
124
+ throw new Error("Failed to parse JSON!");
125
+ }
126
+
127
+ export function deserializeSet<T extends Set<any>>(srcStart: usize, srcEnd: usize, dst: usize): T {
128
+ const out = changetype<nonnull<T>>(dst || changetype<usize>(instantiate<T>()));
129
+ out.clear();
130
+
131
+ while (srcStart < srcEnd && isSpace(load<u16>(srcStart))) srcStart += 2;
132
+ while (srcEnd > srcStart && isSpace(load<u16>(srcEnd - 2))) srcEnd -= 2;
133
+
134
+ if (srcStart >= srcEnd) throw new Error("Input string had zero length or was all whitespace");
135
+ const end = deserializeSetDirect<T>(srcStart, srcEnd, out, true);
136
+ if (end != srcEnd) throw new Error("Expected ']' at end of set");
168
137
  return out;
169
138
  }
139
+
140
+ // @ts-expect-error: Decorator valid here
141
+ @inline export function deserializeSetInto<T extends Set<any>>(srcStart: usize, srcEnd: usize, out: T): usize {
142
+ changetype<nonnull<T>>(out).clear();
143
+ return deserializeSetDirect<T>(srcStart, srcEnd, changetype<nonnull<T>>(out));
144
+ }
145
+
146
+ // @ts-expect-error: Decorator valid here
147
+ @inline export function deserializeSetField<T extends Set<any>>(srcStart: usize, srcEnd: usize, dstObj: usize, dstOffset: usize = 0): usize {
148
+ let out = load<T>(dstObj, dstOffset);
149
+ if (!changetype<usize>(out)) {
150
+ out = changetype<T>(instantiate<T>());
151
+ store<T>(dstObj, out, dstOffset);
152
+ }
153
+ return deserializeSetInto<T>(srcStart, srcEnd, out);
154
+ }
@@ -15,6 +15,7 @@ import { deserializeStaticArrayBoolean } from "./staticarray/bool";
15
15
  import { deserializeStaticArrayFloat } from "./staticarray/float";
16
16
  import { deserializeStaticArrayInteger } from "./staticarray/integer";
17
17
  import { deserializeStaticArrayString } from "./staticarray/string";
18
+ import { scanValueEnd } from "../swar/array/shared";
18
19
 
19
20
 
20
21
  @inline function materializeStaticArray<T extends StaticArray<any>>(src: valueof<T>[], dst: usize): T {
@@ -63,10 +64,21 @@ export function deserializeStaticArray<T extends StaticArray<any>>(srcStart: usi
63
64
  } else if (isDefined(type.__DESERIALIZE_CUSTOM)) {
64
65
  return materializeStaticArray<T>(deserializeStructArray<valueof<T>[]>(srcStart, srcEnd, 0), dst);
65
66
  // @ts-ignore: supplied by transform
66
- } else if (isDefined(type.__DESERIALIZE)) {
67
+ } else if (isDefined(type.__DESERIALIZE_SLOW) || isDefined(type.__DESERIALIZE_FAST)) {
67
68
  return materializeStaticArray<T>(deserializeStructArray<valueof<T>[]>(srcStart, srcEnd, 0), dst);
68
69
  }
69
70
  }
70
71
 
71
72
  throw new Error("Could not parse static array of type " + nameof<T>() + "!");
72
73
  }
74
+
75
+
76
+ @inline export function deserializeStaticArrayField<T extends StaticArray<any>>(srcStart: usize, srcEnd: usize, dstObj: usize, dstOffset: usize = 0): usize {
77
+ const valueEnd = scanValueEnd(srcStart, srcEnd);
78
+ if (!valueEnd) throw new Error("Failed to parse JSON!");
79
+
80
+ const fieldPtr = dstObj + dstOffset;
81
+ const out = deserializeStaticArray<T>(srcStart, valueEnd, load<usize>(fieldPtr));
82
+ store<T>(fieldPtr, out);
83
+ return valueEnd;
84
+ }
@@ -1,4 +1,5 @@
1
1
  import { OBJECT, TOTAL_OVERHEAD } from "rt/common";
2
+ import { __heap_base } from "memory";
2
3
  import { bs } from "../../../lib/as-bs";
3
4
  import { BACK_SLASH, QUOTE } from "../../custom/chars";
4
5
  import { DESERIALIZE_ESCAPE_TABLE, ESCAPE_HEX_TABLE } from "../../globals/tables";
@@ -13,11 +14,13 @@ import { hex4_to_u16_swar } from "../../util/swar";
13
14
 
14
15
  const current = load<usize>(dstFieldPtr);
15
16
  let stringPtr: usize;
16
- if (current != 0 && changetype<OBJECT>(current - TOTAL_OVERHEAD).rtSize == byteLength) {
17
- stringPtr = current;
18
- } else if (current != 0 && current != changetype<usize>("")) {
19
- stringPtr = __renew(current, byteLength);
20
- store<usize>(dstFieldPtr, stringPtr);
17
+ if (current >= __heap_base) {
18
+ if (changetype<OBJECT>(current - TOTAL_OVERHEAD).rtSize == byteLength) {
19
+ stringPtr = current;
20
+ } else {
21
+ stringPtr = __renew(current, byteLength);
22
+ store<usize>(dstFieldPtr, stringPtr);
23
+ }
21
24
  } else {
22
25
  stringPtr = __new(byteLength, idof<string>());
23
26
  store<usize>(dstFieldPtr, stringPtr);
@@ -65,7 +68,8 @@ import { hex4_to_u16_swar } from "../../util/swar";
65
68
  }
66
69
 
67
70
  // @ts-ignore: inline
68
- @inline export function deserializeStringField<T extends string | null>(srcStart: usize, srcEnd: usize, dstFieldPtr: usize): usize {
71
+ @inline export function deserializeStringField<T extends string | null>(srcStart: usize, srcEnd: usize, dstObj: usize, dstOffset: usize = 0): usize {
72
+ const dstFieldPtr = dstObj + dstOffset;
69
73
  if (srcStart + 2 > srcEnd || load<u16>(srcStart) != QUOTE) abort("Expected leading quote");
70
74
 
71
75
  const payloadStart = srcStart + 2;
@@ -82,18 +86,19 @@ import { hex4_to_u16_swar } from "../../util/swar";
82
86
  continue;
83
87
  }
84
88
 
85
- const outStart = bs.offset - bs.buffer;
89
+ bs.offset = bs.buffer;
86
90
  bs.ensureSize(u32(srcEnd - payloadStart));
87
91
  const prefixLen = <u32>(srcStart - payloadStart);
88
92
  if (prefixLen != 0) {
89
- memory.copy(bs.offset, payloadStart, prefixLen);
93
+ memory.copy(bs.buffer, payloadStart, prefixLen);
90
94
  bs.offset += prefixLen;
91
95
  }
92
96
 
93
97
  while (srcStart < srcEnd) {
94
98
  const block = load<u16>(srcStart);
95
99
  if (block == QUOTE) {
96
- bs.toField(outStart, dstFieldPtr);
100
+ writeStringToField(dstFieldPtr, bs.buffer, <u32>(bs.offset - bs.buffer));
101
+ bs.offset = bs.buffer;
97
102
  return srcStart + 2;
98
103
  }
99
104
 
@@ -118,7 +123,7 @@ import { hex4_to_u16_swar } from "../../util/swar";
118
123
  bs.offset += 2;
119
124
  }
120
125
 
121
- bs.offset = bs.buffer + outStart;
126
+ bs.offset = bs.buffer;
122
127
  break;
123
128
  }
124
129
 
@@ -1,165 +1,17 @@
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
- import { isSpace, isUnescapedQuote, scanStringEnd } from "../../util";
3
-
4
1
  export function deserializeStruct<T>(srcStart: usize, srcEnd: usize, dst: usize): T {
5
2
  const out = changetype<nonnull<T>>(dst || __new(offsetof<T>(), idof<T>()));
6
3
 
7
4
  // @ts-ignore: supplied by transform
8
5
  if (isDefined(out.__INITIALIZE)) out.__INITIALIZE();
9
-
10
- let keyStart: usize = 0;
11
- let keyEnd: usize = 0;
12
- let isKey = false;
13
- let depth = 0;
14
- let lastIndex: usize = 0;
15
-
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) throw new Error("Input string had zero length or was all whitespace");
20
- if (load<u16>(srcStart) != BRACE_LEFT) throw new Error("Expected '{' at start of object at position " + (srcEnd - srcStart).toString());
21
- if (load<u16>(srcEnd - 2) != BRACE_RIGHT) throw new Error("Expected '}' at end of object at position " + (srcEnd - srcStart).toString());
22
-
23
- srcStart += 2;
24
- while (srcStart < srcEnd) {
25
- let code = load<u16>(srcStart); // while (isSpace(code)) code = load<u16>(srcStart += 2);
26
- if (keyStart == 0) {
27
- if (code == QUOTE && isUnescapedQuote(srcStart)) {
28
- if (isKey) {
29
- keyStart = lastIndex;
30
- keyEnd = srcStart;
31
- // console.log("Key: " + ptrToStr(lastIndex, srcStart));
32
- // console.log("Next: " + String.fromCharCode(load<u16>(srcStart + 2)));
33
- while (isSpace((code = load<u16>((srcStart += 2))))) {}
34
- if (code !== COLON) throw new Error("Expected ':' after key at position " + (srcEnd - srcStart).toString());
35
- isKey = false;
36
- } else {
37
- // console.log("Got key start");
38
- isKey = true; // i don't like this
39
- lastIndex = srcStart + 2;
40
- }
41
- }
42
- // isKey = !isKey;
43
- srcStart += 2;
44
- } else {
45
- if (code == QUOTE) {
46
- lastIndex = srcStart;
47
- srcStart = scanStringEnd(srcStart, srcEnd);
48
- if (srcStart >= srcEnd) throw new Error("Unterminated string in JSON object");
49
- // @ts-ignore: exists
50
- out.__DESERIALIZE(keyStart, keyEnd, lastIndex, srcStart + 2, changetype<usize>(out));
51
- srcStart += 2;
52
- keyStart = 0;
53
- continue;
54
- } else if (code - 48 <= 9 || code == 45) {
55
- lastIndex = srcStart;
56
- srcStart += 2;
57
- while (srcStart < srcEnd) {
58
- const code = load<u16>(srcStart);
59
- if (code == COMMA || code == BRACE_RIGHT || isSpace(code)) {
60
- // console.log("Value (number): " + ptrToStr(lastIndex, srcStart));
61
- // @ts-ignore: exists
62
- out.__DESERIALIZE(keyStart, keyEnd, lastIndex, srcStart, changetype<usize>(out));
63
- // while (isSpace(load<u16>((srcStart += 2)))) {
64
- // /* empty */
65
- // }
66
- srcStart += 2;
67
- // console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
68
- keyStart = 0;
69
- break;
70
- }
71
- srcStart += 2;
72
- }
73
- } else if (code == BRACE_LEFT) {
74
- lastIndex = srcStart;
75
- depth++;
76
- srcStart += 2;
77
- while (srcStart < srcEnd) {
78
- const code = load<u16>(srcStart);
79
- if (code == QUOTE) {
80
- srcStart = scanStringEnd(srcStart, srcEnd);
81
- if (srcStart >= srcEnd) throw new Error("Unterminated string in JSON object");
82
- } else if (code == BRACE_RIGHT) {
83
- if (--depth == 0) {
84
- // console.log("Value (object): " + ptrToStr(lastIndex, srcStart + 2));
85
- // @ts-ignore: exists
86
- out.__DESERIALIZE(keyStart, keyEnd, lastIndex, (srcStart += 2), changetype<usize>(out));
87
- // console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
88
- keyStart = 0;
89
- // while (isSpace(load<u16>(srcStart))) {
90
- // /* empty */
91
- // }
92
- break;
93
- }
94
- } else if (code == BRACE_LEFT) depth++;
95
- srcStart += 2;
96
- }
97
- } else if (code == BRACKET_LEFT) {
98
- lastIndex = srcStart;
99
- depth++;
100
- srcStart += 2;
101
- while (srcStart < srcEnd) {
102
- const code = load<u16>(srcStart);
103
- if (code == QUOTE) {
104
- srcStart = scanStringEnd(srcStart, srcEnd);
105
- if (srcStart >= srcEnd) throw new Error("Unterminated string in JSON object");
106
- } else if (code == BRACKET_RIGHT) {
107
- if (--depth == 0) {
108
- // console.log("Value (array): " + ptrToStr(lastIndex, srcStart + 2));
109
- // @ts-ignore: exists
110
- out.__DESERIALIZE(keyStart, keyEnd, lastIndex, (srcStart += 2), changetype<usize>(out));
111
- // console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
112
- keyStart = 0;
113
- // while (isSpace(load<u16>((srcStart += 2)))) {
114
- // /* empty */
115
- // }
116
- break;
117
- }
118
- } else if (code == BRACKET_LEFT) depth++;
119
- srcStart += 2;
120
- }
121
- } else if (code == CHAR_T) {
122
- if (load<u64>(srcStart) == 28429475166421108) {
123
- // console.log("Value (bool): " + ptrToStr(srcStart, srcStart + 8));
124
- // @ts-ignore: exists
125
- out.__DESERIALIZE(keyStart, keyEnd, srcStart, (srcStart += 8), changetype<usize>(out));
126
- // while (isSpace(load<u16>((srcStart += 2)))) {
127
- // /* empty */
128
- // }
129
- srcStart += 2;
130
- // console.log("Next: " + String.fromCharCode(load<u16>(srcStart)) + " " + (srcStart < srcEnd).toString());
131
- keyStart = 0;
132
- }
133
- } else if (code == CHAR_F) {
134
- if (load<u64>(srcStart, 2) == 28429466576093281) {
135
- // console.log("Value (bool): " + ptrToStr(srcStart, srcStart + 10));
136
- // @ts-ignore: exists
137
- out.__DESERIALIZE(keyStart, keyEnd, srcStart, (srcStart += 10), changetype<usize>(out));
138
- // while (isSpace(load<u16>((srcStart += 2)))) {
139
- // /* empty */
140
- // }
141
- srcStart += 2;
142
- // console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
143
- keyStart = 0;
144
- }
145
- } else if (code == CHAR_N) {
146
- if (load<u64>(srcStart) == 30399761348886638) {
147
- // console.log("Value (null): " + ptrToStr(srcStart, srcStart + 8));
148
- // @ts-ignore: exists
149
- out.__DESERIALIZE(keyStart, keyEnd, srcStart, (srcStart += 8), changetype<usize>(out));
150
- // while (isSpace(load<u16>((srcStart += 2)))) {
151
- /* empty */
152
- // }
153
- srcStart += 2;
154
- // console.log("Next: " + String.fromCharCode(load<u16>(srcStart)));
155
- keyStart = 0;
156
- }
157
- } else if (isSpace(code)) {
158
- srcStart += 2;
159
- } else {
160
- throw new Error("Unexpected character in JSON object '" + String.fromCharCode(code) + "' at position " + (srcEnd - srcStart).toString());
161
- }
162
- }
6
+ // @ts-ignore: supplied by transform
7
+ if (isDefined(out.__DESERIALIZE_FAST)) {
8
+ // @ts-ignore: supplied by transform
9
+ out.__DESERIALIZE_FAST(srcStart, srcEnd, out);
10
+ } else if (isDefined(out.__DESERIALIZE_SLOW)) {
11
+ // @ts-ignore: supplied by transform
12
+ out.__DESERIALIZE_SLOW(srcStart, srcEnd, out);
13
+ } else {
14
+ throw new Error("Missing __DESERIALIZE_FAST/__DESERIALIZE_SLOW");
163
15
  }
164
16
  return out;
165
17
  }
@@ -1,5 +1,5 @@
1
1
  import { COMMA, BRACKET_RIGHT } from "../../custom/chars";
2
- import { deserializeFloat } from "../index/float";
2
+ import { deserializeFloat } from "./float";
3
3
  import { atoi, isSpace } from "../../util";
4
4
 
5
5
 
@@ -1,4 +1,4 @@
1
- import { atoi } from "../util/atoi";
1
+ import { atoi } from "../../util/atoi";
2
2
 
3
3
  // @ts-ignore: inline
4
4
  @inline export function deserializeUnsigned<T>(srcStart: usize, srcEnd: usize): T {
@@ -6,7 +6,8 @@ import { atoi } from "../util/atoi";
6
6
  }
7
7
 
8
8
  // @ts-ignore: inline
9
- @inline export function deserializeUnsignedField<T extends number>(srcStart: usize, srcEnd: usize, fieldPtr: usize): usize {
9
+ @inline export function deserializeUnsignedField<T extends number>(srcStart: usize, srcEnd: usize, dstObj: usize, dstOffset: usize = 0): usize {
10
+ const fieldPtr = dstObj + dstOffset;
10
11
  let digit = <u32>load<u16>(srcStart) - 48;
11
12
  if (digit > 9) unreachable();
12
13
 
@@ -1,10 +1,10 @@
1
+ import { JSON } from "../../..";
1
2
  import { BRACKET_LEFT, BRACKET_RIGHT, COMMA } from "../../../custom/chars";
2
- import { deserializeArrayField } from "../array";
3
- import { ensureArrayElementSlot, ensureArrayField } from "./shared";
3
+ import { deserializeFloatArrayInto } from "./float";
4
+ import { ensureArrayField, scanValueEnd } from "./shared";
4
5
 
5
6
 
6
- @inline export function deserializeArrayArrayField<T extends unknown[][]>(srcStart: usize, srcEnd: usize, fieldPtr: usize): usize {
7
- const out = ensureArrayField<T>(fieldPtr);
7
+ @inline export function deserializeArrayArrayInto<T extends unknown[][]>(srcStart: usize, srcEnd: usize, out: T): usize {
8
8
  let index = 0;
9
9
 
10
10
  do {
@@ -17,9 +17,39 @@ import { ensureArrayElementSlot, ensureArrayField } from "./shared";
17
17
  }
18
18
 
19
19
  while (srcStart < srcEnd) {
20
- const slot = ensureArrayElementSlot<T>(out, index);
21
- srcStart = deserializeArrayField<valueof<T>>(srcStart, srcEnd, slot);
22
- if (!srcStart || srcStart >= srcEnd) break;
20
+ if (isFloat<valueof<valueof<T>>>()) {
21
+ let value: valueof<T>;
22
+ if (index < out.length) {
23
+ value = unchecked(out[index]);
24
+ } else {
25
+ value = changetype<valueof<T>>(instantiate<valueof<T>>());
26
+ out.push(value);
27
+ }
28
+ srcStart = deserializeFloatArrayInto<valueof<T>>(srcStart, srcEnd, value);
29
+ if (!srcStart || srcStart >= srcEnd) break;
30
+ } else if (isArray<valueof<valueof<T>>>()) {
31
+ let value: valueof<T>;
32
+ if (index < out.length) {
33
+ value = unchecked(out[index]);
34
+ } else {
35
+ value = changetype<valueof<T>>(instantiate<valueof<T>>());
36
+ out.push(value);
37
+ }
38
+ srcStart = deserializeArrayArrayInto<valueof<T>>(srcStart, srcEnd, value);
39
+ if (!srcStart || srcStart >= srcEnd) break;
40
+ } else {
41
+ const valueEnd = scanValueEnd(srcStart, srcEnd);
42
+ if (!valueEnd || valueEnd <= srcStart) break;
43
+
44
+ let valuePtr: usize = 0;
45
+ if (index < out.length) {
46
+ valuePtr = changetype<usize>(unchecked(out[index]));
47
+ }
48
+ const value = JSON.__deserialize<valueof<T>>(srcStart, valueEnd, valuePtr);
49
+ if (index < out.length) unchecked((out[index] = value));
50
+ else out.push(value);
51
+ srcStart = valueEnd;
52
+ }
23
53
 
24
54
  const code = load<u16>(srcStart);
25
55
  if (code == COMMA) {
@@ -37,3 +67,8 @@ import { ensureArrayElementSlot, ensureArrayField } from "./shared";
37
67
 
38
68
  throw new Error("Failed to parse JSON!");
39
69
  }
70
+
71
+
72
+ @inline export function deserializeArrayArrayField<T extends unknown[][]>(srcStart: usize, srcEnd: usize, fieldPtr: usize): usize {
73
+ return deserializeArrayArrayInto<T>(srcStart, srcEnd, ensureArrayField<T>(fieldPtr));
74
+ }