///|
/// A strict forward-only cursor over immutable bytes.
priv struct ByteCursor {
  data : Bytes
  base_offset : Int
  mut position : Int
}

///|
fn ByteCursor::new(data : Bytes) -> ByteCursor {
  { data, base_offset: 0, position: 0 }
}

///|
fn ByteCursor::with_base(data : Bytes, base_offset : Int) -> ByteCursor {
  { data, base_offset, position: 0 }
}

///|
fn ByteCursor::offset(self : ByteCursor) -> Int {
  self.base_offset + self.position
}

///|
fn ByteCursor::remaining(self : ByteCursor) -> Int {
  self.data.length() - self.position
}

///|
fn ByteCursor::read_byte(self : ByteCursor) -> Byte raise VcdiffError {
  if self.position >= self.data.length() {
    raise TruncatedInput(offset=self.position, needed=1, available=0)
  }
  let value = self.data[self.position]
  self.position += 1
  value
}

///|
fn ByteCursor::read_exact(
  self : ByteCursor,
  count : Int,
) -> Bytes raise VcdiffError {
  if count < 0 {
    raise InvalidOption(option="count", reason="must not be negative")
  }
  let available = self.remaining()
  if count > available {
    raise TruncatedInput(offset=self.position, needed=count, available~)
  }
  let start = self.position
  self.position += count
  self.data[start:self.position].to_owned()
}

///|
fn ByteCursor::read_subcursor(
  self : ByteCursor,
  count : Int,
) -> ByteCursor raise VcdiffError {
  let start = self.offset()
  let data = self.read_exact(count)
  ByteCursor::with_base(data, start)
}