///|
/// `n` uniform random bytes: Go's `rand.Read`, Python's `secrets.token_bytes`.
/// Aborts on a negative `n`.
pub fn[S : Source] bytes(n : Int32, source : S) -> Bytes raise Unavailable {
  if n < 0 {
    abort("moonrand.bytes: a negative length, \{n}")
  }
  let buf = FixedArray::make(n, b'\x00')
  source.fill(buf)
  Bytes::from_array(buf[:])
}

///|
/// A uniform number in [0, `bound`), both big-endian and as wide as `bound`,
/// drawn as Go's `crypto/rand.Int` draws it and from the same bytes: as many
/// bytes as `bound - 1` needs, the unused high bits of the first cleared, drawn
/// again while the value is at or above `bound`. No value is likelier than
/// another; reducing a wider draw modulo `bound` would favour the small ones.
/// A `bound` of 1 reads nothing. Aborts when `bound` is zero.
pub fn[S : Source] below(
  bound : BytesView,
  source : S,
) -> Bytes raise Unavailable {
  let width = bound.length()
  let digits = significant(bound)
  if digits.length() == 0 {
    abort("moonrand.below: the bound is zero")
  }
  let top = minus_one(digits)
  let bits = bit_length(top[:])
  let out = FixedArray::make(width, b'\x00')
  if bits == 0 {
    return Bytes::from_array(out[:])
  }
  let k = (bits + 7) / 8
  let mask = (1 << (if bits % 8 == 0 { 8 } else { bits % 8 })) - 1
  let draw = FixedArray::make(k, b'\x00')
  while true {
    source.fill(draw)
    draw[0] = (draw[0].to_int() & mask).to_byte()
    if less(draw, digits) {
      break
    }
  }
  for i in 0.. Bytes raise Unavailable {
  let width = order.length()
  let digits = significant(order)
  if digits.length() == 0 || (digits.length() == 1 && digits[0] < b'\x02') {
    abort("moonrand.scalar: the order is below 2")
  }
  let size = digits.length()
  let excess = size * 8 - bit_length(digits)
  let draw = FixedArray::make(size, b'\x00')
  while true {
    source.fill(draw)
    if excess > 0 {
      shift_right(draw, excess)
    }
    if !draw.iter().all(x => x == b'\x00') && less(draw, digits) {
      break
    }
  }
  let out = FixedArray::make(width, b'\x00')
  for i in 0.. BytesView {
  let mut lead = 0
  while lead < b.length() && b[lead] == b'\x00' {
    lead += 1
  }
  b[lead:]
}

///|
/// `b - 1` for a nonzero big-endian `b`, as wide as `b`.
fn minus_one(b : BytesView) -> Bytes {
  let out = FixedArray::makei(b.length(), i => b[i])
  let mut i = out.length() - 1
  while out[i] == b'\x00' {
    out[i] = b'\xff'
    i -= 1
  }
  out[i] = (out[i].to_int() - 1).to_byte()
  Bytes::from_array(out[:])
}

///|
/// The number of bits a big-endian number needs; 0 for zero.
fn bit_length(b : BytesView) -> Int32 {
  for i in 0.. Bool {
  if b.length() > a.length() {
    return true
  }
  for i in 0.. Unit {
  for i = b.length() - 1; i >= 0; i = i - 1 {
    let mut v = b[i].to_int() >> shift
    if i > 0 {
      v = v | ((b[i - 1].to_int() << (8 - shift)) & 0xFF)
    }
    b[i] = v.to_byte()
  }
}