///|
pub struct ByteCursor {
  input : Bytes
  mut position_value : Int
} derive(Debug)

///|
pub fn ByteCursor::new(input : Bytes) -> ByteCursor {
  { input, position_value: 0 }
}

///|
pub fn ByteCursor::position(self : ByteCursor) -> Int {
  self.position_value
}

///|
pub fn ByteCursor::remaining(self : ByteCursor) -> Int {
  self.input.length() - self.position_value
}

///|
pub fn ByteCursor::checkpoint(self : ByteCursor) -> Int {
  self.position_value
}

///|
pub fn ByteCursor::restore(self : ByteCursor, checkpoint : Int) -> Unit {
  self.position_value = checkpoint
}

///|
pub fn ByteCursor::peek(self : ByteCursor) -> Byte? {
  if self.remaining() == 0 {
    None
  } else {
    Some(self.input[self.position_value])
  }
}

///|
pub fn ByteCursor::peek_n(self : ByteCursor, count : Int) -> Bytes? {
  if count < 0 || self.remaining() < count {
    None
  } else {
    Some(
      Bytes::from_array(
        self.input.to_array()[self.position_value:self.position_value + count],
      ),
    )
  }
}

///|
pub fn ByteCursor::read_u8(self : ByteCursor) -> Byte? {
  match self.peek() {
    None => None
    Some(v) => {
      self.position_value = self.position_value + 1
      Some(v)
    }
  }
}

///|
pub fn ByteCursor::read_u16_be(self : ByteCursor) -> Int? {
  if self.remaining() < 2 {
    None
  } else {
    let v = (self.input[self.position_value].to_int() << 8) |
      self.input[self.position_value + 1].to_int()
    self.position_value = self.position_value + 2
    Some(v)
  }
}

///|
pub fn ByteCursor::read_u32_be(self : ByteCursor) -> UInt? {
  if self.remaining() < 4 {
    None
  } else {
    let v = (self.input[self.position_value].to_uint() << 24) |
      (self.input[self.position_value + 1].to_uint() << 16) |
      (self.input[self.position_value + 2].to_uint() << 8) |
      self.input[self.position_value + 3].to_uint()
    self.position_value = self.position_value + 4
    Some(v)
  }
}

///|
pub fn ByteCursor::read_exact(self : ByteCursor, count : Int) -> Bytes? {
  match self.peek_n(count) {
    None => None
    Some(v) => {
      self.position_value = self.position_value + count
      Some(v)
    }
  }
}

///|
pub fn ByteCursor::skip(self : ByteCursor, count : Int) -> Bool {
  if count < 0 || self.remaining() < count {
    false
  } else {
    self.position_value = self.position_value + count
    true
  }
}