json-as 0.9.29 → 1.0.0-alpha.2

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