json-as 0.9.28 → 1.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/.github/workflows/nodejs.yml +0 -3
  2. package/.prettierrc.json +4 -1
  3. package/CHANGELOG +13 -0
  4. package/LICENSE +1 -1
  5. package/README.md +22 -7
  6. package/as-test.config.json +1 -1
  7. package/asconfig.json +2 -2
  8. package/assembly/__benches__/misc.bench.ts +17 -31
  9. package/assembly/__tests__/bool.spec.ts +1 -1
  10. package/assembly/__tests__/simd/string.spec.ts +32 -0
  11. package/assembly/__tests__/types.ts +17 -0
  12. package/assembly/custom/chars.ts +2 -2
  13. package/assembly/custom/memory.ts +25 -0
  14. package/assembly/custom/types.ts +1 -0
  15. package/assembly/custom/util.ts +59 -140
  16. package/assembly/deserialize/simd/string.ts +103 -0
  17. package/assembly/deserialize/simple/arbitrary.ts +17 -0
  18. package/assembly/deserialize/simple/array/arbitrary.ts +113 -0
  19. package/assembly/deserialize/simple/array/array.ts +18 -0
  20. package/assembly/deserialize/simple/array/bool.ts +17 -0
  21. package/assembly/deserialize/simple/array/float.ts +28 -0
  22. package/assembly/deserialize/simple/array/integer.ts +27 -0
  23. package/assembly/deserialize/simple/array/map.ts +18 -0
  24. package/assembly/deserialize/simple/array/object.ts +18 -0
  25. package/assembly/deserialize/simple/array/string.ts +22 -0
  26. package/assembly/deserialize/simple/array.ts +48 -0
  27. package/assembly/deserialize/simple/bool.ts +9 -0
  28. package/assembly/deserialize/simple/date.ts +11 -0
  29. package/assembly/deserialize/simple/float.ts +10 -0
  30. package/assembly/deserialize/simple/integer.ts +5 -0
  31. package/assembly/deserialize/simple/map.ts +154 -0
  32. package/assembly/deserialize/simple/object.ts +159 -0
  33. package/assembly/deserialize/simple/string.ts +48 -0
  34. package/assembly/globals/tables.ts +417 -0
  35. package/assembly/index.d.ts +9 -13
  36. package/assembly/index.ts +282 -158
  37. package/assembly/serialize/simd/string.ts +176 -0
  38. package/assembly/serialize/simple/arbitrary.ts +36 -0
  39. package/assembly/serialize/simple/array.ts +32 -0
  40. package/assembly/serialize/simple/bool.ts +19 -0
  41. package/assembly/serialize/simple/date.ts +13 -0
  42. package/assembly/serialize/simple/float.ts +7 -0
  43. package/assembly/serialize/simple/integer.ts +7 -0
  44. package/assembly/serialize/simple/map.ts +43 -0
  45. package/assembly/serialize/simple/object.ts +7 -0
  46. package/assembly/serialize/simple/string.ts +48 -0
  47. package/assembly/test.ts +43 -28
  48. package/assembly/tsconfig.json +2 -91
  49. package/assembly/types.ts +0 -0
  50. package/assembly/util/atoi.ts +35 -0
  51. package/assembly/util/bytes.ts +12 -0
  52. package/assembly/util/concat.ts +9 -0
  53. package/assembly/util/getArrayDepth.ts +17 -0
  54. package/assembly/util/index.ts +5 -0
  55. package/assembly/util/isSpace.ts +4 -0
  56. package/assembly/util/nextPowerOf2.ts +4 -0
  57. package/assembly/util/ptrToStr.ts +7 -0
  58. package/assembly/util/snp.ts +69 -0
  59. package/bench.js +5 -5
  60. package/modules/bs/index.ts +167 -0
  61. package/modules/tsconfig.json +8 -0
  62. package/package.json +42 -47
  63. package/transform/lib/builder.js +1353 -0
  64. package/transform/lib/builder.js.map +1 -0
  65. package/transform/lib/index.js +497 -395
  66. package/transform/lib/index.js.map +1 -1
  67. package/transform/lib/index.old.js +404 -0
  68. package/transform/lib/index.old.js.map +1 -0
  69. package/transform/lib/linker.js +18 -0
  70. package/transform/lib/linker.js.map +1 -0
  71. package/transform/lib/types.js +25 -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 +529 -446
  76. package/transform/lib/visitor.js.map +1 -0
  77. package/transform/package.json +1 -34
  78. package/transform/src/builder.ts +1371 -0
  79. package/transform/src/index.ts +571 -481
  80. package/transform/src/linker.ts +21 -0
  81. package/transform/src/types.ts +27 -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/custom/bs.ts +0 -211
  87. package/assembly/deserialize/array/array.ts +0 -31
  88. package/assembly/deserialize/array/bool.ts +0 -19
  89. package/assembly/deserialize/array/float.ts +0 -24
  90. package/assembly/deserialize/array/integer.ts +0 -24
  91. package/assembly/deserialize/array/map.ts +0 -27
  92. package/assembly/deserialize/array/object.ts +0 -27
  93. package/assembly/deserialize/array/string.ts +0 -29
  94. package/assembly/deserialize/array.ts +0 -46
  95. package/assembly/deserialize/bool.ts +0 -34
  96. package/assembly/deserialize/date.ts +0 -19
  97. package/assembly/deserialize/float.ts +0 -21
  98. package/assembly/deserialize/integer.ts +0 -16
  99. package/assembly/deserialize/map.ts +0 -189
  100. package/assembly/deserialize/object.ts +0 -271
  101. package/assembly/deserialize/string.ts +0 -164
  102. package/assembly/serialize/array.ts +0 -51
  103. package/assembly/serialize/bool.ts +0 -10
  104. package/assembly/serialize/date.ts +0 -4
  105. package/assembly/serialize/float.ts +0 -4
  106. package/assembly/serialize/integer.ts +0 -5
  107. package/assembly/serialize/map.ts +0 -24
  108. package/assembly/serialize/object.ts +0 -13
  109. package/assembly/serialize/string.ts +0 -287
  110. package/logs/test.log.json +0 -1049
@@ -1,135 +1,60 @@
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 (
25
- instr === true && char === QUOTE
26
- && unsafeCharCodeAt(data, i - 1) !== BACK_SLASH
27
- ) instr = false;
28
-
29
- if (instr === false) {
30
- if (!isSpace(char)) result.write(data.charAt(i));
31
- } else {
32
- result.write(data.charAt(i));
33
- }
34
- }
35
- return result.toString();
36
- }
37
-
38
- // @ts-ignore: Decorator
39
- @inline export function escapeChar(char: string): string {
40
- switch (unsafeCharCodeAt(char, 0)) {
41
- case 0x22:
42
- return '\\"';
43
- case 0x5c:
44
- return "\\\\";
45
- case 0x08:
46
- return "\\b";
47
- case 0x0a:
48
- return "\\n";
49
- case 0x0d:
50
- return "\\r";
51
- case 0x09:
52
- return "\\t";
53
- case 0x0c:
54
- return "\\f";
55
- case 0x0b:
56
- return "\\u000b";
57
- default:
58
- return char;
59
- }
60
- }
61
-
62
- /**
63
- * A terrible function which finds the depth of a certain array.
64
- * Suffers no overhead besides function calling and a if/else.
65
- * @returns depth of array
66
- */
67
-
68
- // @ts-ignore: Decorator
69
- export function getArrayDepth<T extends ArrayLike>(depth: i32 = 1): i32 {
70
- if (!isArray<T>()) {
71
- return 0;
72
- } else if (isArray<valueof<T>>()) {
73
- depth++;
74
- return getArrayDepth<valueof<T>>(depth);
75
- } else {
76
- return depth;
77
- }
78
- }
79
4
 
80
5
  /** Scientific Notation Integer Parsing - SNIP
81
6
  * This is absolutely the fastest algorithm I could think of while adding full support for Scientific Notation
82
7
  * Loads 32 bits and retrieves the high/low bits.
83
8
  * The reason why we only load 4 bytes at a time is that numbers in the 32-bit range are 7 chars long at most.
84
9
  * Using SIMD or 64 bit loads would only work well when parsing large 128+ numbers.
85
- *
10
+ *
86
11
  * Here are some benchmarks
87
- * Parsing: "12345"
12
+ * Parsing: "12345"
88
13
  * Results are spread over 5000ms
89
- *
14
+ *
90
15
  * SNIP: 270M iterations
91
16
  * ATOI: 285M iterations
92
- * ParseInt: 176M iterations
93
- *
17
+ * ParseInt: 176M iterations
18
+ *
94
19
  * @param str - Any number. Can include scientific notation.
95
- */
20
+ */
96
21
  // @ts-ignore: Decorator
97
22
  @inline export function snip_fast<T extends number>(str: string, len: u32 = 0, offset: u32 = 0): T {
98
23
  if (isSigned<T>()) {
99
24
  const firstChar: u32 = load<u16>(changetype<usize>(str));
100
- if (firstChar === 48) return 0 as T;
101
- 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
102
27
  let val: T = 0 as T;
103
28
  if (len == 0) len = u32(str.length << 1);
104
29
  if (isNegative) {
105
30
  offset += 2;
106
31
  if (len >= 4) {
107
32
  // 32-bit route
108
- for (; offset < (len - 3); offset += 4) {
33
+ for (; offset < len - 3; offset += 4) {
109
34
  const ch = load<u32>(changetype<usize>(str) + <usize>offset);
110
- const low = ch & 0xFFFF;
35
+ const low = ch & 0xffff;
111
36
  const high = ch >> 16;
112
37
  // 9 is 57. The highest group of two numbers is 114, so if a e or an E is included, this will fire.
113
38
  if (low > 57) {
114
39
  // The first char (f) is E or e
115
40
  // We push the offset up by two and apply the notation.
116
41
  if (load<u16>(changetype<usize>(str) + <usize>offset + 2) == 45) {
117
- return -(val / (10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1))) as T;
42
+ return -(val / 10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1)) as T;
118
43
  } else {
119
44
  // Inlined this operation instead of using a loop
120
- return -(val * (10 ** (__atoi_fast<u32>(str, offset + 2, offset + 4) + 1))) as T;
45
+ return -(val * 10 ** (__atoi_fast<u32>(str, offset + 2, offset + 4) + 1)) as T;
121
46
  }
122
47
  } else if (high > 57) {
123
48
  // The first char (f) is E or e
124
49
  // We push the offset up by two and apply the notation.
125
50
  if (load<u16>(changetype<usize>(str) + <usize>offset + 4) == 45) {
126
- return -(val / (10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1))) as T;
51
+ return -(val / 10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1)) as T;
127
52
  } else {
128
53
  // Inlined this operation instead of using a loop
129
- return -(val * (10 ** (__atoi_fast<u32>(str, offset + 4, offset + 6) + 1))) as T;
54
+ return -(val * 10 ** (__atoi_fast<u32>(str, offset + 4, offset + 6) + 1)) as T;
130
55
  }
131
56
  } else {
132
- val = (val * 100 + ((low - 48) * 10) + (high - 48)) as T;
57
+ val = (val * 100 + (low - 48) * 10 + (high - 48)) as T;
133
58
  }
134
59
  }
135
60
  }
@@ -141,43 +66,43 @@ export function getArrayDepth<T extends ArrayLike>(depth: i32 = 1): i32 {
141
66
  // The first char (f) is E or e
142
67
  // We push the offset up by two and apply the notation.
143
68
  if (load<u16>(changetype<usize>(str) + <usize>offset + 2) == 45) {
144
- return -(val / (10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1))) as T;
69
+ return -(val / 10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1)) as T;
145
70
  } else {
146
71
  // Inlined this operation instead of using a loop
147
- return -(val * (10 ** (__atoi_fast<u32>(str, offset + 2, offset + 4) + 1))) as T;
72
+ return -(val * 10 ** (__atoi_fast<u32>(str, offset + 2, offset + 4) + 1)) as T;
148
73
  }
149
74
  } else {
150
- val = (val * 10) + (ch - 48) as T;
75
+ val = (val * 10 + (ch - 48)) as T;
151
76
  }
152
77
  }
153
78
  return -val as T;
154
79
  } else {
155
80
  if (len >= 4) {
156
81
  // Duplet 16 bit lane load
157
- for (; offset < (len - 3); offset += 4) {
82
+ for (; offset < len - 3; offset += 4) {
158
83
  const ch = load<u32>(changetype<usize>(str) + <usize>offset);
159
- const low = ch & 0xFFFF;
84
+ const low = ch & 0xffff;
160
85
  const high = ch >> 16;
161
86
  // 9 is 57. The highest group of two numbers is 114, so if a e or an E is included, this will fire.
162
87
  if (low > 57) {
163
88
  // The first char (f) is E or e
164
89
  // We push the offset up by two and apply the notation.
165
90
  if (load<u16>(changetype<usize>(str) + <usize>offset + 2) == 45) {
166
- return (val / (10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1))) as T;
91
+ return (val / 10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1)) as T;
167
92
  } else {
168
93
  // Inlined this operation instead of using a loop
169
- return (val * (10 ** (__atoi_fast<u32>(str, offset + 2, offset + 4) + 1))) as T;
94
+ return (val * 10 ** (__atoi_fast<u32>(str, offset + 2, offset + 4) + 1)) as T;
170
95
  }
171
96
  } else if (high > 57) {
172
97
  if (load<u16>(changetype<usize>(str) + <usize>offset + 4) == 45) {
173
- return (val / (10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1))) as T;
98
+ return (val / 10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1)) as T;
174
99
  } else {
175
100
  // Inlined this operation instead of using a loop
176
- return (val * (10 ** (__atoi_fast<u32>(str, offset + 4, offset + 6) + 1))) as T;
101
+ return (val * 10 ** (__atoi_fast<u32>(str, offset + 4, offset + 6) + 1)) as T;
177
102
  }
178
103
  } else {
179
104
  // Optimized with multiplications and shifts.
180
- val = (val * 100 + ((low - 48) * 10) + (high - 48)) as T;
105
+ val = (val * 100 + (low - 48) * 10 + (high - 48)) as T;
181
106
  }
182
107
  }
183
108
  }
@@ -188,49 +113,49 @@ export function getArrayDepth<T extends ArrayLike>(depth: i32 = 1): i32 {
188
113
  // e is 101 and E is 69.
189
114
  if (ch > 57) {
190
115
  if (load<u16>(changetype<usize>(str) + <usize>offset + 2) == 45) {
191
- val = (val / (10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1))) as T;
116
+ val = (val / 10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1)) as T;
192
117
  } else {
193
118
  // Inlined this operation instead of using a loop
194
- val = (val * (10 ** (__atoi_fast<u32>(str, offset + 2, offset + 4) + 1))) as T;
119
+ val = (val * 10 ** (__atoi_fast<u32>(str, offset + 2, offset + 4) + 1)) as T;
195
120
  }
196
121
  return val as T;
197
122
  } else {
198
- val = (val * 10) + (ch - 48) as T;
123
+ val = (val * 10 + (ch - 48)) as T;
199
124
  }
200
125
  }
201
126
  return val as T;
202
127
  }
203
128
  } else {
204
129
  const firstChar: u32 = load<u16>(changetype<usize>(str));
205
- if (firstChar === 48) return 0 as T;
130
+ if (firstChar == 48) return 0 as T;
206
131
  let val: T = 0 as T;
207
132
  if (len == 0) len = u32(str.length << 1);
208
133
  if (len >= 4) {
209
134
  // Duplet 16 bit lane load
210
- for (; offset < (len - 3); offset += 4) {
135
+ for (; offset < len - 3; offset += 4) {
211
136
  const ch = load<u32>(changetype<usize>(str) + <usize>offset);
212
- const low = ch & 0xFFFF;
137
+ const low = ch & 0xffff;
213
138
  const high = ch >> 16;
214
139
  // 9 is 57. The highest group of two numbers is 114, so if a e or an E is included, this will fire.
215
140
  if (low > 57) {
216
141
  // The first char (f) is E or e
217
142
  // We push the offset up by two and apply the notation.
218
143
  if (load<u16>(changetype<usize>(str) + <usize>offset + 2) == 45) {
219
- return (val / (10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1))) as T;
144
+ return (val / 10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1)) as T;
220
145
  } else {
221
146
  // Inlined this operation instead of using a loop
222
- return (val * (10 ** (__atoi_fast<u32>(str, offset + 2, offset + 4) + 1))) as T;
147
+ return (val * 10 ** (__atoi_fast<u32>(str, offset + 2, offset + 4) + 1)) as T;
223
148
  }
224
149
  } else if (high > 57) {
225
150
  if (load<u16>(changetype<usize>(str) + <usize>offset + 4) == 45) {
226
- return (val / (10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1))) as T;
151
+ return (val / 10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1)) as T;
227
152
  } else {
228
153
  // Inlined this operation instead of using a loop
229
- return (val * (10 ** (__atoi_fast<u32>(str, offset + 4, offset + 6) + 1))) as T;
154
+ return (val * 10 ** (__atoi_fast<u32>(str, offset + 4, offset + 6) + 1)) as T;
230
155
  }
231
156
  } else {
232
157
  // Optimized with multiplications and shifts.
233
- val = (val * 100 + ((low - 48) * 10) + (high - 48)) as T;
158
+ val = (val * 100 + (low - 48) * 10 + (high - 48)) as T;
234
159
  }
235
160
  }
236
161
  }
@@ -241,13 +166,13 @@ export function getArrayDepth<T extends ArrayLike>(depth: i32 = 1): i32 {
241
166
  // e is 101 and E is 69.
242
167
  if (ch > 57) {
243
168
  if (load<u16>(changetype<usize>(str) + <usize>offset + 2) == 45) {
244
- return (val / (10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1))) as T;
169
+ return (val / 10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1)) as T;
245
170
  } else {
246
171
  // Inlined this operation instead of using a loop
247
- return (val * (10 ** (__atoi_fast<u32>(str, offset + 2, offset + 4) + 1))) as T;
172
+ return (val * 10 ** (__atoi_fast<u32>(str, offset + 2, offset + 4) + 1)) as T;
248
173
  }
249
174
  } else {
250
- val = (val * 10) + (ch - 48) as T;
175
+ val = (val * 10 + (ch - 48)) as T;
251
176
  }
252
177
  }
253
178
  return val as T;
@@ -265,21 +190,21 @@ export function getArrayDepth<T extends ArrayLike>(depth: i32 = 1): i32 {
265
190
  if (!end) end = start + u32(str.length << 1);
266
191
  if (isSigned<T>()) {
267
192
  // Negative path
268
- if (load<u16>(changetype<usize>(str) + <usize>start) === 45) {
193
+ if (load<u16>(changetype<usize>(str) + <usize>start) == 45) {
269
194
  start += 2;
270
195
  for (; start < end; start += 2) {
271
- val = (val * 10) + (load<u16>(changetype<usize>(str) + <usize>start) - 48) as T;
196
+ val = (val * 10 + (load<u16>(changetype<usize>(str) + <usize>start) - 48)) as T;
272
197
  }
273
198
  return -val as T;
274
199
  } else {
275
200
  for (; start < end; start += 2) {
276
- val = ((val * 10) + (load<u16>(changetype<usize>(str) + <usize>start) - 48)) as T;
201
+ val = (val * 10 + (load<u16>(changetype<usize>(str) + <usize>start) - 48)) as T;
277
202
  }
278
203
  return val as T;
279
204
  }
280
205
  } else {
281
206
  for (; start < end; start += 2) {
282
- val = ((val * 10) + (load<u16>(changetype<usize>(str) + <usize>start) - 48)) as T;
207
+ val = (val * 10 + (load<u16>(changetype<usize>(str) + <usize>start) - 48)) as T;
283
208
  }
284
209
  return val as T;
285
210
  }
@@ -299,14 +224,14 @@ export function getArrayDepth<T extends ArrayLike>(depth: i32 = 1): i32 {
299
224
  let val: T = 0;
300
225
  let offset = 0;
301
226
  let firstChar = load<u16>(changetype<usize>(str) + <usize>offset);
302
- if (firstChar === 45) {
227
+ if (firstChar == 45) {
303
228
  offset = 2;
304
229
  }
305
230
  for (; offset < str.length << 1; offset += 2) {
306
231
  const char = load<u16>(changetype<usize>(str) + <usize>offset);
307
- if (char === 101 || char === 69) {
232
+ if (char == 101 || char == 69) {
308
233
  const char = load<u16>(changetype<usize>(str) + <usize>(offset += 2));
309
- if (char === 45) {
234
+ if (char == 45) {
310
235
  // @ts-ignore
311
236
  val /= sciNote<T>(__atoi_fast<T>(str, (offset += 2)));
312
237
  // @ts-ignore
@@ -322,7 +247,7 @@ export function getArrayDepth<T extends ArrayLike>(depth: i32 = 1): i32 {
322
247
  val = (val << 1) + (val << 3) + (char - 48);
323
248
  // We use load because in this case, there is no need to have bounds-checking
324
249
  }
325
- if (firstChar === 45) {
250
+ if (firstChar == 45) {
326
251
  val = -val as T;
327
252
  }
328
253
  return val;
@@ -345,17 +270,6 @@ export function getArrayDepth<T extends ArrayLike>(depth: i32 = 1): i32 {
345
270
  return res;
346
271
  }
347
272
 
348
- // @ts-ignore
349
- @inline function equalsSlice(p1_data: string, p1_start: i32, p1_end: i32, p2_data: string, p2_start: i32, p2_end: i32): boolean {
350
- const p1_len = p1_end - p1_start;
351
- const p2_len = p2_end - p2_start;
352
- if (p1_len != p2_len) return false;
353
- if (p1_len == 2) {
354
- return load<u16>(changetype<usize>(p1_data) + p1_start) == load<u16>(changetype<usize>(p2_data) + p2_start)
355
- }
356
- return memory.compare(changetype<usize>(p1_data) + p1_start, changetype<usize>(p2_data) + p2_start, p1_len) === 0;
357
- }
358
-
359
273
  // @ts-ignore
360
274
  @inline export function containsCodePoint(str: string, code: u32, start: i32, end: i32): bool {
361
275
  for (let i = start; i <= end; i++) {
@@ -378,18 +292,23 @@ export function getArrayDepth<T extends ArrayLike>(depth: i32 = 1): i32 {
378
292
  // @ts-ignore: Decorator
379
293
  @inline export function intTo16(int: i32): i32 {
380
294
  const high = int >> 4;
381
- const low = int & 0x0F;
295
+ const low = int & 0x0f;
382
296
  if (low < 10) {
383
297
  if (high < 10) {
384
- return ((48 + low) << 16) | 48 + high;
298
+ return ((48 + low) << 16) | (48 + high);
385
299
  } else {
386
- return ((48 + low) << 16) | 87 + high;
300
+ return ((48 + low) << 16) | (87 + high);
387
301
  }
388
302
  } else {
389
303
  if (high < 10) {
390
- return ((87 + low) << 16) | 48 + high;
304
+ return ((87 + low) << 16) | (48 + high);
391
305
  } else {
392
- return ((87 + low) << 16) | 87 + high;
306
+ return ((87 + low) << 16) | (87 + high);
393
307
  }
394
308
  }
395
- }
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
+ }
@@ -0,0 +1,17 @@
1
+ import { CHAR_E, CHAR_F, CHAR_T } from "../../../custom/chars";
2
+
3
+ export function deserializeBooleanArray<T extends boolean[]>(srcStart: usize, srcEnd: usize, dst: usize): T {
4
+ const out = dst ? changetype<T>(dst) : instantiate<T>();
5
+ while (srcStart < srcEnd) {
6
+ const code = load<u16>(srcStart);
7
+ if (code == CHAR_T && load<u16>(srcStart, 8) == CHAR_E) {
8
+ out.push(true);
9
+ srcStart += 10;
10
+ } else if (code == CHAR_F && load<u16>(srcStart, 10) == CHAR_E) {
11
+ out.push(false);
12
+ srcStart += 12;
13
+ }
14
+ srcStart += 2;
15
+ }
16
+ return out;
17
+ }