orx_selfref_col/references/
array_left_most.rs

1use super::{
2    NodePtr,
3    iter::{ArrayLeftMostPtrIter, ArrayLeftMostPtrIterMut},
4    refs::Refs,
5};
6use crate::variant::Variant;
7use core::fmt::Debug;
8
9/// A constant number of left-aligned references.
10///
11/// It differs from [`RefsArray`] due to its additional requirement that:
12/// * all Some references are to the left of all None references.
13///
14/// [`RefsArray`]: crate::RefsArray
15pub struct RefsArrayLeftMost<const N: usize, V>
16where
17    V: Variant,
18{
19    array: [Option<NodePtr<V>>; N],
20    len: usize,
21}
22
23impl<const N: usize, V: Variant> Clone for RefsArrayLeftMost<N, V> {
24    fn clone(&self) -> Self {
25        Self {
26            array: self.array.clone(),
27            len: self.len,
28        }
29    }
30}
31
32impl<const N: usize, V: Variant> Debug for RefsArrayLeftMost<N, V> {
33    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
34        f.debug_tuple("RefsArrayLeftMost")
35            .field(&self.array)
36            .finish()
37    }
38}
39
40impl<const N: usize, V> Refs for RefsArrayLeftMost<N, V>
41where
42    V: Variant,
43{
44    #[inline(always)]
45    fn empty() -> Self {
46        Self {
47            array: [const { None }; N],
48            len: 0,
49        }
50    }
51
52    #[inline(always)]
53    fn is_empty(&self) -> bool {
54        self.len == 0
55    }
56
57    #[inline(always)]
58    fn clear(&mut self) {
59        self.array
60            .iter_mut()
61            .take(self.len)
62            .for_each(|x| _ = x.take());
63        self.len = 0;
64    }
65
66    #[inline(always)]
67    fn remove_at(&mut self, ref_idx: usize) {
68        self.array[ref_idx] = None;
69        for i in (ref_idx + 1)..self.len {
70            self.array[i - 1] = self.array[i].take();
71        }
72        self.len -= 1;
73    }
74
75    #[inline(always)]
76    fn remove(&mut self, ptr: usize) -> Option<usize> {
77        let x = self.array.iter().enumerate().find(|x| match x.1 {
78            Some(x) => x.ptr() as usize == ptr,
79            None => false,
80        });
81        match x {
82            Some((ref_idx, _)) => {
83                self.remove_at(ref_idx);
84                Some(ref_idx)
85            }
86            None => None,
87        }
88    }
89}
90
91impl<const N: usize, V: Variant> RefsArrayLeftMost<N, V> {
92    /// Returns the number of references.
93    pub fn len(&self) -> usize {
94        self.len
95    }
96
97    /// Returns true if the number of references is zero.
98    pub fn is_empty(&self) -> bool {
99        self.len == 0
100    }
101
102    /// Returns a reference to the node pointer at the `ref_idx` position of the references array.
103    pub fn get(&self, ref_idx: usize) -> Option<&NodePtr<V>> {
104        match ref_idx < N {
105            true => self.array[ref_idx].as_ref(),
106            false => None,
107        }
108    }
109
110    /// Returns the optional node pointers as a slice such that:
111    /// * length of the slice is equal to `self.len()`,
112    /// * all elements of the slice are of `Some` variant, and hence,
113    /// * can be safely unwrapped to access the node pointer.
114    pub fn as_slice(&self) -> &[Option<NodePtr<V>>] {
115        &self.array[..self.len]
116    }
117
118    /// Creates an iterator over node pointers of the references collection.
119    pub fn iter(&self) -> ArrayLeftMostPtrIter<'_, V> {
120        let slice = &self.array[..self.len];
121        ArrayLeftMostPtrIter::new(slice.iter())
122    }
123
124    /// Creates a mutable iterator over node pointers of the references collection.
125    pub fn iter_mut(&mut self) -> ArrayLeftMostPtrIterMut<'_, V> {
126        let slice = &mut self.array[..self.len];
127        ArrayLeftMostPtrIterMut::new(slice.iter_mut())
128    }
129
130    /// Returns whether or not the collection has room for another reference.
131    pub fn has_room(&self) -> bool {
132        self.len < N
133    }
134
135    /// Pushes the node references to the end of the references collection.
136    ///
137    /// # Panics
138    ///
139    /// Panics if the array already has `N` references; i.e., when `self.has_room()` is false.
140    pub fn push(&mut self, node_ptr: NodePtr<V>) {
141        self.assert_has_room_for::<1>();
142        self.array[self.len] = Some(node_ptr);
143        self.len += 1;
144    }
145
146    /// Inserts the reference with the given `node_ptr` to the given `position` of the references collection.
147    pub fn insert(&mut self, position: usize, node_ptr: NodePtr<V>) {
148        for q in (position..self.len).rev() {
149            self.array[q + 1] = self.array[q].clone();
150        }
151        self.array[position] = Some(node_ptr);
152        self.len += 1;
153    }
154
155    /// Inserts the reference with the given `node_ptr` just before the given `pivot_ptr` the reference if it exists;
156    /// and returns the position that the new reference is inserted to.
157    ///
158    /// Does nothing leaving the children unchanged if the `pivot_ptr` reference does not exists, and returns None.
159    pub fn push_before(&mut self, pivot_ptr: &NodePtr<V>, node_ptr: NodePtr<V>) -> Option<usize> {
160        self.assert_has_room_for::<1>();
161        let position = self.iter().position(|x| x == pivot_ptr);
162        if let Some(p) = position {
163            self.insert(p, node_ptr);
164        }
165        position
166    }
167
168    /// Inserts the reference with the given `node_ptr` just after the given `pivot_ptr` the reference if it exists;
169    /// and returns the position that the new reference is inserted to.
170    ///
171    /// Does nothing leaving the children unchanged if the `pivot_ptr` reference does not exists, and returns None.
172    pub fn push_after(&mut self, pivot_ptr: &NodePtr<V>, node_ptr: NodePtr<V>) -> Option<usize> {
173        self.assert_has_room_for::<1>();
174        let position = self.iter().position(|x| x == pivot_ptr);
175        if let Some(p) = position {
176            self.insert(p + 1, node_ptr);
177        }
178        position
179    }
180
181    /// Replaces the node reference `old_node_ptr` with the `new_node_ptr` and returns
182    /// the position of the reference.
183    ///
184    /// Does nothing and returns None if the `old_node_ptr` is absent.
185    pub fn replace_with(
186        &mut self,
187        old_node_ptr: &NodePtr<V>,
188        new_node_ptr: NodePtr<V>,
189    ) -> Option<usize> {
190        let position = self.iter().position(|x| x == old_node_ptr);
191        if let Some(p) = position {
192            self.array[p] = Some(new_node_ptr);
193        }
194        position
195    }
196
197    // helpers
198    fn assert_has_room_for<const P: usize>(&self) {
199        assert!(
200            self.len + P <= N,
201            "Pushing the {}-th reference to array-backed references with maximum of {} elements.",
202            N + P,
203            N
204        );
205    }
206}