use super::*;
use crate::Pointer;
use core::mem::MaybeUninit;
use core::ptr::null;
pub struct AvlDrain<'a, P: Pointer, Tag>
where
P::Target: AvlItem<Tag>,
{
tree: &'a mut AvlTree<P, Tag>,
parent: *const P::Target,
dir: Option<AvlDirection>,
}
impl<'a, P: Pointer, Tag> AvlDrain<'a, P, Tag>
where
P::Target: AvlItem<Tag>,
{
#[inline]
pub(super) fn new(tree: &'a mut AvlTree<P, Tag>) -> Self {
Self { tree, parent: null(), dir: None }
}
}
unsafe impl<'a, P, Tag> Send for AvlDrain<'a, P, Tag>
where
P: Pointer + Send,
P::Target: AvlItem<Tag>,
{
}
impl<'a, P: Pointer, Tag> Iterator for AvlDrain<'a, P, Tag>
where
P::Target: AvlItem<Tag>,
{
type Item = P;
fn next(&mut self) -> Option<Self::Item> {
if self.tree.root.is_null() {
return None;
}
let mut node: *const P::Target;
let parent: *const P::Target;
if self.dir.is_none() && self.parent.is_null() {
let mut curr = self.tree.root;
while unsafe { !(*curr).get_node().left.is_null() } {
curr = unsafe { (*curr).get_node().left };
}
node = curr;
} else {
parent = self.parent;
if parent.is_null() {
return None;
}
let child_dir = self.dir.unwrap();
if child_dir == AvlDirection::Right || unsafe { (*parent).get_node().right.is_null() } {
node = parent;
} else {
node = unsafe { (*parent).get_node().right };
while unsafe { !(*node).get_node().left.is_null() } {
node = unsafe { (*node).get_node().left };
}
}
}
if unsafe { !(*node).get_node().right.is_null() } {
node = unsafe { (*node).get_node().right };
}
let next_parent = unsafe { (*node).get_node().parent };
if next_parent.is_null() {
self.tree.root = null();
self.parent = null();
self.dir = Some(AvlDirection::Left);
} else {
self.parent = next_parent;
self.dir = Some(self.tree.parent_direction(node, next_parent));
unsafe { (*next_parent).get_node().set_child(self.dir.unwrap(), null()) };
}
self.tree.count -= 1;
unsafe {
(*node).get_node().detach();
Some(P::from_raw(node))
}
}
}
pub struct AvlIter<'a, P, Tag>
where
P: Pointer,
P::Target: AvlItem<Tag>,
{
tree: &'a AvlTree<P, Tag>,
cur: Option<NonNull<P::Target>>,
dir: AvlDirection,
temp: MaybeUninit<P>,
}
impl<'a, P, Tag> AvlIter<'a, P, Tag>
where
P: Pointer,
P::Target: AvlItem<Tag>,
{
#[inline]
pub(crate) fn new(
tree: &'a AvlTree<P, Tag>, init: Option<NonNull<P::Target>>, dir: AvlDirection,
) -> Self {
Self { tree, cur: init, dir, temp: MaybeUninit::uninit() }
}
#[inline]
pub fn next_ref(&mut self) -> Option<&P> {
let cur: NonNull<P::Target> = self.cur.take()?;
self.temp.write(unsafe { P::from_raw(cur.as_ptr()) });
let p = self.tree.walk_dir(cur, self.dir);
self.cur = p;
Some(unsafe { self.temp.assume_init_ref() })
}
}
unsafe impl<'a, P, Tag> Send for AvlIter<'a, P, Tag>
where
P: Pointer + Send,
P::Target: AvlItem<Tag>,
{
}
impl<'a, P, Tag> Iterator for AvlIter<'a, P, Tag>
where
P: Pointer,
P::Target: AvlItem<Tag>,
{
type Item = &'a P::Target;
fn next(&mut self) -> Option<Self::Item> {
let cur: NonNull<P::Target> = self.cur.take()?;
let p = self.tree.walk_dir(cur, self.dir);
self.cur = p;
Some(unsafe { cur.as_ref() })
}
}