json-as 0.9.23 → 0.9.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG CHANGED
@@ -30,7 +30,8 @@ v0.9.19 - Fix arguments in @omitif declarations not working properly
30
30
  v0.9.20 - Strings were being received with quotes attached via the toString functionality. Removed that.
31
31
  v0.9.22 - Fix #89 and #93. Several bug fixes some severe such as ",null" being prepended when using @omit. Properly warn when a schema has fields that are not compatible with json
32
32
  v0.9.23 - Comment out SIMD-related code for now
33
-
33
+ v0.9.24 - Remove transform changes from previous release
34
+ v0.9.25 - Implement JSON.parseSafe
34
35
  [UNRELEASED] v1.0.0
35
36
  - Allow nullable primitives
36
37
  - Port over JSON.Value
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  __| || __|| || | | ___ | _ || __|
4
4
  | | ||__ || | || | | ||___|| ||__ |
5
5
  |_____||_____||_____||_|___| |__|__||_____|
6
- v0.9.23
6
+ v0.9.25
7
7
  </pre>
8
8
  </h5>
9
9
 
@@ -0,0 +1,33 @@
1
+ import { JSON } from "..";
2
+ import { BRACE_LEFT, BRACKET_LEFT, CHAR_F, CHAR_T, QUOTE } from "../custom/chars";
3
+
4
+ bench("Match Type (string)", () => {
5
+ blackbox<boolean>(matchType(blackbox<string>("\""), JSON.Types.String));
6
+ });
7
+
8
+ bench("Match Type (bool)", () => {
9
+ blackbox<boolean>(matchType(blackbox<string>("t"), JSON.Types.Bool));
10
+ });
11
+
12
+ bench("Match Type (array)", () => {
13
+ blackbox<boolean>(matchType(blackbox<string>("["), JSON.Types.Array));
14
+ });
15
+
16
+ bench("Match Type (struct)", () => {
17
+ blackbox<boolean>(matchType(blackbox<string>("{"), JSON.Types.Obj));
18
+ });
19
+
20
+ bench("Match Type (raw)", () => {
21
+ blackbox<boolean>(matchType(blackbox<string>("\""), JSON.Types.Raw));
22
+ });
23
+
24
+ @inline function matchType(data: string, type: JSON.Types): boolean {
25
+ const firstChar = load<u8>(changetype<usize>(data));
26
+ if (JSON.Types.String == type && firstChar == QUOTE) return true;
27
+ else if (JSON.Types.Bool == type && (firstChar == CHAR_T || firstChar == CHAR_F)) return true;
28
+ else if (JSON.Types.Array == type && firstChar == BRACKET_LEFT) return true;
29
+ else if (JSON.Types.Obj == type && firstChar == BRACE_LEFT) return true;
30
+ else if (type < 7 && type > 0 && (firstChar < 58 && firstChar > 46)) return true;
31
+ else if (JSON.Types.Raw == type) return true;
32
+ else return false;
33
+ }
@@ -1,6 +1,7 @@
1
1
  import { isSpace } from "util/string";
2
- import { BACK_SLASH, QUOTE } from "./chars";
2
+ import { BACK_SLASH, BRACE_LEFT, BRACKET_LEFT, CHAR_F, CHAR_T, QUOTE } from "./chars";
3
3
  import { Sink } from "./sink";
4
+ import { JSON } from "..";
4
5
 
5
6
  // @ts-ignore: Decorator
6
7
  export function isMap<T>(): bool {
@@ -9,12 +10,12 @@ export function isMap<T>(): bool {
9
10
  }
10
11
 
11
12
  // @ts-ignore: Decorator
12
- export function unsafeCharCodeAt(data: string, pos: i32): i32 {
13
+ @inline export function unsafeCharCodeAt(data: string, pos: i32): i32 {
13
14
  return load<u16>(changetype<usize>(data) + ((<usize>pos) << 1));
14
15
  }
15
16
 
16
17
  // @ts-ignore: Decorator
17
- export function removeWhitespace(data: string): string {
18
+ @inline export function removeWhitespace(data: string): string {
18
19
  const result = new Sink();
19
20
  let instr = false;
20
21
  for (let i = 0; i < data.length; i++) {
@@ -35,7 +36,7 @@ export function removeWhitespace(data: string): string {
35
36
  }
36
37
 
37
38
  // @ts-ignore: Decorator
38
- export function escapeChar(char: string): string {
39
+ @inline export function escapeChar(char: string): string {
39
40
  switch (unsafeCharCodeAt(char, 0)) {
40
41
  case 0x22:
41
42
  return '\\"';
@@ -93,7 +94,7 @@ export function getArrayDepth<T extends ArrayLike>(depth: i32 = 1): i32 {
93
94
  * @param str - Any number. Can include scientific notation.
94
95
  */
95
96
  // @ts-ignore: Decorator
96
- export function snip_fast<T extends number>(str: string, len: u32 = 0, offset: u32 = 0): T {
97
+ @inline export function snip_fast<T extends number>(str: string, len: u32 = 0, offset: u32 = 0): T {
97
98
  if (isSigned<T>()) {
98
99
  const firstChar: u32 = load<u16>(changetype<usize>(str));
99
100
  if (firstChar === 48) return 0 as T;
@@ -258,7 +259,7 @@ export function snip_fast<T extends number>(str: string, len: u32 = 0, offset: u
258
259
  */
259
260
 
260
261
  // @ts-ignore
261
- export function __atoi_fast<T extends number>(str: string, start: u32 = 0, end: u32 = 0): T {
262
+ @inline export function __atoi_fast<T extends number>(str: string, start: u32 = 0, end: u32 = 0): T {
262
263
  // @ts-ignore
263
264
  let val: T = 0;
264
265
  if (!end) end = start + u32(str.length << 1);
@@ -293,7 +294,7 @@ export function __atoi_fast<T extends number>(str: string, start: u32 = 0, end:
293
294
  */
294
295
 
295
296
  // @ts-ignore
296
- export function parseSciInteger<T extends number>(str: string): T {
297
+ @inline export function parseSciInteger<T extends number>(str: string): T {
297
298
  // @ts-ignore
298
299
  let val: T = 0;
299
300
  let offset = 0;
@@ -328,7 +329,7 @@ export function parseSciInteger<T extends number>(str: string): T {
328
329
  }
329
330
 
330
331
  // @ts-ignore
331
- function sciNote<T extends number>(num: T): T {
332
+ @inline function sciNote<T extends number>(num: T): T {
332
333
  let res = 1;
333
334
  // @ts-ignore
334
335
  if (num > 0) {
@@ -345,7 +346,7 @@ function sciNote<T extends number>(num: T): T {
345
346
  }
346
347
 
347
348
  // @ts-ignore
348
- function equalsSlice(p1_data: string, p1_start: i32, p1_end: i32, p2_data: string, p2_start: i32, p2_end: i32): boolean {
349
+ @inline function equalsSlice(p1_data: string, p1_start: i32, p1_end: i32, p2_data: string, p2_start: i32, p2_end: i32): boolean {
349
350
  const p1_len = p1_end - p1_start;
350
351
  const p2_len = p2_end - p2_start;
351
352
  if (p1_len != p2_len) return false;
@@ -356,14 +357,15 @@ function equalsSlice(p1_data: string, p1_start: i32, p1_end: i32, p2_data: strin
356
357
  }
357
358
 
358
359
  // @ts-ignore
359
- export function containsCodePoint(str: string, code: u32, start: i32, end: i32): bool {
360
+ @inline export function containsCodePoint(str: string, code: u32, start: i32, end: i32): bool {
360
361
  for (let i = start; i <= end; i++) {
361
362
  if (unsafeCharCodeAt(str, i) == code) return true;
362
363
  }
363
364
  return false;
364
365
  }
365
366
 
366
- export function _intTo16(int: i32): i32 {
367
+ // @ts-ignore: Decorator
368
+ @inline export function _intTo16(int: i32): i32 {
367
369
  if (int < 10) {
368
370
  // 0-10
369
371
  return 48 + int;
@@ -373,6 +375,7 @@ export function _intTo16(int: i32): i32 {
373
375
  }
374
376
  }
375
377
 
378
+ // @ts-ignore: Decorator
376
379
  @inline export function intTo16(int: i32): i32 {
377
380
  const high = int >> 4;
378
381
  const low = int & 0x0F;
@@ -1,3 +1,4 @@
1
+ import { BRACKET_LEFT } from "../custom/chars";
1
2
  import { isMap } from "../custom/util";
2
3
  import { deserializeArrayArray } from "./array/array";
3
4
  import { deserializeBooleanArray } from "./array/bool";
@@ -36,3 +37,10 @@ export function deserializeArray<T extends unknown[]>(data: string): T {
36
37
  throw new Error("Could not parse array of type " + nameof<T>() + "!");
37
38
  }
38
39
  }
40
+
41
+ // @ts-ignore: Decorator valid here
42
+ export function deserializeArray_Safe<T extends unknown[]>(data: string): T {
43
+ const firstChar = load<u8>(changetype<usize>(data));
44
+ if (firstChar != BRACKET_LEFT) throw new Error("Mismatched Types! Expected " + nameof<T>() + " but got \"" + data.slice(0, 100) + "\" instead!");
45
+ return deserializeArray<T>(data);
46
+ }
@@ -15,4 +15,20 @@ import { unsafeCharCodeAt } from "../custom/util";
15
15
  if (len === 4 && firstChar === CHAR_T && load<u64>(ptr) === 28429475166421108) return true;
16
16
  else if (len === 5 && firstChar === CHAR_F && load<u64>(ptr, 2) === 28429466576093281) return false;
17
17
  return false//ERROR(`Expected to find boolean, but found "${data.slice(0, 100)}" instead!`);
18
+ }
19
+
20
+ /**
21
+ * Deserialize a string to type boolean (safely)
22
+ * @param data data to parse
23
+ * @returns boolean
24
+ */
25
+ // @ts-ignore: Decorator valid here
26
+ @inline export function deserializeBoolean_Safe(data: string, start: i32 = 0, end: i32 = 0): boolean {
27
+ if (!end) end = data.length;
28
+ const len = end - start;
29
+ const ptr = changetype<usize>(data) + <usize>(start << 1);
30
+ const firstChar = unsafeCharCodeAt(data, start);
31
+ if (len === 4 && firstChar === CHAR_T && load<u64>(ptr) === 28429475166421108) return true;
32
+ else if (len === 5 && firstChar === CHAR_F && load<u64>(ptr, 2) === 28429466576093281) return false;
33
+ throw new Error("Mismatched Types! Expected boolean but got \"" + data.slice(0, 100) + "\" instead!");
18
34
  }
@@ -1,11 +1,19 @@
1
+ import { QUOTE } from "../custom/chars";
2
+
1
3
  // @ts-ignore: Decorator valid here
2
4
  @inline export function deserializeDate(dateTimeString: string): Date {
3
- // Use AssemblyScript's date parser
4
- const d = Date.fromString(dateTimeString);
5
-
6
- // Return a new object instead of the one that the parser returned.
7
- // This may seem redundant, but addreses the issue when Date
8
- // is globally aliased to wasi_Date (or some other superclass).
9
- return new Date(d.getTime());
10
- }
11
-
5
+ // Use AssemblyScript's date parser
6
+ const d = Date.fromString(dateTimeString);
7
+
8
+ // Return a new object instead of the one that the parser returned.
9
+ // This may seem redundant, but addreses the issue when Date
10
+ // is globally aliased to wasi_Date (or some other superclass).
11
+ return new Date(d.getTime());
12
+ }
13
+
14
+ // @ts-ignore: Decorator valid here
15
+ @inline export function deserializeDate_Safe(dateTimeString: string): Date {
16
+ const firstChar = load<u8>(changetype<usize>(dateTimeString));
17
+ if (firstChar != QUOTE) throw new Error("Mismatched Types! Expected Date but got \"" + dateTimeString.slice(0, 100) + "\" instead!");
18
+ return deserializeDate(dateTimeString);
19
+ }
@@ -6,4 +6,16 @@
6
6
  if (type instanceof f64) return f64.parse(data);
7
7
  // @ts-ignore
8
8
  return f32.parse(data);
9
+ }
10
+
11
+ // @ts-ignore: Decorator valid here
12
+ @inline export function deserializeFloat_Safe<T>(data: string): T {
13
+ const firstChar = load<u8>(changetype<usize>(data));
14
+ if ((firstChar < 48 || firstChar > 57) && firstChar != 45) throw new Error("Mismatched Types! Expected float but got \""+data.slice(0, 100)+"\" instead!");
15
+ // @ts-ignore
16
+ const type: T = 0;
17
+ // @ts-ignore
18
+ if (type instanceof f64) return f64.parse(data);
19
+ // @ts-ignore
20
+ return f32.parse(data);
9
21
  }
@@ -4,4 +4,13 @@ import { snip_fast } from "../custom/util";
4
4
  @inline export function deserializeInteger<T>(data: string): T {
5
5
  // @ts-ignore
6
6
  return snip_fast<T>(data);
7
+ }
8
+
9
+ // @ts-ignore: Decorator valid here
10
+ @inline export function deserializeInteger_Safe<T>(data: string): T {
11
+ const firstChar = load<u8>(changetype<usize>(data));
12
+ console.log(firstChar.toString())
13
+ if ((firstChar < 48 || firstChar > 57) && firstChar != 45) throw new Error("Mismatched Types! Expected " + nameof<T>() + " but got \""+data.slice(0, 100)+"\" instead!");
14
+ // @ts-ignore
15
+ return snip_fast<T>(data);
7
16
  }
@@ -180,3 +180,10 @@ function deserializeMapKey<T>(key: Virtual<string>): T {
180
180
 
181
181
  throw new Error(`JSON: Cannot parse JSON object to a Map with a key of type ${nameof<T>()}`);
182
182
  }
183
+
184
+ // @ts-ignore: Decorator valid here
185
+ @inline export function deserializeMap_Safe<T extends Map>(data: string): T {
186
+ const firstChar = load<u8>(changetype<usize>(data));
187
+ if (firstChar != BRACE_LEFT) throw new Error("Mismatched Types! Expected " + nameof<T>() + " but got \"" + data.slice(0, 100) + "\" instead!");
188
+ return deserializeMap<T>(data);
189
+ }
@@ -133,4 +133,139 @@ import { isSpace } from "util/string";
133
133
  }
134
134
  }
135
135
  return schema;
136
+ }
137
+
138
+ // @ts-ignore: Decorator valid here
139
+ @inline export function deserializeObject_Safe<T>(data: string): T {
140
+ const firstChar = load<u8>(changetype<usize>(data));
141
+ if (firstChar != BRACE_LEFT) throw new Error("Mismatched Types! Expected " + nameof<T>() + " but got \"" + data.slice(0, 100) + "\" instead!");
142
+ const schema: nonnull<T> = changetype<nonnull<T>>(
143
+ __new(offsetof<nonnull<T>>(), idof<nonnull<T>>())
144
+ );
145
+
146
+ // @ts-ignore
147
+ schema.__INITIALIZE();
148
+
149
+ let key_start: i32 = 0;
150
+ let key_end: i32 = 0;
151
+ let isKey = false;
152
+ let depth = 0;
153
+ let outerLoopIndex = 1;
154
+ for (; outerLoopIndex < data.length - 1; outerLoopIndex++) {
155
+ const char = unsafeCharCodeAt(data, outerLoopIndex);
156
+ if (char === BRACKET_LEFT) {
157
+ for (
158
+ let arrayValueIndex = outerLoopIndex;
159
+ arrayValueIndex < data.length - 1;
160
+ arrayValueIndex++
161
+ ) {
162
+ const char = unsafeCharCodeAt(data, arrayValueIndex);
163
+ if (char === BRACKET_LEFT) {
164
+ depth++;
165
+ } else if (char === BRACKET_RIGHT) {
166
+ depth--;
167
+ if (depth === 0) {
168
+ ++arrayValueIndex;
169
+ // @ts-ignore
170
+ schema.__DESERIALIZE_SAFE(data, key_start, key_end, outerLoopIndex, arrayValueIndex);
171
+ outerLoopIndex = arrayValueIndex;
172
+ isKey = false;
173
+ break;
174
+ }
175
+ }
176
+ }
177
+ } else if (char === BRACE_LEFT) {
178
+ for (
179
+ let objectValueIndex = outerLoopIndex;
180
+ objectValueIndex < data.length - 1;
181
+ objectValueIndex++
182
+ ) {
183
+ const char = unsafeCharCodeAt(data, objectValueIndex);
184
+ if (char === BRACE_LEFT) {
185
+ depth++;
186
+ } else if (char === BRACE_RIGHT) {
187
+ depth--;
188
+ if (depth === 0) {
189
+ ++objectValueIndex;
190
+ // @ts-ignore
191
+ schema.__DESERIALIZE_SAFE(data, key_start, key_end, outerLoopIndex, objectValueIndex);
192
+ outerLoopIndex = objectValueIndex;
193
+ isKey = false;
194
+ break;
195
+ }
196
+ }
197
+ }
198
+ } else if (char === QUOTE) {
199
+ let escaping = false;
200
+ for (
201
+ let stringValueIndex = ++outerLoopIndex;
202
+ stringValueIndex < data.length - 1;
203
+ stringValueIndex++
204
+ ) {
205
+ const char = unsafeCharCodeAt(data, stringValueIndex);
206
+ if (char === BACK_SLASH && !escaping) {
207
+ escaping = true;
208
+ } else {
209
+ if (char === QUOTE && !escaping) {
210
+ if (isKey === false) {
211
+ key_start = outerLoopIndex;
212
+ key_end = stringValueIndex;
213
+ isKey = true;
214
+ } else {
215
+ // @ts-ignore
216
+ schema.__DESERIALIZE_SAFE(data, key_start, key_end, outerLoopIndex - 1, stringValueIndex + 1);
217
+ isKey = false;
218
+ }
219
+ outerLoopIndex = ++stringValueIndex;
220
+ break;
221
+ }
222
+ escaping = false;
223
+ }
224
+ }
225
+ } else if (
226
+ char == CHAR_N &&
227
+ unsafeCharCodeAt(data, outerLoopIndex + 1) === CHAR_U &&
228
+ unsafeCharCodeAt(data, outerLoopIndex + 2) === CHAR_L &&
229
+ unsafeCharCodeAt(data, outerLoopIndex + 3) === CHAR_L
230
+ ) {
231
+ // @ts-ignore
232
+ schema.__DESERIALIZE_SAFE(data, key_start, key_end, outerLoopIndex, outerLoopIndex + 4);
233
+ outerLoopIndex += 3;
234
+ isKey = false;
235
+ } else if (
236
+ char === CHAR_T &&
237
+ unsafeCharCodeAt(data, outerLoopIndex + 1) === CHAR_R &&
238
+ unsafeCharCodeAt(data, outerLoopIndex + 2) === CHAR_U &&
239
+ unsafeCharCodeAt(data, outerLoopIndex + 3) === CHAR_E
240
+ ) {
241
+ // @ts-ignore
242
+ schema.__DESERIALIZE_SAFE(data, key_start, key_end, outerLoopIndex, outerLoopIndex + 4);
243
+ outerLoopIndex += 3;
244
+ isKey = false;
245
+ } else if (
246
+ char === CHAR_F &&
247
+ unsafeCharCodeAt(data, outerLoopIndex + 1) === CHAR_A &&
248
+ unsafeCharCodeAt(data, outerLoopIndex + 2) === CHAR_L &&
249
+ unsafeCharCodeAt(data, outerLoopIndex + 3) === CHAR_S &&
250
+ unsafeCharCodeAt(data, outerLoopIndex + 4) === CHAR_E
251
+ ) {
252
+ // @ts-ignore
253
+ schema.__DESERIALIZE_SAFE(data, key_start, key_end, outerLoopIndex, outerLoopIndex + 5);
254
+ outerLoopIndex += 4;
255
+ isKey = false;
256
+ } else if ((char >= 48 && char <= 57) || char === 45) {
257
+ let numberValueIndex = ++outerLoopIndex;
258
+ for (; numberValueIndex < data.length; numberValueIndex++) {
259
+ const char = unsafeCharCodeAt(data, numberValueIndex);
260
+ if (char === COMMA || char === BRACE_RIGHT || isSpace(char)) {
261
+ // @ts-ignore
262
+ schema.__DESERIALIZE_SAFE(data, key_start, key_end, outerLoopIndex - 1, numberValueIndex);
263
+ outerLoopIndex = numberValueIndex;
264
+ isKey = false;
265
+ break;
266
+ }
267
+ }
268
+ }
269
+ }
270
+ return schema;
136
271
  }
@@ -1,4 +1,3 @@
1
- import { bs } from "../custom/bs";
2
1
  import {
3
2
  CHAR_B,
4
3
  BACK_SLASH,
@@ -155,4 +154,11 @@ import { unsafeCharCodeAt } from "../custom/util";
155
154
  // if (end > last) {
156
155
  // result.write(data, last, end);
157
156
  // }
158
- // }
157
+ // }
158
+
159
+ // @ts-ignore: Decorator valid here
160
+ @inline export function deserializeString_Safe(data: string, start: i32 = 0, end: i32 = 0): string {
161
+ const firstChar = load<u8>(changetype<usize>(data));
162
+ if (firstChar != QUOTE) throw new Error("Mismatched Types! Expected string but got \""+data.slice(0, 100)+"\" instead!");
163
+ return deserializeString(data, start, end);
164
+ }
package/assembly/index.ts CHANGED
@@ -7,15 +7,15 @@ import { serializeObject, serializeObject_Pretty } from "./serialize/object";
7
7
  import { serializeDate } from "./serialize/date";
8
8
  import { serializeArray } from "./serialize/array";
9
9
  import { serializeMap } from "./serialize/map";
10
- import { deserializeBoolean } from "./deserialize/bool";
11
- import { deserializeArray } from "./deserialize/array";
10
+ import { deserializeBoolean, deserializeBoolean_Safe } from "./deserialize/bool";
11
+ import { deserializeArray, deserializeArray_Safe } from "./deserialize/array";
12
12
  import { deserializeFloat } from "./deserialize/float";
13
- import { deserializeObject } from "./deserialize/object";
14
- import { deserializeMap } from "./deserialize/map";
13
+ import { deserializeObject, deserializeObject_Safe } from "./deserialize/object";
14
+ import { deserializeMap, deserializeMap_Safe } from "./deserialize/map";
15
15
  import { deserializeDate } from "./deserialize/date";
16
- import { NULL_WORD } from "./custom/chars";
17
- import { deserializeInteger } from "./deserialize/integer";
18
- import { deserializeString } from "./deserialize/string";
16
+ import { BRACE_LEFT, BRACKET_LEFT, CHAR_F, CHAR_N, CHAR_T, NULL_WORD, QUOTE } from "./custom/chars";
17
+ import { deserializeInteger, deserializeInteger_Safe } from "./deserialize/integer";
18
+ import { deserializeString, deserializeString_Safe } from "./deserialize/string";
19
19
  import { Sink } from "./custom/sink";
20
20
  import { getArrayDepth } from "./custom/util";
21
21
 
@@ -174,7 +174,7 @@ export namespace JSON {
174
174
  * @returns string
175
175
  */
176
176
  // @ts-ignore: Decorator
177
- export function stringify<T>(data: T/*, options: SerializeOptions = DEFAULT_SERIALIZE_OPTIONS*/): string {
177
+ @inline export function stringify<T>(data: T/*, options: SerializeOptions = DEFAULT_SERIALIZE_OPTIONS*/): string {
178
178
  if (isBoolean<T>()) {
179
179
  return serializeBool(data as bool);
180
180
  } else if (isInteger<T>()) {
@@ -222,7 +222,7 @@ export namespace JSON {
222
222
  */
223
223
 
224
224
  // @ts-ignore: Decorator
225
- export function parse<T>(data: string): T {
225
+ @inline export function parse<T>(data: string): T {
226
226
  if (isBoolean<T>()) {
227
227
  return deserializeBoolean(data) as T;
228
228
  } else if (isInteger<T>()) {
@@ -256,14 +256,62 @@ export namespace JSON {
256
256
  );
257
257
  }
258
258
  }
259
+ /**
260
+ * Parses valid JSON strings into their original format (safely).
261
+ * ```js
262
+ * JSON.parseSafe<T>(data)
263
+ * ```
264
+ * @param data string
265
+ * @returns T
266
+ */
267
+
268
+ // @ts-ignore: Decorator
269
+ @inline export function parseSafe<T>(data: string): T {
270
+ if (isBoolean<T>()) {
271
+ return deserializeBoolean_Safe(data) as T;
272
+ } else if (isInteger<T>()) {
273
+ return deserializeInteger_Safe<T>(data);
274
+ } else if (isFloat<T>()) {
275
+ return deserializeFloat<T>(data);
276
+ } else if (isNullable<T>() && data.length === 4 && data == "null") {
277
+ // @ts-ignore
278
+ return null;
279
+ } else if (isString<T>()) {
280
+ // @ts-ignore
281
+ return deserializeString_Safe(data);
282
+ } else if (isArray<T>()) {
283
+ // @ts-ignore
284
+ return deserializeArray_Safe<nonnull<T>>(data);
285
+ }
286
+ let type: nonnull<T> = changetype<nonnull<T>>(0);
287
+ // @ts-ignore: Defined by transform
288
+ if (isDefined(type.__DESERIALIZE)) {
289
+ // @ts-ignore
290
+ return deserializeObject_Safe<nonnull<T>>(data.trimStart());
291
+ } else if (type instanceof Map) {
292
+ // @ts-ignore
293
+ return deserializeMap_Safe<nonnull<T>>(data.trimStart());
294
+ } else if (type instanceof Date) {
295
+ // @ts-ignore
296
+ return deserializeDate_Safe(data);
297
+ } else {
298
+ throw new Error(
299
+ `Could not deserialize data ${data} to type ${nameof<T>()}. Make sure to add the correct decorators to classes.`
300
+ );
301
+ }
302
+ }
259
303
  }
260
304
 
261
305
  // This allows JSON.stringify and JSON.parse to be available globally through an alias
262
306
  // @ts-ignore: Decorator
263
- @global function __SERIALIZE<T>(data: T): string {
307
+ @global @inline function __SERIALIZE<T>(data: T): string {
264
308
  return JSON.stringify(data);
265
309
  }
266
310
  // @ts-ignore: Decorator
267
- @global function __DESERIALIZE<T>(data: string): T {
311
+ @global @inline function __DESERIALIZE<T>(data: string): T {
268
312
  return JSON.parse<T>(data);
313
+ }
314
+ // @ts-ignore: Decorator
315
+ @global @inline function __DESERIALIZE_SAFE<T>(data: string): T {
316
+ return JSON.parseSafe<T>(data);
269
317
  }
@@ -4,19 +4,7 @@
4
4
  * @returns string
5
5
  */
6
6
 
7
- import { bs } from "../custom/bs";
8
-
9
7
  // @ts-ignore: Decorator valid here
10
8
  @inline export function serializeBool(data: bool): string {
11
9
  return data ? "true" : "false";
12
- }
13
-
14
- @inline export function serializeBool_BS(data: bool): void {
15
- if (data === true) {
16
- bs.write_64(28429475166421108); /* true */
17
- } else {
18
- //bs.write_128_n(i16x8(102, 97, 108, 115, 101, 0, 0, 0), 10);
19
- bs.write_64(32370086184550502); /* fals */
20
- bs.write_16(101); /* e */
21
- }
22
10
  }
@@ -1,14 +1,3 @@
1
- import {
2
- BACK_SLASH,
3
- BACKSPACE,
4
- CARRIAGE_RETURN,
5
- FORM_FEED,
6
- NEW_LINE,
7
- QUOTE,
8
- TAB
9
- } from "../custom/chars";
10
- import { OBJECT, TOTAL_OVERHEAD } from "rt/common";
11
- import { bs } from "../custom/bs";
12
1
  import { _intTo16, intTo16, unsafeCharCodeAt } from "../custom/util";
13
2
  import { Sink } from "../custom/sink";
14
3
 
package/assembly/test.ts CHANGED
@@ -1,34 +1,34 @@
1
1
  import { JSON } from "."
2
2
 
3
3
  @json
4
- class Vec3<T> {
4
+ class Vec3 {
5
5
  public x: i32 = 0;
6
6
  public y: i32 = 0;
7
- public z: T;
7
+ public z: i32 = 0;
8
8
  }
9
9
 
10
- @json
11
- class Base {
12
- public bam: string = "harekogkeorgke"
13
- }
10
+ // @json
11
+ // class Base {
12
+ // public bam: string = "harekogkeorgke"
13
+ // }
14
14
 
15
- @json
16
- class Foo extends Base {
17
- public bar: JSON.Raw = "\"this is ok\'"
18
- public baz: i32 = 0;
19
- public pos: Vec3<Vec3<i32>> = {
20
- x: 1,
21
- y: 2,
22
- z: {
23
- x: 1,
24
- y: 2,
25
- z: 3
26
- }
27
- }
28
- // ^ this is not okay
29
- }
15
+ // @json
16
+ // class Foo extends Base {
17
+ // public bar: JSON.Raw = "\"this is ok\'"
18
+ // public baz: i32 = 0;
19
+ // public pos: Vec3<Vec3<i32>> = {
20
+ // x: 1,
21
+ // y: 2,
22
+ // z: {
23
+ // x: 1,
24
+ // y: 2,
25
+ // z: 3
26
+ // }
27
+ // }
28
+ // // ^ this is not okay
29
+ // }
30
30
 
31
- const serialized = JSON.stringify(new Foo());
31
+ const serialized = JSON.stringify(new Vec3());
32
32
  console.log("Serialized: " + serialized);
33
- const deserialized = JSON.parse<Foo>(serialized);
33
+ const deserialized = JSON.parseSafe<Vec3>(`{"x":1,"y":true,"z":3}`);
34
34
  console.log("Deserialized: " + JSON.stringify(deserialized));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "json-as",
3
- "version": "0.9.23",
3
+ "version": "0.9.25",
4
4
  "description": "The only JSON library you'll need for AssemblyScript. SIMD enabled",
5
5
  "types": "assembly/index.ts",
6
6
  "author": "Jairus Tanaka",
@@ -19,7 +19,7 @@
19
19
  "test": "ast test && rm -rf ./build/",
20
20
  "pretest": "rm -rf ./build/ && ast build",
21
21
  "bench": "astral --enable simd --runtime stub",
22
- "build:test": "rm -rf ./build/ && asc assembly/test.ts --transform ./transform -o ./build/test.wasm",
22
+ "build:test": "rm -rf ./build/ && JSON_DEBUG=true asc assembly/test.ts --transform ./transform -o ./build/test.wasm",
23
23
  "build:transform": "tsc -p ./transform",
24
24
  "test:wasmtime": "wasmtime ./build/test.wasm",
25
25
  "test:wavm": "wavm run ./build/test.wasm",
@@ -44,6 +44,7 @@
44
44
  "visitor-as": "^0.11.4"
45
45
  },
46
46
  "dependencies": {
47
+ "@hypermode/modus-sdk-as": "^0.13.0-prerelease-test-1",
47
48
  "as-virtual": "^0.2.0",
48
49
  "chalk": "^5.3.0"
49
50
  },