use crate::Result;
use crate::db::Db;
use crate::error::Error;
use crate::format::{P_INVALID, P_ROOT};
use crate::page::PageView;
use std::borrow::Cow;
use std::iter::FusedIterator;
#[derive(Clone, Debug)]
pub struct Entry<'a> {
key: Cow<'a, [u8]>,
value: Cow<'a, [u8]>,
}
impl<'a> Entry<'a> {
#[inline]
#[must_use]
pub fn key(&self) -> &[u8] {
&self.key
}
#[inline]
#[must_use]
pub fn value(&self) -> &[u8] {
&self.value
}
#[must_use]
pub fn into_parts(self) -> (Cow<'a, [u8]>, Cow<'a, [u8]>) {
(self.key, self.value)
}
}
pub struct Iter<'a> {
db: &'a Db,
state: State<'a>,
}
enum State<'a> {
Pristine,
Active(Cursor<'a>),
Done,
}
struct Cursor<'a> {
view: PageView<'a>,
index: usize,
}
impl<'a> Iter<'a> {
pub(crate) const fn new(db: &'a Db) -> Self {
Self {
db,
state: State::Pristine,
}
}
fn initial_state(&self) -> Result<State<'a>> {
let mut pgno = P_ROOT;
loop {
let view = PageView::parse(pgno, self.db.page(pgno)?, self.db.swap())?;
if view.nentries() == 0 {
return Ok(State::Done);
}
if view.is_leaf() {
return Ok(State::Active(Cursor { view, index: 0 }));
}
if !view.is_internal() {
return Err(Error::CorruptPage {
pgno,
reason: "non-internal page during seq descent",
});
}
pgno = view.internal_entry(0)?.child;
}
}
fn advance_leaf(&self, mut next_pg: u32) -> Result<State<'a>> {
while next_pg != P_INVALID {
let view = PageView::parse(next_pg, self.db.page(next_pg)?, self.db.swap())?;
if !view.is_leaf() {
return Err(Error::CorruptPage {
pgno: next_pg,
reason: "seq sibling is not a leaf",
});
}
if view.nentries() > 0 {
return Ok(State::Active(Cursor { view, index: 0 }));
}
next_pg = view.next_pg;
}
Ok(State::Done)
}
fn yield_current(&mut self, cursor: Cursor<'a>) -> Result<Entry<'a>> {
let leaf = cursor.view.leaf_entry(cursor.index)?;
let key = self.db.materialise(&cursor.view, leaf.key)?;
let value = self.db.materialise(&cursor.view, leaf.data)?;
self.state = if cursor.index + 1 < cursor.view.nentries() {
State::Active(Cursor {
view: cursor.view,
index: cursor.index + 1,
})
} else {
self.advance_leaf(cursor.view.next_pg)?
};
Ok(Entry { key, value })
}
}
impl<'a> Iterator for Iter<'a> {
type Item = Result<Entry<'a>>;
fn next(&mut self) -> Option<Self::Item> {
loop {
match std::mem::replace(&mut self.state, State::Done) {
State::Done => return None,
State::Pristine => match self.initial_state() {
Ok(state) => self.state = state,
Err(e) => return Some(Err(e)),
},
State::Active(cursor) => return Some(self.yield_current(cursor)),
}
}
}
}
impl FusedIterator for Iter<'_> {}