Skip to main content

embed_avl/
iter.rs

1use super::*;
2use core::ptr::null_mut;
3use pointers::Pointer;
4
5// TODO IntoIter
6
7pub struct AvlDrain<'a, P: Pointer, Tag>
8where
9    P::Target: AvlItem<Tag>,
10{
11    tree: &'a mut AvlTree<P, Tag>,
12    parent: *mut P::Target,
13    dir: Option<Dir>,
14}
15
16impl<'a, P: Pointer, Tag> AvlDrain<'a, P, Tag>
17where
18    P::Target: AvlItem<Tag>,
19{
20    #[inline]
21    pub(super) fn new(tree: &'a mut AvlTree<P, Tag>) -> Self {
22        Self { tree, parent: null_mut(), dir: None }
23    }
24}
25
26unsafe impl<'a, P, Tag> Send for AvlDrain<'a, P, Tag>
27where
28    P: Pointer + Send,
29    P::Target: AvlItem<Tag>,
30{
31}
32
33impl<'a, P: Pointer, Tag> Iterator for AvlDrain<'a, P, Tag>
34where
35    P::Target: AvlItem<Tag>,
36{
37    type Item = P;
38
39    fn next(&mut self) -> Option<Self::Item> {
40        if self.tree.root.is_null() {
41            return None;
42        }
43
44        let mut node: *mut P::Target;
45        let parent: *mut P::Target;
46
47        if self.dir.is_none() && self.parent.is_null() {
48            // Initial call: find the leftmost node
49            let mut curr = self.tree.root;
50            loop {
51                let left = unsafe { (*curr).get_node().left() };
52                if !left.is_null() {
53                    curr = left;
54                } else {
55                    break;
56                }
57            }
58            node = curr;
59        } else {
60            parent = self.parent;
61            if parent.is_null() {
62                // Should not happen if root was nulled
63                return None;
64            }
65            let child_dir = self.dir.unwrap();
66            // child_dir child of parent was just nulled in previous call?
67            // NO, we null it in THIS call.
68
69            if child_dir == DIR_RIGHT || unsafe { (*parent).get_node().right().is_null() } {
70                node = parent;
71            } else {
72                // Finished left, go to right sibling
73                node = unsafe { (*parent).get_node().right() };
74                loop {
75                    let left = unsafe { (*node).get_node().left() };
76                    if !left.is_null() {
77                        node = left;
78                    } else {
79                        break;
80                    }
81                }
82            }
83        }
84        let right = unsafe { (*node).get_node().right() };
85
86        // Goto check_right_side logic
87        if !right.is_null() {
88            // It has a right child, so we must yield that first (in post-order)
89            // Note: in AVL, if left is null, right must be a leaf.
90            node = right;
91        }
92
93        // Determine next state
94        let next_parent = unsafe { (*node).get_node().parent };
95        if next_parent.is_null() {
96            self.tree.root = null_mut();
97            self.parent = null_mut();
98            self.dir = Some(DIR_LEFT);
99        } else {
100            self.parent = next_parent;
101            let next_parent_node = unsafe { (*next_parent).get_node() };
102            let _dir = next_parent_node._child_direction(node);
103            // Unlink from parent NOW
104            next_parent_node.set_child(_dir, null_mut());
105            self.dir = Some(_dir);
106        }
107
108        self.tree.count -= 1;
109        unsafe {
110            (*node).get_node().detach();
111            Some(P::from_raw(node))
112        }
113    }
114}
115
116/// Return a reference of P (you can P.clone() of P has Clone)
117///
118/// # Example
119///
120/// ```rust
121/// use embed_avl::{AvlTree, AvlItem, AvlNode, impl_ord_with_borrow};
122/// use core::cell::UnsafeCell;
123/// use core::cmp::Ordering;
124/// use core::borrow::Borrow;
125/// extern crate alloc;
126/// use alloc::sync::Arc;
127///
128/// #[derive(format_attr::DebugAttr)]
129/// #[fmt("MyNode {value}")]
130/// struct MyNode {
131///     value: i32,
132///     avl_node: UnsafeCell<AvlNode<MyNode, ()>>,
133/// }
134///
135/// impl Borrow<i32> for MyNode {
136///     fn borrow(&self) -> &i32 {
137///         &self.value
138///     }
139/// }
140///
141/// unsafe impl AvlItem<()> for MyNode {
142///     fn get_node(&self) -> &mut AvlNode<MyNode, ()> {
143///         unsafe { &mut *self.avl_node.get() }
144///     }
145/// }
146/// impl_ord_with_borrow!(MyNode, i32);
147///
148/// let mut tree = AvlTree::<Arc<MyNode>, ()>::new();
149///
150/// let new_node = | n: i32| {
151///     Arc::new(MyNode { value: n, avl_node: UnsafeCell::new(Default::default()) })
152/// };
153/// tree.add(new_node(1)).expect("add");
154/// tree.add(new_node(2)).expect("add");
155/// tree.add(new_node(3)).expect("add");
156/// assert_eq!(tree.len(), 3);
157///
158/// let mut iter = tree.iter_rev();
159/// let mut all_nodes_rev = Vec::with_capacity(tree.len());
160/// while let Some(node) = iter.next() {
161///     all_nodes_rev.push(node.clone_ref());
162/// }
163/// ```
164pub struct AvlIter<'a, P, Tag>
165where
166    P: Pointer,
167    P::Target: AvlItem<Tag>,
168{
169    tree: &'a AvlTree<P, Tag>,
170    cur: Option<NonNull<P::Target>>,
171    dir: Dir,
172    left: usize,
173}
174
175/// A lending iterator for AvlTree
176///
177/// The iterator yield [NodeRef], so that you can clone the reference if it's `Arc`
178impl<'a, P, Tag> AvlIter<'a, P, Tag>
179where
180    P: Pointer,
181    P::Target: AvlItem<Tag>,
182{
183    #[inline]
184    pub(crate) fn new(
185        tree: &'a AvlTree<P, Tag>, init: Option<NonNull<P::Target>>, dir: Dir,
186    ) -> Self {
187        Self { tree, cur: init, dir, left: tree.len() }
188    }
189}
190
191unsafe impl<'a, P, Tag> Send for AvlIter<'a, P, Tag>
192where
193    P: Pointer + Send,
194    P::Target: AvlItem<Tag>,
195{
196}
197
198impl<'a, P, Tag> Iterator for AvlIter<'a, P, Tag>
199where
200    P: Pointer,
201    P::Target: AvlItem<Tag>,
202{
203    type Item = NodeRef<'a, P>;
204
205    fn next(&mut self) -> Option<Self::Item> {
206        let cur: NonNull<P::Target> = self.cur.take()?;
207        self.left -= 1;
208        self.cur = self.tree._walk_dir(cur, self.dir);
209        Some(NodeRef::<'a, P>::new(cur.as_ptr()))
210    }
211}
212
213impl<'a, P, Tag> ExactSizeIterator for AvlIter<'a, P, Tag>
214where
215    P: Pointer,
216    P::Target: AvlItem<Tag>,
217{
218    #[inline]
219    fn len(&self) -> usize {
220        self.left
221    }
222}