///|
priv struct CursorValidity {
  mut valid : Bool
}

///|
/// 当前事务的只读前向游标;任何被接受的写尝试都使它失效。
pub struct Cursor {
  priv txn : Txn
  priv validity : CursorValidity
  priv end : Bytes?
  priv mut index : PageIndex?
  priv mut slot : Int32
  priv mut remaining : Int32
}

///|
fn Txn::invalidate_cursors(self : Txn) -> Unit {
  if self.cursor_validity is Some(validity) {
    validity.valid = false
  }
}

///|
fn Txn::cursor_generation(self : Txn) -> CursorValidity {
  if self.cursor_validity is Some(validity) && validity.valid {
    validity
  } else {
    let validity = { valid: true, }
    self.cursor_validity = Some(validity)
    validity
  }
}

///|
fn Tree::seek_cursor(
  self : Tree,
  start : Bytes,
) -> (PageIndex, Int32)? raise DbError {
  let mut id = self.root
  let mut remaining = self.next_page
  while id != 0 {
    guard id > 0 && id < self.next_page && remaining > 0 else {
      raise DbError::Corrupt
    }
    remaining -= 1
    let page = match self.pages.get(id) {
      Some(page) => page
      None => raise DbError::Corrupt
    }
    guard page.length() == page_size else { raise DbError::Corrupt }
    let index = self.page_index(id, page)
    if page[0] == kind_leaf {
      return Some((index, index_position(index, start[:], branch=false)))
    }
    guard page[0] == kind_branch else { raise DbError::Corrupt }
    id = lookup_child(index, start)
  }
  None
}

///|
#warnings("-unused_async")
/// 遍历字节字典序的半开区间 `[start, end)`;省略 end 表示无上界。
pub async fn Txn::scan(
  self : Txn,
  start : Bytes,
  end? : Bytes,
) -> Cursor raise DbError {
  require_txn(self)
  let empty = match end {
    Some(bound) => {
      let order = compare_bytes(start, bound)
      guard order <= 0 else { raise DbError::InvalidRange }
      order == 0
    }
    None => false
  }
  let position = if empty { None } else { self.db.tree.seek_cursor(start) }
  let (index, slot) = match position {
    Some((index, slot)) => (Some(index), slot)
    None => (None, 0)
  }
  {
    txn: self,
    validity: self.cursor_generation(),
    end,
    index,
    slot,
    remaining: self.db.tree.next_page,
  }
}

///|
/// 遍历具有任意二进制前缀的键;空前缀遍历全部键。
pub async fn Txn::scan_prefix(
  self : Txn,
  prefix : Bytes,
) -> Cursor raise DbError {
  require_txn(self)
  let mut length = prefix.length()
  while length > 0 && prefix[length - 1] == b'\xff' {
    length -= 1
  }
  if length == 0 {
    self.scan(prefix)
  } else {
    let upper = Bytes::makei(length, i => {
      if i == length - 1 {
        (prefix[i].to_int() + 1).to_byte()
      } else {
        prefix[i]
      }
    })
    self.scan(prefix, end=upper)
  }
}

///|
#warnings("-unused_async")
/// 返回独立拥有的键值行;有效耗尽后重复返回 None,仍检查事务状态和失效。
pub async fn Cursor::next(self : Cursor) -> (Bytes, Bytes)? raise DbError {
  require_txn(self.txn)
  guard self.validity.valid else { raise DbError::CursorInvalidated }
  while self.index is Some(index) {
    if self.slot < index.offsets.length() {
      let offset = index.offsets[self.slot]
      let key_len = read_u16(index.page, offset)
      let value_len = read_u16(index.page, offset + 2)
      let start = offset + 4
      let key = index.page[start:start + key_len]
      if self.end is Some(end) && compare_bytes_view(key, end[:]) >= 0 {
        self.index = None
        return None
      }
      self.slot += 1
      return Some(
        (
          key.to_owned(),
          index.page[start + key_len:start + key_len + value_len].to_owned(),
        ),
      )
    }
    let id = read_u32(index.page, 3).reinterpret_as_int()
    if id == 0 {
      self.index = None
      return None
    }
    let tree = self.txn.db.tree
    guard id > 0 && id < tree.next_page && self.remaining > 0 else {
      raise DbError::Corrupt
    }
    self.remaining -= 1
    let page = match tree.pages.get(id) {
      Some(page) => page
      None => raise DbError::Corrupt
    }
    guard page.length() == page_size && page[0] == kind_leaf else {
      raise DbError::Corrupt
    }
    self.index = Some(tree.page_index(id, page))
    self.slot = 0
  }
  None
}