use super::iter_ptr::PostOrderIterPtr;
use super::post_enumeration::PostOrderEnumeration;
use super::states::State;
use crate::TreeVariant;
use crate::aliases::Col;
use crate::memory::MemoryPolicy;
use crate::pinned_storage::PinnedStorage;
use alloc::vec::Vec;
use orx_self_or::SoM;
use orx_selfref_col::{NodePtr, Refs};
pub struct PostOrderIterInto<'a, V, M, P, E, S>
where
V: TreeVariant,
M: MemoryPolicy,
P: PinnedStorage,
E: PostOrderEnumeration,
S: SoM<Vec<State<V>>>,
{
col: &'a mut Col<V, M, P>,
root_ptr: NodePtr<V>,
iter: PostOrderIterPtr<V, E, S>,
}
impl<'a, V, M, P, E, S> PostOrderIterInto<'a, V, M, P, E, S>
where
V: TreeVariant,
M: MemoryPolicy,
P: PinnedStorage,
E: PostOrderEnumeration,
S: SoM<Vec<State<V>>>,
{
#[allow(clippy::type_complexity)]
pub(crate) unsafe fn from(
(col, iter, root_ptr): (&'a mut Col<V, M, P>, PostOrderIterPtr<V, E, S>, NodePtr<V>),
) -> Self {
let node = unsafe { &mut *root_ptr.ptr_mut() };
match node.prev().get() {
Some(parent) => {
let parent = unsafe { &mut *parent.ptr_mut() };
let sibling_idx = parent.next_mut().remove(unsafe { root_ptr.ptr() as usize });
debug_assert!(sibling_idx.is_some());
node.prev_mut().clear();
}
None => {
col.ends_mut().clear();
}
}
Self {
col,
root_ptr,
iter,
}
}
fn take_element(&mut self, element: E::Item<NodePtr<V>>) -> E::Item<V::Item> {
E::map_node_data(element, |ptr| {
let col = unsafe { &mut *(self.col as *mut Col<V, M, P>) };
col.close(ptr)
})
}
}
impl<V, M, P, E, S> Iterator for PostOrderIterInto<'_, V, M, P, E, S>
where
V: TreeVariant,
M: MemoryPolicy,
P: PinnedStorage,
E: PostOrderEnumeration,
S: SoM<Vec<State<V>>>,
{
type Item = E::Item<V::Item>;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|element| self.take_element(element))
}
}
impl<V, M, P, E, S> Drop for PostOrderIterInto<'_, V, M, P, E, S>
where
V: TreeVariant,
M: MemoryPolicy,
P: PinnedStorage,
E: PostOrderEnumeration,
S: SoM<Vec<State<V>>>,
{
fn drop(&mut self) {
while let Some(element) = self.iter.next() {
self.take_element(element);
}
self.col.reclaim_from_closed_node(self.root_ptr);
}
}