@amritk/nish-aarch64-darwin 0.34.0 → 0.35.0

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.
package/std/bytes.ts CHANGED
@@ -26,7 +26,10 @@
26
26
  * inside a call, and after `getU32LE` inlines, LLVM keeps the checks on
27
27
  * `off + 1` to `off + 3`, because the guard compares the length truncated to
28
28
  * `i32` and the checks compare it unsigned at 64 bits. A loop that needs them
29
- * gone indexes the bytes itself.
29
+ * gone indexes the bytes itself. `getU64BE`, and with it `getI64BE` and
30
+ * `getF64BE`, is the exception: it checks the whole range once and reads the
31
+ * eight bytes unchecked, which lowers to one load and a byte swap. An offset
32
+ * outside the range still goes byte by byte, so it panics as the others do.
30
33
  *
31
34
  * The in-range answers are byte for byte those of the copies `std/` keeps for
32
35
  * itself: `sha256LoadWord` (`std/crypto/sha256.ts`) for `getU32BE`,
@@ -91,8 +94,8 @@ export const getU64LE = (b: u8[], off: i32): u64 => {
91
94
  return v
92
95
  }
93
96
 
94
- /** The `u64` whose bytes, most significant first, are `b[off]` to `b[off + 7]`. */
95
- export const getU64BE = (b: u8[], off: i32): u64 => {
97
+ /** `getU64BE` a byte at a time, each index checked: the path for an offset whose eight bytes are not all in the array. */
98
+ const getU64BEByByte = (b: u8[], off: i32): u64 => {
96
99
  let v = toU64(0)
97
100
  for (let i: i32 = 0; i < 8; i++) {
98
101
  v = (v << toU64(8)) | toU64(b[off + i])
@@ -100,6 +103,26 @@ export const getU64BE = (b: u8[], off: i32): u64 => {
100
103
  return v
101
104
  }
102
105
 
106
+ /**
107
+ * The `u64` whose bytes, most significant first, are `b[off]` to `b[off + 7]`.
108
+ * The fast path's ors are grouped in pairs, which LLVM folds into one load and
109
+ * a `bswap`; a flat chain of eight `or`s stayed byte by byte. The byte loop is
110
+ * its own function so its last load is not merged with the fast path's.
111
+ */
112
+ export const getU64BE = (b: u8[], off: i32): u64 => {
113
+ if (off >= 0 && off < 2147483640 && off + 8 <= toI32(b.length)) {
114
+ return (
115
+ (toU64(b[off]) << toU64(56)) |
116
+ (toU64(b[off + 1]) << toU64(48)) |
117
+ ((toU64(b[off + 2]) << toU64(40)) | (toU64(b[off + 3]) << toU64(32))) |
118
+ ((toU64(b[off + 4]) << toU64(24)) |
119
+ (toU64(b[off + 5]) << toU64(16)) |
120
+ ((toU64(b[off + 6]) << toU64(8)) | toU64(b[off + 7])))
121
+ )
122
+ }
123
+ return getU64BEByByte(b, off)
124
+ }
125
+
103
126
  /** `getU32LE`'s bits as a two's-complement `i32`. */
104
127
  export const getI32LE = (b: u8[], off: i32): i32 => toI32(getU32LE(b, off))
105
128
 
@@ -278,7 +301,7 @@ export const skipJsonPlain = (b: u8[], from: i32, to: i32): i32 => {
278
301
  * panics `copyBytes` before any byte is written. Natively the copy is one
279
302
  * `llvm.memmove`.
280
303
  */
281
- export const copyBytes = (dst: u8[], at: i32, src: u8[], from: i32, count: i32): void => {
304
+ export const copyBytes = (dst: u8[], at: i32, src: readonly u8[], from: i32, count: i32): void => {
282
305
  if (count < 0 || at < 0 || from < 0 || at > toI32(dst.length) - count || from > toI32(src.length) - count) {
283
306
  panic("copyBytes: the range lies outside an array")
284
307
  }
@@ -402,7 +425,7 @@ const skipJsonPlainWalk = (b: u8[], from: i32, to: i32): i32 => {
402
425
  }
403
426
 
404
427
  /** `copyBytes`'s walk, once its ranges are checked: forward, or backward when `dst` is `src` and the bytes move up. */
405
- const copyBytesWalk = (dst: u8[], at: i32, src: u8[], from: i32, count: i32): void => {
428
+ const copyBytesWalk = (dst: u8[], at: i32, src: readonly u8[], from: i32, count: i32): void => {
406
429
  if (at <= from) {
407
430
  let k: i32 = 0
408
431
  while (k < count) {
@@ -127,8 +127,9 @@ export const base64urlEncode = (data: u8[]): string => {
127
127
  * one canonical spelling of any byte string — see the module comment for the
128
128
  * five refusals.
129
129
  *
130
- * The same accumulator as `base64urlEncode`, run the other way: six bits in per
131
- * character, eight out per byte.
130
+ * Each group of four characters becomes one 24-bit word, six bits a
131
+ * character, which splits into three bytes; a short final group of two or
132
+ * three characters fills the top of the word and gives one or two.
132
133
  */
133
134
  export const base64urlDecode = (text: string): u8[] | null => {
134
135
  // A text past 2^31 - 1 bytes is refused before `toI32`, which would
@@ -148,31 +149,51 @@ export const base64urlDecode = (text: string): u8[] | null => {
148
149
  // short final group; `n * 3 / 4` would overflow for a text over 700 MB.
149
150
  const out: u8[] = new Array<u8>((n >> 2) * 3 + (tail === 0 ? 0 : tail - 1))
150
151
  const outLen: i32 = toI32(out.length)
151
- // All ones once any character is outside the alphabet (its sextet of `-1`
152
+ // All ones once any character is outside the alphabet (a sextet of `-1`
152
153
  // shifted right by 31), and non-zero once the text ends on a bit that
153
154
  // encodes no byte.
154
155
  let bad: i32 = 0
155
- let acc: i32 = 0
156
- let bits: i32 = 0
156
+ // Four characters make one 24-bit word and three bytes, so a full group has
157
+ // no count of waiting bits to test, and its four sextets are independent.
157
158
  let j: i32 = 0
158
- for (let k: i32 = 0; k < n; k++) {
159
- const v: i32 = base64urlSextetOf(toI32(text.charCodeAt(k)))
160
- bad = bad | (v >> 31)
161
- acc = ((acc << 6) | (v & 63)) & 0xfff
162
- bits += 6
163
- if (bits >= 8) {
164
- bits -= 8
165
- // Always true — `out` was sized from the same length — but written out
166
- // so that the store keeps no bounds check.
167
- if (j >= 0 && j < outLen) {
168
- out[j] = toU8((acc >> bits) & 255)
169
- }
170
- j++
159
+ for (let k: i32 = 0; k + 3 < n; k += 4) {
160
+ const s0: i32 = base64urlSextetOf(toI32(text.charCodeAt(k)))
161
+ const s1: i32 = base64urlSextetOf(toI32(text.charCodeAt(k + 1)))
162
+ const s2: i32 = base64urlSextetOf(toI32(text.charCodeAt(k + 2)))
163
+ const s3: i32 = base64urlSextetOf(toI32(text.charCodeAt(k + 3)))
164
+ bad = bad | ((s0 | s1 | s2 | s3) >> 31)
165
+ const word: i32 = ((s0 & 63) << 18) | ((s1 & 63) << 12) | ((s2 & 63) << 6) | (s3 & 63)
166
+ // Always true — `out` was sized from the same length — but written out so
167
+ // that the three stores keep no bounds check.
168
+ if (j >= 0 && j + 2 < outLen) {
169
+ out[j] = toU8(word >> 16)
170
+ out[j + 1] = toU8((word >> 8) & 255)
171
+ out[j + 2] = toU8(word & 255)
171
172
  }
173
+ j += 3
174
+ }
175
+ // A short final group of two or three characters: one or two bytes, and the
176
+ // four or two bits left over belong to no byte, so they must be zero for `AA`
177
+ // to be the only spelling of a zero byte and `AB` refused (RFC 4648 §3.5).
178
+ if (tail !== 0) {
179
+ const k: i32 = n - tail
180
+ const s0: i32 = base64urlSextetOf(toI32(text.charCodeAt(k)))
181
+ const s1: i32 = base64urlSextetOf(toI32(text.charCodeAt(k + 1)))
182
+ // A third character only when the tail has one; a two-character tail reads
183
+ // its place as `A`, the zero sextet, which adds no bits.
184
+ const s2: i32 = tail === 3 ? base64urlSextetOf(toI32(text.charCodeAt(k + 2))) : 0
185
+ bad = bad | ((s0 | s1 | s2) >> 31)
186
+ const word: i32 = ((s0 & 63) << 18) | ((s1 & 63) << 12) | ((s2 & 63) << 6)
187
+ if (j >= 0 && j < outLen) {
188
+ out[j] = toU8(word >> 16)
189
+ }
190
+ if (tail === 3 && j + 1 >= 0 && j + 1 < outLen) {
191
+ out[j + 1] = toU8((word >> 8) & 255)
192
+ }
193
+ // The bits under the last byte written: sixteen of the word when one byte
194
+ // was, eight when two were.
195
+ bad = bad | (word & (tail === 2 ? 0xffff : 0xff))
172
196
  }
173
- // The two or four bits left over belong to no byte, and must be zero so that
174
- // `AA` is the only spelling of a zero byte and `AB` is refused (RFC 4648 §3.5).
175
- bad = bad | (acc & ((1 << bits) - 1))
176
197
  if (bad !== 0) {
177
198
  return null
178
199
  }