Skip to main content

embed_avl/
entry.rs

1use super::*;
2use core::fmt::Debug;
3use core::ops::Deref;
4use pointers::{CloneablePointer, Pointer};
5
6/// Result of a search operation in an [`AvlTree`].
7pub enum Entry<'a, P, Tag, K>
8where
9    P: Pointer,
10    P::Target: AvlItem<Tag>,
11{
12    Vacant(VacantEntry<'a, P, Tag, K>),
13    Occupied(OccupiedEntry<'a, P, Tag>),
14}
15
16impl<'a, P, Tag, K> Entry<'a, P, Tag, K>
17where
18    P: Pointer,
19    P::Target: AvlItem<Tag>,
20{
21    #[inline]
22    pub fn unwrap_occupied(self) -> OccupiedEntry<'a, P, Tag>
23    where
24        K: Debug,
25    {
26        match self {
27            Self::Occupied(ent) => ent,
28            Self::Vacant(ent) => {
29                panic!("called unwrap_occupied on vacent entry {:?}", ent.key);
30            }
31        }
32    }
33
34    #[inline]
35    pub fn unwrap_vacant(self) -> VacantEntry<'a, P, Tag, K>
36    where
37        P::Target: Debug,
38    {
39        match self {
40            Self::Vacant(ent) => ent,
41            Self::Occupied(ent) => {
42                panic!("called unwrap_occupied on vacent entry {:?}", ent.as_ref());
43            }
44        }
45    }
46}
47
48pub struct OccupiedEntry<'a, P, Tag>
49where
50    P: Pointer,
51    P::Target: AvlItem<Tag>,
52{
53    /// The matching node or the parent for insertion.
54    pub(crate) node: NonNull<P::Target>,
55    pub(crate) tree: &'a mut AvlTree<P, Tag>,
56}
57
58impl<'a, P, Tag> OccupiedEntry<'a, P, Tag>
59where
60    P: Pointer,
61    P::Target: AvlItem<Tag>,
62{
63    #[inline]
64    pub fn get(&self) -> &'a P::Target {
65        unsafe { self.node.as_ref() }
66    }
67
68    #[inline]
69    pub fn clone_ref(&self) -> P
70    where
71        P: CloneablePointer,
72    {
73        unsafe { CloneablePointer::from_raw_and_clone(self.node.as_ptr()) }
74    }
75
76    /// Remove the node from the tree
77    #[inline]
78    pub fn remove(self) -> P {
79        let p = self.node.as_ptr();
80        unsafe {
81            self.tree._remove(p);
82            P::from_raw(p)
83        }
84    }
85
86    /// Remove the next node if it exists and return the reference, without changing the current position.
87    #[inline]
88    pub fn remove_prev(&mut self) -> Option<P> {
89        if let Some(prev) = self.tree._walk_dir(self.node, DIR_LEFT) {
90            unsafe {
91                self.tree._remove(prev.as_ptr());
92                return Some(P::from_raw(prev.as_ptr()));
93            }
94        }
95        None
96    }
97
98    /// Remove the next node if it exists and return the reference, without changing the current position.
99    #[inline]
100    pub fn remove_next(&mut self) -> Option<P> {
101        if let Some(next) = self.tree._walk_dir(self.node, DIR_RIGHT) {
102            unsafe {
103                self.tree._remove(next.as_ptr());
104                return Some(P::from_raw(next.as_ptr()));
105            }
106        }
107        None
108    }
109
110    #[inline]
111    pub fn peek_prev(&self) -> Option<&'a P::Target> {
112        if let Some(p) = self.tree._walk_dir(self.node, DIR_LEFT) {
113            Some(unsafe { p.as_ref() })
114        } else {
115            None
116        }
117    }
118
119    #[inline]
120    pub fn peek_next(&self) -> Option<&'a P::Target> {
121        if let Some(p) = self.tree._walk_dir(self.node, DIR_RIGHT) {
122            Some(unsafe { p.as_ref() })
123        } else {
124            None
125        }
126    }
127
128    #[inline]
129    pub fn move_prev(mut self) -> Option<Self> {
130        if let Some(p) = self.tree._walk_dir(self.node, DIR_LEFT) {
131            self.node = p;
132            Some(self)
133        } else {
134            None
135        }
136    }
137
138    #[inline]
139    pub fn move_next(mut self) -> Option<Self> {
140        if let Some(p) = self.tree._walk_dir(self.node, DIR_RIGHT) {
141            self.node = p;
142            Some(self)
143        } else {
144            None
145        }
146    }
147
148    /// Insert before the current node.
149    /// The entry position is unchanged.
150    ///
151    /// # Safety
152    ///
153    /// Caller should make sure the new_node is exactly before the current node.
154    ///
155    /// otherwise the new_node is way smaller than its ancestor
156    /// (with value not adjacent to current node) will break the tree total ordering.
157    #[inline]
158    pub unsafe fn insert_prev_unchecked(&mut self, new_node: P) {
159        unsafe {
160            let new_ptr = new_node.into_raw() as *mut P::Target;
161            self.tree._insert_here(new_ptr, self.node, DIR_LEFT);
162        }
163    }
164
165    /// Insert before the current node,
166    /// with entry position is changed to newly inserted node.
167    ///
168    /// # Safety
169    ///
170    /// Caller should make sure the new_node is exactly before the current node.
171    ///
172    /// otherwise the new_node is way smaller than its ancestor
173    /// (with value not adjacent to current node) will break the tree total ordering.
174    #[inline]
175    pub unsafe fn insert_move_prev_unchecked(self, new_node: P) -> Self {
176        unsafe {
177            let new_ptr = new_node.into_raw() as *mut P::Target;
178            self.tree._insert_here(new_ptr, self.node, DIR_LEFT);
179            Self { node: NonNull::new_unchecked(new_ptr), tree: self.tree }
180        }
181    }
182
183    /// Insert after the current node.
184    /// The entry position is unchanged.
185    ///
186    /// # Safety
187    ///
188    /// Caller should make sure the new_node is exactly after the current node.
189    ///
190    /// Otherwise the new_node is way smaller than its ancestor
191    /// (with value not adjacent to current node) will break the tree total ordering.
192    #[inline]
193    pub unsafe fn insert_next_unchecked(&mut self, new_node: P) {
194        unsafe {
195            let new_ptr = new_node.into_raw() as *mut P::Target;
196            self.tree._insert_here(new_ptr, self.node, DIR_RIGHT);
197        }
198    }
199
200    /// Insert after the current node,
201    /// with entry position is changed to newly inserted node.
202    ///
203    /// # Safety
204    ///
205    /// Caller should make sure the new_node is exactly after the current node.
206    ///
207    /// Otherwise the new_node is way smaller than its ancestor
208    /// (with value not adjacent to current node) will break the tree total ordering.
209    #[inline]
210    pub unsafe fn insert_move_next_unchecked(self, new_node: P) -> Self {
211        unsafe {
212            let new_ptr = new_node.into_raw() as *mut P::Target;
213            self.tree._insert_here(new_ptr, self.node, DIR_RIGHT);
214            Self { node: NonNull::new_unchecked(new_ptr), tree: self.tree }
215        }
216    }
217}
218
219impl<'a, P, Tag> Deref for OccupiedEntry<'a, P, Tag>
220where
221    P: Pointer,
222    P::Target: AvlItem<Tag>,
223{
224    type Target = P::Target;
225
226    #[inline]
227    fn deref(&self) -> &Self::Target {
228        self.as_ref()
229    }
230}
231
232impl<'a, P, Tag> AsRef<P::Target> for OccupiedEntry<'a, P, Tag>
233where
234    P: Pointer,
235    P::Target: AvlItem<Tag>,
236{
237    #[inline]
238    fn as_ref(&self) -> &P::Target {
239        Self::get(self)
240    }
241}
242
243/// # Examples
244///
245/// ```rust
246/// use embed_avl::{AvlTree, AvlItem, AvlNode, Entry};
247/// use core::cell::UnsafeCell;
248/// use core::borrow::Borrow;
249/// extern crate alloc;
250/// use alloc::sync::Arc;
251///
252/// struct MyNode {
253///     value: i32,
254///     avl_node: UnsafeCell<AvlNode<MyNode, ()>>,
255/// }
256///
257/// unsafe impl AvlItem<()> for MyNode {
258///
259///     fn get_node(&self) -> &mut AvlNode<MyNode, ()> {
260///         unsafe { &mut *self.avl_node.get() }
261///     }
262/// }
263/// impl Borrow<i32> for MyNode {
264///     fn borrow(&self) -> &i32 {
265///         &self.value
266///     }
267/// }
268///
269/// let mut tree = AvlTree::<Arc<MyNode>, ()>::new();
270/// let key = 42;
271/// if let Entry::Vacant(ent) = tree.entry(key) {
272///     ent.insert_node(Arc::new(MyNode {
273///         value: key,
274///         avl_node: UnsafeCell::new(Default::default()),
275///     }));
276/// }
277/// ```
278pub struct VacantEntry<'a, P, Tag, K>
279where
280    P: Pointer,
281    P::Target: AvlItem<Tag>,
282{
283    pub(crate) node: *mut P::Target,
284    pub(crate) direction: Dir,
285    pub(crate) tree: &'a mut AvlTree<P, Tag>,
286    pub(crate) key: K,
287}
288
289impl<'a, P, Tag, K> VacantEntry<'a, P, Tag, K>
290where
291    P: Pointer,
292    P::Target: AvlItem<Tag>,
293{
294    /// Return the nearest node in the search result
295    #[inline(always)]
296    pub fn nearest(&self) -> Option<&P::Target> {
297        if !self.node.is_null() { unsafe { self.node.as_ref() } } else { None }
298    }
299
300    #[inline]
301    pub fn peek_prev(&self) -> Option<&P::Target> {
302        if !self.node.is_null() {
303            unsafe {
304                if self.direction == DIR_RIGHT {
305                    return Some(&*self.node);
306                } else if let Some(node) =
307                    self.tree._walk_dir(NonNull::new_unchecked(self.node), DIR_LEFT)
308                {
309                    return Some(node.as_ref());
310                }
311            }
312        }
313        None
314    }
315
316    #[inline]
317    pub fn key(&self) -> &K {
318        &self.key
319    }
320
321    #[inline]
322    pub fn peek_next(&self) -> Option<&P::Target> {
323        if !self.node.is_null() {
324            unsafe {
325                if self.direction == DIR_LEFT {
326                    return Some(&*self.node);
327                } else if let Some(node) =
328                    self.tree._walk_dir(NonNull::new_unchecked(self.node), DIR_RIGHT)
329                {
330                    return Some(node.as_ref());
331                }
332            }
333        }
334        None
335    }
336
337    #[inline]
338    pub fn move_prev(self) -> Option<OccupiedEntry<'a, P, Tag>> {
339        if !self.node.is_null() {
340            unsafe {
341                let p = NonNull::new_unchecked(self.node);
342                if self.direction == DIR_RIGHT {
343                    return Some(OccupiedEntry { node: p, tree: self.tree });
344                } else if let Some(node) = self.tree._walk_dir(p, DIR_LEFT) {
345                    return Some(OccupiedEntry { node, tree: self.tree });
346                }
347            }
348        }
349        None
350    }
351
352    #[inline]
353    pub fn move_next(self) -> Option<OccupiedEntry<'a, P, Tag>> {
354        if !self.node.is_null() {
355            unsafe {
356                let p = NonNull::new_unchecked(self.node);
357                if self.direction == DIR_LEFT {
358                    return Some(OccupiedEntry { node: p, tree: self.tree });
359                } else if let Some(node) = self.tree._walk_dir(p, DIR_RIGHT) {
360                    return Some(OccupiedEntry { node, tree: self.tree });
361                }
362            }
363        }
364        None
365    }
366
367    /// # Safety
368    ///
369    /// Caller should make sure `new_node` have the same value to the search key to `entry()`,
370    ///
371    /// ignoring `K` captured in VacantEntry
372    #[inline]
373    pub unsafe fn insert_node_unchecked(self, new_node: P) -> OccupiedEntry<'a, P, Tag> {
374        let new_ptr = new_node.into_raw() as *mut P::Target;
375        self.tree._insert(new_ptr, self.node, self.direction);
376        OccupiedEntry { node: unsafe { NonNull::new_unchecked(new_ptr) }, tree: self.tree }
377    }
378}
379
380impl<'a, P, Tag, K> VacantEntry<'a, P, Tag, K>
381where
382    P: Pointer,
383    P::Target: AvlItem<Tag> + Borrow<K>,
384    K: PartialEq,
385{
386    /// insert new_node at the position, for entry search by borrowed key
387    ///
388    /// # Safety
389    ///
390    /// We have debug_assert_eq the key an the node
391    #[inline]
392    pub fn insert_node(self, new_node: P) -> OccupiedEntry<'a, P, Tag> {
393        debug_assert!(&self.key == new_node.as_ref().borrow());
394        let new_ptr = new_node.into_raw() as *mut P::Target;
395        self.tree._insert(new_ptr, self.node, self.direction);
396        OccupiedEntry { node: unsafe { NonNull::new_unchecked(new_ptr) }, tree: self.tree }
397    }
398}