use core::{borrow::Borrow, marker::PhantomData};
use crate::{
AugmentedRBTreeInt, alloc_proxy::proxy::Allocator, augmented_rbtree::TreeLocation,
cursor::NavCursor, node::internal_details::NodeRef, policy,
};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum TraversalPhase {
Above,
Left,
Right,
}
pub trait InOrderPruningPolicy<K, V, S> {
fn is_match(&self, key: &K, value: &V, stats: &S) -> bool;
fn should_explore_left(&self, left: (&K, &V, &S), current: (&K, &V, &S)) -> bool;
fn should_explore_right(&self, right: (&K, &V, &S), current: (&K, &V, &S)) -> bool;
}
#[derive(Debug)]
pub struct InOrderIter<'a, K, V, S, P>
where
P: InOrderPruningPolicy<K, V, S>,
{
cur: Option<NodeRef<K, V, S>>,
policy: P,
subtree_root: Option<NodeRef<K, V, S>>,
direction: TraversalPhase,
_marker: PhantomData<&'a (K, V, S)>,
}
impl<'a, K, V, S, P> Iterator for InOrderIter<'a, K, V, S, P>
where
P: InOrderPruningPolicy<K, V, S>,
{
type Item = (&'a K, &'a V, &'a S);
fn next(&mut self) -> Option<Self::Item> {
loop {
let node = self.cur?;
let (key, value, stats) = unsafe { (node.key(), node.value(), node.stats()) };
match self.direction {
TraversalPhase::Above => {
if let Some(left_node) = node.left() {
let (left_key, left_value, left_stats) =
unsafe { (left_node.key(), left_node.value(), left_node.stats()) };
if self.policy.should_explore_left(
(left_key, left_value, left_stats),
(key, value, stats),
) {
self.cur = Some(left_node);
self.direction = TraversalPhase::Above; continue;
}
}
self.direction = TraversalPhase::Left;
}
TraversalPhase::Left => {
let is_matching_node = self.policy.is_match(key, value, stats);
if let Some(right_node) = node.right() {
let (right_key, right_value, right_stats) =
unsafe { (right_node.key(), right_node.value(), right_node.stats()) };
if self.policy.should_explore_right(
(right_key, right_value, right_stats),
(key, value, stats),
) {
self.cur = Some(right_node);
self.direction = TraversalPhase::Above;
if is_matching_node {
return Some((key, value, stats));
}
continue;
}
}
if is_matching_node {
self.ascend_and_update_state();
return Some((key, value, stats));
}
self.ascend_and_update_state();
}
TraversalPhase::Right => {
self.ascend_and_update_state();
}
}
}
}
}
impl<K, V, S, P> InOrderIter<'_, K, V, S, P>
where
P: InOrderPruningPolicy<K, V, S>,
{
pub fn new<A, R, Q>(
tree: &AugmentedRBTreeInt<K, V, S, A, R>,
location: TreeLocation<&Q>,
policy: P,
) -> Self
where
A: Allocator,
R: policy::internal_details::TreePolicy<K = K, V = V, S = S>,
K: Borrow<Q> + Ord,
Q: Ord,
{
let cur = tree.get_tree_location(location);
Self {
cur,
policy,
subtree_root: cur, direction: TraversalPhase::Above,
_marker: PhantomData,
}
}
pub fn from_cursor(cursor: &NavCursor<'_, K, V, S>, policy: P) -> Self {
let starting_node = cursor.current;
Self {
cur: starting_node,
policy,
subtree_root: starting_node,
direction: TraversalPhase::Above,
_marker: PhantomData,
}
}
fn ascend_and_update_state(&mut self) {
if self.cur == self.subtree_root {
self.cur = None; return;
}
if let Some(node) = self.cur {
let parent = node
.parent()
.expect("Invariant violation: Node must have a parent");
if parent.left() == Some(node) {
self.direction = TraversalPhase::Left;
} else {
self.direction = TraversalPhase::Right;
}
self.cur = Some(parent);
}
}
}