json-as 1.3.5 → 1.3.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/CHANGELOG.md +17 -1
  2. package/assembly/deserialize/helpers/uint.ts +4 -1
  3. package/assembly/deserialize/index/arbitrary.ts +5 -1
  4. package/assembly/deserialize/index/array.ts +13 -3
  5. package/assembly/deserialize/index/integer.ts +68 -1
  6. package/assembly/deserialize/index/string.ts +4 -1
  7. package/assembly/deserialize/index/typedarray.ts +13 -3
  8. package/assembly/deserialize/index/unsigned.ts +78 -1
  9. package/assembly/deserialize/simd/array/integer.ts +327 -50
  10. package/assembly/deserialize/simd/integer.ts +233 -0
  11. package/assembly/deserialize/simd/string.ts +45 -11
  12. package/assembly/deserialize/simple/arbitrary.ts +11 -4
  13. package/assembly/deserialize/simple/array/arbitrary.ts +24 -5
  14. package/assembly/deserialize/simple/array/array.ts +8 -2
  15. package/assembly/deserialize/simple/array/bool.ts +38 -7
  16. package/assembly/deserialize/simple/array/box.ts +8 -2
  17. package/assembly/deserialize/simple/array/float.ts +36 -9
  18. package/assembly/deserialize/simple/array/generic.ts +12 -4
  19. package/assembly/deserialize/simple/array/integer.ts +8 -2
  20. package/assembly/deserialize/simple/array/map.ts +26 -6
  21. package/assembly/deserialize/simple/array/object.ts +26 -6
  22. package/assembly/deserialize/simple/array/raw.ts +34 -7
  23. package/assembly/deserialize/simple/array/string.ts +8 -2
  24. package/assembly/deserialize/simple/array/struct.ts +26 -6
  25. package/assembly/deserialize/simple/array.ts +13 -3
  26. package/assembly/deserialize/simple/bool.ts +6 -2
  27. package/assembly/deserialize/simple/float.ts +6 -1
  28. package/assembly/deserialize/simple/integer.ts +10 -2
  29. package/assembly/deserialize/simple/map.ts +95 -22
  30. package/assembly/deserialize/simple/object.ts +63 -14
  31. package/assembly/deserialize/simple/raw.ts +4 -1
  32. package/assembly/deserialize/simple/set.ts +59 -14
  33. package/assembly/deserialize/simple/staticarray/string.ts +11 -3
  34. package/assembly/deserialize/simple/staticarray.ts +64 -14
  35. package/assembly/deserialize/simple/string.ts +5 -92
  36. package/assembly/deserialize/simple/struct.ts +5 -1
  37. package/assembly/deserialize/simple/typedarray.ts +16 -3
  38. package/assembly/deserialize/simple/unsigned.ts +10 -15
  39. package/assembly/deserialize/swar/array/arbitrary.ts +5 -1
  40. package/assembly/deserialize/swar/array/array.ts +30 -6
  41. package/assembly/deserialize/swar/array/bool.ts +22 -4
  42. package/assembly/deserialize/swar/array/box.ts +5 -1
  43. package/assembly/deserialize/swar/array/float.ts +15 -3
  44. package/assembly/deserialize/swar/array/generic.ts +24 -7
  45. package/assembly/deserialize/swar/array/integer.ts +328 -84
  46. package/assembly/deserialize/swar/array/map.ts +5 -1
  47. package/assembly/deserialize/swar/array/object.ts +27 -7
  48. package/assembly/deserialize/swar/array/raw.ts +5 -1
  49. package/assembly/deserialize/swar/array/shared.ts +36 -11
  50. package/assembly/deserialize/swar/array/string.ts +20 -4
  51. package/assembly/deserialize/swar/array/struct.ts +27 -7
  52. package/assembly/deserialize/swar/array.ts +19 -4
  53. package/assembly/deserialize/swar/integer.ts +246 -0
  54. package/assembly/deserialize/swar/string.ts +98 -194
  55. package/assembly/index.d.ts +3 -1
  56. package/assembly/index.ts +312 -81
  57. package/assembly/serialize/index/float.ts +5 -1
  58. package/assembly/serialize/index/typedarray.ts +25 -7
  59. package/assembly/serialize/simd/string.ts +6 -2
  60. package/assembly/serialize/simple/array.ts +179 -1
  61. package/assembly/serialize/simple/float.ts +4 -1
  62. package/assembly/serialize/simple/integer.ts +9 -9
  63. package/assembly/serialize/simple/map.ts +6 -2
  64. package/assembly/serialize/simple/raw.ts +5 -1
  65. package/assembly/serialize/simple/set.ts +6 -1
  66. package/assembly/serialize/simple/staticarray.ts +6 -1
  67. package/assembly/serialize/simple/string.ts +0 -1
  68. package/assembly/serialize/simple/typedarray.ts +10 -3
  69. package/assembly/serialize/swar/string.ts +25 -8
  70. package/assembly/tsconfig.json +1 -21
  71. package/assembly/util/atoi-fast.ts +81 -0
  72. package/assembly/util/concat.ts +5 -1
  73. package/assembly/util/dragonbox-cache.ts +443 -2
  74. package/assembly/util/dragonbox.ts +43 -14
  75. package/assembly/util/itoa-fast.ts +230 -0
  76. package/assembly/util/masks.ts +18 -1
  77. package/assembly/util/parsefloat-fast.ts +167 -0
  78. package/assembly/util/simd-int.ts +191 -0
  79. package/assembly/util/snp.ts +4 -1
  80. package/assembly/util/swar-int.ts +248 -0
  81. package/assembly/util/swar.ts +13 -3
  82. package/lib/as-bs.ts +13 -5
  83. package/package.json +12 -4
  84. package/transform/lib/builder.d.ts.map +1 -1
  85. package/transform/lib/builder.js +13 -5
  86. package/transform/lib/builder.js.map +1 -1
  87. package/transform/lib/index.d.ts +1 -0
  88. package/transform/lib/index.d.ts.map +1 -1
  89. package/transform/lib/index.js +1030 -241
  90. package/transform/lib/index.js.map +1 -1
  91. package/transform/lib/linkers/alias.d.ts.map +1 -1
  92. package/transform/lib/linkers/alias.js.map +1 -1
  93. package/transform/lib/linkers/custom.d.ts.map +1 -1
  94. package/transform/lib/linkers/custom.js +3 -2
  95. package/transform/lib/linkers/custom.js.map +1 -1
  96. package/transform/lib/linkers/imports.d.ts.map +1 -1
  97. package/transform/lib/linkers/imports.js.map +1 -1
  98. package/transform/lib/types.d.ts.map +1 -1
  99. package/transform/lib/types.js +54 -16
  100. package/transform/lib/types.js.map +1 -1
  101. package/transform/lib/util.d.ts.map +1 -1
  102. package/transform/lib/util.js +1 -1
  103. package/transform/lib/util.js.map +1 -1
  104. package/transform/lib/visitor.d.ts.map +1 -1
  105. package/transform/lib/visitor.js +2 -1
  106. package/transform/lib/visitor.js.map +1 -1
  107. package/assembly/custom/util.ts +0 -310
@@ -1,310 +0,0 @@
1
- /** Scientific Notation Integer Parsing - SNIP
2
- * This is absolutely the fastest algorithm I could think of while adding full support for Scientific Notation
3
- * Loads 32 bits and retrieves the high/low bits.
4
- * 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.
5
- * Using SIMD or 64 bit loads would only work well when parsing large 128+ numbers.
6
- *
7
- * Here are some benchmarks
8
- * Parsing: "12345"
9
- * Results are spread over 5000ms
10
- *
11
- * SNIP: 270M iterations
12
- * ATOI: 285M iterations
13
- * ParseInt: 176M iterations
14
- *
15
- * @param str - Any number. Can include scientific notation.
16
- */
17
- // @ts-ignore: Decorator
18
- @inline export function snip_fast<T extends number>(str: string, len: u32 = 0, offset: u32 = 0): T {
19
- if (isSigned<T>()) {
20
- const firstChar: u32 = load<u16>(changetype<usize>(str));
21
- if (firstChar == 48) return 0 as T;
22
- const isNegative = firstChar == 45; // Check if the number is negative
23
- let val: T = 0 as T;
24
- if (len == 0) len = u32(str.length << 1);
25
- if (isNegative) {
26
- offset += 2;
27
- if (len >= 4) {
28
- // 32-bit route
29
- for (; offset < len - 3; offset += 4) {
30
- const ch = load<u32>(changetype<usize>(str) + <usize>offset);
31
- const low = ch & 0xffff;
32
- const high = ch >> 16;
33
- // 9 is 57. The highest group of two numbers is 114, so if a e or an E is included, this will fire.
34
- if (low > 57) {
35
- // The first char (f) is E or e
36
- // We push the offset up by two and apply the notation.
37
- if (load<u16>(changetype<usize>(str) + <usize>offset + 2) == 45) {
38
- return -(val / 10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1)) as T;
39
- } else {
40
- // Inlined this operation instead of using a loop
41
- return -(val * 10 ** (__atoi_fast<u32>(str, offset + 2, offset + 4) + 1)) as T;
42
- }
43
- } else if (high > 57) {
44
- // The first char (f) is E or e
45
- // We push the offset up by two and apply the notation.
46
- if (load<u16>(changetype<usize>(str) + <usize>offset + 4) == 45) {
47
- return -(val / 10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1)) as T;
48
- } else {
49
- // Inlined this operation instead of using a loop
50
- return -(val * 10 ** (__atoi_fast<u32>(str, offset + 4, offset + 6) + 1)) as T;
51
- }
52
- } else {
53
- val = (val * 100 + (low - 48) * 10 + (high - 48)) as T;
54
- }
55
- }
56
- }
57
- // Finish up the remainder with 16 bits.
58
- for (; offset < len; offset += 2) {
59
- const ch = load<u16>(changetype<usize>(str) + <usize>offset);
60
- // 9 is 57. E and e are larger. Assumes valid JSON.
61
- if (ch > 57) {
62
- // The first char (f) is E or e
63
- // We push the offset up by two and apply the notation.
64
- if (load<u16>(changetype<usize>(str) + <usize>offset + 2) == 45) {
65
- return -(val / 10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1)) as T;
66
- } else {
67
- // Inlined this operation instead of using a loop
68
- return -(val * 10 ** (__atoi_fast<u32>(str, offset + 2, offset + 4) + 1)) as T;
69
- }
70
- } else {
71
- val = (val * 10 + (ch - 48)) as T;
72
- }
73
- }
74
- return -val as T;
75
- } else {
76
- if (len >= 4) {
77
- // Duplet 16 bit lane load
78
- for (; offset < len - 3; offset += 4) {
79
- const ch = load<u32>(changetype<usize>(str) + <usize>offset);
80
- const low = ch & 0xffff;
81
- const high = ch >> 16;
82
- // 9 is 57. The highest group of two numbers is 114, so if a e or an E is included, this will fire.
83
- if (low > 57) {
84
- // The first char (f) is E or e
85
- // We push the offset up by two and apply the notation.
86
- if (load<u16>(changetype<usize>(str) + <usize>offset + 2) == 45) {
87
- return (val / 10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1)) as T;
88
- } else {
89
- // Inlined this operation instead of using a loop
90
- return (val * 10 ** (__atoi_fast<u32>(str, offset + 2, offset + 4) + 1)) as T;
91
- }
92
- } else if (high > 57) {
93
- if (load<u16>(changetype<usize>(str) + <usize>offset + 4) == 45) {
94
- return (val / 10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1)) as T;
95
- } else {
96
- // Inlined this operation instead of using a loop
97
- return (val * 10 ** (__atoi_fast<u32>(str, offset + 4, offset + 6) + 1)) as T;
98
- }
99
- } else {
100
- // Optimized with multiplications and shifts.
101
- val = (val * 100 + (low - 48) * 10 + (high - 48)) as T;
102
- }
103
- }
104
- }
105
- // Cover the remaining numbers with 16 bit loads.
106
- for (; offset < len; offset += 2) {
107
- const ch = load<u16>(changetype<usize>(str) + <usize>offset);
108
- // 0's char is 48 and 9 is 57. Anything above this range would signify an exponent (e or E).
109
- // e is 101 and E is 69.
110
- if (ch > 57) {
111
- if (load<u16>(changetype<usize>(str) + <usize>offset + 2) == 45) {
112
- val = (val / 10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1)) as T;
113
- } else {
114
- // Inlined this operation instead of using a loop
115
- val = (val * 10 ** (__atoi_fast<u32>(str, offset + 2, offset + 4) + 1)) as T;
116
- }
117
- return val as T;
118
- } else {
119
- val = (val * 10 + (ch - 48)) as T;
120
- }
121
- }
122
- return val as T;
123
- }
124
- } else {
125
- const firstChar: u32 = load<u16>(changetype<usize>(str));
126
- if (firstChar == 48) return 0 as T;
127
- let val: T = 0 as T;
128
- if (len == 0) len = u32(str.length << 1);
129
- if (len >= 4) {
130
- // Duplet 16 bit lane load
131
- for (; offset < len - 3; offset += 4) {
132
- const ch = load<u32>(changetype<usize>(str) + <usize>offset);
133
- const low = ch & 0xffff;
134
- const high = ch >> 16;
135
- // 9 is 57. The highest group of two numbers is 114, so if a e or an E is included, this will fire.
136
- if (low > 57) {
137
- // The first char (f) is E or e
138
- // We push the offset up by two and apply the notation.
139
- if (load<u16>(changetype<usize>(str) + <usize>offset + 2) == 45) {
140
- return (val / 10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1)) as T;
141
- } else {
142
- // Inlined this operation instead of using a loop
143
- return (val * 10 ** (__atoi_fast<u32>(str, offset + 2, offset + 4) + 1)) as T;
144
- }
145
- } else if (high > 57) {
146
- if (load<u16>(changetype<usize>(str) + <usize>offset + 4) == 45) {
147
- return (val / 10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1)) as T;
148
- } else {
149
- // Inlined this operation instead of using a loop
150
- return (val * 10 ** (__atoi_fast<u32>(str, offset + 4, offset + 6) + 1)) as T;
151
- }
152
- } else {
153
- // Optimized with multiplications and shifts.
154
- val = (val * 100 + (low - 48) * 10 + (high - 48)) as T;
155
- }
156
- }
157
- }
158
- // Cover the remaining numbers with 16 bit loads.
159
- for (; offset < len; offset += 2) {
160
- const ch = load<u16>(changetype<usize>(str) + <usize>offset);
161
- // 0's char is 48 and 9 is 57. Anything above this range would signify an exponent (e or E).
162
- // e is 101 and E is 69.
163
- if (ch > 57) {
164
- if (load<u16>(changetype<usize>(str) + <usize>offset + 2) == 45) {
165
- return (val / 10 ** (__atoi_fast<u32>(str, offset + 6, offset + 8) - 1)) as T;
166
- } else {
167
- // Inlined this operation instead of using a loop
168
- return (val * 10 ** (__atoi_fast<u32>(str, offset + 2, offset + 4) + 1)) as T;
169
- }
170
- } else {
171
- val = (val * 10 + (ch - 48)) as T;
172
- }
173
- }
174
- return val as T;
175
- }
176
- }
177
-
178
- /**
179
- * Implementation of ATOI. Can be much much faster with SIMD.
180
- */
181
-
182
- // @ts-ignore
183
- @inline export function __atoi_fast<T extends number>(str: string, start: u32 = 0, end: u32 = 0): T {
184
- // @ts-ignore
185
- let val: T = 0;
186
- if (!end) end = start + u32(str.length << 1);
187
- if (isSigned<T>()) {
188
- // Negative path
189
- if (load<u16>(changetype<usize>(str) + <usize>start) == 45) {
190
- start += 2;
191
- for (; start < end; start += 2) {
192
- val = (val * 10 + (load<u16>(changetype<usize>(str) + <usize>start) - 48)) as T;
193
- }
194
- return -val as T;
195
- } else {
196
- for (; start < end; start += 2) {
197
- val = (val * 10 + (load<u16>(changetype<usize>(str) + <usize>start) - 48)) as T;
198
- }
199
- return val as T;
200
- }
201
- } else {
202
- for (; start < end; start += 2) {
203
- val = (val * 10 + (load<u16>(changetype<usize>(str) + <usize>start) - 48)) as T;
204
- }
205
- return val as T;
206
- }
207
- }
208
-
209
- /**
210
- * Parses an integer using __atoi_fast and applies the appended exponential number to it as scientific notation.
211
- * Benchmark: Hovers around 30m ops/s
212
- * Only safe if the string is valid.
213
- * @param str integer to parse. example: 123e1, 123e-1, 123E100
214
- * @returns
215
- */
216
-
217
- // @ts-ignore
218
- @inline export function parseSciInteger<T extends number>(str: string): T {
219
- // @ts-ignore
220
- let val: T = 0;
221
- let offset = 0;
222
- let firstChar = load<u16>(changetype<usize>(str) + <usize>offset);
223
- if (firstChar == 45) {
224
- offset = 2;
225
- }
226
- for (; offset < str.length << 1; offset += 2) {
227
- const char = load<u16>(changetype<usize>(str) + <usize>offset);
228
- if (char == 101 || char == 69) {
229
- const char = load<u16>(changetype<usize>(str) + <usize>(offset += 2));
230
- if (char == 45) {
231
- // @ts-ignore
232
- val /= sciNote<T>(__atoi_fast<T>(str, (offset += 2)));
233
- // @ts-ignore
234
- return val;
235
- } else {
236
- // @ts-ignore
237
- val *= sciNote<T>(__atoi_fast<T>(str, offset));
238
- // @ts-ignore
239
- return val;
240
- }
241
- }
242
- // @ts-ignore
243
- val = (val << 1) + (val << 3) + (char - 48);
244
- // We use load because in this case, there is no need to have bounds-checking
245
- }
246
- if (firstChar == 45) {
247
- val = -val as T;
248
- }
249
- return val;
250
- }
251
-
252
- // @ts-ignore
253
- @inline function sciNote<T extends number>(num: T): T {
254
- let res = 1;
255
- // @ts-ignore
256
- if (num > 0) {
257
- for (let i: T = <T>0; i < num; i++) {
258
- res *= 10;
259
- }
260
- } else {
261
- for (let i: T = <T>0; i < num; i++) {
262
- res /= 10;
263
- }
264
- }
265
- // @ts-ignore
266
- return res;
267
- }
268
-
269
- // @ts-ignore
270
- @inline export function containsCodePoint(str: string, code: u32, start: i32, end: i32): bool {
271
- for (let i = start; i <= end; i++) {
272
- if (unsafeCharCodeAt(str, i) == code) return true;
273
- }
274
- return false;
275
- }
276
-
277
- // @ts-ignore: Decorator
278
- @inline export function _intTo16(int: i32): i32 {
279
- if (int < 10) {
280
- // 0-10
281
- return 48 + int;
282
- } else {
283
- // a-f
284
- return 87 + int;
285
- }
286
- }
287
-
288
- // @ts-ignore: Decorator
289
- @inline export function intTo16(int: i32): i32 {
290
- const high = int >> 4;
291
- const low = int & 0x0f;
292
- if (low < 10) {
293
- if (high < 10) {
294
- return ((48 + low) << 16) | (48 + high);
295
- } else {
296
- return ((48 + low) << 16) | (87 + high);
297
- }
298
- } else {
299
- if (high < 10) {
300
- return ((87 + low) << 16) | (48 + high);
301
- } else {
302
- return ((87 + low) << 16) | (87 + high);
303
- }
304
- }
305
- }
306
-
307
- // @ts-ignore: Decorator valid here
308
- @inline export function nextPowerOf2(n: u32): u32 {
309
- return 1 << (32 - clz(n - 1));
310
- }