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
@@ -19,8 +19,5 @@ jobs:
19
19
  - name: Install Dependencies
20
20
  run: bun install
21
21
 
22
- - name: Build Tests
23
- run: bun run pretest
24
-
25
22
  - name: Run Tests
26
23
  run: bun run test
package/.gitmodules ADDED
File without changes
package/.prettierrc.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
+ "pluginSearchDirs": ["node_modules"],
3
+ "plugins": ["assemblyscript-prettier"],
2
4
  "singleQuote": false,
3
5
  "printWidth": 65536,
4
- "pluginSearchDirs": ["node_modules"],
5
- "plugins": ["assemblyscript-prettier"]
6
+ "tabWidth": 2
6
7
  }
package/CHANGELOG ADDED
@@ -0,0 +1,24 @@
1
+ # Change Log
2
+
3
+ ## UNRELEASED
4
+
5
+ ## 2025-01-20 - 1.0.0-alpha.2
6
+
7
+ - fix: disable SIMD in generated transform code by default
8
+ - fix: re-add as-bs dependency so that it will not break in non-local environments
9
+ - fix: remove AS201 'conversion from type usize to i32' warning
10
+ - fix: add as-bs to peer dependencies so only one version is installed
11
+ - fix: point as-bs imports to submodule
12
+ - fix: remove submodule in favor of static module
13
+ - fix: bs.ensureSize would not grow and thus cause memory faults
14
+ - fix: bs.ensureSize triggering unintentionally
15
+
16
+ ## 2025-01-20 - 1.0.0-alpha.1
17
+
18
+ - feat: finish implementation of arbitrary data serialization and deserialization using JSON.Value
19
+ - feat: reinstate usage of `JSON.Box<T>()` to support nullable primitive types
20
+ - feat: eliminate the need to import the `JSON` namespace when defining a schema
21
+ - feat: reduce memory usage so that it is viable for low-memory environments
22
+ - feat: write to a central buffer and reduce memory overhead
23
+ - feat: rewrite the transform to properly resolve schemas and link them together
24
+ - feat: pre-allocate and compute the minimum size of a schema to avoid memory out of range errors
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2023 Jairus Tanaka <jairus.v.tanaka@outlook.com>
3
+ Copyright (c) 2025 Jairus Tanaka <me@jairus.dev>
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -6,29 +6,29 @@
6
6
  ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
7
7
  █████ ███████ ██████ ██ ████ ██ ██ ███████
8
8
  </span>
9
- AssemblyScript - v0.9.29
9
+ AssemblyScript - v1.0.0-alpha.2
10
10
  </pre>
11
11
  </h5>
12
12
 
13
13
  ## Installation
14
14
 
15
15
  ```bash
16
- npm install json-as visitor-as
16
+ npm install json-as@1.0.0-alpha.2
17
17
  ```
18
18
 
19
19
  Add the `--transform` to your `asc` command (e.g. in package.json)
20
20
 
21
21
  ```bash
22
- --transform json-as/transform
22
+ --transform json-as
23
23
  ```
24
24
 
25
25
  Alternatively, add it to your `asconfig.json`
26
26
 
27
- ```json
27
+ ```
28
28
  {
29
29
  // ...
30
30
  "options": {
31
- "transform": ["json-as/transform"]
31
+ "transform": ["json-as"]
32
32
  }
33
33
  }
34
34
  ```
@@ -38,7 +38,7 @@ If you'd like to see the code that the transform generates, run with `JSON_DEBUG
38
38
  ## Usage
39
39
 
40
40
  ```js
41
- import { JSON } from "json-as/assembly";
41
+ import { JSON } from "json-as";
42
42
 
43
43
  // @json or @serializable work here
44
44
  @json
@@ -55,7 +55,8 @@ class Player {
55
55
  lastName!: string;
56
56
  lastActive!: i32[];
57
57
  // Drop in a code block, function, or expression that evaluates to a boolean
58
- @omitif("this.age < 18")
58
+ @omitif((age) => age < 18)
59
+ @omitif('this.age <= 0')
59
60
  age!: i32;
60
61
  @omitnull()
61
62
  pos!: Vec3 | null;
@@ -110,8 +111,23 @@ const serialized = JSON.stringify(arr);
110
111
  const parsed = JSON.parse<Base[]>(serialized);
111
112
  ```
112
113
 
114
+ You can also add it to your `asconfig.json`
115
+
116
+ ```json
117
+ {
118
+ // ...
119
+ "options": {
120
+ "transform": ["json-as/transform"]
121
+ }
122
+ }
123
+ ```
124
+
113
125
  If you use this project in your codebase, consider dropping a [star](https://github.com/JairusSW/as-json). I would really appreciate it!
114
126
 
127
+ ## Notes
128
+
129
+ If you want a feature, drop an issue (and again, maybe a star). I'll likely add it in less than 7 days.
130
+
115
131
  ## Contact
116
132
 
117
133
  - [Email](mailto:me@jairus.dev)
@@ -6,7 +6,7 @@
6
6
  "coverage": false
7
7
  },
8
8
  "buildOptions": {
9
- "args": ["--transform ./transform"],
9
+ "args": ["--enable simd", "--runtime stub"],
10
10
  "target": "wasi"
11
11
  },
12
12
  "runOptions": {
package/asconfig.json CHANGED
@@ -29,8 +29,8 @@
29
29
  }
30
30
  },
31
31
  "options": {
32
- "transform": ["./transform", "as-test/transform"],
33
- "disableWarning": [226]
32
+ "transform": [],
33
+ "disableWarning": []
34
34
  },
35
35
  "extends": "./node_modules/@assemblyscript/wasi-shim/asconfig.json"
36
36
  }
@@ -1,34 +0,0 @@
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
-
25
- @inline function matchType(data: string, type: JSON.Types): boolean {
26
- const firstChar = load<u8>(changetype<usize>(data));
27
- if (JSON.Types.String == type && firstChar == QUOTE) return true;
28
- else if (JSON.Types.Bool == type && (firstChar == CHAR_T || firstChar == CHAR_F)) return true;
29
- else if (JSON.Types.Array == type && firstChar == BRACKET_LEFT) return true;
30
- else if (JSON.Types.Obj == type && firstChar == BRACE_LEFT) return true;
31
- else if (type < 7 && type > 0 && firstChar < 58 && firstChar > 46) return true;
32
- else if (JSON.Types.Raw == type) return true;
33
- else return false;
34
- }
@@ -1,4 +1,4 @@
1
- import { JSON } from "json-as";
1
+ import { JSON } from "../";
2
2
  import { describe, expect, run } from "as-test/assembly";
3
3
 
4
4
  describe("Should serialize booleans", () => {
@@ -0,0 +1,32 @@
1
+ import { describe, expect, run } from "as-test/assembly";
2
+ import { serializeString_SIMD } from "../../serialize/simd/string";
3
+ import { deserializeString_SIMD } from "../../deserialize/simd/string";
4
+
5
+ const out = changetype<usize>(new ArrayBuffer(512));
6
+
7
+ const serialize_simd = (data: string): string => String.UTF16.decodeUnsafe(out, serializeString_SIMD(data, out));
8
+ const deserialize_simd = (data: string): string => String.UTF16.decodeUnsafe(out, deserializeString_SIMD(data, out));
9
+ describe("Should serialize strings", () => {
10
+ expect(serialize_simd("abcdefg")).toBe('"abcdefg"');
11
+
12
+ expect(serialize_simd('st"ring" w""ith quotes"')).toBe('"st\\"ring\\" w\\"\\"ith quotes\\""');
13
+
14
+ expect(serialize_simd('string "with random spa\nces and \nnewlines\n\n\n')).toBe('"string \\"with random spa\\nces and \\nnewlines\\n\\n\\n"');
15
+
16
+ expect(serialize_simd('string with colon : comma , brace [ ] bracket { } and quote " and other quote "')).toBe('"string with colon : comma , brace [ ] bracket { } and quote \\" and other quote \\""');
17
+
18
+ expect(serialize_simd("\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008\u0009\u000a\u000b\u000c\u000d\u000e\u000f\u000f\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f")).toBe('"\\u0000\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\\b\\t\\n\\u000b\\f\\r\\u000e\\u000f\\u000f\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017\\u0018\\u0019\\u001a\\u001b\\u001c\\u001d\\u001e\\u001f"');
19
+ });
20
+
21
+ describe("Should deserialize strings", () => {
22
+ expect(deserialize_simd('"abcdefg"')).toBe("abcdefg");
23
+ expect(deserialize_simd('"st\\"ring\\" w\\"\\"ith quotes\\""')).toBe('st"ring" w""ith quotes"');
24
+
25
+ expect(deserialize_simd('"string \\"with random spa\\nces and \\nnewlines\\n\\n\\n"')).toBe('string "with random spa\nces and \nnewlines\n\n\n');
26
+
27
+ expect(deserialize_simd('"string with colon : comma , brace [ ] bracket { } and quote \\" and other quote \\""')).toBe('string with colon : comma , brace [ ] bracket { } and quote " and other quote "');
28
+
29
+ expect(deserialize_simd('"\\u0000\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\\b\\t\\n\\u000b\\f\\r\\u000e\\u000f\\u000f\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017\\u0018\\u0019\\u001a\\u001b\\u001c\\u001d\\u001e\\u001f"')).toBe("\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008\u0009\u000a\u000b\u000c\u000d\u000e\u000f\u000f\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f");
30
+ });
31
+
32
+ run();
@@ -0,0 +1,25 @@
1
+ import { BLOCK_MAXSIZE, OBJECT, TOTAL_OVERHEAD } from "rt/common";
2
+ import { E_INVALIDLENGTH } from "util/error";
3
+
4
+ // @ts-ignore: Decorator valid here
5
+ @inline export function ensureCapacity<T>(obj: T, newSize: usize): usize {
6
+ const ptr = changetype<usize>(obj);
7
+ const oldCapacity = changetype<OBJECT>(ptr - TOTAL_OVERHEAD).rtSize;
8
+ if (newSize > oldCapacity) {
9
+ if (newSize > BLOCK_MAXSIZE) throw new RangeError(E_INVALIDLENGTH);
10
+ const newCapacity = max(min(oldCapacity << 1, BLOCK_MAXSIZE), newSize);
11
+ const newObj = __renew(ptr, newCapacity);
12
+ return newObj;
13
+ }
14
+ return ptr;
15
+ }
16
+
17
+ // @ts-ignore: Decorator valid here
18
+ @inline export function setCapacity<T>(obj: T, oldCapacity: usize, newCapacity: usize): usize {
19
+ const ptr = changetype<usize>(obj);
20
+ if (newCapacity > oldCapacity) {
21
+ if (newCapacity > BLOCK_MAXSIZE) throw new RangeError(E_INVALIDLENGTH);
22
+ return __renew(ptr, newCapacity);
23
+ }
24
+ return ptr;
25
+ }
@@ -1,78 +1,6 @@
1
1
  import { isSpace } from "util/string";
2
- import { BACK_SLASH, BRACE_LEFT, BRACKET_LEFT, CHAR_F, CHAR_T, QUOTE } from "./chars";
2
+ import { BACK_SLASH, QUOTE } from "./chars";
3
3
  import { Sink } from "./sink";
4
- import { JSON } from "..";
5
-
6
- // @ts-ignore: Decorator
7
- export function isMap<T>(): bool {
8
- let type = changetype<T>(0);
9
- return type instanceof Map;
10
- }
11
-
12
- // @ts-ignore: Decorator
13
- @inline export function unsafeCharCodeAt(data: string, pos: i32): i32 {
14
- return load<u16>(changetype<usize>(data) + ((<usize>pos) << 1));
15
- }
16
-
17
- // @ts-ignore: Decorator
18
- @inline export function removeWhitespace(data: string): string {
19
- const result = new Sink();
20
- let instr = false;
21
- for (let i = 0; i < data.length; i++) {
22
- const char = unsafeCharCodeAt(data, i);
23
- if (instr === false && char === QUOTE) instr = true;
24
- else if (instr === true && char === QUOTE && unsafeCharCodeAt(data, i - 1) !== BACK_SLASH) instr = false;
25
-
26
- if (instr === false) {
27
- if (!isSpace(char)) result.write(data.charAt(i));
28
- } else {
29
- result.write(data.charAt(i));
30
- }
31
- }
32
- return result.toString();
33
- }
34
-
35
- // @ts-ignore: Decorator
36
- @inline export function escapeChar(char: string): string {
37
- switch (unsafeCharCodeAt(char, 0)) {
38
- case 0x22:
39
- return '\\"';
40
- case 0x5c:
41
- return "\\\\";
42
- case 0x08:
43
- return "\\b";
44
- case 0x0a:
45
- return "\\n";
46
- case 0x0d:
47
- return "\\r";
48
- case 0x09:
49
- return "\\t";
50
- case 0x0c:
51
- return "\\f";
52
- case 0x0b:
53
- return "\\u000b";
54
- default:
55
- return char;
56
- }
57
- }
58
-
59
- /**
60
- * A terrible function which finds the depth of a certain array.
61
- * Suffers no overhead besides function calling and a if/else.
62
- * @returns depth of array
63
- */
64
-
65
- // @ts-ignore: Decorator
66
- export function getArrayDepth<T extends ArrayLike>(depth: i32 = 1): i32 {
67
- if (!isArray<T>()) {
68
- return 0;
69
- } else if (isArray<valueof<T>>()) {
70
- depth++;
71
- return getArrayDepth<valueof<T>>(depth);
72
- } else {
73
- return depth;
74
- }
75
- }
76
4
 
77
5
  /** Scientific Notation Integer Parsing - SNIP
78
6
  * This is absolutely the fastest algorithm I could think of while adding full support for Scientific Notation
@@ -94,8 +22,8 @@ export function getArrayDepth<T extends ArrayLike>(depth: i32 = 1): i32 {
94
22
  @inline export function snip_fast<T extends number>(str: string, len: u32 = 0, offset: u32 = 0): T {
95
23
  if (isSigned<T>()) {
96
24
  const firstChar: u32 = load<u16>(changetype<usize>(str));
97
- if (firstChar === 48) return 0 as T;
98
- const isNegative = firstChar === 45; // Check if the number is negative
25
+ if (firstChar == 48) return 0 as T;
26
+ const isNegative = firstChar == 45; // Check if the number is negative
99
27
  let val: T = 0 as T;
100
28
  if (len == 0) len = u32(str.length << 1);
101
29
  if (isNegative) {
@@ -199,7 +127,7 @@ export function getArrayDepth<T extends ArrayLike>(depth: i32 = 1): i32 {
199
127
  }
200
128
  } else {
201
129
  const firstChar: u32 = load<u16>(changetype<usize>(str));
202
- if (firstChar === 48) return 0 as T;
130
+ if (firstChar == 48) return 0 as T;
203
131
  let val: T = 0 as T;
204
132
  if (len == 0) len = u32(str.length << 1);
205
133
  if (len >= 4) {
@@ -262,7 +190,7 @@ export function getArrayDepth<T extends ArrayLike>(depth: i32 = 1): i32 {
262
190
  if (!end) end = start + u32(str.length << 1);
263
191
  if (isSigned<T>()) {
264
192
  // Negative path
265
- if (load<u16>(changetype<usize>(str) + <usize>start) === 45) {
193
+ if (load<u16>(changetype<usize>(str) + <usize>start) == 45) {
266
194
  start += 2;
267
195
  for (; start < end; start += 2) {
268
196
  val = (val * 10 + (load<u16>(changetype<usize>(str) + <usize>start) - 48)) as T;
@@ -296,14 +224,14 @@ export function getArrayDepth<T extends ArrayLike>(depth: i32 = 1): i32 {
296
224
  let val: T = 0;
297
225
  let offset = 0;
298
226
  let firstChar = load<u16>(changetype<usize>(str) + <usize>offset);
299
- if (firstChar === 45) {
227
+ if (firstChar == 45) {
300
228
  offset = 2;
301
229
  }
302
230
  for (; offset < str.length << 1; offset += 2) {
303
231
  const char = load<u16>(changetype<usize>(str) + <usize>offset);
304
- if (char === 101 || char === 69) {
232
+ if (char == 101 || char == 69) {
305
233
  const char = load<u16>(changetype<usize>(str) + <usize>(offset += 2));
306
- if (char === 45) {
234
+ if (char == 45) {
307
235
  // @ts-ignore
308
236
  val /= sciNote<T>(__atoi_fast<T>(str, (offset += 2)));
309
237
  // @ts-ignore
@@ -319,7 +247,7 @@ export function getArrayDepth<T extends ArrayLike>(depth: i32 = 1): i32 {
319
247
  val = (val << 1) + (val << 3) + (char - 48);
320
248
  // We use load because in this case, there is no need to have bounds-checking
321
249
  }
322
- if (firstChar === 45) {
250
+ if (firstChar == 45) {
323
251
  val = -val as T;
324
252
  }
325
253
  return val;
@@ -342,17 +270,6 @@ export function getArrayDepth<T extends ArrayLike>(depth: i32 = 1): i32 {
342
270
  return res;
343
271
  }
344
272
 
345
- // @ts-ignore
346
- @inline function equalsSlice(p1_data: string, p1_start: i32, p1_end: i32, p2_data: string, p2_start: i32, p2_end: i32): boolean {
347
- const p1_len = p1_end - p1_start;
348
- const p2_len = p2_end - p2_start;
349
- if (p1_len != p2_len) return false;
350
- if (p1_len == 2) {
351
- return load<u16>(changetype<usize>(p1_data) + p1_start) == load<u16>(changetype<usize>(p2_data) + p2_start);
352
- }
353
- return memory.compare(changetype<usize>(p1_data) + p1_start, changetype<usize>(p2_data) + p2_start, p1_len) === 0;
354
- }
355
-
356
273
  // @ts-ignore
357
274
  @inline export function containsCodePoint(str: string, code: u32, start: i32, end: i32): bool {
358
275
  for (let i = start; i <= end; i++) {
@@ -390,3 +307,8 @@ export function getArrayDepth<T extends ArrayLike>(depth: i32 = 1): i32 {
390
307
  }
391
308
  }
392
309
  }
310
+
311
+ // @ts-ignore: Decorator valid here
312
+ @inline export function nextPowerOf2(n: u32): u32 {
313
+ return 1 << (32 - clz(n - 1));
314
+ }
@@ -0,0 +1,103 @@
1
+ import { BACK_SLASH } from "../../custom/chars";
2
+ import { DESERIALIZE_ESCAPE_TABLE, ESCAPE_HEX_TABLE } from "../../globals/tables";
3
+
4
+ const SPLAT_92 = i16x8.splat(92); /* \ */
5
+
6
+ /**
7
+ * Deserializes strings back into into their original form using SIMD operations
8
+ * @param src string to deserialize
9
+ * @param dst buffer to write to
10
+ * @returns number of bytes written
11
+ */
12
+ // todo: optimize and stuff. it works, its not pretty. ideally, i'd like this to be (nearly) branchless
13
+ export function deserializeString_SIMD(src: string, srcStart: usize, srcEnd: usize, dst: usize): usize {
14
+ let src_ptr = srcStart + 2;
15
+ let dst_ptr = changetype<usize>(dst);
16
+
17
+ const src_end = srcEnd - 2;
18
+ const src_end_15 = src_end - 15;
19
+
20
+ while (src_ptr < src_end_15) {
21
+ const block = v128.load(src_ptr);
22
+ v128.store(dst_ptr, block);
23
+
24
+ const backslash_indices = i16x8.eq(block, SPLAT_92);
25
+ let mask = i16x8.bitmask(backslash_indices);
26
+
27
+ while (mask != 0) {
28
+ const lane_index = ctz(mask) << 1;
29
+ const dst_offset = dst_ptr + lane_index;
30
+ const src_offset = src_ptr + lane_index;
31
+ const code = load<u16>(src_offset, 2);
32
+
33
+ mask &= mask - 1;
34
+ if (code == 117 && load<u32>(src_offset, 4) == 3145776) {
35
+ const block = load<u32>(src_offset, 8);
36
+ const codeA = block & 0xffff;
37
+ const codeB = (block >> 16) & 0xffff;
38
+ const escapedA = load<u8>(ESCAPE_HEX_TABLE + codeA);
39
+ const escapedB = load<u8>(ESCAPE_HEX_TABLE + codeB);
40
+ const escaped = (escapedA << 4) + escapedB;
41
+ // console.log("Escaped:");
42
+ // console.log(" a: " + escapedA.toString())
43
+ // console.log(" b: " + escapedB.toString());
44
+ // console.log(" c: " + escaped.toString());
45
+ // console.log(" o: " + (dst_ptr - dst).toString());
46
+ // console.log(" d: " + (dst_offset - dst).toString())
47
+ // console.log(" l: " + (lane_index).toString())
48
+ store<u16>(dst_offset, escaped);
49
+ v128.store(dst_offset, v128.load(src_offset, 4), 2);
50
+ if (lane_index >= 6) {
51
+ const bytes_left = lane_index - 4;
52
+ src_ptr += bytes_left;
53
+ dst_ptr += bytes_left;
54
+ // console.log(" e: " + (bytes_left).toString())
55
+ }
56
+ dst_ptr -= 10;
57
+ } else {
58
+ const escaped = load<u8>(DESERIALIZE_ESCAPE_TABLE + code);
59
+ store<u16>(dst_offset, escaped);
60
+ v128.store(dst_offset, v128.load(src_offset, 4), 2);
61
+ // console.log("Escaped:");
62
+ if (lane_index == 14) {
63
+ src_ptr += 2;
64
+ } else {
65
+ dst_ptr -= 2;
66
+ }
67
+ }
68
+ }
69
+
70
+ src_ptr += 16;
71
+ dst_ptr += 16;
72
+
73
+ // console.log("src: " + (src_ptr - changetype<usize>(src)).toString());
74
+ // console.log("dst: " + (dst_ptr - dst).toString());
75
+ }
76
+ while (src_ptr < src_end) {
77
+ let code = load<u16>(src_ptr);
78
+ if (code == BACK_SLASH) {
79
+ code = load<u16>(DESERIALIZE_ESCAPE_TABLE + load<u8>(src_ptr, 2));
80
+ if (code == 117 && load<u32>(src_ptr, 4) == 3145776) {
81
+ const block = load<u32>(src_ptr, 8);
82
+ const codeA = block & 0xffff;
83
+ const codeB = (block >> 16) & 0xffff;
84
+ const escapedA = load<u8>(ESCAPE_HEX_TABLE + codeA);
85
+ const escapedB = load<u8>(ESCAPE_HEX_TABLE + codeB);
86
+ const escaped = (escapedA << 4) + escapedB;
87
+ store<u16>(dst_ptr, escaped);
88
+ dst_ptr += 2;
89
+ src_ptr += 12;
90
+ } else {
91
+ store<u16>(dst_ptr, code);
92
+ dst_ptr += 2;
93
+ src_ptr += 4;
94
+ }
95
+ } else {
96
+ store<u16>(dst_ptr, code);
97
+ dst_ptr += 2;
98
+ src_ptr += 2;
99
+ }
100
+ }
101
+
102
+ return dst_ptr - dst;
103
+ }
@@ -0,0 +1,17 @@
1
+ import { JSON } from "../..";
2
+ import { deserializeArray } from "./array";
3
+ import { deserializeBoolean } from "./bool";
4
+ import { deserializeFloat } from "./float";
5
+ import { deserializeObject } from "./object";
6
+ import { deserializeString } from "./string";
7
+
8
+ export function deserializeArbitrary(srcStart: usize, srcEnd: usize, dst: usize): JSON.Value {
9
+ const firstChar = load<u16>(srcStart);
10
+ if (firstChar == 34) return JSON.Value.from(deserializeString(srcStart, srcEnd, dst));
11
+ else if (firstChar == 123) return JSON.Value.from(deserializeObject(srcStart, srcEnd, dst));
12
+ else if (firstChar - 48 <= 9 || firstChar == 45) return JSON.Value.from(deserializeFloat<f64>(srcStart, srcEnd));
13
+ else if (firstChar == 91) {
14
+ return JSON.Value.from(deserializeArray<JSON.Value[]>(srcStart, srcEnd, dst));
15
+ } else if (firstChar == 116 || firstChar == 102) return JSON.Value.from(deserializeBoolean(srcStart, srcEnd));
16
+ return unreachable();
17
+ }
@@ -0,0 +1,113 @@
1
+ import { BACK_SLASH, BRACE_LEFT, BRACE_RIGHT, BRACKET_LEFT, BRACKET_RIGHT, CHAR_F, CHAR_N, CHAR_T, COMMA, QUOTE } from "../../../custom/chars";
2
+ import { JSON } from "../../../";
3
+ import { isSpace } from "util/string";
4
+
5
+ export function deserializeArbitraryArray<T extends JSON.Value>(srcStart: usize, srcEnd: usize, dst: usize): JSON.Value[] {
6
+ const out = dst ? changetype<T>(dst) : instantiate<T>();
7
+ let lastIndex: usize = 0;
8
+ let depth: u32 = 0;
9
+ while (srcStart < srcEnd) {
10
+ const code = load<u16>(srcStart);
11
+ if (code == QUOTE) {
12
+ lastIndex = srcStart;
13
+ srcStart += 2;
14
+ while (srcStart < srcEnd) {
15
+ const code = load<u16>(srcStart);
16
+ if (code == QUOTE && load<u16>(srcStart - 2) !== BACK_SLASH) {
17
+ while (isSpace(load<u16>((srcStart += 2)))) {
18
+ /* empty */
19
+ }
20
+ // console.log("Value (string): " + ptrToStr(lastIndex, srcStart));
21
+ // @ts-ignore: exists
22
+ out.push(JSON.__deserialize<valueof<T>>(lastIndex, srcStart));
23
+ break;
24
+ }
25
+ srcStart += 2;
26
+ }
27
+ } else if (code - 48 <= 9 || code == 45) {
28
+ lastIndex = srcStart;
29
+ srcStart += 2;
30
+ while (srcStart < srcEnd) {
31
+ const code = load<u16>(srcStart);
32
+ if (code == COMMA || code == BRACE_RIGHT || isSpace(code)) {
33
+ // @ts-ignore: type
34
+ out.push(JSON.__deserialize<valueof<T>>(lastIndex, srcStart));
35
+ // console.log("Value (number): " + ptrToStr(lastIndex, srcStart));
36
+ while (isSpace(load<u16>((srcStart += 2)))) {
37
+ /* empty */
38
+ }
39
+ break;
40
+ }
41
+ srcStart += 2;
42
+ }
43
+ } else if (code == BRACE_LEFT) {
44
+ lastIndex = srcStart;
45
+ depth++;
46
+ srcStart += 2;
47
+ while (srcStart < srcEnd) {
48
+ const code = load<u16>(srcStart);
49
+ if (code == BRACE_RIGHT) {
50
+ if (--depth == 0) {
51
+ // @ts-ignore: type
52
+ out.push(JSON.__deserialize<valueof<T>>(lastIndex, srcStart));
53
+ // console.log("Value (object): " + ptrToStr(lastIndex, srcStart));
54
+ while (isSpace(load<u16>((srcStart += 2)))) {
55
+ /* empty */
56
+ }
57
+ break;
58
+ }
59
+ } else if (code == BRACE_LEFT) depth++;
60
+ srcStart += 2;
61
+ }
62
+ } else if (code == BRACKET_LEFT) {
63
+ lastIndex = srcStart;
64
+ depth++;
65
+ srcStart += 2;
66
+ while (srcStart < srcEnd) {
67
+ const code = load<u16>(srcStart);
68
+ if (code == BRACKET_RIGHT) {
69
+ if (--depth == 0) {
70
+ // @ts-ignore: type
71
+ out.push(JSON.__deserialize<valueof<T>>(lastIndex, srcStart));
72
+ // console.log("Value (array): " + ptrToStr(lastIndex, srcStart));
73
+ while (isSpace(load<u16>((srcStart += 2)))) {
74
+ /* empty */
75
+ }
76
+ break;
77
+ }
78
+ } else if (code == BRACKET_LEFT) depth++;
79
+ srcStart += 2;
80
+ }
81
+ } else if (code == CHAR_T) {
82
+ if (load<u64>(srcStart) == 28429475166421108) {
83
+ // @ts-ignore: type
84
+ out.push(JSON.__deserialize<valueof<T>>(lastIndex, (srcStart += 8)));
85
+ // console.log("Value (bool): " + ptrToStr(srcStart - 8, srcStart));
86
+ while (isSpace(load<u16>((srcStart += 2)))) {
87
+ /* empty */
88
+ }
89
+ }
90
+ } else if (code == CHAR_F) {
91
+ if (load<u64>(srcStart, 2) == 28429466576093281) {
92
+ // @ts-ignore: type
93
+ out.push(JSON.__deserialize<valueof<T>>(lastIndex, (srcStart += 10)));
94
+ // console.log("Value (bool): " + ptrToStr(srcStart - 10, srcStart));
95
+ while (isSpace(load<u16>((srcStart += 2)))) {
96
+ /* empty */
97
+ }
98
+ }
99
+ } else if (code == CHAR_N) {
100
+ if (load<u64>(srcStart) == 30399761348886638) {
101
+ // @ts-ignore: type
102
+ out.push(JSON.__deserialize<valueof<T>>(lastIndex, (srcStart += 8)));
103
+ // console.log("Value (null): " + ptrToStr(srcStart - 8, srcStart));
104
+ while (isSpace(load<u16>((srcStart += 2)))) {
105
+ /* empty */
106
+ }
107
+ }
108
+ }
109
+ srcStart += 2;
110
+ }
111
+ // @ts-ignore: type
112
+ return out;
113
+ }
@@ -0,0 +1,18 @@
1
+ import { BRACKET_LEFT, BRACKET_RIGHT } from "../../../custom/chars";
2
+ import { JSON } from "../../../";
3
+
4
+ export function deserializeArrayArray<T extends unknown[][]>(srcStart: usize, srcEnd: usize, dst: usize): T {
5
+ const out = dst ? changetype<T>(dst) : instantiate<T>();
6
+ let lastIndex: usize = 0;
7
+ let depth: u32 = 0;
8
+ while (srcStart < srcEnd) {
9
+ const code = load<u16>(srcStart);
10
+ if (code == BRACKET_LEFT && depth++ == 0) {
11
+ lastIndex = srcStart;
12
+ } else if (code == BRACKET_RIGHT && --depth == 0) {
13
+ out.push(JSON.__deserialize<valueof<T>>(lastIndex, srcStart));
14
+ }
15
+ srcStart += 2;
16
+ }
17
+ return out;
18
+ }