use crate::SearchMode;
use crate::tree::{RadixNode, common_prefix_length};
pub struct SearchIterator<'a, T> {
stack: Vec<(&'a RadixNode<T>, usize, Vec<u8>)>,
mode: SearchMode,
search_key: Vec<u8>,
}
impl<'a, T> SearchIterator<'a, T> {
pub(crate) fn new(root: &'a RadixNode<T>, prefix: &[u8], mode: SearchMode) -> Self {
let mut iterator = Self {
stack: Vec::new(),
mode,
search_key: prefix.to_vec(),
};
if let Some((start_node, key_prefix)) = Self::find_starting_node(root, prefix, Vec::new()) {
iterator.stack.push((start_node, 0, key_prefix));
}
iterator
}
fn find_starting_node(
node: &'a RadixNode<T>,
prefix: &[u8],
current_key: Vec<u8>,
) -> Option<(&'a RadixNode<T>, Vec<u8>)> {
if prefix.is_empty() {
return Some((node, current_key));
}
let first_byte = prefix[0];
if let Ok(index) = node
.children
.binary_search_by_key(&first_byte, |(byte, _)| *byte)
{
let (_, child) = &node.children[index];
let common_len = common_prefix_length(&child.key, prefix);
if common_len == child.key.len() {
let mut new_current_key = current_key;
new_current_key.extend_from_slice(&child.key);
let remaining_prefix = &prefix[common_len..];
return Self::find_starting_node(child, remaining_prefix, new_current_key);
} else if common_len == prefix.len() && child.key.starts_with(prefix) {
let mut new_current_key = current_key;
new_current_key.extend_from_slice(&child.key);
return Some((child, new_current_key));
}
}
None
}
}
impl<'a, T> Iterator for SearchIterator<'a, T> {
type Item = (Vec<u8>, &'a T);
fn next(&mut self) -> Option<Self::Item> {
loop {
let (node, child_index, current_key) = self.stack.pop()?;
if child_index == 0 {
if let Some(ref value) = node.value {
let matches = match self.mode {
SearchMode::Exact => current_key == self.search_key,
SearchMode::Prefix => true, };
if matches {
if !node.children.is_empty() {
self.stack.push((node, 1, current_key.clone()));
}
return Some((current_key, value));
}
}
if !node.children.is_empty() {
let should_continue = match self.mode {
SearchMode::Prefix => true, SearchMode::Exact => current_key.len() < self.search_key.len(), };
if should_continue {
self.stack.push((node, 1, current_key));
}
}
continue;
}
let current_child_idx = child_index - 1;
if current_child_idx < node.children.len() {
if current_child_idx + 1 < node.children.len() {
let should_continue_siblings = match self.mode {
SearchMode::Prefix => true,
SearchMode::Exact => current_key.len() <= self.search_key.len(),
};
if should_continue_siblings {
self.stack
.push((node, child_index + 1, current_key.clone()));
}
}
let (_, child) = &node.children[current_child_idx];
let mut child_key = current_key;
child_key.extend_from_slice(&child.key);
let should_process_child = match self.mode {
SearchMode::Prefix => true, SearchMode::Exact => {
child_key.len() <= self.search_key.len()
&& self.search_key.starts_with(&child_key)
}
};
if should_process_child {
self.stack.push((child, 0, child_key));
}
}
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(0, None)
}
}