json-as 0.9.29 → 1.0.0-alpha.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 (107) hide show
  1. package/.github/workflows/nodejs.yml +0 -3
  2. package/.prettierrc.json +3 -2
  3. package/CHANGELOG +13 -0
  4. package/LICENSE +1 -1
  5. package/README.md +22 -7
  6. package/as-test.config.json +1 -1
  7. package/asconfig.json +2 -2
  8. package/assembly/__benches__/misc.bench.ts +17 -32
  9. package/assembly/__tests__/bool.spec.ts +1 -1
  10. package/assembly/__tests__/simd/string.spec.ts +32 -0
  11. package/assembly/custom/memory.ts +25 -0
  12. package/assembly/custom/util.ts +14 -92
  13. package/assembly/deserialize/simd/string.ts +103 -0
  14. package/assembly/deserialize/simple/arbitrary.ts +17 -0
  15. package/assembly/deserialize/simple/array/arbitrary.ts +113 -0
  16. package/assembly/deserialize/simple/array/array.ts +18 -0
  17. package/assembly/deserialize/simple/array/bool.ts +17 -0
  18. package/assembly/deserialize/simple/array/float.ts +28 -0
  19. package/assembly/deserialize/simple/array/integer.ts +27 -0
  20. package/assembly/deserialize/simple/array/map.ts +18 -0
  21. package/assembly/deserialize/simple/array/object.ts +18 -0
  22. package/assembly/deserialize/simple/array/string.ts +22 -0
  23. package/assembly/deserialize/simple/array.ts +48 -0
  24. package/assembly/deserialize/simple/bool.ts +9 -0
  25. package/assembly/deserialize/simple/date.ts +11 -0
  26. package/assembly/deserialize/simple/float.ts +10 -0
  27. package/assembly/deserialize/simple/integer.ts +5 -0
  28. package/assembly/deserialize/simple/map.ts +154 -0
  29. package/assembly/deserialize/simple/object.ts +159 -0
  30. package/assembly/deserialize/simple/string.ts +48 -0
  31. package/assembly/globals/tables.ts +417 -0
  32. package/assembly/index.d.ts +9 -13
  33. package/assembly/index.ts +266 -146
  34. package/assembly/serialize/simd/string.ts +176 -0
  35. package/assembly/serialize/simple/arbitrary.ts +36 -0
  36. package/assembly/serialize/simple/array.ts +32 -0
  37. package/assembly/serialize/simple/bool.ts +19 -0
  38. package/assembly/serialize/simple/date.ts +13 -0
  39. package/assembly/serialize/simple/float.ts +7 -0
  40. package/assembly/serialize/simple/integer.ts +7 -0
  41. package/assembly/serialize/simple/map.ts +43 -0
  42. package/assembly/serialize/simple/object.ts +7 -0
  43. package/assembly/serialize/simple/string.ts +48 -0
  44. package/assembly/test.ts +41 -27
  45. package/assembly/tsconfig.json +2 -91
  46. package/assembly/types.ts +0 -0
  47. package/assembly/util/atoi.ts +35 -0
  48. package/assembly/util/bytes.ts +12 -0
  49. package/assembly/util/concat.ts +9 -0
  50. package/assembly/util/getArrayDepth.ts +17 -0
  51. package/assembly/util/index.ts +5 -0
  52. package/assembly/util/isSpace.ts +4 -0
  53. package/assembly/util/nextPowerOf2.ts +4 -0
  54. package/assembly/util/ptrToStr.ts +7 -0
  55. package/assembly/util/snp.ts +69 -0
  56. package/bench.js +5 -5
  57. package/modules/bs/index.ts +167 -0
  58. package/modules/tsconfig.json +8 -0
  59. package/package.json +42 -48
  60. package/transform/lib/builder.js +1353 -0
  61. package/transform/lib/builder.js.map +1 -0
  62. package/transform/lib/index.js +497 -332
  63. package/transform/lib/index.js.map +1 -1
  64. package/transform/lib/index.old.js +404 -0
  65. package/transform/lib/index.old.js.map +1 -0
  66. package/transform/lib/linker.js +18 -0
  67. package/transform/lib/linker.js.map +1 -0
  68. package/transform/lib/types.js +25 -0
  69. package/transform/lib/types.js.map +1 -0
  70. package/transform/lib/util.js +47 -0
  71. package/transform/lib/util.js.map +1 -0
  72. package/transform/lib/visitor.js +529 -446
  73. package/transform/lib/visitor.js.map +1 -0
  74. package/transform/package.json +1 -34
  75. package/transform/src/builder.ts +1371 -0
  76. package/transform/src/index.ts +564 -341
  77. package/transform/src/linker.ts +21 -0
  78. package/transform/src/types.ts +27 -0
  79. package/transform/src/util.ts +56 -0
  80. package/transform/src/visitor.ts +531 -0
  81. package/transform/tsconfig.json +3 -1
  82. package/assembly/__benches__/as-tral.d.ts +0 -1
  83. package/assembly/__tests__/date.spec.ts +0 -12
  84. package/assembly/custom/bs.ts +0 -202
  85. package/assembly/deserialize/array/array.ts +0 -31
  86. package/assembly/deserialize/array/bool.ts +0 -19
  87. package/assembly/deserialize/array/float.ts +0 -24
  88. package/assembly/deserialize/array/integer.ts +0 -24
  89. package/assembly/deserialize/array/map.ts +0 -27
  90. package/assembly/deserialize/array/object.ts +0 -27
  91. package/assembly/deserialize/array/string.ts +0 -29
  92. package/assembly/deserialize/array.ts +0 -46
  93. package/assembly/deserialize/bool.ts +0 -34
  94. package/assembly/deserialize/date.ts +0 -19
  95. package/assembly/deserialize/float.ts +0 -21
  96. package/assembly/deserialize/integer.ts +0 -16
  97. package/assembly/deserialize/map.ts +0 -139
  98. package/assembly/deserialize/object.ts +0 -211
  99. package/assembly/deserialize/string.ts +0 -149
  100. package/assembly/serialize/array.ts +0 -44
  101. package/assembly/serialize/bool.ts +0 -10
  102. package/assembly/serialize/date.ts +0 -4
  103. package/assembly/serialize/float.ts +0 -4
  104. package/assembly/serialize/integer.ts +0 -5
  105. package/assembly/serialize/map.ts +0 -24
  106. package/assembly/serialize/object.ts +0 -13
  107. package/assembly/serialize/string.ts +0 -284
package/assembly/index.ts CHANGED
@@ -1,23 +1,31 @@
1
1
  /// <reference path="./index.d.ts" />
2
- import { serializeString } from "./serialize/string";
3
- import { serializeBool } from "./serialize/bool";
4
- import { serializeInteger } from "./serialize/integer";
5
- import { serializeFloat } from "./serialize/float";
6
- import { serializeObject } from "./serialize/object";
7
- import { serializeDate } from "./serialize/date";
8
- import { serializeArray } from "./serialize/array";
9
- import { serializeMap } from "./serialize/map";
10
- import { deserializeBoolean, deserializeBoolean_Safe } from "./deserialize/bool";
11
- import { deserializeArray, deserializeArray_Safe } from "./deserialize/array";
12
- import { deserializeFloat } from "./deserialize/float";
13
- import { deserializeObject, deserializeObject_Safe } from "./deserialize/object";
14
- import { deserializeMap, deserializeMap_Safe } from "./deserialize/map";
15
- import { deserializeDate } from "./deserialize/date";
16
- import { NULL_WORD } from "./custom/chars";
17
- import { deserializeInteger, deserializeInteger_Safe } from "./deserialize/integer";
18
- import { deserializeString, deserializeString_Safe } from "./deserialize/string";
2
+ import { bs } from "../modules/bs";
3
+
4
+ import { serializeString } from "./serialize/simple/string";
5
+ import { serializeArray } from "./serialize/simple/array";
6
+ import { serializeMap } from "./serialize/simple/map";
7
+ import { deserializeBoolean } from "./deserialize/simple/bool";
8
+ import { deserializeArray } from "./deserialize/simple/array";
9
+ import { deserializeFloat } from "./deserialize/simple/float";
10
+ import { deserializeObject } from "./deserialize/simple/object";
11
+ import { deserializeMap } from "./deserialize/simple/map";
12
+ import { deserializeDate } from "./deserialize/simple/date";
13
+ import { deserializeInteger } from "./deserialize/simple/integer";
14
+ import { deserializeString } from "./deserialize/simple/string";
15
+ import { serializeArbitrary } from "./serialize/simple/arbitrary";
16
+
19
17
  import { Sink } from "./custom/sink";
20
- import { getArrayDepth } from "./custom/util";
18
+ import { NULL_WORD, QUOTE } from "./custom/chars";
19
+ import { dtoa_buffered, itoa_buffered } from "util/number";
20
+ import { serializeBool } from "./serialize/simple/bool";
21
+ import { serializeInteger } from "./serialize/simple/integer";
22
+ import { serializeFloat } from "./serialize/simple/float";
23
+ import { serializeObject } from "./serialize/simple/object";
24
+ import { ptrToStr } from "./util/ptrToStr";
25
+ import { bytes } from "./util";
26
+ import { serializeString_SIMD } from "./serialize/simd/string";
27
+
28
+ export type Raw = string;
21
29
 
22
30
  /**
23
31
  * Offset of the 'storage' property in the JSON.Value class.
@@ -29,6 +37,158 @@ import { getArrayDepth } from "./custom/util";
29
37
  * JSON Encoder/Decoder for AssemblyScript
30
38
  */
31
39
  export namespace JSON {
40
+ /**
41
+ * Serializes valid JSON data
42
+ * ```js
43
+ * JSON.stringify<T>(data)
44
+ * ```
45
+ * @param data T
46
+ * @returns string
47
+ */
48
+ export function stringify<T>(data: T, out: string | null = null): string {
49
+ if (isBoolean<T>()) {
50
+ if (out) {
51
+ if (<bool>data == true) {
52
+ out = changetype<string>(__renew(changetype<usize>(out), 8));
53
+ store<u64>(changetype<usize>(out), 28429475166421108);
54
+ } else {
55
+ out = changetype<string>(__renew(changetype<usize>(out), 10));
56
+ store<u64>(changetype<usize>(out), 32370086184550502);
57
+ store<u16>(changetype<usize>(out), 101, 8);
58
+ }
59
+ return out;
60
+ }
61
+ return data ? "true" : "false";
62
+ } else if (isInteger<T>() && nameof<T>() == "usize" && data == 0) {
63
+ if (out) {
64
+ out = changetype<string>(__renew(changetype<usize>(out), 8));
65
+ store<u64>(changetype<usize>(out), 30399761348886638);
66
+ return out;
67
+ }
68
+ return NULL_WORD;
69
+ } else if (isInteger<T>(data)) {
70
+ if (out) {
71
+ out = changetype<string>(__renew(changetype<usize>(out), sizeof<T>() << 3));
72
+
73
+ // @ts-ignore
74
+ const bytes = itoa_buffered(changetype<usize>(out), data) << 1;
75
+ return (out = changetype<string>(__renew(changetype<usize>(out), bytes)));
76
+ }
77
+ return data.toString();
78
+ } else if (isFloat<T>(data)) {
79
+ if (out) {
80
+ out = changetype<string>(__renew(changetype<usize>(out), 64));
81
+
82
+ // @ts-ignore
83
+ const bytes = dtoa_buffered(changetype<usize>(out), data) << 1;
84
+ return (out = changetype<string>(__renew(changetype<usize>(out), bytes)));
85
+ }
86
+ return data.toString();
87
+ // @ts-ignore: Function is generated by transform
88
+ } else if (isNullable<T>() && changetype<usize>(data) == <usize>0) {
89
+ if (out) {
90
+ out = changetype<string>(__renew(changetype<usize>(out), 8));
91
+ store<u64>(changetype<usize>(out), 30399761348886638);
92
+ return out;
93
+ }
94
+ return NULL_WORD;
95
+ // @ts-ignore
96
+ } else if (isString<nonnull<T>>()) {
97
+ if (out) {
98
+ out = changetype<string>(__renew(changetype<usize>(out), bytes(data) + 4));
99
+ // const oldSize = bs.byteLength;
100
+ const oldBuf = bs.buffer;
101
+ const newSize = bytes(data) + 4;
102
+ const newBuf = __new(newSize, idof<string>());
103
+ bs.setBuffer(newBuf);
104
+ serializeString(changetype<string>(data));
105
+ bs.setBuffer(oldBuf);
106
+ return changetype<string>(newBuf);
107
+ }
108
+ serializeString(changetype<string>(data));
109
+ return bs.out<string>();
110
+ // @ts-ignore: Supplied by transform
111
+ } else if (isDefined(data.__SERIALIZE) && isDefined(data.__ALLOCATE)) {
112
+ // @ts-ignore
113
+ data.__ALLOCATE();
114
+ // @ts-ignore
115
+ data.__SERIALIZE(changetype<usize>(data));
116
+ return bs.out<string>();
117
+ // @ts-ignore: Supplied by transform
118
+ } else if (data instanceof Date) {
119
+ out = out ? changetype<string>(__renew(changetype<usize>(out), 52)) : changetype<string>(__new(52, idof<string>()));
120
+
121
+ store<u16>(changetype<usize>(out), QUOTE);
122
+ memory.copy(changetype<usize>(out) + 2, changetype<usize>(data.toISOString()), 48);
123
+ store<u16>(changetype<usize>(out), 50);
124
+ return out;
125
+ } else if (data instanceof Array) {
126
+ // @ts-ignore
127
+ serializeArray(changetype<nonnull<T>>(data));
128
+ return bs.out<string>();
129
+ } else if (data instanceof Map) {
130
+ // @ts-ignore
131
+ serializeMap(changetype<nonnull<T>>(data));
132
+ return bs.out<string>();
133
+ } else if (data instanceof JSON.Value) {
134
+ serializeArbitrary(data);
135
+ return bs.out<string>();
136
+ } else if (data instanceof JSON.Box) {
137
+ return JSON.stringify(data.value);
138
+ } else {
139
+ ERROR(`Could not serialize data of type ${nameof<T>()}. Make sure to add the correct decorators to classes.`);
140
+ }
141
+ }
142
+
143
+ /**
144
+ * Parses valid JSON strings into their original format
145
+ * ```js
146
+ * JSON.parse<T>(data)
147
+ * ```
148
+ * @param data string
149
+ * @returns T
150
+ */
151
+ export function parse<T>(data: string): T {
152
+ const dataSize = bytes(data);
153
+ const dataPtr = changetype<usize>(data);
154
+ if (isBoolean<T>()) {
155
+ return deserializeBoolean(dataPtr, dataPtr + dataSize) as T;
156
+ } else if (isInteger<T>()) {
157
+ return deserializeInteger<T>(dataPtr, dataPtr + dataSize);
158
+ } else if (isFloat<T>()) {
159
+ return deserializeFloat<T>(dataPtr, dataPtr + dataSize);
160
+ } else if (isNullable<T>() && data.length == 4 && data == "null") {
161
+ // @ts-ignore
162
+ return null;
163
+ } else if (isString<T>()) {
164
+ // @ts-ignore
165
+ return deserializeString(dataPtr, dataPtr + dataSize);
166
+ } else if (isArray<T>()) {
167
+ // @ts-ignore
168
+ return deserializeArray<nonnull<T>>(dataPtr, dataPtr + dataSize, changetype<usize>(instantiate<T>()));
169
+ }
170
+ let type: nonnull<T> = changetype<nonnull<T>>(0);
171
+ // @ts-ignore: Defined by transform
172
+ if (isDefined(type.__DESERIALIZE) && isDefined(type.__INITIALIZE)) {
173
+ const out = __new(offsetof<nonnull<T>>(), idof<nonnull<T>>());
174
+ // @ts-ignore
175
+ changetype<nonnull<T>>(out).__INITIALIZE();
176
+ // @ts-ignore
177
+ return deserializeObject<nonnull<T>>(dataPtr, dataPtr + dataSize, out);
178
+ } else if (type instanceof Map) {
179
+ // @ts-ignore
180
+ return deserializeMap<nonnull<T>>(dataPtr, dataPtr + dataSize);
181
+ } else if (type instanceof Date) {
182
+ // @ts-ignore
183
+ return deserializeDate(dataPtr, dataPtr + dataSize);
184
+ } else if (type instanceof JSON.Box) {
185
+ // @ts-ignore
186
+ return new JSON.Box(JSON.parse<indexof<T>>(data));
187
+ } else {
188
+ ERROR(`Could not deserialize data ${data} to type ${nameof<T>()}. Make sure to add the correct decorators to classes.`);
189
+ }
190
+ }
191
+
32
192
  /**
33
193
  * Enum representing the different types supported by JSON.
34
194
  */
@@ -42,11 +202,15 @@ export namespace JSON {
42
202
  F64 = 6,
43
203
  Bool = 7,
44
204
  String = 8,
45
- Obj = 8,
46
- Array = 9,
205
+ Object = 9,
206
+ Array = 10,
207
+ Struct = 11,
47
208
  }
209
+
48
210
  export type Raw = string;
211
+
49
212
  export class Value {
213
+ static METHODS: Map<u32, u32> = new Map<u32, u32>();
50
214
  public type: i32;
51
215
 
52
216
  // @ts-ignore
@@ -103,11 +267,19 @@ export namespace JSON {
103
267
  if (idof<T>() !== idof<Map<string, JSON.Value>>()) {
104
268
  abort("Maps must be of type Map<string, JSON.Value>!");
105
269
  }
106
- this.type = JSON.Types.Obj;
270
+ this.type = JSON.Types.Struct;
271
+ store<T>(changetype<usize>(this), value, STORAGE);
272
+ // @ts-ignore
273
+ } else if (isDefined(value.__SERIALIZE)) {
274
+ this.type = idof<T>() + JSON.Types.Struct;
275
+ // @ts-ignore
276
+ if (!JSON.Value.METHODS.has(idof<T>())) JSON.Value.METHODS.set(idof<T>(), value.__SERIALIZE.index);
277
+ // @ts-ignore
107
278
  store<T>(changetype<usize>(this), value, STORAGE);
108
- } else if (isArray<T>()) {
279
+ // @ts-ignore
280
+ } else if (isArray<T>() && idof<valueof<T>>() == idof<JSON.Value>()) {
109
281
  // @ts-ignore: T satisfies constraints of any[]
110
- this.type = JSON.Types.Array + getArrayDepth<T>(0);
282
+ this.type = JSON.Types.Array;
111
283
  store<T>(changetype<usize>(this), value, STORAGE);
112
284
  }
113
285
  }
@@ -122,7 +294,6 @@ export namespace JSON {
122
294
 
123
295
  /**
124
296
  * Converts the JSON.Value to a string representation.
125
- * @param useString - If true, treats Buffer as a string.
126
297
  * @returns The string representation of the JSON.Value.
127
298
  */
128
299
  toString(): string {
@@ -139,7 +310,7 @@ export namespace JSON {
139
310
  return '"' + this.get<string>() + '"';
140
311
  case JSON.Types.Bool:
141
312
  return this.get<boolean>() ? "true" : "false";
142
- default: {
313
+ case JSON.Types.Array: {
143
314
  const arr = this.get<JSON.Value[]>();
144
315
  if (!arr.length) return "[]";
145
316
  const out = Sink.fromStringLiteral("[");
@@ -156,158 +327,107 @@ export namespace JSON {
156
327
  out.write("]");
157
328
  return out.toString();
158
329
  }
330
+ default: {
331
+ const fn = JSON.Value.METHODS.get(this.type - JSON.Types.Struct);
332
+ const value = this.get<usize>();
333
+ return call_indirect<string>(fn, 0, value);
334
+ }
159
335
  }
160
336
  }
161
337
  }
338
+
339
+ /**
340
+ * Box for primitive types
341
+ */
162
342
  export class Box<T> {
163
343
  constructor(public value: T) {}
164
-
165
-
344
+ /**
345
+ * Creates a reference to a primitive type
346
+ * This means that it can create a nullable primitive
347
+ * ```js
348
+ * JSON.stringify<Box<i32> | null>(null);
349
+ * // null
350
+ * ```
351
+ * @param from T
352
+ * @returns Box<T>
353
+ */
166
354
  @inline static from<T>(value: T): Box<T> {
167
355
  return new Box(value);
168
356
  }
169
357
  }
170
358
 
171
- /**
172
- * Stringifies valid JSON data.
173
- * ```js
174
- * JSON.stringify<T>(data)
175
- * ```
176
- * @param data T
177
- * @returns string
178
- */
179
- export function stringify<T>(data: T /*, options: SerializeOptions = DEFAULT_SERIALIZE_OPTIONS*/): string {
359
+ export function __serialize<T>(src: T): void {
180
360
  if (isBoolean<T>()) {
181
- return serializeBool(data as bool);
182
- } else if (isInteger<T>() && nameof<T>() == "usize" && data == 0) {
183
- return NULL_WORD;
361
+ serializeBool(src as bool);
362
+ } else if (isInteger<T>() && nameof<T>() == "usize" && src == 0) {
363
+ bs.ensureSize(8);
364
+ store<u64>(bs.offset, 30399761348886638);
365
+ bs.offset += 8;
184
366
  } else if (isInteger<T>()) {
185
367
  // @ts-ignore
186
- return serializeInteger<T>(data);
187
- } else if (isFloat<T>(data)) {
368
+ serializeInteger<T>(src);
369
+ } else if (isFloat<T>(src)) {
188
370
  // @ts-ignore
189
- return serializeFloat<T>(data);
371
+ serializeFloat<T>(src);
190
372
  // @ts-ignore: Function is generated by transform
191
- } else if (isNullable<T>() && changetype<usize>(data) == <usize>0) {
192
- return NULL_WORD;
193
- // @ts-ignore
373
+ } else if (isNullable<T>() && changetype<usize>(src) == <usize>0) {
374
+ bs.ensureSize(8);
375
+ store<u64>(bs.offset, 30399761348886638);
376
+ bs.offset += 8;
194
377
  } else if (isString<nonnull<T>>()) {
195
- return serializeString(changetype<string>(data));
378
+ if (ASC_FEATURE_SIMD) {
379
+ serializeString_SIMD(src as string);
380
+ } else {
381
+ serializeString(src as string);
382
+ }
196
383
  // @ts-ignore: Supplied by transform
197
- } else if (isDefined(data.__SERIALIZE)) {
198
- /*if (options.pretty) {
199
- // @ts-ignore
200
- return serializeObject_Pretty(changetype<nonnull<T>>(data));
201
- }*/
384
+ } else if (isDefined(src.__SERIALIZE)) {
202
385
  // @ts-ignore
203
- return serializeObject(changetype<nonnull<T>>(data));
204
- } else if (data instanceof Date) {
386
+ serializeObject(changetype<nonnull<T>>(src));
387
+ } else if (src instanceof Date) {
205
388
  // @ts-ignore
206
- return serializeDate(changetype<nonnull<T>>(data));
207
- } else if (data instanceof Array) {
389
+ serializeDate(changetype<nonnull<T>>(src));
390
+ } else if (src instanceof Array) {
208
391
  // @ts-ignore
209
- return serializeArray(changetype<nonnull<T>>(data));
210
- } else if (data instanceof Map) {
392
+ serializeArray(changetype<nonnull<T>>(src));
393
+ } else if (src instanceof Map) {
211
394
  // @ts-ignore
212
- return serializeMap(changetype<nonnull<T>>(data));
395
+ serializeMap(changetype<nonnull<T>>(src));
396
+ } else if (src instanceof JSON.Value) {
397
+ serializeArbitrary(src);
398
+ } else if (src instanceof JSON.Box) {
399
+ __serialize(src.value);
213
400
  } else {
214
- throw new Error(`Could not serialize data of type ${nameof<T>()}. Make sure to add the correct decorators to classes.`);
401
+ ERROR(`Could not serialize provided data. Make sure to add the correct decorators to classes.`);
215
402
  }
216
403
  }
217
- /**
218
- * Parses valid JSON strings into their original format.
219
- * ```js
220
- * JSON.parse<T>(data)
221
- * ```
222
- * @param data string
223
- * @returns T
224
- */
225
- export function parse<T>(data: string): T {
404
+ export function __deserialize<T>(srcStart: usize, srcEnd: usize, dst: usize = 0): T {
226
405
  if (isBoolean<T>()) {
227
- return deserializeBoolean(data) as T;
406
+ // @ts-ignore: type
407
+ return deserializeBoolean(srcStart, srcEnd);
228
408
  } else if (isInteger<T>()) {
229
- return deserializeInteger<T>(data);
409
+ return deserializeInteger<T>(srcStart, srcEnd);
230
410
  } else if (isFloat<T>()) {
231
- return deserializeFloat<T>(data);
232
- } else if (isNullable<T>() && data.length === 4 && data == "null") {
233
- // @ts-ignore
234
- return null;
411
+ return deserializeFloat<T>(srcStart, srcEnd);
235
412
  } else if (isString<T>()) {
236
- // @ts-ignore
237
- return deserializeString(data);
413
+ // @ts-ignore: type
414
+ return deserializeString(srcStart, srcEnd, dst);
238
415
  } else if (isArray<T>()) {
239
416
  // @ts-ignore
240
- return deserializeArray<nonnull<T>>(data);
241
- }
242
- let type: nonnull<T> = changetype<nonnull<T>>(0);
243
- // @ts-ignore: Defined by transform
244
- if (isDefined(type.__DESERIALIZE)) {
245
- // @ts-ignore
246
- return deserializeObject<nonnull<T>>(data.trimStart());
247
- } else if (type instanceof Map) {
248
- // @ts-ignore
249
- return deserializeMap<nonnull<T>>(data.trimStart());
250
- } else if (type instanceof Date) {
251
- // @ts-ignore
252
- return deserializeDate(data);
253
- } else {
254
- throw new Error(`Could not deserialize data ${data} to type ${nameof<T>()}. Make sure to add the correct decorators to classes.`);
255
- }
256
- }
257
- /**
258
- * Parses valid JSON strings into their original format (safely).
259
- * ```js
260
- * JSON.parseSafe<T>(data)
261
- * ```
262
- * @param data string
263
- * @returns T
264
- */
265
-
266
- // @ts-ignore: Decorator
267
- @inline export function parseSafe<T>(data: string): T {
268
- if (isBoolean<T>()) {
269
- return deserializeBoolean_Safe(data) as T;
270
- } else if (isInteger<T>()) {
271
- return deserializeInteger_Safe<T>(data);
272
- } else if (isFloat<T>()) {
273
- return deserializeFloat<T>(data);
274
- } else if (isNullable<T>() && data.length === 4 && data == "null") {
275
- // @ts-ignore
276
- return null;
277
- } else if (isString<T>()) {
278
- // @ts-ignore
279
- return deserializeString_Safe(data);
280
- } else if (isArray<T>()) {
281
- // @ts-ignore
282
- return deserializeArray_Safe<nonnull<T>>(data);
283
- }
284
- let type: nonnull<T> = changetype<nonnull<T>>(0);
285
- // @ts-ignore: Defined by transform
286
- if (isDefined(type.__DESERIALIZE)) {
287
- // @ts-ignore
288
- return deserializeObject_Safe<nonnull<T>>(data.trimStart());
289
- } else if (type instanceof Map) {
290
- // @ts-ignore
291
- return deserializeMap_Safe<nonnull<T>>(data.trimStart());
292
- } else if (type instanceof Date) {
293
- // @ts-ignore
294
- return deserializeDate_Safe(data);
417
+ return deserializeArray<T>(srcStart, srcEnd, dst);
295
418
  } else {
296
- throw new Error(`Could not deserialize data ${data} to type ${nameof<T>()}. Make sure to add the correct decorators to classes.`);
419
+ let type: nonnull<T> = changetype<nonnull<T>>(0);
420
+ // @ts-ignore: declared by transform
421
+ if (isDefined(type.__DESERIALIZE)) {
422
+ return deserializeObject<T>(srcStart, srcEnd, dst);
423
+ } else if (type instanceof Map) {
424
+ // @ts-ignore: type
425
+ return deserializeMap<T>(srcStart, srcEnd, dst);
426
+ } else if (type instanceof Date) {
427
+ // @ts-ignore: type
428
+ return deserializeDate(srcStart, srcEnd);
429
+ }
297
430
  }
431
+ throw new Error(`Could not deserialize data '${ptrToStr(srcStart, srcEnd).slice(0, 100)}' to type. Make sure to add the correct decorators to classes.`);
298
432
  }
299
433
  }
300
-
301
- // This allows JSON.stringify and JSON.parse to be available globally through an alias
302
- // @ts-ignore: Decorator
303
- @global @inline function __SERIALIZE<T>(data: T): string {
304
- return JSON.stringify(data);
305
- }
306
- // @ts-ignore: Decorator
307
- @global @inline function __DESERIALIZE<T>(data: string): T {
308
- return JSON.parse<T>(data);
309
- }
310
- // @ts-ignore: Decorator
311
- @global @inline function __DESERIALIZE_SAFE<T>(data: string): T {
312
- return JSON.parseSafe<T>(data);
313
- }
@@ -0,0 +1,176 @@
1
+ import { bs } from "../../../modules/bs";
2
+ import { BACK_SLASH } from "../../custom/chars";
3
+ import { SERIALIZE_ESCAPE_TABLE } from "../../globals/tables";
4
+ import { OBJECT, TOTAL_OVERHEAD } from "rt/common";
5
+
6
+ const SPLAT_34 = i16x8.splat(34); /* " */
7
+ const SPLAT_92 = i16x8.splat(92); /* \ */
8
+
9
+ const SPLAT_32 = i16x8.splat(32); /* [ESC] */
10
+ const SPLAT_0 = i16x8.splat(0); /* 0 */
11
+
12
+ /**
13
+ * Serializes strings into their JSON counterparts using SIMD operations
14
+ * @param srcStart pointer to begin serializing at
15
+ * @param srcEnd pointer to end serialization at
16
+ */
17
+ export function serializeString_SIMD(src: string): void {
18
+ const srcSize = changetype<OBJECT>(changetype<usize>(src) - TOTAL_OVERHEAD).rtSize;
19
+ let srcStart = changetype<usize>(src);
20
+ const srcEnd = srcStart + srcSize;
21
+ bs.ensureSize(srcSize + 4);
22
+ const srcEnd16 = srcEnd - 15;
23
+
24
+ store<u8>(changetype<usize>(bs.offset), 34); /* " */
25
+ bs.offset += 2;
26
+
27
+ while (srcStart < srcEnd16) {
28
+ const block = v128.load(srcStart);
29
+ v128.store(bs.offset, block);
30
+
31
+ const backslash_indices = i16x8.eq(block, SPLAT_92);
32
+ const quote_indices = i16x8.eq(block, SPLAT_34);
33
+ const escape_indices = i16x8.lt_u(block, SPLAT_32);
34
+ const sieve = v128.or(v128.or(backslash_indices, quote_indices), escape_indices);
35
+
36
+ let mask = i16x8.bitmask(sieve);
37
+
38
+ while (mask != 0) {
39
+ const lane_index = ctz(mask) << 1;
40
+ const dst_offset = bs.offset + lane_index;
41
+ const src_offset = srcStart + lane_index;
42
+ const code = load<u16>(src_offset) << 2;
43
+ const escaped = load<u32>(SERIALIZE_ESCAPE_TABLE + code);
44
+
45
+ mask &= mask - 1;
46
+
47
+ if ((escaped & 0xffff) != BACK_SLASH) {
48
+ bs.ensureSize(10);
49
+ store<u64>(dst_offset, 13511005048209500);
50
+ store<u32>(dst_offset, escaped, 8);
51
+ v128.store(dst_offset, v128.load(src_offset, 2), 12);
52
+ bs.offset += 10;
53
+ } else {
54
+ bs.ensureSize(2);
55
+ store<u32>(dst_offset, escaped);
56
+ v128.store(dst_offset, v128.load(src_offset, 2), 4);
57
+ bs.offset += 2;
58
+ }
59
+ }
60
+
61
+ srcStart += 16;
62
+ bs.offset += 16;
63
+ }
64
+
65
+ let rem = srcEnd - srcStart;
66
+
67
+ if (rem & 8) {
68
+ const block = v128.load64_zero(srcStart);
69
+ v128.store64_lane(bs.offset, block, 0);
70
+
71
+ const backslash_indices = i16x8.eq(block, SPLAT_92);
72
+ const quote_indices = i16x8.eq(block, SPLAT_34);
73
+ const escape_indices = i16x8.lt_u(block, SPLAT_32);
74
+ const zero_indices = i16x8.eq(block, SPLAT_0);
75
+ const sieve = v128.and(v128.or(v128.or(backslash_indices, quote_indices), escape_indices), v128.not(zero_indices));
76
+
77
+ let mask = i16x8.bitmask(sieve);
78
+ while (mask != 0) {
79
+ let lane_index = ctz(mask) << 1;
80
+ const dst_offset = bs.offset + lane_index;
81
+ const src_offset = srcStart + lane_index;
82
+ const code = load<u16>(src_offset) << 2;
83
+ const escaped = load<u32>(SERIALIZE_ESCAPE_TABLE + code);
84
+ mask &= mask - 1;
85
+
86
+ if ((escaped & 0xffff) != BACK_SLASH) {
87
+ bs.ensureSize(10);
88
+ store<u64>(dst_offset, 13511005048209500);
89
+ store<u32>(dst_offset, escaped, 8);
90
+ while (lane_index < 6) {
91
+ store<u8>(bs.offset + lane_index, load<u8>(srcStart + lane_index, 2), 12);
92
+ lane_index += 2;
93
+ }
94
+ bs.offset += 10;
95
+ } else {
96
+ bs.ensureSize(2);
97
+ store<u32>(dst_offset, escaped);
98
+
99
+ while (lane_index < 6) {
100
+ store<u8>(bs.offset + lane_index, load<u8>(srcStart + lane_index, 2), 4);
101
+ lane_index += 2;
102
+ }
103
+ bs.offset += 2;
104
+ }
105
+ }
106
+
107
+ bs.offset += 8;
108
+ srcStart += 8;
109
+ }
110
+ if (rem & 4) {
111
+ const block = load<u32>(srcStart);
112
+ const codeA = block & 0xffff;
113
+ const codeB = (block >> 16) & 0xffff;
114
+
115
+ if (codeA == 92 || codeA == 34 || codeA < 32) {
116
+ const escaped = load<u32>(SERIALIZE_ESCAPE_TABLE + (codeA << 2));
117
+
118
+ if ((escaped & 0xffff) != BACK_SLASH) {
119
+ bs.ensureSize(10);
120
+ store<u64>(bs.offset, 13511005048209500);
121
+ store<u32>(bs.offset, escaped, 8);
122
+ bs.offset += 12;
123
+ } else {
124
+ bs.ensureSize(2);
125
+ store<u32>(bs.offset, escaped);
126
+ bs.offset += 4;
127
+ }
128
+ } else {
129
+ store<u16>(bs.offset, codeA);
130
+ bs.offset += 2;
131
+ }
132
+
133
+ if (codeB == 92 || codeB == 34 || codeB < 32) {
134
+ const escaped = load<u32>(SERIALIZE_ESCAPE_TABLE + (codeB << 2));
135
+
136
+ if ((escaped & 0xffff) != BACK_SLASH) {
137
+ bs.ensureSize(10);
138
+ store<u64>(bs.offset, 13511005048209500);
139
+ store<u32>(bs.offset, escaped, 8);
140
+ bs.offset += 12;
141
+ } else {
142
+ bs.ensureSize(2);
143
+ store<u32>(bs.offset, escaped);
144
+ bs.offset += 4;
145
+ }
146
+ } else {
147
+ store<u16>(bs.offset, codeB);
148
+ bs.offset += 2;
149
+ }
150
+
151
+ srcStart += 4;
152
+ }
153
+ if (rem & 2) {
154
+ const code = load<u16>(srcStart);
155
+ if (code == 92 || code == 34 || code < 32) {
156
+ const escaped = load<u32>(SERIALIZE_ESCAPE_TABLE + (code << 2));
157
+
158
+ if ((escaped & 0xffff) != BACK_SLASH) {
159
+ bs.ensureSize(10);
160
+ store<u64>(bs.offset, 13511005048209500);
161
+ store<u32>(bs.offset, escaped, 8);
162
+ bs.offset += 12;
163
+ } else {
164
+ bs.ensureSize(2);
165
+ store<u32>(bs.offset, escaped);
166
+ bs.offset += 4;
167
+ }
168
+ } else {
169
+ store<u16>(bs.offset, code);
170
+ bs.offset += 2;
171
+ }
172
+ }
173
+
174
+ store<u8>(bs.offset, 34); /* " */
175
+ bs.offset += 2;
176
+ }