use alloc::vec::Vec;
use core::iter::FusedIterator;
use crate::indexable::Indexable;
use crate::node::Node;
use crate::predicate::Predicate;
enum LeafMode {
Filtered,
DumpAll,
}
pub struct QueryIter<'a, T> {
predicate: Predicate,
stack: Vec<(&'a Node<T>, bool)>,
leaf: core::slice::Iter<'a, T>,
leaf_mode: LeafMode,
}
impl<'a, T> QueryIter<'a, T> {
pub(crate) fn new(
root: &'a Node<T>,
predicate: Predicate,
height: usize,
max_fanout: usize,
) -> Self {
let capacity = height.saturating_sub(1) * max_fanout.saturating_sub(1) + max_fanout;
let mut stack = Vec::with_capacity(capacity);
stack.push((root, false));
Self {
predicate,
stack,
leaf: [].iter(),
leaf_mode: LeafMode::Filtered,
}
}
}
impl<'a, T: Indexable> Iterator for QueryIter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<&'a T> {
loop {
match self.leaf_mode {
LeafMode::Filtered => {
for value in self.leaf.by_ref() {
if self.predicate.matches(&value.bounds()) {
return Some(value);
}
}
}
LeafMode::DumpAll => {
if let Some(value) = self.leaf.next() {
return Some(value);
}
}
}
let (node, covered) = self.stack.pop()?;
match node {
Node::Leaf(values) => {
self.leaf = values.iter();
self.leaf_mode = if covered {
LeafMode::DumpAll
} else {
LeafMode::Filtered
};
}
Node::Branch(children) => {
if covered {
for (_, child) in children.iter().rev() {
self.stack.push((child, true));
}
} else {
for (bounds, child) in children.iter().rev() {
if self.predicate.could_match(bounds) {
self.stack.push((child, self.predicate.covers_all(bounds)));
}
}
}
}
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(0, None)
}
}
impl<T: Indexable> FusedIterator for QueryIter<'_, T> {}