use super::{
node::{Node, NodeType},
BTreeMap,
};
use crate::{types::NULL, Address, Memory, Storable};
use std::borrow::Cow;
use std::ops::{Bound, RangeBounds};
pub(crate) enum Cursor<K: Storable + Ord + Clone> {
Address(Address),
Node { node: Node<K>, next: Index },
}
pub(crate) enum Index {
Child(usize),
Entry(usize),
}
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct Iter<'a, K, V, M>
where
K: Storable + Ord + Clone,
V: Storable,
M: Memory,
{
map: &'a BTreeMap<K, V, M>,
cursors: Vec<Cursor<K>>,
range: (Bound<K>, Bound<K>),
}
impl<'a, K, V, M> Iter<'a, K, V, M>
where
K: Storable + Ord + Clone,
V: Storable,
M: Memory,
{
pub(crate) fn new(map: &'a BTreeMap<K, V, M>) -> Self {
Self {
map,
cursors: vec![Cursor::Address(map.root_addr)],
range: (Bound::Unbounded, Bound::Unbounded),
}
}
pub(crate) fn null(map: &'a BTreeMap<K, V, M>) -> Self {
Self {
map,
cursors: vec![],
range: (Bound::Unbounded, Bound::Unbounded),
}
}
pub(crate) fn new_in_range(
map: &'a BTreeMap<K, V, M>,
range: (Bound<K>, Bound<K>),
cursors: Vec<Cursor<K>>,
) -> Self {
Self {
map,
cursors,
range,
}
}
fn next_map<T, F: Fn(&Node<K>, usize) -> T>(&mut self, map: F) -> Option<T> {
match self.cursors.pop()? {
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_map(map)
}
Cursor::Node {
node,
next: Index::Child(child_idx),
} => {
let child_address = node.child(child_idx);
self.cursors.push(Cursor::Node {
node,
next: Index::Entry(child_idx),
});
self.cursors.push(Cursor::Address(child_address));
self.next_map(map)
}
Cursor::Node {
node,
next: Index::Entry(entry_idx),
} => {
if entry_idx >= node.entries_len() {
return self.next_map(map);
}
if !self.range.contains(node.key(entry_idx)) {
self.cursors = vec![];
return None;
}
let res = map(&node, entry_idx);
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,
});
Some(res)
}
}
}
}
impl<K, V, M> Iterator for Iter<'_, K, V, M>
where
K: Storable + Ord + Clone,
V: Storable,
M: Memory,
{
type Item = (K, V);
fn next(&mut self) -> Option<Self::Item> {
self.next_map(|node, entry_idx| {
let (key, encoded_value) = node.entry(entry_idx, self.map.memory());
(key, V::from_bytes(Cow::Owned(encoded_value)))
})
}
fn count(mut self) -> usize
where
Self: Sized,
{
let mut cnt = 0;
while self.next_map(|_, _| ()).is_some() {
cnt += 1;
}
cnt
}
}
#[cfg(test)]
mod test {
use super::*;
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);
for i in 0..10u8 {
btree.insert(i, i + 1);
}
let mut i = 0;
for (key, value) in btree.iter() {
assert_eq!(key, i);
assert_eq!(value, i + 1);
i += 1;
}
assert_eq!(i, 10u8);
}
#[test]
fn iterate_children() {
let mem = make_memory();
let mut btree = BTreeMap::new(mem);
for i in (0..100u64).rev() {
btree.insert(i, i + 1);
}
let mut i = 0;
for (key, value) in btree.iter() {
assert_eq!(key, i);
assert_eq!(value, i + 1);
i += 1;
}
assert_eq!(i, 100);
}
}