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        self.nodes.index_of_ptr(node_ptr.ptr_mut())
100    }
101
102    /// Returns the position of the node with the given `node_ptr`.
103    ///
104    /// # Panics
105    ///
106    /// Panics if the pointer is not valid.
107    #[inline(always)]
108    pub fn position_of_unchecked(&self, node_ptr: &NodePtr<V>) -> usize {
109        self.nodes
110            .index_of_ptr(node_ptr.ptr_mut())
111            .expect("Pointer does not belong to the collection")
112    }
113
114    /// Returns a reference to the data.
115    ///
116    /// # Panics
117    ///
118    /// Panics if the node is already closed.
119    ///
120    /// # Safety
121    ///
122    /// Does not perform bounds check; hence, the caller must guarantee that the
123    /// `node_ptr` belongs to (created from) this collection.
124    #[inline(always)]
125    pub unsafe fn data_unchecked(&self, node_ptr: &NodePtr<V>) -> &V::Item {
126        unsafe { &*node_ptr.ptr_mut() }
127            .data()
128            .expect("node is closed")
129    }
130
131    /// Returns a reference to the ends of the collection.
132    #[inline(always)]
133    pub fn ends(&self) -> &V::Ends {
134        &self.ends
135    }
136
137    /// Returns the pointer of the element with the given `node_position`
138    /// in the underlying nodes storage.
139    ///
140    /// # Panics
141    ///
142    /// Panics if the `node_position` is out of bounds.
143    #[inline(always)]
144    pub fn node_ptr_at_pos(&self, node_position: usize) -> NodePtr<V> {
145        let ptr = self.nodes.get_ptr(node_position).expect("out-of-bounds");
146        NodePtr::new(ptr as *mut Node<V>)
147    }
148
149    // mut
150
151    pub(crate) fn clear_core(&mut self) {
152        self.len = 0;
153        self.ends.clear();
154        self.nodes.clear();
155    }
156
157    /// Returns a mutable reference to the underlying nodes storage.
158    #[inline(always)]
159    pub fn nodes_mut(&mut self) -> &mut P {
160        &mut self.nodes
161    }
162
163    /// Pushes the element with the given `data` and returns its pointer.
164    pub fn push(&mut self, data: V::Item) -> NodePtr<V> {
165        self.len += 1;
166        let ptr = self.nodes.push_get_ptr(Node::new_free_node(data));
167        NodePtr::new(ptr as *mut Node<V>)
168    }
169
170    /// Returns a mutable reference to the data.
171    ///
172    /// # Panics
173    ///
174    /// Panics if the node is already closed.
175    ///
176    /// # Safety
177    ///
178    /// Does not perform bounds check; hence, the caller must guarantee that the
179    /// `node_ptr` belongs to (created from) this collection.
180    #[inline(always)]
181    pub unsafe fn data_mut_unchecked(&mut self, node_ptr: &NodePtr<V>) -> &mut V::Item {
182        unsafe { &mut *node_ptr.ptr_mut() }
183            .data_mut()
184            .expect("node is closed")
185    }
186
187    /// Closes the node at the given `node_ptr` and returns its data.
188    ///
189    /// # Panics
190    ///
191    /// Panics if the node was already closed.
192    #[inline(always)]
193    pub fn close(&mut self, node_ptr: &NodePtr<V>) -> V::Item {
194        self.len -= 1;
195        unsafe { &mut *node_ptr.ptr_mut() }.close()
196    }
197
198    /// Closes the node at the given `node_ptr` and returns its data the node was active.
199    /// Does nothing and returns None if the node was already closed.
200    pub fn close_if_active(&mut self, node_ptr: &NodePtr<V>) -> Option<V::Item> {
201        let node = unsafe { &mut *node_ptr.ptr_mut() };
202        match node.is_active() {
203            true => {
204                self.len -= 1;
205                Some(node.close())
206            }
207            false => None,
208        }
209    }
210
211    /// Returns a mutable reference to the ends of the collection.
212    pub fn ends_mut(&mut self) -> &mut V::Ends {
213        &mut self.ends
214    }
215
216    /// Returns a mutable reference to the node with the given `node_ptr`.
217    #[inline(always)]
218    pub fn node_mut(&mut self, node_ptr: &NodePtr<V>) -> &mut Node<V> {
219        unsafe { &mut *node_ptr.ptr_mut() }
220    }
221
222    /// Swaps the closed node at the `closed_position` with the active node
223    /// at the `active_position`.
224    pub fn move_node(&mut self, closed_position: usize, active_position: usize) {
225        debug_assert!(closed_position < active_position);
226        debug_assert!(self.nodes[closed_position].is_closed());
227        debug_assert!(self.nodes[active_position].is_active());
228
229        self.nodes_mut().swap(active_position, closed_position);
230    }
231
232    // data
233    /// Swaps the underlying data of the element at the given `node_ptr` with the `new_value`,
234    /// and returns the old value.
235    ///
236    /// # Panics
237    ///
238    /// Panics if the node was already closed.
239    pub fn swap_data(&mut self, node_ptr: &NodePtr<V>, new_value: V::Item) -> V::Item {
240        let node = unsafe { &mut *node_ptr.ptr_mut() };
241        node.swap_data(new_value)
242    }
243}
244
245impl<V> CoreCol<V, SplitVec<Node<V>, Recursive>>
246where
247    V: Variant,
248{
249    /// Appends the `nodes` to this collection.
250    pub fn append_nodes(&mut self, nodes: SplitVec<Node<V>, Recursive>) {
251        self.len += nodes.len();
252        self.nodes.append(nodes)
253    }
254}