///|
impl Read with fn read_u8(self) {
  self.read_exact(1)[0]
}

///|
fn[R : Read] read_fixed(
  reader : R,
  width : Int32,
  big_endian : Bool,
) -> UInt64 raise DecodeError {
  let bytes = reader.read_exact(width)
  let mut value = 0UL
  for i in 0..= 128 {
    for shift = 6; shift < 70; shift = shift + 7 {
      let byte = self.read_u8().to_int()
      guard shift < 62 || byte <= 3 else {
        raise InvalidData("signed integer overflow")
      }
      bits = bits | ((byte & 127).to_uint64() << shift)
      if byte < 128 {
        break
      }
    }
  }
  guard bits <=
    (if negative { 0x8000_0000_0000_0000UL } else { 0x7fff_ffff_ffff_ffffUL }) else {
    raise InvalidData("signed integer overflow")
  }
  ((if negative { 0UL - bits } else { bits }).reinterpret_as_int64(), negative)
}

///|
impl Read with fn read_var_int(self) {
  self.read_var_signed().0
}

///|
impl Read with fn read_buf(self) {
  let length = self.read_var_uint()
  guard length <= 0x7fff_ffffUL else {
    raise InvalidData("buffer length overflow")
  }
  self.read_exact(length.to_int())
}

///|
impl Read with fn read_string(self) {
  @utf8.decode(self.read_buf(), ignore_bom=false) catch {
    _ => raise InvalidData("invalid UTF-8")
  }
}