orx_selfref_col/
core_col.rs

1use crate::{NodePtr, Refs, Utilization, Variant, node::Node};
2use orx_pinned_vec::PinnedVec;
3use orx_split_vec::{Recursive, SplitVec};
4
5/// Core collection of the self referential collection.
6pub struct CoreCol<V, P>
7where
8    V: Variant,
9    P: PinnedVec<Node<V>>,
10{
11    nodes: P,
12    ends: V::Ends,
13    len: usize,
14}
15
16impl<V, P> Default for CoreCol<V, P>
17where
18    V: Variant,
19    P: PinnedVec<Node<V>> + Default,
20{
21    fn default() -> Self {
22        Self::new()
23    }
24}
25
26impl<V, P> CoreCol<V, P>
27where
28    V: Variant,
29    P: PinnedVec<Node<V>>,
30{
31    /// Creates a new empty collection.
32    pub fn new() -> Self
33    where
34        P: Default,
35    {
36        Self {
37            nodes: P::default(),
38            ends: Refs::empty(),
39            len: 0,
40        }
41    }
42
43    pub(crate) fn from_raw_parts(nodes: P, ends: V::Ends, len: usize) -> Self {
44        Self { nodes, ends, len }
45    }
46
47    /// Destructs the collection into its inner pinned vec, ends and length.
48    pub fn into_inner(self) -> (P, V::Ends, usize) {
49        (self.nodes, self.ends, self.len)
50    }
51
52    pub(crate) fn with_active_nodes(nodes: P) -> Self {
53        debug_assert!(nodes.iter().all(|x| x.data().is_some()));
54        Self {
55            len: nodes.len(),
56            nodes,
57            ends: Refs::empty(),
58        }
59    }
60
61    // get
62
63    /// Returns current node utilization of the collection.
64    pub fn utilization(&self) -> Utilization {
65        Utilization {
66            capacity: self.nodes.capacity(),
67            num_active_nodes: self.len,
68            num_closed_nodes: self.nodes.len() - self.len,
69        }
70    }
71
72    /// Returns length of the self referential collection.
73    #[inline(always)]
74    pub fn len(&self) -> usize {
75        self.len
76    }
77
78    /// Returns whether or not the self referential collection is empty.
79    pub fn is_empty(&self) -> bool {
80        self.len == 0
81    }
82
83    /// Returns a reference to the underlying nodes storage.
84    #[inline(always)]
85    pub fn nodes(&self) -> &P {
86        &self.nodes
87    }
88
89    /// Returns a reference to the node with the given `node_ptr`.
90    #[inline(always)]
91    pub fn node(&self, node_ptr: NodePtr<V>) -> &Node<V> {
92        unsafe { &*node_ptr.ptr_mut() }
93    }
94
95    /// Returns the position of the node with the given `node_ptr`,
96    /// None if the pointer is not valid.
97    #[inline(always)]
98    pub fn position_of(&self, node_ptr: NodePtr<V>) -> Option<usize> {
99        // SAFETY: it is safe to call PinnedVec::index_of_ptr with any pointer
100        self.nodes.index_of_ptr(unsafe { node_ptr.ptr_mut() })
101    }
102
103    /// Returns the position of the node with the given `node_ptr`.
104    ///
105    /// # Panics
106    ///
107    /// Panics if the pointer is not valid.
108    #[inline(always)]
109    pub fn position_of_unchecked(&self, node_ptr: NodePtr<V>) -> usize {
110        // SAFETY: it is safe to call PinnedVec::index_of_ptr with any pointer
111        self.nodes
112            .index_of_ptr(unsafe { node_ptr.ptr_mut() })
113            .expect("Pointer does not belong to the collection")
114    }
115
116    /// Returns a reference to the data.
117    ///
118    /// # Panics
119    ///
120    /// Panics if the node is already closed.
121    ///
122    /// # Safety
123    ///
124    /// Does not perform bounds check; hence, the caller must guarantee that the
125    /// `node_ptr` belongs to (created from) this collection.
126    #[inline(always)]
127    pub unsafe fn data_unchecked(&self, node_ptr: NodePtr<V>) -> &V::Item {
128        unsafe { &*node_ptr.ptr_mut() }
129            .data()
130            .expect("node is closed")
131    }
132
133    /// Returns a reference to the ends of the collection.
134    #[inline(always)]
135    pub fn ends(&self) -> &V::Ends {
136        &self.ends
137    }
138
139    /// Returns the pointer of the element with the given `node_position`
140    /// in the underlying nodes storage.
141    ///
142    /// # Panics
143    ///
144    /// Panics if the `node_position` is out of bounds.
145    #[inline(always)]
146    pub fn node_ptr_at_pos(&self, node_position: usize) -> NodePtr<V> {
147        let ptr = self.nodes.get_ptr(node_position).expect("out-of-bounds");
148        NodePtr::new(ptr as *mut Node<V>)
149    }
150
151    // mut
152
153    pub(crate) fn clear_core(&mut self) {
154        self.len = 0;
155        self.ends.clear();
156        self.nodes.clear();
157    }
158
159    /// Returns a mutable reference to the underlying nodes storage.
160    #[inline(always)]
161    pub fn nodes_mut(&mut self) -> &mut P {
162        &mut self.nodes
163    }
164
165    /// Pushes the element with the given `data` and returns its pointer.
166    pub fn push(&mut self, data: V::Item) -> NodePtr<V> {
167        self.len += 1;
168        let ptr = self.nodes.push_get_ptr(Node::new_free_node(data));
169        NodePtr::new(ptr as *mut Node<V>)
170    }
171
172    /// Returns a mutable reference to the data.
173    ///
174    /// # Panics
175    ///
176    /// Panics if the node is already closed.
177    ///
178    /// # Safety
179    ///
180    /// Does not perform bounds check; hence, the caller must guarantee that the
181    /// `node_ptr` belongs to (created from) this collection.
182    #[inline(always)]
183    pub unsafe fn data_mut_unchecked(&mut self, node_ptr: NodePtr<V>) -> &mut V::Item {
184        unsafe { &mut *node_ptr.ptr_mut() }
185            .data_mut()
186            .expect("node is closed")
187    }
188
189    /// Closes the node at the given `node_ptr` and returns its data.
190    ///
191    /// # Panics
192    ///
193    /// Panics if the node was already closed.
194    #[inline(always)]
195    pub fn close(&mut self, node_ptr: NodePtr<V>) -> V::Item {
196        self.len -= 1;
197        unsafe { &mut *node_ptr.ptr_mut() }.close()
198    }
199
200    /// Closes the node at the given `node_ptr` and returns its data the node was active.
201    /// Does nothing and returns None if the node was already closed.
202    pub fn close_if_active(&mut self, node_ptr: NodePtr<V>) -> Option<V::Item> {
203        let node = unsafe { &mut *node_ptr.ptr_mut() };
204        match node.is_active() {
205            true => {
206                self.len -= 1;
207                Some(node.close())
208            }
209            false => None,
210        }
211    }
212
213    /// Returns a mutable reference to the ends of the collection.
214    pub fn ends_mut(&mut self) -> &mut V::Ends {
215        &mut self.ends
216    }
217
218    /// Returns a mutable reference to the node with the given `node_ptr`.
219    #[inline(always)]
220    pub fn node_mut(&mut self, node_ptr: NodePtr<V>) -> &mut Node<V> {
221        unsafe { &mut *node_ptr.ptr_mut() }
222    }
223
224    /// Swaps the closed node at the `closed_position` with the active node
225    /// at the `active_position`.
226    pub fn move_node(&mut self, closed_position: usize, active_position: usize) {
227        debug_assert!(closed_position < active_position);
228        debug_assert!(self.nodes[closed_position].is_closed());
229        debug_assert!(self.nodes[active_position].is_active());
230
231        self.nodes_mut().swap(active_position, closed_position);
232    }
233
234    // data
235    /// Swaps the underlying data of the element at the given `node_ptr` with the `new_value`,
236    /// and returns the old value.
237    ///
238    /// # Panics
239    ///
240    /// Panics if the node was already closed.
241    pub fn swap_data(&mut self, node_ptr: NodePtr<V>, new_value: V::Item) -> V::Item {
242        let node = unsafe { &mut *node_ptr.ptr_mut() };
243        node.swap_data(new_value)
244    }
245}
246
247impl<V> CoreCol<V, SplitVec<Node<V>, Recursive>>
248where
249    V: Variant,
250{
251    /// Appends the `nodes` to this collection.
252    pub fn append_nodes(&mut self, nodes: SplitVec<Node<V>, Recursive>) {
253        self.len += nodes.len();
254        self.nodes.append(nodes)
255    }
256}