use super::{
node::{Node, NodeType},
BTreeMap,
};
use crate::{types::NULL, Address, Memory, Storable};
pub(crate) enum Cursor {
Address(Address),
Node { node: Node, next: Index },
}
pub(crate) enum Index {
Child(usize),
Entry(usize),
}
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct Iter<'a, M: Memory, K: Storable, V: Storable> {
map: &'a BTreeMap<M, K, V>,
cursors: Vec<Cursor>,
prefix: Option<Vec<u8>>,
offset: Option<Vec<u8>>,
}
impl<'a, M: Memory, K: Storable, V: Storable> Iter<'a, M, K, V> {
pub(crate) fn new(map: &'a BTreeMap<M, K, V>) -> Self {
Self {
map,
cursors: vec![Cursor::Address(map.root_addr)],
prefix: None,
offset: None,
}
}
pub(crate) fn null(map: &'a BTreeMap<M, K, V>) -> Self {
Self {
map,
cursors: vec![],
prefix: None,
offset: None,
}
}
pub(crate) fn new_with_prefix(
map: &'a BTreeMap<M, K, V>,
prefix: Vec<u8>,
cursors: Vec<Cursor>,
) -> Self {
Self {
map,
cursors,
prefix: Some(prefix),
offset: None,
}
}
pub(crate) fn new_with_prefix_and_offset(
map: &'a BTreeMap<M, K, V>,
prefix: Vec<u8>,
offset: Vec<u8>,
cursors: Vec<Cursor>,
) -> Self {
Self {
map,
cursors,
prefix: Some(prefix),
offset: Some(offset),
}
}
}
impl<M: Memory + Clone, K: Storable, V: Storable> Iterator for Iter<'_, M, K, V> {
type Item = (K, V);
fn next(&mut self) -> Option<Self::Item> {
match self.cursors.pop() {
Some(Cursor::Address(address)) => {
if address != NULL {
let node = self.map.load_node(address);
self.cursors.push(Cursor::Node {
next: match node.node_type {
NodeType::Internal => Index::Child(0),
NodeType::Leaf => Index::Entry(0),
},
node,
});
}
self.next()
}
Some(Cursor::Node {
node,
next: Index::Child(child_idx),
}) => {
let child_address = *node
.children
.get(child_idx)
.expect("Iterating over children went out of bounds.");
self.cursors.push(Cursor::Node {
node,
next: Index::Entry(child_idx),
});
self.cursors.push(Cursor::Address(child_address));
self.next()
}
Some(Cursor::Node {
mut node,
next: Index::Entry(entry_idx),
}) => {
if entry_idx >= node.entries.len() {
return self.next();
}
let entry = node.swap_entry(entry_idx, (vec![], vec![]));
self.cursors.push(Cursor::Node {
next: match node.node_type {
NodeType::Internal => Index::Child(entry_idx + 1),
NodeType::Leaf => Index::Entry(entry_idx + 1),
},
node,
});
if let Some(prefix) = &self.prefix {
if !entry.0.starts_with(prefix) {
self.cursors = vec![];
return None;
} else if let Some(offset) = &self.offset {
let mut prefix_with_offset = prefix.clone();
prefix_with_offset.extend_from_slice(offset);
if entry.0 < prefix_with_offset {
self.cursors = vec![];
return None;
}
}
}
Some((K::from_bytes(entry.0), V::from_bytes(entry.1)))
}
None => {
None
}
}
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::btreemap::node::CAPACITY;
use std::cell::RefCell;
use std::rc::Rc;
fn make_memory() -> Rc<RefCell<Vec<u8>>> {
Rc::new(RefCell::new(Vec::new()))
}
#[test]
fn iterate_leaf() {
let mem = make_memory();
let mut btree = BTreeMap::new(mem, 1, 1);
for i in 0..CAPACITY as u8 {
btree.insert(vec![i], vec![i + 1]).unwrap();
}
let mut i = 0;
for (key, value) in btree.iter() {
assert_eq!(key, vec![i]);
assert_eq!(value, vec![i + 1]);
i += 1;
}
assert_eq!(i, CAPACITY as u8);
}
#[test]
fn iterate_children() {
let mem = make_memory();
let mut btree = BTreeMap::new(mem, 1, 1);
for i in (0..100).rev() {
btree.insert(vec![i], vec![i + 1]).unwrap();
}
let mut i = 0;
for (key, value) in btree.iter() {
assert_eq!(key, vec![i]);
assert_eq!(value, vec![i + 1]);
i += 1;
}
assert_eq!(i, 100);
}
}