orx_selfref_col/
selfref_col.rs

1use crate::{
2    CoreCol, MemoryPolicy, MemoryState, NodeIdx, NodeIdxError, NodePtr, Variant, node::Node,
3};
4use core::ops::{Deref, DerefMut};
5use orx_pinned_vec::PinnedVec;
6
7/// `SelfRefCol` is a core data structure to conveniently build safe and efficient self referential collections, such as linked lists and trees.
8pub struct SelfRefCol<V, M, P>
9where
10    V: Variant,
11    M: MemoryPolicy<V>,
12    P: PinnedVec<Node<V>>,
13{
14    core: CoreCol<V, P>,
15    policy: M,
16    state: MemoryState,
17}
18
19impl<V, M, P> Default for SelfRefCol<V, M, P>
20where
21    V: Variant,
22    M: MemoryPolicy<V>,
23    P: PinnedVec<Node<V>> + Default,
24{
25    fn default() -> Self {
26        Self::new()
27    }
28}
29
30impl<V, M, P> Deref for SelfRefCol<V, M, P>
31where
32    V: Variant,
33    M: MemoryPolicy<V>,
34    P: PinnedVec<Node<V>>,
35{
36    type Target = CoreCol<V, P>;
37
38    fn deref(&self) -> &Self::Target {
39        &self.core
40    }
41}
42
43impl<V, M, P> DerefMut for SelfRefCol<V, M, P>
44where
45    V: Variant,
46    M: MemoryPolicy<V>,
47    P: PinnedVec<Node<V>>,
48{
49    fn deref_mut(&mut self) -> &mut Self::Target {
50        &mut self.core
51    }
52}
53
54impl<V, M, P> SelfRefCol<V, M, P>
55where
56    V: Variant,
57    M: MemoryPolicy<V>,
58    P: PinnedVec<Node<V>>,
59{
60    /// Creates a new empty collection.
61    pub fn new() -> Self
62    where
63        P: Default,
64    {
65        Self {
66            core: CoreCol::new(),
67            policy: M::default(),
68            state: MemoryState::default(),
69        }
70    }
71
72    /// Breaks the self referential collection into its core collection and memory state.
73    pub fn into_inner(self) -> (CoreCol<V, P>, MemoryState) {
74        let state = self.memory_state();
75        (self.core, state)
76    }
77
78    pub(crate) fn from_raw_parts(core: CoreCol<V, P>, policy: M, state: MemoryState) -> Self {
79        Self {
80            core,
81            policy,
82            state,
83        }
84    }
85
86    pub(crate) fn with_active_nodes(nodes: P) -> Self {
87        Self {
88            core: CoreCol::with_active_nodes(nodes),
89            policy: M::default(),
90            state: MemoryState::default(),
91        }
92    }
93
94    // get
95
96    /// Memory state of the collection.
97    pub fn memory_state(&self) -> MemoryState {
98        self.state
99    }
100
101    /// Memory policy of the collection.
102    pub fn memory(&self) -> &M {
103        &self.policy
104    }
105
106    /// Closes the node with the given `node_ptr`, returns its taken out value,
107    /// and reclaims closed nodes if necessary.
108    pub fn close_and_reclaim(&mut self, node_ptr: &NodePtr<V>) -> V::Item {
109        let data = self.core.close(node_ptr);
110
111        let state_changed = M::reclaim_closed_nodes(self, node_ptr);
112        self.update_state(state_changed);
113
114        data
115    }
116
117    /// Succeeding the operation of closing of node with the given `node_ptr`,
118    /// reclaims closed nodes if necessary.
119    ///
120    /// Returns whether the memory state changed.
121    pub fn reclaim_from_closed_node(&mut self, node_ptr: &NodePtr<V>) -> bool {
122        let state_changed = M::reclaim_closed_nodes(self, node_ptr);
123        self.update_state(state_changed);
124        state_changed
125    }
126
127    /// If `state_changed` is true, proceeds to the next memory state.
128    #[inline(always)]
129    pub fn update_state(&mut self, state_changed: bool) {
130        if state_changed {
131            self.state = self.state.successor_state();
132        }
133    }
134
135    /// Returns a reference to the node with the given `NodeIdx`;
136    /// returns None if the index is invalid.
137    #[inline(always)]
138    pub fn node_from_idx(&self, idx: &NodeIdx<V>) -> Option<&Node<V>> {
139        match idx.is_in_state(self.state) && self.nodes().contains_ptr(idx.ptr()) {
140            true => Some(unsafe { &*idx.ptr() }),
141            false => None,
142        }
143    }
144
145    /// Tries to create a reference to the node with the given `NodeIdx`;
146    /// returns the error if the index is invalid.
147    #[inline(always)]
148    pub fn try_node_from_idx(&self, idx: &NodeIdx<V>) -> Result<&Node<V>, NodeIdxError> {
149        match self.nodes().contains_ptr(idx.ptr()) {
150            true => match idx.is_in_state(self.state) {
151                true => Ok(unsafe { &*idx.ptr() }),
152                false => Err(NodeIdxError::ReorganizedCollection),
153            },
154            false => Err(NodeIdxError::OutOfBounds),
155        }
156    }
157
158    /// Returns the node index error if the index is invalid.
159    /// Returns None if it is valid.
160    #[inline(always)]
161    pub fn node_idx_error(&self, idx: &NodeIdx<V>) -> Option<NodeIdxError> {
162        match self.try_node_from_idx(idx) {
163            Ok(node) => match node.is_active() {
164                true => None,
165                false => Some(NodeIdxError::RemovedNode),
166            },
167            Err(err) => Some(err),
168        }
169    }
170
171    /// Tries to get a valid pointer to the node with the given `NodeIdx`;
172    /// returns the error if the index is invalid.
173    #[inline(always)]
174    pub fn try_get_ptr(&self, idx: &NodeIdx<V>) -> Result<NodePtr<V>, NodeIdxError> {
175        match self.nodes().contains_ptr(idx.ptr()) {
176            true => match idx.is_in_state(self.state) {
177                true => {
178                    let ptr = idx.ptr();
179                    match unsafe { &*ptr }.is_active() {
180                        true => Ok(NodePtr::new(ptr)),
181                        false => Err(NodeIdxError::RemovedNode),
182                    }
183                }
184                false => Err(NodeIdxError::ReorganizedCollection),
185            },
186            false => Err(NodeIdxError::OutOfBounds),
187        }
188    }
189
190    /// Tries to get a valid pointer to the node with the given `NodeIdx`;
191    /// returns None if the index is invalid.
192    #[inline(always)]
193    pub fn get_ptr(&self, idx: &NodeIdx<V>) -> Option<NodePtr<V>> {
194        match self.nodes().contains_ptr(idx.ptr()) {
195            true => match idx.is_in_state(self.state) {
196                true => {
197                    let ptr = idx.ptr();
198                    match unsafe { &*ptr }.is_active() {
199                        true => Some(NodePtr::new(ptr)),
200                        false => None,
201                    }
202                }
203                false => None,
204            },
205            false => None,
206        }
207    }
208
209    // mut
210
211    /// Clears the collection and changes the memory state.
212    pub fn clear(&mut self) {
213        self.core.clear_core();
214        self.state = self.state.successor_state();
215    }
216
217    /// Returns a mutable reference to the node with the given `NodeIdx`;
218    /// returns None if the index is invalid.
219    #[inline(always)]
220    pub fn node_mut_from_idx(&mut self, idx: &NodeIdx<V>) -> Option<&mut Node<V>> {
221        match idx.is_in_state(self.state) && self.nodes().contains_ptr(idx.ptr()) {
222            true => Some(unsafe { &mut *idx.ptr_mut() }),
223            false => None,
224        }
225    }
226
227    /// Tries to create a mutable reference to the node with the given `NodeIdx`;
228    /// returns the error if the index is invalid.
229    #[inline(always)]
230    pub fn try_node_mut_from_idx(
231        &mut self,
232        idx: &NodeIdx<V>,
233    ) -> Result<&mut Node<V>, NodeIdxError> {
234        match self.nodes().contains_ptr(idx.ptr()) {
235            true => match idx.is_in_state(self.state) {
236                true => Ok(unsafe { &mut *idx.ptr_mut() }),
237                false => Err(NodeIdxError::ReorganizedCollection),
238            },
239            false => Err(NodeIdxError::OutOfBounds),
240        }
241    }
242
243    /// Pushes the element with the given `data` and returns its index.
244    pub fn push_get_idx(&mut self, data: V::Item) -> NodeIdx<V> {
245        let node_ptr = self.push(data);
246        NodeIdx::new(self.memory_state(), &node_ptr)
247    }
248}