json-as 1.2.6 → 1.3.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 (135) hide show
  1. package/CHANGELOG.md +417 -0
  2. package/README.md +135 -36
  3. package/assembly/custom/util.ts +24 -70
  4. package/assembly/deserialize/float.ts +181 -0
  5. package/assembly/deserialize/helpers/uint.ts +12 -0
  6. package/assembly/deserialize/index/arbitrary.ts +25 -0
  7. package/assembly/deserialize/index/array.ts +61 -0
  8. package/assembly/deserialize/index/bool.ts +1 -0
  9. package/assembly/deserialize/index/date.ts +1 -0
  10. package/assembly/deserialize/index/float.ts +1 -0
  11. package/assembly/deserialize/index/integer.ts +1 -0
  12. package/assembly/deserialize/index/map.ts +1 -0
  13. package/assembly/deserialize/index/object.ts +1 -0
  14. package/assembly/deserialize/index/raw.ts +1 -0
  15. package/assembly/deserialize/index/set.ts +1 -0
  16. package/assembly/deserialize/index/staticarray.ts +1 -0
  17. package/assembly/deserialize/index/string.ts +15 -0
  18. package/assembly/deserialize/index/struct.ts +1 -0
  19. package/assembly/deserialize/index/typedarray.ts +15 -0
  20. package/assembly/deserialize/index/unsigned.ts +1 -0
  21. package/assembly/deserialize/index.ts +14 -0
  22. package/assembly/deserialize/integer.ts +42 -0
  23. package/assembly/deserialize/simd/array/integer.ts +307 -0
  24. package/assembly/deserialize/simd/string.ts +130 -11
  25. package/assembly/deserialize/simple/arbitrary.ts +5 -12
  26. package/assembly/deserialize/simple/array/arbitrary.ts +12 -36
  27. package/assembly/deserialize/simple/array/array.ts +2 -8
  28. package/assembly/deserialize/simple/array/bool.ts +2 -8
  29. package/assembly/deserialize/simple/array/box.ts +2 -8
  30. package/assembly/deserialize/simple/array/float.ts +2 -8
  31. package/assembly/deserialize/simple/array/integer.ts +2 -8
  32. package/assembly/deserialize/simple/array/map.ts +6 -26
  33. package/assembly/deserialize/simple/array/object.ts +6 -26
  34. package/assembly/deserialize/simple/array/raw.ts +18 -61
  35. package/assembly/deserialize/simple/array/string.ts +5 -10
  36. package/assembly/deserialize/simple/array/struct.ts +6 -26
  37. package/assembly/deserialize/simple/array.ts +2 -5
  38. package/assembly/deserialize/simple/bool.ts +2 -6
  39. package/assembly/deserialize/simple/map.ts +29 -102
  40. package/assembly/deserialize/simple/object.ts +24 -81
  41. package/assembly/deserialize/simple/raw.ts +1 -4
  42. package/assembly/deserialize/simple/set.ts +11 -37
  43. package/assembly/deserialize/simple/staticarray/array.ts +1 -1
  44. package/assembly/deserialize/simple/staticarray/bool.ts +1 -1
  45. package/assembly/deserialize/simple/staticarray/float.ts +1 -1
  46. package/assembly/deserialize/simple/staticarray/integer.ts +1 -1
  47. package/assembly/deserialize/simple/staticarray/string.ts +7 -14
  48. package/assembly/deserialize/simple/staticarray/struct.ts +1 -1
  49. package/assembly/deserialize/simple/staticarray.ts +57 -21
  50. package/assembly/deserialize/simple/string.ts +90 -10
  51. package/assembly/deserialize/simple/struct.ts +25 -121
  52. package/assembly/deserialize/simple/typedarray.ts +94 -0
  53. package/assembly/deserialize/swar/array/arbitrary.ts +8 -0
  54. package/assembly/deserialize/swar/array/array.ts +39 -0
  55. package/assembly/deserialize/swar/array/bool.ts +47 -0
  56. package/assembly/deserialize/swar/array/box.ts +8 -0
  57. package/assembly/deserialize/swar/array/float.ts +39 -0
  58. package/assembly/deserialize/swar/array/integer.ts +461 -0
  59. package/assembly/deserialize/swar/array/map.ts +7 -0
  60. package/assembly/deserialize/swar/array/object.ts +44 -0
  61. package/assembly/deserialize/swar/array/raw.ts +8 -0
  62. package/assembly/deserialize/swar/array/shared.ts +96 -0
  63. package/assembly/deserialize/swar/array/string.ts +39 -0
  64. package/assembly/deserialize/swar/array/struct.ts +44 -0
  65. package/assembly/deserialize/swar/array.ts +49 -0
  66. package/assembly/deserialize/swar/string.ts +648 -15
  67. package/assembly/deserialize/unsigned.ts +75 -0
  68. package/assembly/index.d.ts +1 -3
  69. package/assembly/index.ts +316 -374
  70. package/assembly/serialize/index/arbitrary.ts +75 -0
  71. package/assembly/serialize/index/array.ts +1 -0
  72. package/assembly/serialize/index/bool.ts +1 -0
  73. package/assembly/serialize/index/date.ts +1 -0
  74. package/assembly/serialize/index/float.ts +1 -0
  75. package/assembly/serialize/index/integer.ts +1 -0
  76. package/assembly/serialize/index/map.ts +1 -0
  77. package/assembly/serialize/index/object.ts +46 -0
  78. package/assembly/serialize/index/raw.ts +1 -0
  79. package/assembly/serialize/index/set.ts +1 -0
  80. package/assembly/serialize/index/staticarray.ts +1 -0
  81. package/assembly/serialize/index/string.ts +15 -0
  82. package/assembly/serialize/index/struct.ts +1 -0
  83. package/assembly/serialize/index/typedarray.ts +66 -0
  84. package/assembly/serialize/index.ts +13 -0
  85. package/assembly/serialize/simd/string.ts +4 -13
  86. package/assembly/serialize/simple/arbitrary.ts +6 -0
  87. package/assembly/serialize/simple/raw.ts +1 -5
  88. package/assembly/serialize/simple/string.ts +3 -11
  89. package/assembly/serialize/simple/typedarray.ts +63 -0
  90. package/assembly/serialize/swar/string.ts +6 -21
  91. package/assembly/util/concat.ts +1 -5
  92. package/assembly/util/index.ts +1 -0
  93. package/assembly/util/masks.ts +12 -18
  94. package/assembly/util/memory.ts +0 -0
  95. package/assembly/util/snp.ts +1 -4
  96. package/assembly/util/stringScan.ts +24 -0
  97. package/assembly/util/swar.ts +50 -6
  98. package/lib/as-bs.ts +137 -127
  99. package/package.json +26 -5
  100. package/transform/lib/builder.d.ts.map +1 -1
  101. package/transform/lib/builder.js +5 -13
  102. package/transform/lib/builder.js.map +1 -1
  103. package/transform/lib/index.d.ts +1 -0
  104. package/transform/lib/index.d.ts.map +1 -1
  105. package/transform/lib/index.js +672 -757
  106. package/transform/lib/index.js.map +1 -1
  107. package/transform/lib/linkers/alias.d.ts.map +1 -1
  108. package/transform/lib/linkers/alias.js.map +1 -1
  109. package/transform/lib/linkers/custom.d.ts.map +1 -1
  110. package/transform/lib/linkers/custom.js +8 -9
  111. package/transform/lib/linkers/custom.js.map +1 -1
  112. package/transform/lib/linkers/imports.d.ts.map +1 -1
  113. package/transform/lib/linkers/imports.js.map +1 -1
  114. package/transform/lib/types.d.ts +6 -0
  115. package/transform/lib/types.d.ts.map +1 -1
  116. package/transform/lib/types.js +83 -21
  117. package/transform/lib/types.js.map +1 -1
  118. package/transform/lib/util.d.ts.map +1 -1
  119. package/transform/lib/util.js +1 -1
  120. package/transform/lib/util.js.map +1 -1
  121. package/transform/lib/visitor.d.ts.map +1 -1
  122. package/transform/lib/visitor.js +1 -2
  123. package/transform/lib/visitor.js.map +1 -1
  124. package/.prettierrc +0 -3
  125. package/ARCHITECTURE.md +0 -320
  126. package/CONTRIBUTING.md +0 -238
  127. package/TODO +0 -1
  128. package/assembly/deserialize/simple/float.ts +0 -11
  129. package/assembly/deserialize/simple/integer.ts +0 -9
  130. package/assembly/test.ts +0 -30
  131. package/eslint.config.js +0 -60
  132. package/lib/tsconfig.json +0 -8
  133. package/tools/assemblyscript-eslint-local.js +0 -29
  134. package/tools/assemblyscript-eslint.js +0 -29
  135. package/transform/tsconfig.json +0 -35
package/assembly/index.ts CHANGED
@@ -1,46 +1,40 @@
1
1
  /// <reference path="./index.d.ts" />
2
2
 
3
3
  import { bs } from "../lib/as-bs";
4
- import { serializeArray } from "./serialize/simple/array";
5
- import { serializeMap } from "./serialize/simple/map";
6
- import { serializeDate } from "./serialize/simple/date";
7
- import { deserializeBoolean } from "./deserialize/simple/bool";
8
- import { deserializeArray } from "./deserialize/simple/array";
9
- import { deserializeFloat } from "./deserialize/simple/float";
10
- import { deserializeMap } from "./deserialize/simple/map";
11
- import { deserializeDate } from "./deserialize/simple/date";
12
- import { deserializeInteger } from "./deserialize/simple/integer";
13
- import { serializeArbitrary } from "./serialize/simple/arbitrary";
14
- import { serializeSet } from "./serialize/simple/set";
15
- import { deserializeSet } from "./deserialize/simple/set";
16
- import { serializeStaticArray } from "./serialize/simple/staticarray";
17
- import { deserializeStaticArray } from "./deserialize/simple/staticarray";
4
+ import { OBJECT, TOTAL_OVERHEAD } from "rt/common";
5
+ import { serializeArray } from "./serialize/index/array";
6
+ import { serializeMap } from "./serialize/index/map";
7
+ import { serializeDate } from "./serialize/index/date";
8
+ import { deserializeBoolean } from "./deserialize/index/bool";
9
+ import { deserializeArray } from "./deserialize/index/array";
10
+ import { deserializeFloat } from "./deserialize/index/float";
11
+ import { deserializeMap } from "./deserialize/index/map";
12
+ import { deserializeDate } from "./deserialize/index/date";
13
+ import { deserializeInteger } from "./deserialize/index/integer";
14
+ import { deserializeUnsigned } from "./deserialize/index/unsigned";
15
+ import { serializeArbitrary } from "./serialize/index/arbitrary";
16
+ import { serializeSet } from "./serialize/index/set";
17
+ import { deserializeSet } from "./deserialize/index/set";
18
+ import { serializeStaticArray } from "./serialize/index/staticarray";
19
+ import { deserializeStaticArray } from "./deserialize/index/staticarray";
18
20
 
19
- import {
20
- NULL_WORD,
21
- QUOTE,
22
- NULL_WORD_U64,
23
- TRUE_WORD_U64,
24
- FALSE_WORD_U64,
25
- } from "./custom/chars";
21
+ import { NULL_WORD, QUOTE, NULL_WORD_U64, TRUE_WORD_U64, FALSE_WORD_U64 } from "./custom/chars";
26
22
  import { dtoa_buffered, itoa_buffered } from "util/number";
27
- import { serializeBool } from "./serialize/simple/bool";
28
- import { serializeInteger } from "./serialize/simple/integer";
29
- import { serializeFloat } from "./serialize/simple/float";
30
- import { serializeStruct } from "./serialize/simple/struct";
23
+ import { serializeBool } from "./serialize/index/bool";
24
+ import { serializeInteger } from "./serialize/index/integer";
25
+ import { serializeFloat } from "./serialize/index/float";
26
+ import { serializeStruct } from "./serialize/index/struct";
31
27
  import { ptrToStr } from "./util/ptrToStr";
32
28
  import { atoi, bytes } from "./util";
33
- import { deserializeArbitrary } from "./deserialize/simple/arbitrary";
34
- import { serializeObject } from "./serialize/simple/object";
35
- import { deserializeObject } from "./deserialize/simple/object";
36
- import { serializeRaw } from "./serialize/simple/raw";
37
- import { deserializeRaw } from "./deserialize/simple/raw";
38
- import { serializeString_SIMD } from "./serialize/simd/string";
39
- import { serializeString_SWAR } from "./serialize/swar/string";
40
- import { deserializeString_SWAR } from "./deserialize/swar/string";
41
- import { deserializeString } from "./deserialize/simple/string";
42
- import { serializeString } from "./serialize/simple/string";
43
- import { deserializeString_SIMD } from "./deserialize/simd/string";
29
+ import { deserializeArbitrary } from "./deserialize/index/arbitrary";
30
+ import { serializeObject } from "./serialize/index/object";
31
+ import { deserializeObject } from "./deserialize/index/object";
32
+ import { serializeRaw } from "./serialize/index/raw";
33
+ import { deserializeRaw } from "./deserialize/index/raw";
34
+ import { deserializeString } from "./deserialize/index/string";
35
+ import { serializeString } from "./serialize/index/string";
36
+ import { deserializeArrayBuffer, deserializeTypedArray } from "./deserialize/index/typedarray";
37
+ import { serializeArrayBufferUnsafe, serializeDynamic, serializeTypedArray } from "./serialize/index/typedarray";
44
38
 
45
39
  /**
46
40
  * Offset of the 'storage' property in the JSON.Value class.
@@ -65,7 +59,7 @@ export namespace JSON {
65
59
  * ```
66
60
  */
67
61
  export function shrink(): void {
68
- bs.resize(64);
62
+ bs.shrink();
69
63
  }
70
64
  }
71
65
  /**
@@ -77,10 +71,7 @@ export namespace JSON {
77
71
  * @returns string
78
72
  */
79
73
  // @ts-expect-error: inline
80
- @inline export function stringify<T>(
81
- data: T,
82
- out: string | null = null,
83
- ): string {
74
+ @inline export function stringify<T>(data: T, out: string | null = null): string {
84
75
  if (isBoolean<T>()) {
85
76
  if (out) {
86
77
  if (<bool>data == true) {
@@ -94,12 +85,7 @@ export namespace JSON {
94
85
  return out;
95
86
  }
96
87
  return data ? "true" : "false";
97
- } else if (
98
- isInteger<T>() &&
99
- !isSigned<T>() &&
100
- nameof<T>() == "usize" &&
101
- data == 0
102
- ) {
88
+ } else if (isInteger<T>() && !isSigned<T>() && nameof<T>() == "usize" && data == 0) {
103
89
  if (out) {
104
90
  out = changetype<string>(__renew(changetype<usize>(out), 8));
105
91
  store<u64>(changetype<usize>(out), NULL_WORD_U64);
@@ -108,14 +94,10 @@ export namespace JSON {
108
94
  return NULL_WORD;
109
95
  } else if (isInteger<T>(data)) {
110
96
  if (out) {
111
- out = changetype<string>(
112
- __renew(changetype<usize>(out), sizeof<T>() << 3),
113
- );
97
+ out = changetype<string>(__renew(changetype<usize>(out), sizeof<T>() << 3));
114
98
 
115
99
  const bytes = itoa_buffered(changetype<usize>(out), data) << 1;
116
- return (out = changetype<string>(
117
- __renew(changetype<usize>(out), bytes),
118
- ));
100
+ return (out = changetype<string>(__renew(changetype<usize>(out), bytes)));
119
101
  }
120
102
  return data.toString();
121
103
  } else if (isFloat<T>(data)) {
@@ -123,9 +105,7 @@ export namespace JSON {
123
105
  out = changetype<string>(__renew(changetype<usize>(out), 64));
124
106
 
125
107
  const bytes = dtoa_buffered(changetype<usize>(out), data) << 1;
126
- return (out = changetype<string>(
127
- __renew(changetype<usize>(out), bytes),
128
- ));
108
+ return (out = changetype<string>(__renew(changetype<usize>(out), bytes)));
129
109
  }
130
110
  return data.toString();
131
111
  } else if (isNullable<T>() && changetype<usize>(data) == <usize>0) {
@@ -136,30 +116,23 @@ export namespace JSON {
136
116
  }
137
117
  return NULL_WORD;
138
118
  } else if (isString<nonnull<T>>()) {
139
- if (JSON_MODE === JSONMode.SIMD) {
140
- serializeString_SIMD(data as string);
141
- } else if (JSON_MODE === JSONMode.SWAR) {
142
- serializeString_SWAR(data as string);
143
- } else {
144
- serializeString(data as string);
145
- }
119
+ serializeString(data as string);
120
+ return bs.out<string>();
121
+ // @ts-expect-error: Defined by transform
122
+ } else if (isDefined(data.__SERIALIZE_CUSTOM)) {
123
+ // @ts-expect-error: Defined by transform
124
+ data.__SERIALIZE_CUSTOM();
146
125
  return bs.out<string>();
147
- // @ts-expect-error: Supplied by transform
126
+ // @ts-expect-error: Defined by transform
148
127
  } else if (isDefined(data.__SERIALIZE)) {
149
- // @ts-expect-error
128
+ // @ts-expect-error: Defined by transform
150
129
  inline.always(data.__SERIALIZE(changetype<usize>(data)));
151
130
  return bs.out<string>();
152
131
  } else if (data instanceof Date) {
153
- out = out
154
- ? changetype<string>(__renew(changetype<usize>(out), 52))
155
- : changetype<string>(__new(52, idof<string>()));
132
+ out = out ? changetype<string>(__renew(changetype<usize>(out), 52)) : changetype<string>(__new(52, idof<string>()));
156
133
 
157
134
  store<u16>(changetype<usize>(out), QUOTE);
158
- memory.copy(
159
- changetype<usize>(out) + 2,
160
- changetype<usize>(data.toISOString()),
161
- 48,
162
- );
135
+ memory.copy(changetype<usize>(out) + 2, changetype<usize>(data.toISOString()), 48);
163
136
  store<u16>(changetype<usize>(out), QUOTE, 50);
164
137
  return changetype<string>(out);
165
138
  } else if (data instanceof Array) {
@@ -170,6 +143,43 @@ export namespace JSON {
170
143
  // @ts-expect-error
171
144
  inline.always(serializeStaticArray(changetype<nonnull<T>>(data)));
172
145
  return bs.out<string>();
146
+ } else if (data instanceof Int8Array) {
147
+ inline.always(serializeTypedArray<Int8Array>(data));
148
+ return bs.out<string>();
149
+ } else if (data instanceof Uint8Array) {
150
+ inline.always(serializeTypedArray<Uint8Array>(data));
151
+ return bs.out<string>();
152
+ } else if (data instanceof Uint8ClampedArray) {
153
+ inline.always(serializeTypedArray<Uint8ClampedArray>(data));
154
+ return bs.out<string>();
155
+ } else if (data instanceof Int16Array) {
156
+ inline.always(serializeTypedArray<Int16Array>(data));
157
+ return bs.out<string>();
158
+ } else if (data instanceof Uint16Array) {
159
+ inline.always(serializeTypedArray<Uint16Array>(data));
160
+ return bs.out<string>();
161
+ } else if (data instanceof Int32Array) {
162
+ inline.always(serializeTypedArray<Int32Array>(data));
163
+ return bs.out<string>();
164
+ } else if (data instanceof Uint32Array) {
165
+ inline.always(serializeTypedArray<Uint32Array>(data));
166
+ return bs.out<string>();
167
+ } else if (data instanceof Int64Array) {
168
+ inline.always(serializeTypedArray<Int64Array>(data));
169
+ return bs.out<string>();
170
+ } else if (data instanceof Uint64Array) {
171
+ inline.always(serializeTypedArray<Uint64Array>(data));
172
+ return bs.out<string>();
173
+ } else if (data instanceof Float32Array) {
174
+ inline.always(serializeTypedArray<Float32Array>(data));
175
+ return bs.out<string>();
176
+ } else if (data instanceof Float64Array) {
177
+ inline.always(serializeTypedArray<Float64Array>(data));
178
+ return bs.out<string>();
179
+ } else if (data instanceof ArrayBuffer) {
180
+ const dataStart = changetype<usize>(data);
181
+ serializeArrayBufferUnsafe(dataStart, changetype<OBJECT>(dataStart - TOTAL_OVERHEAD).rtSize);
182
+ return bs.out<string>();
173
183
  } else if (data instanceof Set) {
174
184
  // @ts-expect-error
175
185
  inline.always(serializeSet(changetype<nonnull<T>>(data)));
@@ -190,11 +200,7 @@ export namespace JSON {
190
200
  } else if (data instanceof JSON.Box) {
191
201
  return JSON.stringify(data.value);
192
202
  } else {
193
- throw new Error(
194
- `Could not serialize data of type '${nameof<T>()}'. ` +
195
- `If this is a custom class, add the @json decorator: @json class ${nameof<T>()} { ... }. ` +
196
- `Supported types: primitives, string, Array, Map, Date, and @json decorated classes.`,
197
- );
203
+ throw new Error(`Could not serialize data of type '${nameof<T>()}'. ` + `If this is a custom class, add the @json decorator: @json class ${nameof<T>()} { ... }. ` + `Supported types: primitives, string, Array, StaticArray, TypedArray, ArrayBuffer, Map, Date, and @json decorated classes.`);
198
204
  }
199
205
  }
200
206
 
@@ -213,61 +219,65 @@ export namespace JSON {
213
219
  if (isBoolean<T>()) {
214
220
  return deserializeBoolean(dataPtr, dataPtr + dataSize) as T;
215
221
  } else if (isInteger<T>()) {
216
- return deserializeInteger<T>(dataPtr, dataPtr + dataSize);
222
+ return isSigned<T>() ? deserializeInteger<T>(dataPtr, dataPtr + dataSize) : deserializeUnsigned<T>(dataPtr, dataPtr + dataSize);
217
223
  } else if (isFloat<T>()) {
218
224
  return deserializeFloat<T>(dataPtr, dataPtr + dataSize);
219
- } else if (
220
- isNullable<T>() &&
221
- dataSize == 8 &&
222
- load<u64>(dataPtr) == NULL_WORD_U64
223
- ) {
225
+ } else if (isNullable<T>() && dataSize == 8 && load<u64>(dataPtr) == NULL_WORD_U64) {
224
226
  return null;
225
227
  } else if (isString<T>()) {
226
- if (JSON_MODE === JSONMode.NAIVE) {
227
- // @ts-expect-error: type
228
- return deserializeString(dataPtr, dataPtr + dataSize);
229
- } else if (JSON_MODE === JSONMode.SWAR) {
230
- // @ts-expect-error: type
231
- return deserializeString_SWAR(dataPtr, dataPtr + dataSize);
232
- } else if (JSON_MODE === JSONMode.SIMD) {
233
- // @ts-expect-error: type
234
- return deserializeString_SIMD(dataPtr, dataPtr + dataSize);
235
- }
228
+ return deserializeString(dataPtr, dataPtr + dataSize) as T;
236
229
  } else {
237
230
  let type: nonnull<T> = changetype<nonnull<T>>(0);
238
- if (type instanceof StaticArray) {
239
- // @ts-expect-error
240
- return inline.always(
241
- deserializeStaticArray<nonnull<T>>(dataPtr, dataPtr + dataSize, 0),
242
- );
243
- } else if (type instanceof Array) {
244
- // @ts-expect-error
245
- return inline.always(
246
- deserializeArray<nonnull<T>>(
247
- dataPtr,
248
- dataPtr + dataSize,
249
- changetype<usize>(instantiate<T>()),
250
- ),
251
- );
252
- } else if (type instanceof Set) {
231
+ // @ts-expect-error: Defined by transform
232
+ if (isDefined(type.__DESERIALIZE_CUSTOM)) {
233
+ const out = changetype<nonnull<T>>(0);
253
234
  // @ts-expect-error
254
- return inline.always(
255
- deserializeSet<nonnull<T>>(dataPtr, dataPtr + dataSize, 0),
256
- );
235
+ return out.__DESERIALIZE_CUSTOM(data);
257
236
  // @ts-expect-error: Defined by transform
258
237
  } else if (isDefined(type.__DESERIALIZE)) {
259
- const out = changetype<nonnull<T>>(
260
- __new(offsetof<nonnull<T>>(), idof<nonnull<T>>()),
261
- );
238
+ const out = changetype<nonnull<T>>(__new(offsetof<nonnull<T>>(), idof<nonnull<T>>()));
262
239
  // @ts-expect-error: Defined by transform
263
240
  if (isDefined(type.__INITIALIZE)) out.__INITIALIZE();
241
+ // @ts-expect-error: Defined by transform
242
+ out.__DESERIALIZE(dataPtr, dataPtr + dataSize, out);
243
+ return out;
244
+ }
245
+ if (type instanceof StaticArray) {
246
+ // @ts-expect-error
247
+ return inline.always(deserializeStaticArray<nonnull<T>>(dataPtr, dataPtr + dataSize, 0));
248
+ } else if (type instanceof Array) {
264
249
  // @ts-expect-error
265
- return out.__DESERIALIZE(dataPtr, dataPtr + dataSize, out);
250
+ return inline.always(deserializeArray<nonnull<T>>(dataPtr, dataPtr + dataSize, changetype<usize>(instantiate<T>())));
251
+ } else if (type instanceof Int8Array) {
252
+ return deserializeTypedArray<nonnull<T>>(dataPtr, dataPtr + dataSize, 0) as T;
253
+ } else if (type instanceof Uint8Array) {
254
+ return deserializeTypedArray<nonnull<T>>(dataPtr, dataPtr + dataSize, 0) as T;
255
+ } else if (type instanceof Uint8ClampedArray) {
256
+ return deserializeTypedArray<nonnull<T>>(dataPtr, dataPtr + dataSize, 0) as T;
257
+ } else if (type instanceof Int16Array) {
258
+ return deserializeTypedArray<nonnull<T>>(dataPtr, dataPtr + dataSize, 0) as T;
259
+ } else if (type instanceof Uint16Array) {
260
+ return deserializeTypedArray<nonnull<T>>(dataPtr, dataPtr + dataSize, 0) as T;
261
+ } else if (type instanceof Int32Array) {
262
+ return deserializeTypedArray<nonnull<T>>(dataPtr, dataPtr + dataSize, 0) as T;
263
+ } else if (type instanceof Uint32Array) {
264
+ return deserializeTypedArray<nonnull<T>>(dataPtr, dataPtr + dataSize, 0) as T;
265
+ } else if (type instanceof Int64Array) {
266
+ return deserializeTypedArray<nonnull<T>>(dataPtr, dataPtr + dataSize, 0) as T;
267
+ } else if (type instanceof Uint64Array) {
268
+ return deserializeTypedArray<nonnull<T>>(dataPtr, dataPtr + dataSize, 0) as T;
269
+ } else if (type instanceof Float32Array) {
270
+ return deserializeTypedArray<nonnull<T>>(dataPtr, dataPtr + dataSize, 0) as T;
271
+ } else if (type instanceof Float64Array) {
272
+ return deserializeTypedArray<nonnull<T>>(dataPtr, dataPtr + dataSize, 0) as T;
273
+ } else if (type instanceof ArrayBuffer) {
274
+ return deserializeArrayBuffer(dataPtr, dataPtr + dataSize, 0) as T;
275
+ } else if (type instanceof Set) {
276
+ // @ts-expect-error
277
+ return inline.always(deserializeSet<nonnull<T>>(dataPtr, dataPtr + dataSize, 0));
266
278
  } else if (type instanceof Map) {
267
279
  // @ts-expect-error
268
- return inline.always(
269
- deserializeMap<nonnull<T>>(dataPtr, dataPtr + dataSize, 0),
270
- );
280
+ return inline.always(deserializeMap<nonnull<T>>(dataPtr, dataPtr + dataSize, 0));
271
281
  } else if (type instanceof Date) {
272
282
  // @ts-expect-error
273
283
  return deserializeDate(dataPtr, dataPtr + dataSize);
@@ -276,9 +286,7 @@ export namespace JSON {
276
286
  return deserializeRaw(dataPtr, dataPtr + dataSize);
277
287
  } else if (type instanceof JSON.Value) {
278
288
  // @ts-expect-error
279
- return inline.always(
280
- deserializeArbitrary(dataPtr, dataPtr + dataSize, 0),
281
- );
289
+ return inline.always(deserializeArbitrary(dataPtr, dataPtr + dataSize, 0));
282
290
  } else if (type instanceof JSON.Obj) {
283
291
  // @ts-expect-error
284
292
  return inline.always(deserializeObject(dataPtr, dataPtr + dataSize, 0));
@@ -286,11 +294,7 @@ export namespace JSON {
286
294
  // @ts-expect-error
287
295
  return new JSON.Box(parseBox(data, changetype<nonnull<T>>(0).value));
288
296
  } else {
289
- throw new Error(
290
- `Could not deserialize JSON to type '${nameof<T>()}'. ` +
291
- `If this is a custom class, ensure it has the @json decorator: @json class ${nameof<T>()} { ... }. ` +
292
- `Input: "${data.length > 50 ? data.slice(0, 50) + "..." : data}"`,
293
- );
297
+ throw new Error(`Could not deserialize JSON to type '${nameof<T>()}'. ` + `If this is a custom class, ensure it has the @json decorator: @json class ${nameof<T>()} { ... }. ` + `Input: "${data.length > 50 ? data.slice(0, 50) + "..." : data}"`);
294
298
  }
295
299
  }
296
300
  }
@@ -304,7 +308,7 @@ export namespace JSON {
304
308
  * Enum-like namespace representing the different types supported by JSON.Value.
305
309
  *
306
310
  * Used internally to track the runtime type of values stored in JSON.Value instances.
307
- * Types 0-17 are reserved for built-in types; custom @json classes use idof<T>() + Struct.
311
+ * Types 0-19 are reserved for built-in types; custom @json classes use idof<T>() + Struct.
308
312
  */
309
313
  export namespace Types {
310
314
  /** Represents a null value */
@@ -345,6 +349,10 @@ export namespace JSON {
345
349
  @inline export const Map: u16 = 16;
346
350
  // @ts-expect-error
347
351
  @inline export const Struct: u16 = 17;
352
+ // @ts-expect-error
353
+ @inline export const TypedArray: u16 = 18;
354
+ // @ts-expect-error
355
+ @inline export const ArrayBuffer: u16 = 19;
348
356
  }
349
357
 
350
358
  /**
@@ -437,9 +445,7 @@ export namespace JSON {
437
445
  * @returns An instance of JSON.Value.
438
446
  */
439
447
  @inline static empty(): JSON.Value {
440
- return changetype<JSON.Value>(
441
- __new(offsetof<JSON.Value>(), idof<JSON.Value>()),
442
- );
448
+ return changetype<JSON.Value>(__new(offsetof<JSON.Value>(), idof<JSON.Value>()));
443
449
  }
444
450
 
445
451
  /**
@@ -449,9 +455,7 @@ export namespace JSON {
449
455
  */
450
456
  @inline static from<T>(value: T): JSON.Value {
451
457
  if (value instanceof JSON.Value) return value;
452
- const out = changetype<JSON.Value>(
453
- __new(offsetof<JSON.Value>(), idof<JSON.Value>()),
454
- );
458
+ const out = changetype<JSON.Value>(__new(offsetof<JSON.Value>(), idof<JSON.Value>()));
455
459
  out.set<T>(value);
456
460
  return out;
457
461
  }
@@ -462,38 +466,40 @@ export namespace JSON {
462
466
  * @returns JSON.Types
463
467
  */
464
468
  @inline getType<T>(value: T): JSON.Types {
465
- if (isNullable<T>() && changetype<usize>(value) === 0)
466
- return JSON.Types.Null;
469
+ if (isNullable<T>() && changetype<usize>(value) === 0) return JSON.Types.Null;
467
470
  if (isBoolean<T>()) return JSON.Types.Bool;
468
- if (
469
- isInteger<T>() &&
470
- !isSigned<T>() &&
471
- changetype<usize>(value) == 0 &&
472
- nameof<T>() == "usize"
473
- )
474
- return JSON.Types.Null;
471
+ if (isInteger<T>() && !isSigned<T>() && changetype<usize>(value) == 0 && nameof<T>() == "usize") return JSON.Types.Null;
475
472
  if (isString<T>()) return JSON.Types.String;
476
473
  // @ts-expect-error: can assume that T is ArrayLike based on previous condition
477
- if (isArray<T>() && idof<valueof<T>>() == idof<JSON.Value>())
478
- return JSON.Types.Array;
474
+ if (isArray<T>() && idof<valueof<T>>() == idof<JSON.Value>()) return JSON.Types.Array;
479
475
  if (value instanceof JSON.Box) return this.getType(value.value);
480
- if (value instanceof u8 || value instanceof i8) return JSON.Types.U8;
481
- if (value instanceof u16 || value instanceof i16) return JSON.Types.U16;
482
- if (value instanceof u32 || value instanceof i32) return JSON.Types.U32;
483
- if (value instanceof u64 || value instanceof i64) return JSON.Types.U64;
484
476
  if (value instanceof i8) return JSON.Types.I8;
485
477
  if (value instanceof i16) return JSON.Types.I16;
486
478
  if (value instanceof i32) return JSON.Types.I32;
487
479
  if (value instanceof i64) return JSON.Types.I64;
480
+ if (value instanceof u8) return JSON.Types.U8;
481
+ if (value instanceof u16) return JSON.Types.U16;
482
+ if (value instanceof u32) return JSON.Types.U32;
483
+ if (value instanceof u64) return JSON.Types.U64;
488
484
  if (value instanceof f32) return JSON.Types.F32;
489
485
  if (value instanceof f64) return JSON.Types.F64;
486
+ // @ts-expect-error: supplied by transform
487
+ if (isDefined(value.__SERIALIZE) && isManaged<T>(value)) return u16(idof<T>()) + JSON.Types.Struct;
488
+ if (value instanceof Int8Array) return JSON.Types.TypedArray;
489
+ if (value instanceof Uint8Array) return JSON.Types.TypedArray;
490
+ if (value instanceof Uint8ClampedArray) return JSON.Types.TypedArray;
491
+ if (value instanceof Int16Array) return JSON.Types.TypedArray;
492
+ if (value instanceof Uint16Array) return JSON.Types.TypedArray;
493
+ if (value instanceof Int32Array) return JSON.Types.TypedArray;
494
+ if (value instanceof Uint32Array) return JSON.Types.TypedArray;
495
+ if (value instanceof Int64Array) return JSON.Types.TypedArray;
496
+ if (value instanceof Uint64Array) return JSON.Types.TypedArray;
497
+ if (value instanceof Float32Array) return JSON.Types.TypedArray;
498
+ if (value instanceof Float64Array) return JSON.Types.TypedArray;
499
+ if (value instanceof ArrayBuffer) return JSON.Types.ArrayBuffer;
490
500
  if (value instanceof Map) return JSON.Types.Map;
491
501
  if (value instanceof JSON.Raw) return JSON.Types.Raw;
492
502
  if (value instanceof JSON.Obj) return JSON.Types.Object;
493
-
494
- // @ts-expect-error: supplied by transform
495
- if (isDefined(value.__SERIALIZE) && isManaged<T>(value))
496
- return u16(idof<T>()) + JSON.Types.Struct;
497
503
  return JSON.Types.Null;
498
504
  }
499
505
  /**
@@ -504,37 +510,34 @@ export namespace JSON {
504
510
  this.type = this.getType<T>(value);
505
511
 
506
512
  if (value instanceof JSON.Box) this.set(value.value);
507
- else if (isBoolean<T>())
508
- store<T>(changetype<usize>(this), value, STORAGE);
509
- else if (
510
- isInteger<T>() &&
511
- !isSigned<T>() &&
512
- changetype<usize>(value) == 0 &&
513
- nameof<T>() == "usize"
514
- )
515
- store<usize>(changetype<usize>(this), 0, STORAGE);
516
- else if (isInteger<T>() || isFloat<T>())
517
- store<T>(changetype<usize>(this), value, STORAGE);
518
- else if (isNullable<T>() && changetype<usize>(value) === 0)
519
- store<usize>(changetype<usize>(this), 0, STORAGE);
513
+ else if (isBoolean<T>()) store<T>(changetype<usize>(this), value, STORAGE);
514
+ else if (isInteger<T>() && !isSigned<T>() && changetype<usize>(value) == 0 && nameof<T>() == "usize") store<usize>(changetype<usize>(this), 0, STORAGE);
515
+ else if (isInteger<T>() || isFloat<T>()) store<T>(changetype<usize>(this), value, STORAGE);
516
+ else if (isNullable<T>() && changetype<usize>(value) === 0) store<usize>(changetype<usize>(this), 0, STORAGE);
520
517
  else if (isString<T>()) store<T>(changetype<usize>(this), value, STORAGE);
521
- else if (value instanceof JSON.Raw)
522
- store<T>(changetype<usize>(this), value, STORAGE);
518
+ else if (value instanceof JSON.Raw) store<T>(changetype<usize>(this), value, STORAGE);
519
+ // @ts-expect-error: supplied by transform
520
+ else if (isDefined(value.__SERIALIZE) && isManaged<T>(value)) {
521
+ // @ts-expect-error
522
+ if (!JSON.Value.METHODS.has(idof<T>())) JSON.Value.METHODS.set(idof<T>(), value.__SERIALIZE.index);
523
+ store<usize>(changetype<usize>(this), changetype<usize>(value), STORAGE);
524
+ } else if (value instanceof Int8Array) store<T>(changetype<usize>(this), value, STORAGE);
525
+ else if (value instanceof Uint8Array) store<T>(changetype<usize>(this), value, STORAGE);
526
+ else if (value instanceof Uint8ClampedArray) store<T>(changetype<usize>(this), value, STORAGE);
527
+ else if (value instanceof Int16Array) store<T>(changetype<usize>(this), value, STORAGE);
528
+ else if (value instanceof Uint16Array) store<T>(changetype<usize>(this), value, STORAGE);
529
+ else if (value instanceof Int32Array) store<T>(changetype<usize>(this), value, STORAGE);
530
+ else if (value instanceof Uint32Array) store<T>(changetype<usize>(this), value, STORAGE);
531
+ else if (value instanceof Int64Array) store<T>(changetype<usize>(this), value, STORAGE);
532
+ else if (value instanceof Uint64Array) store<T>(changetype<usize>(this), value, STORAGE);
533
+ else if (value instanceof Float32Array) store<T>(changetype<usize>(this), value, STORAGE);
534
+ else if (value instanceof Float64Array) store<T>(changetype<usize>(this), value, STORAGE);
535
+ else if (value instanceof ArrayBuffer) store<T>(changetype<usize>(this), value, STORAGE);
523
536
  else if (value instanceof Map) {
524
537
  if (idof<T>() !== idof<Map<string, JSON.Value>>()) {
525
538
  abort("Maps must be of type Map<string, JSON.Value>!");
526
539
  }
527
540
  store<T>(changetype<usize>(this), value, STORAGE);
528
- // @ts-expect-error: supplied by transform
529
- } else if (isDefined(value.__SERIALIZE) && isManaged<T>(value)) {
530
- // @ts-expect-error
531
- if (!JSON.Value.METHODS.has(idof<T>()))
532
- JSON.Value.METHODS.set(idof<T>(), value.__SERIALIZE.index);
533
- store<usize>(
534
- changetype<usize>(this),
535
- changetype<usize>(value),
536
- STORAGE,
537
- );
538
541
  } else if (value instanceof JSON.Obj) {
539
542
  store<T>(changetype<usize>(this), value, STORAGE);
540
543
  // @ts-expect-error
@@ -586,6 +589,14 @@ export namespace JSON {
586
589
  return this.get<u32>().toString();
587
590
  case JSON.Types.U64:
588
591
  return this.get<u64>().toString();
592
+ case JSON.Types.I8:
593
+ return this.get<i8>().toString();
594
+ case JSON.Types.I16:
595
+ return this.get<i16>().toString();
596
+ case JSON.Types.I32:
597
+ return this.get<i32>().toString();
598
+ case JSON.Types.I64:
599
+ return this.get<i64>().toString();
589
600
  case JSON.Types.F32:
590
601
  return this.get<f32>().toString();
591
602
  case JSON.Types.F64:
@@ -612,6 +623,11 @@ export namespace JSON {
612
623
 
613
624
  return out.toString();
614
625
  }
626
+ case JSON.Types.TypedArray:
627
+ case JSON.Types.ArrayBuffer: {
628
+ serializeDynamic(this.type, this.get<usize>());
629
+ return bs.out<string>();
630
+ }
615
631
  case JSON.Types.Object: {
616
632
  return JSON.stringify(this.get<JSON.Obj>());
617
633
  }
@@ -732,11 +748,25 @@ export namespace JSON {
732
748
  */
733
749
  @inline static from<T>(value: T): JSON.Obj {
734
750
  if (value instanceof JSON.Obj) return value;
735
- const out = new JSON.Obj();
736
-
737
751
  if (value instanceof Map) {
752
+ const out = new JSON.Obj();
753
+ if (!isString<indexof<T>>()) {
754
+ throw new Error("JSON.Obj.from only supports maps with string keys");
755
+ }
756
+
757
+ const keys = value.keys();
758
+ const values = value.values();
759
+ for (let i = 0; i < keys.length; i++) {
760
+ out.set(unchecked(keys[i]), unchecked(values[i]));
761
+ }
762
+ return out;
738
763
  }
739
- return out;
764
+
765
+ const parsed = JSON.parse<JSON.Value>(JSON.stringify(value));
766
+ if (parsed.type != JSON.Types.Object) {
767
+ throw new Error("JSON.Obj.from expects a value that serializes to a JSON object");
768
+ }
769
+ return parsed.get<JSON.Obj>();
740
770
  }
741
771
  }
742
772
  /**
@@ -744,8 +774,7 @@ export namespace JSON {
744
774
  */
745
775
  export class Box<T> {
746
776
  constructor(public value: T) {
747
- if (!isInteger<T>() && !isFloat<T>())
748
- ERROR("JSON.Box should only hold primitive types!");
777
+ if (!isInteger<T>() && !isFloat<T>() && !isBoolean<T>()) ERROR("JSON.Box should only hold primitive types!");
749
778
  }
750
779
  /**
751
780
  * Set the internal value of Box to new value
@@ -768,11 +797,9 @@ export namespace JSON {
768
797
  * @returns Box<T> | null
769
798
  */
770
799
  @inline static fromValue<T>(value: JSON.Value): Box<T> | null {
771
- if (!(value instanceof JSON.Value))
772
- throw new Error("value must be of type JSON.Value");
800
+ if (!(value instanceof JSON.Value)) throw new Error("value must be of type JSON.Value");
773
801
  if (value.type === JSON.Types.Null) return null;
774
- const v =
775
- value.type === JSON.Types.F64 ? value.get<f64>() : value.get<T>();
802
+ const v = value.type === JSON.Types.F64 ? value.get<f64>() : value.get<T>();
776
803
  // @ts-expect-error
777
804
  return new Box(isInteger<T>() || isFloat<T>() ? <T>v : v);
778
805
  }
@@ -821,20 +848,14 @@ export namespace JSON {
821
848
  store<u64>(bs.offset, NULL_WORD_U64);
822
849
  bs.offset += 8;
823
850
  } else if (isString<nonnull<T>>()) {
824
- if (JSON_MODE === JSONMode.SIMD) {
825
- serializeString_SIMD(data as string);
826
- } else if (JSON_MODE === JSONMode.SWAR) {
827
- serializeString_SWAR(data as string);
828
- } else {
829
- serializeString(data as string);
830
- }
831
- // @ts-expect-error: Supplied by transform
851
+ serializeString(data as string);
852
+ // @ts-expect-error: Defined by transform
832
853
  } else if (isDefined(data.__SERIALIZE_CUSTOM)) {
833
854
  // @ts-expect-error
834
855
  return data.__SERIALIZE_CUSTOM();
835
- // @ts-expect-error: Supplied by transform
856
+ // @ts-expect-error: Defined by transform
836
857
  } else if (isDefined(data.__SERIALIZE)) {
837
- // @ts-expect-error
858
+ // @ts-expect-error: type
838
859
  serializeStruct(changetype<nonnull<T>>(data));
839
860
  } else if (data instanceof Date) {
840
861
  // @ts-expect-error
@@ -845,6 +866,31 @@ export namespace JSON {
845
866
  } else if (data instanceof StaticArray) {
846
867
  // @ts-expect-error
847
868
  serializeStaticArray(changetype<nonnull<T>>(data));
869
+ } else if (data instanceof Int8Array) {
870
+ serializeTypedArray<Int8Array>(data);
871
+ } else if (data instanceof Uint8Array) {
872
+ serializeTypedArray<Uint8Array>(data);
873
+ } else if (data instanceof Uint8ClampedArray) {
874
+ serializeTypedArray<Uint8ClampedArray>(data);
875
+ } else if (data instanceof Int16Array) {
876
+ serializeTypedArray<Int16Array>(data);
877
+ } else if (data instanceof Uint16Array) {
878
+ serializeTypedArray<Uint16Array>(data);
879
+ } else if (data instanceof Int32Array) {
880
+ serializeTypedArray<Int32Array>(data);
881
+ } else if (data instanceof Uint32Array) {
882
+ serializeTypedArray<Uint32Array>(data);
883
+ } else if (data instanceof Int64Array) {
884
+ serializeTypedArray<Int64Array>(data);
885
+ } else if (data instanceof Uint64Array) {
886
+ serializeTypedArray<Uint64Array>(data);
887
+ } else if (data instanceof Float32Array) {
888
+ serializeTypedArray<Float32Array>(data);
889
+ } else if (data instanceof Float64Array) {
890
+ serializeTypedArray<Float64Array>(data);
891
+ } else if (data instanceof ArrayBuffer) {
892
+ const dataStart = changetype<usize>(data);
893
+ serializeArrayBufferUnsafe(dataStart, changetype<OBJECT>(dataStart - TOTAL_OVERHEAD).rtSize);
848
894
  } else if (data instanceof Set) {
849
895
  // @ts-expect-error
850
896
  serializeSet(changetype<nonnull<T>>(data));
@@ -860,11 +906,7 @@ export namespace JSON {
860
906
  } else if (data instanceof JSON.Box) {
861
907
  __serialize(data.value);
862
908
  } else {
863
- throw new Error(
864
- `Could not serialize data of type '${nameof<T>()}'. ` +
865
- `If this is a custom class, add the @json decorator: @json class ${nameof<T>()} { ... }. ` +
866
- `Supported types: primitives, string, Array, Map, Date, and @json decorated classes.`,
867
- );
909
+ throw new Error(`Could not serialize data of type '${nameof<T>()}'. ` + `If this is a custom class, add the @json decorator: @json class ${nameof<T>()} { ... }. ` + `Supported types: primitives, string, Array, StaticArray, TypedArray, ArrayBuffer, Map, Date, and @json decorated classes.`);
868
910
  }
869
911
  }
870
912
 
@@ -876,52 +918,69 @@ export namespace JSON {
876
918
  * @param dst - usize
877
919
  * @returns void
878
920
  */
879
- export function __deserialize<T>(
880
- srcStart: usize,
881
- srcEnd: usize,
882
- dst: usize = 0,
883
- ): T {
921
+ export function __deserialize<T>(srcStart: usize, srcEnd: usize, dst: usize = 0): T {
884
922
  if (isBoolean<T>()) {
885
923
  // @ts-expect-error: type
886
924
  return deserializeBoolean(srcStart, srcEnd);
887
925
  } else if (isInteger<T>()) {
888
- return atoi<T>(srcStart, srcEnd);
926
+ return isSigned<T>() ? deserializeInteger<T>(srcStart, srcEnd) : deserializeUnsigned<T>(srcStart, srcEnd);
889
927
  } else if (isFloat<T>()) {
890
928
  return deserializeFloat<T>(srcStart, srcEnd);
891
929
  } else if (isString<T>()) {
892
- if (srcEnd - srcStart < 4)
893
- throw new Error(
894
- "Cannot parse data as string because it was formatted incorrectly!",
895
- );
930
+ if (srcEnd - srcStart < 4) throw new Error("Cannot parse data as string because it was formatted incorrectly!");
896
931
 
897
- // @ts-expect-error: type
898
- return deserializeString(srcStart, srcEnd);
899
- } else if (
900
- isNullable<T>() &&
901
- srcEnd - srcStart == 8 &&
902
- load<u64>(srcStart) == NULL_WORD_U64
903
- ) {
932
+ return deserializeString(srcStart, srcEnd) as T;
933
+ } else if (isNullable<T>() && srcEnd - srcStart == 8 && load<u64>(srcStart) == NULL_WORD_U64) {
904
934
  return null;
905
935
  } else {
906
936
  let type: nonnull<T> = changetype<nonnull<T>>(0);
937
+ // @ts-expect-error: Defined by transform
938
+ if (isDefined(type.__DESERIALIZE_CUSTOM)) {
939
+ const out = changetype<nonnull<T>>(0);
940
+ // @ts-expect-error: Defined by transform
941
+ return out.__DESERIALIZE_CUSTOM(ptrToStr(srcStart, srcEnd));
942
+ // @ts-expect-error: Defined by transform
943
+ } else if (isDefined(type.__DESERIALIZE)) {
944
+ const out = changetype<nonnull<T>>(dst || __new(offsetof<nonnull<T>>(), idof<nonnull<T>>()));
945
+ // @ts-expect-error: Defined by transform
946
+ if (isDefined(type.__INITIALIZE)) out.__INITIALIZE();
947
+ // @ts-expect-error: Defined by transform
948
+ out.__DESERIALIZE(srcStart, srcEnd, out);
949
+ return out;
950
+ }
907
951
  if (type instanceof StaticArray) {
908
952
  // @ts-expect-error: type
909
953
  return deserializeStaticArray<T>(srcStart, srcEnd, dst);
910
954
  } else if (type instanceof Array) {
911
955
  // @ts-expect-error: type
912
956
  return deserializeArray<T>(srcStart, srcEnd, dst);
957
+ } else if (type instanceof Int8Array) {
958
+ return deserializeTypedArray<nonnull<T>>(srcStart, srcEnd, dst) as T;
959
+ } else if (type instanceof Uint8Array) {
960
+ return deserializeTypedArray<nonnull<T>>(srcStart, srcEnd, dst) as T;
961
+ } else if (type instanceof Uint8ClampedArray) {
962
+ return deserializeTypedArray<nonnull<T>>(srcStart, srcEnd, dst) as T;
963
+ } else if (type instanceof Int16Array) {
964
+ return deserializeTypedArray<nonnull<T>>(srcStart, srcEnd, dst) as T;
965
+ } else if (type instanceof Uint16Array) {
966
+ return deserializeTypedArray<nonnull<T>>(srcStart, srcEnd, dst) as T;
967
+ } else if (type instanceof Int32Array) {
968
+ return deserializeTypedArray<nonnull<T>>(srcStart, srcEnd, dst) as T;
969
+ } else if (type instanceof Uint32Array) {
970
+ return deserializeTypedArray<nonnull<T>>(srcStart, srcEnd, dst) as T;
971
+ } else if (type instanceof Int64Array) {
972
+ return deserializeTypedArray<nonnull<T>>(srcStart, srcEnd, dst) as T;
973
+ } else if (type instanceof Uint64Array) {
974
+ return deserializeTypedArray<nonnull<T>>(srcStart, srcEnd, dst) as T;
975
+ } else if (type instanceof Float32Array) {
976
+ return deserializeTypedArray<nonnull<T>>(srcStart, srcEnd, dst) as T;
977
+ } else if (type instanceof Float64Array) {
978
+ return deserializeTypedArray<nonnull<T>>(srcStart, srcEnd, dst) as T;
979
+ } else if (type instanceof ArrayBuffer) {
980
+ return deserializeArrayBuffer(srcStart, srcEnd, dst) as T;
913
981
  } else if (type instanceof Set) {
914
982
  // @ts-expect-error: type
915
983
  return deserializeSet<T>(srcStart, srcEnd, dst);
916
- // @ts-expect-error: Defined by transform
917
- } else if (isDefined(type.__DESERIALIZE)) {
918
- const out = changetype<nonnull<T>>(
919
- dst || __new(offsetof<nonnull<T>>(), idof<nonnull<T>>()),
920
- );
921
- // @ts-expect-error: Defined by transform
922
- if (isDefined(type.__INITIALIZE)) out.__INITIALIZE();
923
- // @ts-expect-error: Defined by transform
924
- return out.__DESERIALIZE(srcStart, srcEnd, out);
925
984
  } else if (type instanceof Map) {
926
985
  // @ts-expect-error: type
927
986
  return deserializeMap<T>(srcStart, srcEnd, dst);
@@ -939,22 +998,11 @@ export namespace JSON {
939
998
  return deserializeObject(srcStart, srcEnd, 0);
940
999
  } else if (type instanceof JSON.Box) {
941
1000
  // @ts-expect-error: type
942
- return new JSON.Box(
943
- deserializeBox(
944
- srcStart,
945
- srcEnd,
946
- dst,
947
- changetype<nonnull<T>>(0).value,
948
- ),
949
- );
1001
+ return new JSON.Box(deserializeBox(srcStart, srcEnd, dst, changetype<nonnull<T>>(0).value));
950
1002
  }
951
1003
  }
952
1004
  const snippet = ptrToStr(srcStart, srcEnd);
953
- throw new Error(
954
- `Could not deserialize JSON to type '${nameof<T>()}'. ` +
955
- `If this is a custom class, ensure it has the @json decorator: @json class ${nameof<T>()} { ... }. ` +
956
- `Input: "${snippet.length > 50 ? snippet.slice(0, 50) + "..." : snippet}"`,
957
- );
1005
+ throw new Error(`Could not deserialize JSON to type '${nameof<T>()}'. ` + `If this is a custom class, ensure it has the @json decorator: @json class ${nameof<T>()} { ... }. ` + `Input: "${snippet.length > 50 ? snippet.slice(0, 50) + "..." : snippet}"`);
958
1006
  }
959
1007
  export namespace Util {
960
1008
  // @ts-expect-error: decorator
@@ -970,7 +1018,8 @@ export namespace JSON {
970
1018
  }
971
1019
  }
972
1020
  /**
973
- * Methods for use when using JSON methods inside another JSON method or custom serializer/deserializer.
1021
+ * Methods for use when using JSON methods inside another JSON method or custom serializer/deserializer
1022
+ * Transform will automatically convert JSON.x calls to JSON.internal.x when in a custom (de)serializer
974
1023
  */
975
1024
  export namespace internal {
976
1025
  /**
@@ -980,133 +1029,31 @@ export namespace JSON {
980
1029
  * @returns - string
981
1030
  */
982
1031
  // @ts-expect-error: inline
983
- @inline export function stringify<T>(
984
- data: T,
985
- out: string | null = null,
986
- ): string {
987
- if (isBoolean<T>()) {
988
- if (out) {
989
- if (<bool>data == true) {
990
- out = changetype<string>(__renew(changetype<usize>(out), 8));
991
- store<u64>(changetype<usize>(out), TRUE_WORD_U64);
992
- } else {
993
- out = changetype<string>(__renew(changetype<usize>(out), 10));
994
- store<u64>(changetype<usize>(out), FALSE_WORD_U64);
995
- store<u16>(changetype<usize>(out), 101, 8);
996
- }
997
- return out;
998
- }
999
- return data ? "true" : "false";
1000
- } else if (
1001
- isInteger<T>() &&
1002
- !isSigned<T>() &&
1003
- nameof<T>() == "usize" &&
1004
- data == 0
1005
- ) {
1006
- if (out) {
1007
- out = changetype<string>(__renew(changetype<usize>(out), 8));
1008
- store<u64>(changetype<usize>(out), NULL_WORD_U64);
1009
- return out;
1010
- }
1011
- return NULL_WORD;
1012
- } else if (isInteger<T>(data)) {
1013
- if (out) {
1014
- out = changetype<string>(
1015
- __renew(changetype<usize>(out), sizeof<T>() << 3),
1016
- );
1017
-
1018
- const bytes = itoa_buffered(changetype<usize>(out), data) << 1;
1019
- return (out = changetype<string>(
1020
- __renew(changetype<usize>(out), bytes),
1021
- ));
1022
- }
1023
- return data.toString();
1024
- } else if (isFloat<T>(data)) {
1025
- if (out) {
1026
- out = changetype<string>(__renew(changetype<usize>(out), 64));
1027
-
1028
- const bytes = dtoa_buffered(changetype<usize>(out), data) << 1;
1029
- return (out = changetype<string>(
1030
- __renew(changetype<usize>(out), bytes),
1031
- ));
1032
- }
1033
- return data.toString();
1034
- } else if (isNullable<T>() && changetype<usize>(data) == <usize>0) {
1035
- if (out) {
1036
- out = changetype<string>(__renew(changetype<usize>(out), 8));
1037
- store<u64>(changetype<usize>(out), NULL_WORD_U64);
1038
- return out;
1039
- }
1040
- return NULL_WORD;
1041
- } else if (isString<nonnull<T>>()) {
1042
- if (JSON_MODE === JSONMode.SIMD) {
1043
- serializeString_SIMD(data as string);
1044
- } else if (JSON_MODE === JSONMode.SWAR) {
1045
- serializeString_SWAR(data as string);
1046
- } else {
1047
- serializeString(data as string);
1048
- }
1049
- return bs.cpyOut<string>();
1050
- // @ts-expect-error: Supplied by transform
1051
- } else if (isDefined(data.__SERIALIZE)) {
1052
- bs.saveState();
1053
- // @ts-expect-error
1054
- inline.always(data.__SERIALIZE(changetype<usize>(data)));
1055
- return bs.cpyOut<string>();
1056
- } else if (data instanceof Date) {
1057
- out = out
1058
- ? changetype<string>(__renew(changetype<usize>(out), 52))
1059
- : changetype<string>(__new(52, idof<string>()));
1060
-
1061
- store<u16>(changetype<usize>(out), QUOTE);
1062
- memory.copy(
1063
- changetype<usize>(out) + 2,
1064
- changetype<usize>(data.toISOString()),
1065
- 48,
1066
- );
1067
- store<u16>(changetype<usize>(out), QUOTE, 50);
1068
- return changetype<string>(out);
1069
- } else if (data instanceof Array) {
1070
- bs.saveState();
1071
- // @ts-expect-error
1072
- inline.always(serializeArray(changetype<nonnull<T>>(data)));
1073
- return bs.cpyOut<string>();
1074
- } else if (data instanceof StaticArray) {
1075
- bs.saveState();
1076
- // @ts-expect-error
1077
- inline.always(serializeStaticArray(changetype<nonnull<T>>(data)));
1078
- return bs.cpyOut<string>();
1079
- } else if (data instanceof Set) {
1080
- bs.saveState();
1081
- // @ts-expect-error
1082
- inline.always(serializeSet(changetype<nonnull<T>>(data)));
1083
- return bs.cpyOut<string>();
1084
- } else if (data instanceof Map) {
1085
- bs.saveState();
1086
- // @ts-expect-error
1087
- inline.always(serializeMap(changetype<nonnull<T>>(data)));
1088
- return bs.cpyOut<string>();
1089
- } else if (data instanceof JSON.Raw) {
1090
- bs.saveState();
1091
- serializeRaw(data);
1092
- return bs.cpyOut<string>();
1093
- } else if (data instanceof JSON.Value) {
1094
- bs.saveState();
1095
- inline.always(serializeArbitrary(data));
1096
- return bs.cpyOut<string>();
1097
- } else if (data instanceof JSON.Obj) {
1098
- bs.saveState();
1099
- inline.always(serializeObject(data));
1100
- return bs.cpyOut<string>();
1101
- } else if (data instanceof JSON.Box) {
1102
- return JSON.internal.stringify(data.value);
1103
- } else {
1104
- throw new Error(
1105
- `Could not serialize data of type '${nameof<T>()}'. ` +
1106
- `If this is a custom class, add the @json decorator: @json class ${nameof<T>()} { ... }. ` +
1107
- `Supported types: primitives, string, Array, Map, Date, and @json decorated classes.`,
1108
- );
1032
+ @inline export function stringify<T>(data: T, out: string | null = null): string {
1033
+ bs.saveState();
1034
+ JSON.__serialize<T>(data);
1035
+ const result = bs.cpyOut<string>();
1036
+ if (out) {
1037
+ const len = bytes(result);
1038
+ out = changetype<string>(__renew(changetype<usize>(out), len));
1039
+ memory.copy(changetype<usize>(out), changetype<usize>(result), len);
1040
+ return out;
1109
1041
  }
1042
+ return result;
1043
+ }
1044
+
1045
+ /**
1046
+ * Parses JSON data without mutating the caller's active serialization buffer state.
1047
+ * Don't use this directly, use `JSON.parse` instead.
1048
+ * @param data - string
1049
+ * @returns - T
1050
+ */
1051
+ // @ts-expect-error: inline
1052
+ @inline export function parse<T>(data: string): T {
1053
+ bs.saveState();
1054
+ const result = JSON.parse<T>(data);
1055
+ bs.loadState();
1056
+ return result;
1110
1057
  }
1111
1058
  }
1112
1059
  }
@@ -1122,12 +1069,7 @@ export enum JSONMode {
1122
1069
  return JSON.parse<T>(data);
1123
1070
  }
1124
1071
  // @ts-expect-error: inline
1125
- @inline function deserializeBox<T>(
1126
- srcStart: usize,
1127
- srcEnd: usize,
1128
- dst: usize,
1129
- ty: T,
1130
- ): T {
1072
+ @inline function deserializeBox<T>(srcStart: usize, srcEnd: usize, dst: usize, ty: T): T {
1131
1073
  return JSON.__deserialize<T>(srcStart, srcEnd, dst);
1132
1074
  }
1133
1075