use crate::{PrefixReadOps, iptrie, node::NodePrefixIter};
pub struct LookupIter<'n, T> {
pub(super) value: Option<&'n T>,
pub(super) stack: heapless::Vec<(&'n dyn PrefixReadOps<T = T>, u8), { iptrie::MAX_DEPTH }>,
pub(super) prefix_iter: Option<NodePrefixIter<'n, T>>,
}
impl<T> Default for LookupIter<'_, T> {
fn default() -> Self {
Self {
value: None,
stack: Default::default(),
prefix_iter: None,
}
}
}
impl<'n, T> Iterator for LookupIter<'n, T>
where
T: 'static,
{
type Item = &'n T;
fn next(&mut self) -> Option<Self::Item> {
if let Some(val) = self.value.take() {
return Some(val);
}
walk_stack(&mut self.stack, &mut self.prefix_iter)
}
}
pub(super) fn walk_stack<'n, T>(
stack: &mut heapless::Vec<(&'n dyn PrefixReadOps<T = T>, u8), { iptrie::MAX_DEPTH }>,
prefix_iter: &mut Option<NodePrefixIter<'n, T>>,
) -> Option<&'n T>
where
T: 'static,
{
while let Some(&(node, octet)) = stack.last() {
if let Some(iter) = prefix_iter {
if let Some((_idx, val)) = iter.next() {
return Some(val);
}
prefix_iter.take();
stack.pop();
continue;
}
*prefix_iter = Some(NodePrefixIter::for_octet(node, octet));
}
None
}