Skip to main content

embed_avl/
entry.rs

1use super::*;
2use core::cmp::Ordering;
3use core::fmt::Debug;
4use core::ops::Deref;
5use pointers::{CloneablePointer, Pointer};
6
7/// Result of a search operation in an [`AvlTree`].
8pub enum Entry<'a, P, Tag, K>
9where
10    P: Pointer,
11    P::Target: AvlItem<Tag>,
12{
13    Vacant(VacantEntry<'a, P, Tag, K>),
14    Occupied(OccupiedEntry<'a, P, Tag>),
15}
16
17impl<'a, P, Tag, K> Entry<'a, P, Tag, K>
18where
19    P: Pointer,
20    P::Target: AvlItem<Tag>,
21{
22    #[inline]
23    pub fn unwrap_occupied(self) -> OccupiedEntry<'a, P, Tag>
24    where
25        K: Debug,
26    {
27        match self {
28            Self::Occupied(ent) => ent,
29            Self::Vacant(ent) => {
30                panic!("called unwrap_occupied on vacent entry {:?}", ent.key);
31            }
32        }
33    }
34
35    #[inline]
36    pub fn unwrap_vacant(self) -> VacantEntry<'a, P, Tag, K>
37    where
38        P::Target: Debug,
39    {
40        match self {
41            Self::Vacant(ent) => ent,
42            Self::Occupied(ent) => {
43                panic!("called unwrap_occupied on vacent entry {:?}", ent.as_ref());
44            }
45        }
46    }
47
48    #[inline]
49    pub fn try_occupied(self) -> Option<OccupiedEntry<'a, P, Tag>> {
50        match self {
51            Self::Occupied(ent) => Some(ent),
52            Self::Vacant(_ent) => None,
53        }
54    }
55
56    #[inline]
57    pub fn try_vacant(self) -> Option<VacantEntry<'a, P, Tag, K>> {
58        match self {
59            Self::Vacant(ent) => Some(ent),
60            Self::Occupied(_ent) => None,
61        }
62    }
63}
64
65impl<'a, P, Tag, K> From<Entry<'a, P, Tag, K>> for Option<OccupiedEntry<'a, P, Tag>>
66where
67    P: Pointer,
68    P::Target: AvlItem<Tag>,
69{
70    #[inline]
71    fn from(ent: Entry<'a, P, Tag, K>) -> Option<OccupiedEntry<'a, P, Tag>> {
72        ent.try_occupied()
73    }
74}
75
76impl<'a, P, Tag, K> From<Entry<'a, P, Tag, K>> for Option<VacantEntry<'a, P, Tag, K>>
77where
78    P: Pointer,
79    P::Target: AvlItem<Tag>,
80{
81    #[inline]
82    fn from(ent: Entry<'a, P, Tag, K>) -> Option<VacantEntry<'a, P, Tag, K>> {
83        ent.try_vacant()
84    }
85}
86
87/// Use to mark last entry
88pub struct Last();
89
90impl fmt::Debug for Last {
91    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
92        write!(f, "last")
93    }
94}
95
96impl<'a, P, Tag> Entry<'a, P, Tag, Last>
97where
98    P: Pointer,
99    P::Target: AvlItem<Tag>,
100{
101    /// Append node to the last entry, return the new entry.
102    ///
103    /// For efficient batch insert without redundant seeking to the last,
104    /// only rotation will be triggered after insert.
105    ///
106    /// # Safety
107    ///
108    /// You have to make sure the node append in total ordering
109    pub unsafe fn append_unchecked(self, node: P) -> Self {
110        match self {
111            Self::Occupied(ent) => Self::Occupied(unsafe { ent.insert_move_next_unchecked(node) }),
112            Self::Vacant(ent) => {
113                debug_assert!(
114                    ent.node.is_null(),
115                    "can only append to VacantEntry when tree is empty"
116                );
117                debug_assert_eq!(ent.direction, DIR_RIGHT);
118                let p = node.into_raw() as *mut P::Target;
119                ent.tree._insert(p, null_mut(), DIR_RIGHT);
120                Self::Occupied(OccupiedEntry {
121                    node: unsafe { NonNull::new_unchecked(p) },
122                    tree: ent.tree,
123                })
124            }
125        }
126    }
127
128    /// Append node to the last entry with check, return the new entry.
129    ///
130    /// For efficient batch insert without redundant seeking to the last,
131    /// only rotation will be triggered after insert.
132    ///
133    /// # Arguments:
134    /// - `node`: the node to insert
135    /// - `cmp_f`: compare `P::Target` of the entry and `node`.
136    ///   If it returns Ordering::Less, insert `node` and return `Ok`; otherwise return `Err(node)`
137    pub fn append<F>(self, node: P, cmp_f: F) -> Result<Self, P>
138    where
139        F: FnOnce(&P::Target, &P::Target) -> Ordering,
140    {
141        match self {
142            Self::Occupied(ent) => {
143                if cmp_f(ent.get(), node.as_ref()) == Ordering::Less {
144                    Ok(Self::Occupied(unsafe { ent.insert_move_next_unchecked(node) }))
145                } else {
146                    Err(node)
147                }
148            }
149            Self::Vacant(ent) => {
150                debug_assert!(
151                    ent.node.is_null(),
152                    "can only append to VacantEntry when tree is empty"
153                );
154                debug_assert_eq!(ent.direction, DIR_RIGHT);
155                let p = node.into_raw() as *mut P::Target;
156                ent.tree._insert(p, null_mut(), DIR_RIGHT);
157                Ok(Self::Occupied(OccupiedEntry {
158                    node: unsafe { NonNull::new_unchecked(p) },
159                    tree: ent.tree,
160                }))
161            }
162        }
163    }
164}
165
166/// Use to mark first entry
167pub struct First();
168
169impl fmt::Debug for First {
170    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
171        write!(f, "first")
172    }
173}
174
175impl<'a, P, Tag> Entry<'a, P, Tag, First>
176where
177    P: Pointer,
178    P::Target: AvlItem<Tag>,
179{
180    /// Prepend node to the first entry, return the new entry.
181    ///
182    /// For efficient batch insert without redundant seeking to the first,
183    /// only rotation will be triggered after insert.
184    ///
185    /// # Safety
186    ///
187    /// You have to make sure the node append in total ordering
188    pub unsafe fn prepend_unchecked(self, node: P) -> Self {
189        match self {
190            Self::Occupied(ent) => Self::Occupied(unsafe { ent.insert_move_prev_unchecked(node) }),
191            Self::Vacant(ent) => {
192                debug_assert!(
193                    ent.node.is_null(),
194                    "can only append to VacantEntry when tree is empty"
195                );
196                debug_assert_eq!(ent.direction, DIR_LEFT);
197                let p = node.into_raw() as *mut P::Target;
198                ent.tree._insert(p, null_mut(), DIR_LEFT);
199                Self::Occupied(OccupiedEntry {
200                    node: unsafe { NonNull::new_unchecked(p) },
201                    tree: ent.tree,
202                })
203            }
204        }
205    }
206
207    /// Prepend node to the first entry with check, return the new entry.
208    ///
209    /// For efficient batch insert without redundant seeking to the first,
210    /// only rotation will be triggered after insert.
211    ///
212    /// # Arguments:
213    /// - `node`: the node to insert
214    /// - `cmp_f`: compare `P::Target` of the `node` and entry.
215    ///   If it returns Ordering::Less, insert `node` and return `Ok`; otherwise return `Err(node)`
216    pub fn prepend<F>(self, node: P, cmp_f: F) -> Result<Self, P>
217    where
218        F: FnOnce(&P::Target, &P::Target) -> Ordering,
219    {
220        match self {
221            Self::Occupied(ent) => {
222                if cmp_f(node.as_ref(), ent.get()) == Ordering::Less {
223                    Ok(Self::Occupied(unsafe { ent.insert_move_prev_unchecked(node) }))
224                } else {
225                    Err(node)
226                }
227            }
228            Self::Vacant(ent) => {
229                debug_assert!(
230                    ent.node.is_null(),
231                    "can only append to VacantEntry when tree is empty"
232                );
233                debug_assert_eq!(ent.direction, DIR_LEFT);
234                let p = node.into_raw() as *mut P::Target;
235                ent.tree._insert(p, null_mut(), DIR_LEFT);
236                Ok(Self::Occupied(OccupiedEntry {
237                    node: unsafe { NonNull::new_unchecked(p) },
238                    tree: ent.tree,
239                }))
240            }
241        }
242    }
243}
244
245pub struct OccupiedEntry<'a, P, Tag>
246where
247    P: Pointer,
248    P::Target: AvlItem<Tag>,
249{
250    /// The matching node or the parent for insertion.
251    pub(crate) node: NonNull<P::Target>,
252    pub(crate) tree: &'a mut AvlTree<P, Tag>,
253}
254
255impl<'a, P, Tag> OccupiedEntry<'a, P, Tag>
256where
257    P: Pointer,
258    P::Target: AvlItem<Tag>,
259{
260    #[inline]
261    pub fn get(&self) -> &'a P::Target {
262        unsafe { self.node.as_ref() }
263    }
264
265    #[inline]
266    pub fn clone_ref(&self) -> P
267    where
268        P: CloneablePointer,
269    {
270        unsafe { CloneablePointer::from_raw_and_clone(self.node.as_ptr()) }
271    }
272
273    /// Remove the node from the tree
274    #[inline]
275    pub fn remove(self) -> P {
276        let p = self.node.as_ptr();
277        unsafe {
278            self.tree._remove(p);
279            P::from_raw(p)
280        }
281    }
282
283    /// Remove the next node if it exists and return the reference, without changing the current position.
284    #[inline]
285    pub fn remove_prev(&mut self) -> Option<P> {
286        if let Some(prev) = AvlTree::<P, Tag>::_walk_dir(self.node, DIR_LEFT) {
287            unsafe {
288                self.tree._remove(prev.as_ptr());
289                return Some(P::from_raw(prev.as_ptr()));
290            }
291        }
292        None
293    }
294
295    /// Remove the next node if it exists and return the reference, without changing the current position.
296    #[inline]
297    pub fn remove_next(&mut self) -> Option<P> {
298        if let Some(next) = AvlTree::<P, Tag>::_walk_dir(self.node, DIR_RIGHT) {
299            unsafe {
300                self.tree._remove(next.as_ptr());
301                return Some(P::from_raw(next.as_ptr()));
302            }
303        }
304        None
305    }
306
307    #[inline]
308    pub fn peek_prev(&self) -> Option<&'a P::Target> {
309        if let Some(p) = AvlTree::<P, Tag>::_walk_dir(self.node, DIR_LEFT) {
310            Some(unsafe { p.as_ref() })
311        } else {
312            None
313        }
314    }
315
316    #[inline]
317    pub fn peek_next(&self) -> Option<&'a P::Target> {
318        if let Some(p) = AvlTree::<P, Tag>::_walk_dir(self.node, DIR_RIGHT) {
319            Some(unsafe { p.as_ref() })
320        } else {
321            None
322        }
323    }
324
325    #[inline]
326    pub fn move_prev(mut self) -> Option<Self> {
327        if let Some(p) = AvlTree::<P, Tag>::_walk_dir(self.node, DIR_LEFT) {
328            self.node = p;
329            Some(self)
330        } else {
331            None
332        }
333    }
334
335    #[inline]
336    pub fn move_next(mut self) -> Option<Self> {
337        if let Some(p) = AvlTree::<P, Tag>::_walk_dir(self.node, DIR_RIGHT) {
338            self.node = p;
339            Some(self)
340        } else {
341            None
342        }
343    }
344
345    /// Insert before the current node.
346    /// The entry position is unchanged.
347    ///
348    /// # Safety
349    ///
350    /// Caller should make sure the new_node is exactly before the current node.
351    ///
352    /// otherwise the new_node is way smaller than its ancestor
353    /// (with value not adjacent to current node) will break the tree total ordering.
354    #[inline]
355    pub unsafe fn insert_prev_unchecked(&mut self, new_node: P) {
356        unsafe {
357            let new_ptr = new_node.into_raw() as *mut P::Target;
358            self.tree._insert_here(new_ptr, self.node, DIR_LEFT);
359        }
360    }
361
362    /// Insert before the current node,
363    /// with entry position is changed to newly inserted node.
364    ///
365    /// # Safety
366    ///
367    /// Caller should make sure the new_node is exactly before the current node.
368    ///
369    /// otherwise the new_node is way smaller than its ancestor
370    /// (with value not adjacent to current node) will break the tree total ordering.
371    #[inline]
372    pub unsafe fn insert_move_prev_unchecked(self, new_node: P) -> Self {
373        unsafe {
374            let new_ptr = new_node.into_raw() as *mut P::Target;
375            self.tree._insert_here(new_ptr, self.node, DIR_LEFT);
376            Self { node: NonNull::new_unchecked(new_ptr), tree: self.tree }
377        }
378    }
379
380    /// Insert after the current node.
381    /// The entry position is unchanged.
382    ///
383    /// # Safety
384    ///
385    /// Caller should make sure the new_node is exactly after the current node.
386    ///
387    /// Otherwise the new_node is way smaller than its ancestor
388    /// (with value not adjacent to current node) will break the tree total ordering.
389    #[inline]
390    pub unsafe fn insert_next_unchecked(&mut self, new_node: P) {
391        unsafe {
392            let new_ptr = new_node.into_raw() as *mut P::Target;
393            self.tree._insert_here(new_ptr, self.node, DIR_RIGHT);
394        }
395    }
396
397    /// Insert after the current node,
398    /// with entry position is changed to newly inserted node.
399    ///
400    /// # Safety
401    ///
402    /// Caller should make sure the new_node is exactly after the current node.
403    ///
404    /// Otherwise the new_node is way smaller than its ancestor
405    /// (with value not adjacent to current node) will break the tree total ordering.
406    #[inline]
407    pub unsafe fn insert_move_next_unchecked(self, new_node: P) -> Self {
408        unsafe {
409            let new_ptr = new_node.into_raw() as *mut P::Target;
410            self.tree._insert_here(new_ptr, self.node, DIR_RIGHT);
411            Self { node: NonNull::new_unchecked(new_ptr), tree: self.tree }
412        }
413    }
414}
415
416impl<'a, P, Tag> Deref for OccupiedEntry<'a, P, Tag>
417where
418    P: Pointer,
419    P::Target: AvlItem<Tag>,
420{
421    type Target = P::Target;
422
423    #[inline]
424    fn deref(&self) -> &Self::Target {
425        self.as_ref()
426    }
427}
428
429impl<'a, P, Tag> AsRef<P::Target> for OccupiedEntry<'a, P, Tag>
430where
431    P: Pointer,
432    P::Target: AvlItem<Tag>,
433{
434    #[inline]
435    fn as_ref(&self) -> &P::Target {
436        Self::get(self)
437    }
438}
439
440/// # Examples
441///
442/// ```rust
443/// use embed_avl::{AvlTree, AvlItem, AvlNode, Entry};
444/// use core::cell::UnsafeCell;
445/// use core::borrow::Borrow;
446/// extern crate alloc;
447/// use alloc::sync::Arc;
448///
449/// struct MyNode {
450///     value: i32,
451///     avl_node: UnsafeCell<AvlNode<MyNode, ()>>,
452/// }
453///
454/// unsafe impl AvlItem<()> for MyNode {
455///
456///     fn get_node(&self) -> &mut AvlNode<MyNode, ()> {
457///         unsafe { &mut *self.avl_node.get() }
458///     }
459/// }
460/// impl Borrow<i32> for MyNode {
461///     fn borrow(&self) -> &i32 {
462///         &self.value
463///     }
464/// }
465///
466/// let mut tree = AvlTree::<Arc<MyNode>, ()>::new();
467/// let key = 42;
468/// if let Entry::Vacant(ent) = tree.entry(key) {
469///     ent.insert_node(Arc::new(MyNode {
470///         value: key,
471///         avl_node: UnsafeCell::new(Default::default()),
472///     }));
473/// }
474/// ```
475pub struct VacantEntry<'a, P, Tag, K>
476where
477    P: Pointer,
478    P::Target: AvlItem<Tag>,
479{
480    pub(crate) node: *mut P::Target,
481    pub(crate) direction: Dir,
482    pub(crate) tree: &'a mut AvlTree<P, Tag>,
483    pub(crate) key: K,
484}
485
486impl<'a, P, Tag, K> VacantEntry<'a, P, Tag, K>
487where
488    P: Pointer,
489    P::Target: AvlItem<Tag>,
490{
491    /// Return the nearest node in the search result
492    #[inline(always)]
493    pub fn nearest(&self) -> Option<&P::Target> {
494        if !self.node.is_null() { unsafe { self.node.as_ref() } } else { None }
495    }
496
497    #[inline]
498    pub fn peek_prev(&self) -> Option<&P::Target> {
499        if !self.node.is_null() {
500            unsafe {
501                if self.direction == DIR_RIGHT {
502                    return Some(&*self.node);
503                } else if let Some(node) =
504                    AvlTree::<P, Tag>::_walk_dir(NonNull::new_unchecked(self.node), DIR_LEFT)
505                {
506                    return Some(node.as_ref());
507                }
508            }
509        }
510        None
511    }
512
513    #[inline]
514    pub fn key(&self) -> &K {
515        &self.key
516    }
517
518    #[inline]
519    pub fn peek_next(&self) -> Option<&P::Target> {
520        if !self.node.is_null() {
521            unsafe {
522                if self.direction == DIR_LEFT {
523                    return Some(&*self.node);
524                } else if let Some(node) =
525                    AvlTree::<P, Tag>::_walk_dir(NonNull::new_unchecked(self.node), DIR_RIGHT)
526                {
527                    return Some(node.as_ref());
528                }
529            }
530        }
531        None
532    }
533
534    #[inline]
535    pub fn move_prev(self) -> Option<OccupiedEntry<'a, P, Tag>> {
536        if !self.node.is_null() {
537            unsafe {
538                let p = NonNull::new_unchecked(self.node);
539                if self.direction == DIR_RIGHT {
540                    return Some(OccupiedEntry { node: p, tree: self.tree });
541                } else if let Some(node) = AvlTree::<P, Tag>::_walk_dir(p, DIR_LEFT) {
542                    return Some(OccupiedEntry { node, tree: self.tree });
543                }
544            }
545        }
546        None
547    }
548
549    #[inline]
550    pub fn move_next(self) -> Option<OccupiedEntry<'a, P, Tag>> {
551        if !self.node.is_null() {
552            unsafe {
553                let p = NonNull::new_unchecked(self.node);
554                if self.direction == DIR_LEFT {
555                    return Some(OccupiedEntry { node: p, tree: self.tree });
556                } else if let Some(node) = AvlTree::<P, Tag>::_walk_dir(p, DIR_RIGHT) {
557                    return Some(OccupiedEntry { node, tree: self.tree });
558                }
559            }
560        }
561        None
562    }
563
564    /// # Safety
565    ///
566    /// Caller should make sure `new_node` have the same value to the search key to `entry()`,
567    ///
568    /// ignoring `K` captured in VacantEntry
569    #[inline]
570    pub unsafe fn insert_node_unchecked(self, new_node: P) -> OccupiedEntry<'a, P, Tag> {
571        let new_ptr = new_node.into_raw() as *mut P::Target;
572        self.tree._insert(new_ptr, self.node, self.direction);
573        OccupiedEntry { node: unsafe { NonNull::new_unchecked(new_ptr) }, tree: self.tree }
574    }
575}
576
577impl<'a, P, Tag, K> VacantEntry<'a, P, Tag, K>
578where
579    P: Pointer,
580    P::Target: AvlItem<Tag> + Borrow<K>,
581    K: PartialEq,
582{
583    /// insert new_node at the position, for entry search by borrowed key
584    ///
585    /// # Safety
586    ///
587    /// We have debug_assert_eq the key an the node
588    #[inline]
589    pub fn insert_node(self, new_node: P) -> OccupiedEntry<'a, P, Tag> {
590        debug_assert!(&self.key == new_node.as_ref().borrow());
591        let new_ptr = new_node.into_raw() as *mut P::Target;
592        self.tree._insert(new_ptr, self.node, self.direction);
593        OccupiedEntry { node: unsafe { NonNull::new_unchecked(new_ptr) }, tree: self.tree }
594    }
595}