///|
async fn random_seed(source : String?) -> Bytes {
  guard source is Some(path) else {
    return match @env.rand(16) {
      Some(seed) => seed
      None => raise CliError("sort: secure random source is unavailable")
    }
  }
  let file = @fs.open(path, mode=ReadOnly) catch {
    @os_error.OSError(_) as error => {
      let name = if path == "" { "''" } else { path }
      raise CliError("sort: open failed: \{name}: \{os_message(error)}")
    }
    error => raise error
  }
  defer file.close()
  read_random_seed(file, path)
}

///|
async fn read_random_seed(reader : &@io.Reader, path : String) -> Bytes {
  let seed = FixedArray::make(16, b'\x00')
  let mut used = 0
  while used < 16 {
    let count = reader.read(seed, offset=used, max_len=16 - used) catch {
      @os_error.OSError(_) as error =>
        raise CliError("sort: '\{path}': \{os_message(error)}")
      error => raise error
    }
    if count == 0 {
      raise CliError("sort: '\{path}': end of file")
    }
    used += count
  }
  seed.unsafe_reinterpret_as_bytes()
}

///|
fn os_message(error : @os_error.OSError) -> String {
  if error.is_ENOENT() {
    "No such file or directory"
  } else if error.is_EACCES() {
    "Permission denied"
  } else if error.is_ENOTDIR() {
    "Not a directory"
  } else if error.is_EEXIST() {
    "File exists"
  } else {
    error.to_string()
  }
}

///|
fn random_key(seed : Bytes, key : Bytes) -> Bytes {
  let state = @crypto.MD5::new()
  state.update(seed)
  state.update(key)
  Bytes::from_array(state.finalize())
}

///|
fn prepared_key(key : Bytes, modifiers : Modifiers, seed : Bytes) -> Bytes {
  let effective = transformed_key(key, modifiers)
  if modifiers.mode != Random {
    return effective
  }
  let digest = random_key(seed, effective)
  let encoded = FixedArray::make(16 + effective.length(), b'\x00')
  for index in 0..<16 {
    encoded[index] = digest[index]
  }
  for index in 0..