json-as 1.2.1 → 1.2.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 (92) hide show
  1. package/README.md +31 -1
  2. package/assembly/deserialize/simd/string.ts +62 -63
  3. package/assembly/deserialize/simple/arbitrary.ts +4 -4
  4. package/assembly/deserialize/simple/array/arbitrary.ts +1 -1
  5. package/assembly/index.d.ts +9 -0
  6. package/assembly/index.ts +211 -112
  7. package/assembly/serialize/simd/string.ts +16 -3
  8. package/assembly/serialize/simple/arbitrary.ts +16 -2
  9. package/assembly/serialize/swar/string.ts +41 -15
  10. package/assembly/test.ts +38 -0
  11. package/lib/as-bs.ts +113 -22
  12. package/package.json +4 -3
  13. package/transform/lib/index.js +34 -1
  14. package/transform/lib/index.js.map +1 -1
  15. package/.github/FUNDING.yml +0 -1
  16. package/.github/dependabot.yml +0 -11
  17. package/.github/workflows/benchmark.yml +0 -72
  18. package/.github/workflows/release-package.yml +0 -47
  19. package/.github/workflows/tests.yml +0 -25
  20. package/.prettierignore +0 -9
  21. package/.prettierrc.json +0 -7
  22. package/.trunk/configs/.markdownlint.yaml +0 -2
  23. package/.trunk/configs/.shellcheckrc +0 -7
  24. package/.trunk/configs/.yamllint.yaml +0 -7
  25. package/.trunk/trunk.yaml +0 -37
  26. package/CHANGELOG.md +0 -334
  27. package/SECURITY.md +0 -32
  28. package/asconfig.json +0 -7
  29. package/assembly/__benches__/abc.bench.ts +0 -28
  30. package/assembly/__benches__/large.bench.ts +0 -238
  31. package/assembly/__benches__/lib/bench.ts +0 -85
  32. package/assembly/__benches__/medium.bench.ts +0 -128
  33. package/assembly/__benches__/small.bench.ts +0 -46
  34. package/assembly/__benches__/throughput.ts +0 -172
  35. package/assembly/__benches__/vec3.bench.ts +0 -37
  36. package/assembly/__tests__/arbitrary.spec.ts +0 -35
  37. package/assembly/__tests__/array.spec.ts +0 -145
  38. package/assembly/__tests__/bool.spec.ts +0 -12
  39. package/assembly/__tests__/box.spec.ts +0 -27
  40. package/assembly/__tests__/custom.spec.ts +0 -56
  41. package/assembly/__tests__/date.spec.ts +0 -36
  42. package/assembly/__tests__/enum.spec.ts +0 -35
  43. package/assembly/__tests__/float.spec.ts +0 -42
  44. package/assembly/__tests__/generics.spec.ts +0 -49
  45. package/assembly/__tests__/hierarchy.spec.ts +0 -61
  46. package/assembly/__tests__/integer.spec.ts +0 -26
  47. package/assembly/__tests__/lib/index.ts +0 -41
  48. package/assembly/__tests__/map.spec.ts +0 -7
  49. package/assembly/__tests__/namespace.spec.ts +0 -63
  50. package/assembly/__tests__/null.spec.ts +0 -12
  51. package/assembly/__tests__/raw.spec.ts +0 -23
  52. package/assembly/__tests__/resolving.spec.ts +0 -55
  53. package/assembly/__tests__/staticarray.spec.ts +0 -12
  54. package/assembly/__tests__/string.spec.ts +0 -30
  55. package/assembly/__tests__/struct.spec.ts +0 -163
  56. package/assembly/__tests__/test.spec.ts +0 -3
  57. package/assembly/__tests__/types.spec.ts +0 -27
  58. package/assembly/__tests__/types.ts +0 -98
  59. package/assembly/test.tmp.ts +0 -133
  60. package/bench/abc.bench.ts +0 -25
  61. package/bench/large.bench.ts +0 -127
  62. package/bench/lib/bench.d.ts +0 -27
  63. package/bench/lib/bench.js +0 -53
  64. package/bench/lib/chart.ts +0 -217
  65. package/bench/medium.bench.ts +0 -68
  66. package/bench/runners/assemblyscript.js +0 -34
  67. package/bench/small.bench.ts +0 -34
  68. package/bench/throughput.ts +0 -87
  69. package/bench/tsconfig.json +0 -13
  70. package/bench/vec3.bench.ts +0 -30
  71. package/bench.ts +0 -18
  72. package/ci/bench/lib/bench.ts +0 -42
  73. package/ci/bench/runners/assemblyscript.js +0 -29
  74. package/ci/run-bench.as.sh +0 -63
  75. package/publish.sh +0 -78
  76. package/run-bench.as.sh +0 -60
  77. package/run-bench.js.sh +0 -36
  78. package/run-tests.sh +0 -51
  79. package/scripts/build-chart01.ts +0 -38
  80. package/scripts/build-chart02.ts +0 -38
  81. package/scripts/build-chart03.ts +0 -139
  82. package/scripts/build-chart05.ts +0 -47
  83. package/scripts/generate-as-class.ts +0 -50
  84. package/scripts/lib/bench-utils.ts +0 -308
  85. package/transform/src/builder.ts +0 -1375
  86. package/transform/src/index.ts +0 -1486
  87. package/transform/src/linkers/alias.ts +0 -58
  88. package/transform/src/linkers/custom.ts +0 -32
  89. package/transform/src/linkers/imports.ts +0 -22
  90. package/transform/src/types.ts +0 -300
  91. package/transform/src/util.ts +0 -128
  92. package/transform/src/visitor.ts +0 -530
package/assembly/index.ts CHANGED
@@ -31,8 +31,8 @@ import { serializeString_SIMD } from "./serialize/simd/string";
31
31
  import { serializeString_SWAR } from "./serialize/swar/string";
32
32
  import { deserializeString_SWAR } from "./deserialize/swar/string";
33
33
  import { deserializeString } from "./deserialize/simple/string";
34
+ import { serializeString } from "./serialize/simple/string";
34
35
  // import { deserializeString_SIMD } from "./deserialize/simd/string";
35
-
36
36
  /**
37
37
  * Offset of the 'storage' property in the JSON.Value class.
38
38
  */
@@ -106,21 +106,12 @@ export namespace JSON {
106
106
  return NULL_WORD;
107
107
  // @ts-ignore
108
108
  } else if (isString<nonnull<T>>()) {
109
- // if (out) {
110
- // out = changetype<string>(__renew(changetype<usize>(out), bytes(data) + 4));
111
- // // const oldSize = bs.byteLength;
112
- // const oldBuf = bs.buffer;
113
- // const newSize = bytes(data) + 4;
114
- // const newBuf = __new(newSize, idof<string>());
115
- // bs.setBuffer(newBuf);
116
- // serializeString_SWAR(changetype<string>(data));
117
- // bs.setBuffer(oldBuf);
118
- // return changetype<string>(newBuf);
119
- // }
120
- if (ASC_FEATURE_SIMD) {
109
+ if (JSON_MODE === JSONMode.SIMD) {
121
110
  serializeString_SIMD(data as string);
122
- } else {
111
+ } else if (JSON_MODE === JSONMode.SWAR) {
123
112
  serializeString_SWAR(data as string);
113
+ } else {
114
+ serializeString(data as string);
124
115
  }
125
116
  return bs.out<string>();
126
117
  // @ts-ignore: Supplied by transform
@@ -187,7 +178,7 @@ export namespace JSON {
187
178
  // // @ts-ignore
188
179
  // return changetype<string>(deserializeString_SIMD(dataPtr, dataPtr + dataSize, __new(dataSize - 4, idof<string>())));
189
180
  // } else {
190
-
181
+
191
182
  // @ts-ignore
192
183
  return deserializeString(dataPtr, dataPtr + dataSize, 0);
193
184
  // }
@@ -232,19 +223,31 @@ export namespace JSON {
232
223
  * Enum representing the different types supported by JSON.
233
224
  */
234
225
  export enum Types {
235
- Raw = 0,
236
- U8 = 1,
237
- U16 = 2,
238
- U32 = 3,
239
- U64 = 4,
240
- F32 = 5,
241
- F64 = 6,
242
- Null = 7,
226
+ StructNull = -12,
227
+ ArrayNull = -11,
228
+ ObjectNull = -10,
229
+ StringNull = -9,
230
+ BoolNull = -8,
231
+ F64Null = -7,
232
+ F32Null = -6,
233
+ U64Null = -5,
234
+ U32Null = -4,
235
+ U16Null = -3,
236
+ U8Null = -2,
237
+ RawNull = -1, // unused
238
+ Null = 0,
239
+ Raw = 1,
240
+ U8 = 2,
241
+ U16 = 3,
242
+ U32 = 4,
243
+ U64 = 5,
244
+ F32 = 6,
245
+ F64 = 7,
243
246
  Bool = 8,
244
247
  String = 9,
245
248
  Object = 10,
246
- Array = 12,
247
- Struct = 13,
249
+ Array = 11,
250
+ Struct = 12,
248
251
  }
249
252
 
250
253
  export class Raw {
@@ -271,6 +274,7 @@ export namespace JSON {
271
274
  static METHODS: Map<u32, u32> = new Map<u32, u32>();
272
275
  public type: i32;
273
276
 
277
+ public isNull: bool;
274
278
  private storage: u64;
275
279
 
276
280
  private constructor() {
@@ -298,63 +302,125 @@ export namespace JSON {
298
302
  out.set<T>(value);
299
303
  return out;
300
304
  }
301
-
302
- /**
303
- * Sets the value of the JSON.Value instance.
304
- * @param value - The value to be set.
305
- */
306
- @inline set<T>(value: T): void {
307
- if (isBoolean<T>()) {
308
- this.type = JSON.Types.Bool;
305
+ @inline private setPrimitive<T>(value: T): void {
306
+ if (isBoolean(value)) {
307
+ this.type = JSON.Types.BoolNull;
309
308
  store<T>(changetype<usize>(this), value, STORAGE);
310
- } else if (isInteger<T>() && !isSigned<T>() && changetype<usize>(value) == 0 && nameof<T>() == "usize") {
311
- this.type = JSON.Types.Null;
312
- store<usize>(changetype<usize>(this), 0, STORAGE);
313
309
  } else if (value instanceof u8 || value instanceof i8) {
314
- this.type = JSON.Types.U8;
310
+ this.type = JSON.Types.U8Null;
315
311
  store<T>(changetype<usize>(this), value, STORAGE);
316
312
  } else if (value instanceof u16 || value instanceof i16) {
317
313
  this.type = JSON.Types.U16;
318
314
  store<T>(changetype<usize>(this), value, STORAGE);
319
315
  } else if (value instanceof u32 || value instanceof i32) {
320
- this.type = JSON.Types.U32;
316
+ this.type = JSON.Types.U32Null;
321
317
  store<T>(changetype<usize>(this), value, STORAGE);
322
318
  } else if (value instanceof u64 || value instanceof i64) {
323
- this.type = JSON.Types.U64;
319
+ this.type = JSON.Types.U64Null;
324
320
  store<T>(changetype<usize>(this), value, STORAGE);
325
321
  } else if (value instanceof f32) {
326
- this.type = JSON.Types.F32;
322
+ this.type = JSON.Types.F32Null;
327
323
  store<T>(changetype<usize>(this), value, STORAGE);
328
324
  } else if (value instanceof f64) {
329
- this.type = JSON.Types.F64;
330
- store<T>(changetype<usize>(this), value, STORAGE);
331
- } else if (isString<T>()) {
332
- this.type = JSON.Types.String;
333
- store<T>(changetype<usize>(this), value, STORAGE);
334
- } else if (value instanceof JSON.Raw) {
335
- this.type = JSON.Types.Raw;
325
+ this.type = JSON.Types.F64Null;
336
326
  store<T>(changetype<usize>(this), value, STORAGE);
337
- } else if (value instanceof Map) {
338
- if (idof<T>() !== idof<Map<string, JSON.Value>>()) {
339
- abort("Maps must be of type Map<string, JSON.Value>!");
327
+ }
328
+ }
329
+ /**
330
+ * Sets the value of the JSON.Value instance.
331
+ * @param value - The value to be set.
332
+ */
333
+ @inline set<T>(value: T): void {
334
+ if (isNullable<T>()) {
335
+ this.isNull = changetype<usize>(value) === 0;
336
+ if (value instanceof JSON.Box) {
337
+ return this.setPrimitive(value.value);
338
+ } else if (isBoolean<T>()) {
339
+ this.type = JSON.Types.BoolNull;
340
+ store<T>(changetype<usize>(this), value, STORAGE);
341
+ } else if (isString<T>()) {
342
+ this.type = JSON.Types.StringNull;
343
+ store<T>(changetype<usize>(this), value, STORAGE);
344
+ } else if (value instanceof JSON.Raw) {
345
+ this.type = JSON.Types.RawNull;
346
+ store<T>(changetype<usize>(this), value, STORAGE);
347
+ } else if (value instanceof Map) {
348
+ if (idof<T>() !== idof<Map<string, JSON.Value>>()) {
349
+ abort("Maps must be of type Map<string, JSON.Value>!");
350
+ }
351
+ this.type = JSON.Types.StructNull;
352
+ store<T>(changetype<usize>(this), value, STORAGE);
353
+ // @ts-ignore: supplied by transform
354
+ } else if (isDefined(value.__SERIALIZE) && isManaged<T>(value)) {
355
+ this.type = idof<T>() + JSON.Types.StructNull;
356
+ // @ts-ignore
357
+ if (!JSON.Value.METHODS.has(idof<T>())) JSON.Value.METHODS.set(idof<T>(), value.__SERIALIZE.index);
358
+ // @ts-ignore
359
+ store<usize>(changetype<usize>(this), changetype<usize>(value), STORAGE);
360
+ } else if (value instanceof JSON.Obj) {
361
+ this.type = JSON.Types.ObjectNull;
362
+ store<T>(changetype<usize>(this), value, STORAGE);
363
+ // @ts-ignore
364
+ } else if (isArray<T>() && idof<valueof<T>>() == idof<JSON.Value>()) {
365
+ // @ts-ignore: T satisfies constraints of any[]
366
+ this.type = JSON.Types.ArrayNull;
367
+ store<T>(changetype<usize>(this), value, STORAGE);
368
+ }
369
+ } else {
370
+ if (value instanceof JSON.Box) {
371
+ return this.set(value.value);
372
+ } else if (isBoolean<T>()) {
373
+ this.type = JSON.Types.Bool;
374
+ store<T>(changetype<usize>(this), value, STORAGE);
375
+ } else if (isInteger<T>() && !isSigned<T>() && changetype<usize>(value) == 0 && nameof<T>() == "usize") {
376
+ this.type = JSON.Types.Null;
377
+ store<usize>(changetype<usize>(this), 0, STORAGE);
378
+ } else if (value instanceof u8 || value instanceof i8) {
379
+ this.type = JSON.Types.U8;
380
+ store<T>(changetype<usize>(this), value, STORAGE);
381
+ } else if (value instanceof u16 || value instanceof i16) {
382
+ this.type = JSON.Types.U16;
383
+ store<T>(changetype<usize>(this), value, STORAGE);
384
+ } else if (value instanceof u32 || value instanceof i32) {
385
+ this.type = JSON.Types.U32;
386
+ store<T>(changetype<usize>(this), value, STORAGE);
387
+ } else if (value instanceof u64 || value instanceof i64) {
388
+ this.type = JSON.Types.U64;
389
+ store<T>(changetype<usize>(this), value, STORAGE);
390
+ } else if (value instanceof f32) {
391
+ this.type = JSON.Types.F32;
392
+ store<T>(changetype<usize>(this), value, STORAGE);
393
+ } else if (value instanceof f64) {
394
+ this.type = JSON.Types.F64;
395
+ store<T>(changetype<usize>(this), value, STORAGE);
396
+ } else if (isString<T>()) {
397
+ this.type = JSON.Types.String;
398
+ store<T>(changetype<usize>(this), value, STORAGE);
399
+ } else if (value instanceof JSON.Raw) {
400
+ this.type = JSON.Types.Raw;
401
+ store<T>(changetype<usize>(this), value, STORAGE);
402
+ } else if (value instanceof Map) {
403
+ if (idof<T>() !== idof<Map<string, JSON.Value>>()) {
404
+ abort("Maps must be of type Map<string, JSON.Value>!");
405
+ }
406
+ this.type = JSON.Types.Struct;
407
+ store<T>(changetype<usize>(this), value, STORAGE);
408
+ // @ts-ignore: supplied by transform
409
+ } else if (isDefined(value.__SERIALIZE) && isManaged<T>(value)) {
410
+ this.type = idof<T>() + JSON.Types.Struct;
411
+ // @ts-ignore
412
+ if (!JSON.Value.METHODS.has(idof<T>())) JSON.Value.METHODS.set(idof<T>(), value.__SERIALIZE.index);
413
+ // @ts-ignore
414
+ store<usize>(changetype<usize>(this), changetype<usize>(value), STORAGE);
415
+ } else if (value instanceof JSON.Obj) {
416
+ this.type = JSON.Types.Object;
417
+ store<T>(changetype<usize>(this), value, STORAGE);
418
+ // @ts-ignore
419
+ } else if (isArray<T>() && idof<valueof<T>>() == idof<JSON.Value>()) {
420
+ // @ts-ignore: T satisfies constraints of any[]
421
+ this.type = JSON.Types.Array;
422
+ store<T>(changetype<usize>(this), value, STORAGE);
340
423
  }
341
- this.type = JSON.Types.Struct;
342
- store<T>(changetype<usize>(this), value, STORAGE);
343
- // @ts-ignore: supplied by transform
344
- } else if (isDefined(value.__SERIALIZE) && isManaged<T>(value)) {
345
- this.type = idof<T>() + JSON.Types.Struct;
346
- // @ts-ignore
347
- if (!JSON.Value.METHODS.has(idof<T>())) JSON.Value.METHODS.set(idof<T>(), value.__SERIALIZE.index);
348
- // @ts-ignore
349
- store<usize>(changetype<usize>(this), changetype<usize>(value), STORAGE);
350
- } else if (value instanceof JSON.Obj) {
351
- this.type = JSON.Types.Object;
352
- store<T>(changetype<usize>(this), value, STORAGE);
353
- // @ts-ignore
354
- } else if (isArray<T>() && idof<valueof<T>>() == idof<JSON.Value>()) {
355
- // @ts-ignore: T satisfies constraints of any[]
356
- this.type = JSON.Types.Array;
357
- store<T>(changetype<usize>(this), value, STORAGE);
358
424
  }
359
425
  }
360
426
 
@@ -375,12 +441,29 @@ export namespace JSON {
375
441
  return load<T>(changetype<usize>(this), STORAGE);
376
442
  }
377
443
 
444
+ /**
445
+ * Gets the value of the JSON.Value instance as a Box<T>.
446
+ * Alias for .get<T>()
447
+ * @returns The encapsulated value.
448
+ */
449
+ @inline asBox<T>(): Box<T> | null {
450
+ if (this.isNull) return null;
451
+ return changetype<Box<T>>(JSON.Box.fromValue<T>(this));
452
+ }
453
+
378
454
  /**
379
455
  * Converts the JSON.Value to a string representation.
380
456
  * @returns The string representation of the JSON.Value.
381
457
  */
382
458
  toString(): string {
459
+ if (this.type < JSON.Types.Null) {
460
+ if (this.isNull) return "null";
461
+ else this.type = ~this.type + 1;
462
+ }
463
+
383
464
  switch (this.type) {
465
+ case JSON.Types.Null:
466
+ return "null";
384
467
  case JSON.Types.U8:
385
468
  return this.get<u8>().toString();
386
469
  case JSON.Types.U16:
@@ -439,7 +522,7 @@ export namespace JSON {
439
522
  // @ts-ignore: type
440
523
  storage: Map<string, JSON.Value> = new Map<string, JSON.Value>();
441
524
 
442
- constructor() {}
525
+ constructor() { }
443
526
 
444
527
  // @ts-ignore: decorator
445
528
  @inline get size(): i32 {
@@ -509,6 +592,24 @@ export namespace JSON {
509
592
  this.value = value;
510
593
  return this;
511
594
  }
595
+ /**
596
+ * Creates a Box<T> | null from a JSON.Value
597
+ * This means that it can create a nullable primitive from a JSON.Value
598
+ * ```js
599
+ * const value = JSON.parse<i32>("null"); // -> Box<i32> | null
600
+ * const boxed = JSON.Box.fromValue<i32>(value); // -> Box<i32> | null
601
+ * // null
602
+ * ```
603
+ * @param from T
604
+ * @returns Box<T> | null
605
+ */
606
+ @inline static fromValue<T>(value: JSON.Value): Box<T> | null {
607
+ if (!(value instanceof JSON.Value)) throw new Error("value must be of type JSON.Value");
608
+ if (value.isNull) return null;
609
+ const v = value.type === JSON.Types.F64 ?value.get<f64>() : value.get<T>();
610
+ // @ts-ignore
611
+ return new Box(isInteger<T>() || isFloat<T>() ? <T>(v) : v);
612
+ }
512
613
  /**
513
614
  * Creates a reference to a primitive type
514
615
  * This means that it can create a nullable primitive
@@ -533,58 +634,60 @@ export namespace JSON {
533
634
  /**
534
635
  * Serializes JSON data but writes directly to the buffer.
535
636
  * Should only be used if you know what you are doing.
536
- * @param src - T
637
+ * @param data - T
537
638
  * @returns void
538
639
  */
539
- export function __serialize<T>(src: T): void {
640
+ export function __serialize<T>(data: T): void {
540
641
  if (isBoolean<T>()) {
541
- serializeBool(src as bool);
542
- } else if (isInteger<T>() && nameof<T>() == "usize" && src == 0) {
642
+ serializeBool(data as bool);
643
+ } else if (isInteger<T>() && nameof<T>() == "usize" && data == 0) {
543
644
  bs.proposeSize(8);
544
645
  store<u64>(bs.offset, 30399761348886638);
545
646
  bs.offset += 8;
546
647
  } else if (isInteger<T>()) {
547
648
  // @ts-ignore
548
- serializeInteger<T>(src);
549
- } else if (isFloat<T>(src)) {
649
+ serializeInteger<T>(data);
650
+ } else if (isFloat<T>(data)) {
550
651
  // @ts-ignore
551
- serializeFloat<T>(src);
652
+ serializeFloat<T>(data);
552
653
  // @ts-ignore: Function is generated by transform
553
- } else if (isNullable<T>() && changetype<usize>(src) == <usize>0) {
654
+ } else if (isNullable<T>() && changetype<usize>(data) == <usize>0) {
554
655
  bs.proposeSize(8);
555
656
  store<u64>(bs.offset, 30399761348886638);
556
657
  bs.offset += 8;
557
658
  } else if (isString<nonnull<T>>()) {
558
- if (ASC_FEATURE_SIMD) {
559
- serializeString_SIMD(src as string);
659
+ if (JSON_MODE === JSONMode.SIMD) {
660
+ serializeString_SIMD(data as string);
661
+ } else if (JSON_MODE === JSONMode.SWAR) {
662
+ serializeString_SWAR(data as string);
560
663
  } else {
561
- serializeString_SWAR(src as string);
664
+ serializeString(data as string);
562
665
  }
563
666
  // @ts-ignore: Supplied by transform
564
- } else if (isDefined(src.__SERIALIZE_CUSTOM)) {
667
+ } else if (isDefined(data.__SERIALIZE_CUSTOM)) {
565
668
  // @ts-ignore
566
- return src.__SERIALIZE_CUSTOM();
669
+ return data.__SERIALIZE_CUSTOM();
567
670
  // @ts-ignore: Supplied by transform
568
- } else if (isDefined(src.__SERIALIZE)) {
671
+ } else if (isDefined(data.__SERIALIZE)) {
569
672
  // @ts-ignore
570
- serializeStruct(changetype<nonnull<T>>(src));
571
- } else if (src instanceof Date) {
673
+ serializeStruct(changetype<nonnull<T>>(data));
674
+ } else if (data instanceof Date) {
572
675
  // @ts-ignore
573
- inline.always(serializeDate(changetype<nonnull<T>>(src)));
574
- } else if (src instanceof Array || src instanceof StaticArray) {
676
+ inline.always(serializeDate(changetype<nonnull<T>>(data)));
677
+ } else if (data instanceof Array || data instanceof StaticArray) {
575
678
  // @ts-ignore
576
- serializeArray(changetype<nonnull<T>>(src));
577
- } else if (src instanceof Map) {
679
+ serializeArray(changetype<nonnull<T>>(data));
680
+ } else if (data instanceof Map) {
578
681
  // @ts-ignore
579
- serializeMap(changetype<nonnull<T>>(src));
580
- } else if (src instanceof JSON.Raw) {
581
- serializeRaw(src);
582
- } else if (src instanceof JSON.Value) {
583
- serializeArbitrary(src);
584
- } else if (src instanceof JSON.Obj) {
585
- serializeObject(src);
586
- } else if (src instanceof JSON.Box) {
587
- __serialize(src.value);
682
+ serializeMap(changetype<nonnull<T>>(data));
683
+ } else if (data instanceof JSON.Raw) {
684
+ serializeRaw(data);
685
+ } else if (data instanceof JSON.Value) {
686
+ serializeArbitrary(data);
687
+ } else if (data instanceof JSON.Obj) {
688
+ serializeObject(data);
689
+ } else if (data instanceof JSON.Box) {
690
+ __serialize(data.value);
588
691
  } else {
589
692
  throw new Error(`Could not serialize provided data. Make sure to add the correct decorators to classes.`);
590
693
  }
@@ -608,7 +711,7 @@ export namespace JSON {
608
711
  return deserializeFloat<T>(srcStart, srcEnd);
609
712
  } else if (isString<T>()) {
610
713
  if (srcEnd - srcStart < 4) throw new Error("Cannot parse data as string because it was formatted incorrectly!");
611
-
714
+
612
715
  // @ts-ignore: type
613
716
  return deserializeString(srcStart, srcEnd, dst);
614
717
  } else if (isNullable<T>() && srcEnd - srcStart == 8 && load<u64>(srcStart) == 30399761348886638) {
@@ -721,22 +824,12 @@ export namespace JSON {
721
824
  return NULL_WORD;
722
825
  // @ts-ignore
723
826
  } else if (isString<nonnull<T>>()) {
724
- // if (out) {
725
- // out = changetype<string>(__renew(changetype<usize>(out), bytes(data) + 4));
726
- // // const oldSize = bs.byteLength;
727
- // const oldBuf = bs.buffer;
728
- // const newSize = bytes(data) + 4;
729
- // const newBuf = __new(newSize, idof<string>());
730
- // bs.setBuffer(newBuf);
731
- // serializeString_SWAR(changetype<string>(data));
732
- // bs.setBuffer(oldBuf);
733
- // return changetype<string>(newBuf);
734
- // }
735
- if (ASC_FEATURE_SIMD) {
827
+ if (JSON_MODE === JSONMode.SIMD) {
736
828
  serializeString_SIMD(data as string);
737
- } else {
738
- bs.saveState();
829
+ } else if (JSON_MODE === JSONMode.SWAR) {
739
830
  serializeString_SWAR(data as string);
831
+ } else {
832
+ serializeString(data as string);
740
833
  }
741
834
  return bs.cpyOut<string>();
742
835
  // @ts-ignore: Supplied by transform
@@ -784,6 +877,12 @@ export namespace JSON {
784
877
  }
785
878
  }
786
879
 
880
+ export enum JSONMode {
881
+ SWAR = 0,
882
+ SIMD = 1,
883
+ NAIVE = 2
884
+ }
885
+
787
886
  // @ts-ignore: decorator
788
887
  @inline function parseBox<T>(data: string, ty: T): T {
789
888
  return JSON.parse<T>(data);
@@ -1,4 +1,4 @@
1
- import { bs } from "../../../lib/as-bs";
1
+ import { bs, sc } from "../../../lib/as-bs";
2
2
  import { BACK_SLASH } from "../../custom/chars";
3
3
  import { SERIALIZE_ESCAPE_TABLE } from "../../globals/tables";
4
4
  import { bytes } from "../../util";
@@ -7,6 +7,18 @@ import { bytes } from "../../util";
7
7
  * Serializes strings into their JSON counterparts using SIMD operations
8
8
  */
9
9
  export function serializeString_SIMD(src: string): void {
10
+ let srcStart = changetype<usize>(src);
11
+ if (isDefined(JSON_CACHE)) {
12
+ // check cache
13
+ const e = unchecked(sc.entries[(srcStart >> 4) & sc.CACHE_MASK]);
14
+ if (e.key == srcStart) {
15
+ // bs.offset += e.len;
16
+ // bs.stackSize += e.len;
17
+ bs.cacheOutput = e.ptr;
18
+ bs.cacheOutputLen = e.len;
19
+ return;
20
+ }
21
+ }
10
22
  const U00_MARKER = 13511005048209500;
11
23
  const SPLAT_34 = i16x8.splat(34); /* " */
12
24
  const SPLAT_92 = i16x8.splat(92); /* \ */
@@ -14,7 +26,6 @@ export function serializeString_SIMD(src: string): void {
14
26
  const SPLAT_32 = i16x8.splat(32); /* [ESC] */
15
27
 
16
28
  const srcSize = bytes(src);
17
- let srcStart = changetype<usize>(src);
18
29
  const srcEnd = srcStart + srcSize;
19
30
  const srcEnd16 = srcEnd - 16;
20
31
 
@@ -36,7 +47,7 @@ export function serializeString_SIMD(src: string): void {
36
47
  let mask = i16x8.bitmask(sieve);
37
48
 
38
49
  while (mask != 0) {
39
- const lane_index = ctz(mask) << 1;
50
+ const lane_index = ctz(mask) << 1; // 0 2 4 6 8 10 12 14
40
51
  // console.log("lane: " + (lane_index >= 8 ? (lane_index - 8).toString():lane_index.toString()));
41
52
  const src_offset = srcStart + lane_index;
42
53
  const code = load<u16>(src_offset) << 2;
@@ -85,4 +96,6 @@ export function serializeString_SIMD(src: string): void {
85
96
 
86
97
  store<u8>(bs.offset, 34); /* " */
87
98
  bs.offset += 2;
99
+
100
+ if (isDefined(JSON_CACHE)) sc.insertCached(changetype<usize>(src), srcStart, srcSize);
88
101
  }
@@ -1,5 +1,5 @@
1
1
  import { JSON } from "../..";
2
- import { serializeString_SWAR } from "../swar/string";
2
+ import { bs } from "../../../lib/as-bs";
3
3
  import { serializeArray } from "./array";
4
4
  import { serializeBool } from "./bool";
5
5
  import { serializeFloat } from "./float";
@@ -8,7 +8,21 @@ import { serializeObject } from "./object";
8
8
  import { serializeString } from "./string";
9
9
 
10
10
  export function serializeArbitrary(src: JSON.Value): void {
11
+ if (src.type < JSON.Types.Null) {
12
+ if (src.isNull) {
13
+ bs.proposeSize(8);
14
+ store<u64>(bs.offset, 30399761348886638);
15
+ bs.offset += 8;
16
+ return;
17
+ } else src.type = ~src.type + 1;
18
+ }
19
+
11
20
  switch (src.type) {
21
+ case JSON.Types.Null:
22
+ bs.proposeSize(8);
23
+ store<u64>(bs.offset, 30399761348886638);
24
+ bs.offset += 8;
25
+ break;
12
26
  case JSON.Types.U8:
13
27
  serializeInteger<u8>(src.get<u8>());
14
28
  break;
@@ -28,7 +42,7 @@ export function serializeArbitrary(src: JSON.Value): void {
28
42
  serializeFloat<f64>(src.get<f64>());
29
43
  break;
30
44
  case JSON.Types.String:
31
- serializeString_SWAR(src.get<string>());
45
+ serializeString(src.get<string>());
32
46
  break;
33
47
  case JSON.Types.Bool:
34
48
  serializeBool(src.get<bool>());
@@ -1,7 +1,7 @@
1
- import { bs } from "../../../lib/as-bs";
1
+ import { bs, sc } from "../../../lib/as-bs";
2
2
  import { BACK_SLASH } from "../../custom/chars";
3
3
  import { SERIALIZE_ESCAPE_TABLE } from "../../globals/tables";
4
- import { bytes } from "../../util/bytes";
4
+ import { OBJECT, TOTAL_OVERHEAD } from "rt/common";
5
5
 
6
6
 
7
7
  // @ts-ignore: decorator allowed
@@ -22,8 +22,21 @@ import { bytes } from "../../util/bytes";
22
22
  @lazy const U00_MARKER = 13511005048209500;
23
23
 
24
24
  export function serializeString_SWAR(src: string): void {
25
- const srcSize = bytes(src);
26
25
  let srcStart = changetype<usize>(src);
26
+
27
+ if (isDefined(JSON_CACHE)) {
28
+ // check cache
29
+ const e = unchecked(sc.entries[(srcStart >> 4) & sc.CACHE_MASK]);
30
+ if (e.key == srcStart) {
31
+ // bs.offset += e.len;
32
+ // bs.stackSize += e.len;
33
+ bs.cacheOutput = e.ptr;
34
+ bs.cacheOutputLen = e.len;
35
+ return;
36
+ }
37
+ }
38
+
39
+ const srcSize = changetype<OBJECT>(srcStart - TOTAL_OVERHEAD).rtSize
27
40
  const srcEnd = srcStart + srcSize;
28
41
  const srcEnd8 = srcEnd - 8;
29
42
 
@@ -68,7 +81,7 @@ export function serializeString_SWAR(src: string): void {
68
81
  bs.offset += 8;
69
82
  }
70
83
 
71
- while (srcStart <= srcEnd - 2) {
84
+ while (srcStart <= srcEnd - 2) {
72
85
  const code = load<u16>(srcStart);
73
86
  if (code == 92 || code == 34 || code < 32) {
74
87
  const escaped = load<u32>(SERIALIZE_ESCAPE_TABLE + (code << 2));
@@ -91,19 +104,32 @@ while (srcStart <= srcEnd - 2) {
91
104
 
92
105
  store<u16>(bs.offset, 34); // "
93
106
  bs.offset += 2;
107
+
108
+ if (isDefined(JSON_CACHE)) sc.insertCached(changetype<usize>(src), srcStart, srcSize);
94
109
  }
95
110
 
96
111
  // @ts-ignore: decorators allowed
97
112
  @inline function v64x4_should_escape(x: u64): u64 {
98
- x = x ^ 0xFF00FF00FF00FF00;
99
-
100
- const is_ascii: u64 = HIGHS & ~x;
101
- const xor2: u64 = x ^ 0x0202020202020202;
102
- const lt32_or_eq34: u64 = xor2 - 0x2121212121212121;
103
- const sub92: u64 = x ^ 0x5C5C5C5C5C5C5C5C;
104
- const eq92: u64 = sub92 - ONES;
105
-
106
- const high_bits: u64 = (lt32_or_eq34 | eq92) & is_ascii;
107
-
108
- return high_bits
113
+ // console.log("input: " + mask_to_string(x));
114
+ const hi = x & 0xff00_ff00_ff00_ff00;
115
+ const lo = x & 0x00ff_00ff_00ff_00ff;
116
+ x &= 0x00ff_00ff_00ff_00ff;
117
+ // const is_cp = hi & 0x8080_8080_8080_8080;
118
+ const is_ascii = 0x0080_0080_0080_0080 & ~x; // lane remains 0x80 if ascii
119
+ const lt32 = (x - 0x0020_0020_0020_0020);
120
+ const sub34 = x ^ 0x0022_0022_0022_0022;
121
+ const eq34 = (sub34 - 0x0001_0001_0001_0001);
122
+ const sub92 = x ^ 0x005C_005C_005C_005C;
123
+ const eq92 = (sub92 - 0x0001_0001_0001_0001);
124
+ // console.log("low: " + mask_to_string(lo));
125
+ // console.log("high: " + mask_to_string(hi));
126
+ // console.log("is_cp: " + mask_to_string(is_cp));
127
+ // console.log("is_ascii: " + mask_to_string(is_ascii));
128
+ // console.log("lt32: " + mask_to_string(lt32));
129
+ // console.log("sub34: " + mask_to_string(sub34));
130
+ // console.log("eq34: " + mask_to_string(eq34));
131
+ // console.log("eq92: " + mask_to_string(eq92));
132
+ // console.log("pre: " + mask_to_string((lt32 | eq34 | eq92)));
133
+ // console.log("out: " + mask_to_string((lt32 | eq34 | eq92) & is_ascii));
134
+ return ((lt32 | eq34 | eq92)& is_ascii);
109
135
  }
package/assembly/test.ts CHANGED
@@ -0,0 +1,38 @@
1
+ import { JSON } from ".";
2
+
3
+ @json
4
+ class Vec3 {
5
+ x!: f32;
6
+ y!: f32;
7
+ z!: f32;
8
+ }
9
+
10
+ const vec: Vec3 = {
11
+ x: 1.0,
12
+ y: 2.0,
13
+ z: 3.0
14
+ }
15
+ const str: JSON.Value[] = [
16
+ JSON.Value.from<string>("foo"),
17
+ JSON.Value.from("bar"),
18
+ JSON.Value.from(1),
19
+ JSON.Value.from(2),
20
+ JSON.Value.from(true),
21
+ JSON.Value.from<JSON.Box<i32> | null>(null),
22
+ JSON.Value.from(vec),
23
+ JSON.Value.from<Vec3 | null>(null),
24
+ JSON.Value.from<JSON.Box<i32> | null>(JSON.Box.from(123)),
25
+ JSON.Value.from<JSON.Box<i32> | null>(null),
26
+ ];
27
+ const box = JSON.Box.from<i32>(123);
28
+ const value = JSON.Value.from<JSON.Box<i32> | null>(box);
29
+ const reboxed = JSON.Box.fromValue<i32>(value); // Box<i32> | null
30
+ console.log(reboxed !== null ? reboxed!.toString() : "null");
31
+
32
+ // console.log(str[9]!.asBox<i32>()?.toString());
33
+ // console.log(str.toString())
34
+ const serialized = JSON.stringify(str);
35
+ console.log("Serialized: " + serialized);
36
+
37
+ const deserialized = JSON.parse<JSON.Value[]>(serialized);
38
+ console.log("Deserialized: " + JSON.stringify(deserialized).toString());