Skip to main content

augmented_rbtree/
cursor.rs

1use core::marker::PhantomData;
2
3use crate::{
4    NodeGuard, alloc_proxy::proxy::Allocator, layout::AugmentedRBTreeLayout,
5    node::internal_details::NodeRef, policy::internal_details::TreePolicy,
6};
7
8/// A graph-navigational cursor that sits directly on a tree node, exposing raw
9/// topography traversal and augmented subtree metrics.
10///
11/// Unlike a standard, linear cursor that tracks abstract gaps between elements,
12/// the `NavCursor` provides power-users with low-level access to the tree's actual
13/// graph edges (`left`, `right`, and `parent`) along with the node's sorted
14/// sequence links (`next`, `prev`).
15///
16/// # The State Model: Advance-and-Yield
17///
18/// All mutation methods (`next`, `prev`, `left`, `right`, `parent`) follow a
19/// **look-before-you-leap** sequence:
20/// 1. They move the internal cursor pointer to the target destination node first.
21/// 2. If the destination exists, they update the state and yield its data.
22/// 3. If the edge points to an empty child or terminal bound, the internal state
23///    becomes `None`, and the method yields `None`.
24///
25/// ⚠️ **Crucial Warning:** Because movement methods advance the cursor *before*
26/// reading, calling a movement method immediately after initialization will **skip**
27/// the data of the node you started on. Always check [`.get()`](#method.get) first
28/// if you need to process the initial search node.
29///
30///
31#[derive(Debug, Copy)]
32pub struct NavCursor<'a, K, V, S> {
33    pub(crate) current: Option<NodeRef<K, V, S>>,
34    _marker: PhantomData<&'a ()>,
35}
36
37impl<K, V, S> Clone for NavCursor<'_, K, V, S> {
38    fn clone(&self) -> Self {
39        Self {
40            current: self.current,
41            _marker: PhantomData,
42        }
43    }
44}
45
46impl<'a, K, V, S> NavCursor<'a, K, V, S> {
47    pub(crate) fn new(current: Option<NodeRef<K, V, S>>) -> Self {
48        Self {
49            current,
50            _marker: PhantomData,
51        }
52    }
53
54    /// Returns a reference to the current node's key, value, and stats.
55    #[must_use]
56    pub fn get(&self) -> Option<(&'a K, &'a V, &'a S)> {
57        let node = self.current?;
58        unsafe { Some((node.key(), node.value(), node.stats())) }
59    }
60
61    /// Returns a reference to the next node's key, value, and stats without moving the cursor.
62    #[must_use]
63    pub fn peek_next(&self) -> Option<(&'a K, &'a V, &'a S)> {
64        let next = self.current?.next_node()?;
65        unsafe { Some((next.key(), next.value(), next.stats())) }
66    }
67
68    /// Returns a reference to the previous node's key, value, and stats without moving the cursor.
69    #[must_use]
70    pub fn peek_prev(&self) -> Option<(&'a K, &'a V, &'a S)> {
71        let prev = self.current?.prev_node()?;
72        unsafe { Some((prev.key(), prev.value(), prev.stats())) }
73    }
74
75    /// Returns a reference to the parent node's key, value, and stats without moving the cursor.
76    #[must_use]
77    pub fn peek_parent(&self) -> Option<(&'a K, &'a V, &'a S)> {
78        let parent = self.current?.parent()?;
79        unsafe { Some((parent.key(), parent.value(), parent.stats())) }
80    }
81
82    /// Returns a reference to the left child node's key, value, and stats without moving the cursor.
83    #[must_use]
84    pub fn peek_left(&self) -> Option<(&'a K, &'a V, &'a S)> {
85        let left = self.current?.left()?;
86        unsafe { Some((left.key(), left.value(), left.stats())) }
87    }
88
89    /// Returns a reference to the right child node's key, value, and stats without moving the cursor.
90    #[must_use]
91    pub fn peek_right(&self) -> Option<(&'a K, &'a V, &'a S)> {
92        let right = self.current?.right()?;
93        unsafe { Some((right.key(), right.value(), right.stats())) }
94    }
95
96    /// Moves the cursor to the next node in sorted order and returns its key, value, and stats.
97    #[allow(clippy::should_implement_trait)]
98    pub fn next(&mut self) -> Option<(&'a K, &'a V, &'a S)> {
99        self.current = self.current?.next_node();
100        let current = self.current?;
101        unsafe { Some((current.key(), current.value(), current.stats())) }
102    }
103
104    /// Moves the cursor to the previous node in sorted order and returns its key, value, and stats.
105    pub fn prev(&mut self) -> Option<(&'a K, &'a V, &'a S)> {
106        self.current = self.current?.prev_node();
107        let current = self.current?;
108        unsafe { Some((current.key(), current.value(), current.stats())) }
109    }
110
111    /// Moves the cursor to the parent node and returns its key, value, and stats.
112    pub fn parent(&mut self) -> Option<(&'a K, &'a V, &'a S)> {
113        self.current = self.current?.parent();
114        let current = self.current?;
115        unsafe { Some((current.key(), current.value(), current.stats())) }
116    }
117
118    /// Moves the cursor to the left child node and returns its key, value, and stats.
119    pub fn left(&mut self) -> Option<(&'a K, &'a V, &'a S)> {
120        self.current = self.current?.left();
121        let current = self.current?;
122        unsafe { Some((current.key(), current.value(), current.stats())) }
123    }
124
125    /// Moves the cursor to the right child node and returns its key, value, and stats.
126    pub fn right(&mut self) -> Option<(&'a K, &'a V, &'a S)> {
127        self.current = self.current?.right();
128        let current = self.current?;
129        unsafe { Some((current.key(), current.value(), current.stats())) }
130    }
131}
132
133/// A mutable navigation cursor for an augmented Red-Black tree layout.
134///
135/// `NavCursorMut` provides a stateful, bidirectionally navigable handle over the tree nodes.
136/// It uniquely allows for **read-only key access**, **read-only tree statistics access**,
137/// and **mutable value adjustments** via a specialized internal RAII guard ([`crate::NodeGuard`]).
138///
139/// Because values can be modified mutably through this cursor, any mutations that alter
140/// secondary tree properties will trigger the augmentation.
141///
142/// # Lifetime Architecture
143/// * `'a` - Binds the exclusive mutable borrow of the underlying tree structural layout.
144///   This ensures that the tree cannot be mutated or invalidated by other access vectors while
145///   the cursor is actively operating.
146///
147#[derive(Debug)]
148pub struct NavCursorMut<'a, K, V, S, A, P>
149where
150    P: TreePolicy<K = K, V = V, S = S>,
151    A: Allocator,
152{
153    layout: &'a mut AugmentedRBTreeLayout<K, V, S, A, P>,
154    current: Option<NodeRef<K, V, S>>,
155    _marker: PhantomData<(&'a mut (K, V, S), P)>,
156}
157
158impl<'a, K, V, S, A, P> NavCursorMut<'a, K, V, S, A, P>
159where
160    P: TreePolicy<K = K, V = V, S = S>,
161    A: Allocator,
162{
163    /// Constructs a new mutable navigation cursor rooted or positioned at a targeted node.
164    #[inline]
165    pub(crate) fn new(
166        layout: &'a mut AugmentedRBTreeLayout<K, V, S, A, P>,
167        current: Option<NodeRef<K, V, S>>,
168    ) -> Self {
169        Self {
170            layout,
171            current,
172            _marker: PhantomData,
173        }
174    }
175
176    /// Returns a tuple containing an immutable reference to the key, a mutable value guard,
177    /// and an immutable reference to the statistics of the **current** node.
178    ///
179    /// Returns `None` if the cursor is invalid or exhausted.
180    ///
181    pub fn get(&mut self) -> Option<NodeGuard<'_, K, V, S, P>> {
182        let node = self.current?;
183        let guard = NodeGuard::new(node);
184        Some(guard)
185    }
186
187    /// Peeks forward to the next in-order node's data without moving the cursor's position.
188    ///
189    /// Returns `None` if there is no subsequent in-order node.
190    pub fn peek_next(&mut self) -> Option<NodeGuard<'_, K, V, S, P>> {
191        let next = self.current?.next_node()?;
192        let guard = NodeGuard::new(next);
193        Some(guard)
194    }
195
196    /// Peeks backward to the previous in-order node's data without moving the cursor's position.
197    ///
198    /// Returns `None` if there is no prior in-order node.
199    pub fn peek_prev(&mut self) -> Option<NodeGuard<'_, K, V, S, P>> {
200        let prev = self.current?.prev_node()?;
201        let guard = NodeGuard::new(prev);
202        Some(guard)
203    }
204
205    /// Peeks upward to the parent node's data without moving the cursor's position.
206    ///
207    /// Returns `None` if the cursor is at the root of the tree.
208    pub fn peek_parent(&mut self) -> Option<NodeGuard<'_, K, V, S, P>> {
209        let parent = self.current?.parent()?;
210        let guard = NodeGuard::new(parent);
211        Some(guard)
212    }
213
214    /// Peeks downward to the left child node's data without moving the cursor's position.
215    ///
216    /// Returns `None` if there is no left child.
217    pub fn peek_left(&mut self) -> Option<NodeGuard<'_, K, V, S, P>> {
218        let left = self.current?.left()?;
219        let guard = NodeGuard::new(left);
220        Some(guard)
221    }
222
223    /// Peeks downward to the right child node's data without moving the cursor's position.
224    ///
225    /// Returns `None` if there is no right child.
226    pub fn peek_right(&mut self) -> Option<NodeGuard<'_, K, V, S, P>> {
227        let right = self.current?.right()?;
228        let guard = NodeGuard::new(right);
229        Some(guard)
230    }
231
232    /// Moves the cursor to the next sequential node in-order and returns its data components.
233    ///
234    /// If no subsequent node exists, the cursor is advanced to an empty (`None`) state.
235    #[allow(clippy::should_implement_trait)]
236    pub fn next(&mut self) -> Option<NodeGuard<'_, K, V, S, P>> {
237        self.current = self.current?.next_node();
238        let current = self.current?;
239        let guard = NodeGuard::new(current);
240        Some(guard)
241    }
242
243    /// Moves the cursor to the previous sequential node in-order and returns its data components.
244    ///
245    /// If no prior node exists, the cursor is advanced to an empty (`None`) state.
246    pub fn prev(&mut self) -> Option<NodeGuard<'_, K, V, S, P>> {
247        self.current = self.current?.prev_node();
248        let current = self.current?;
249        let guard = NodeGuard::new(current);
250        Some(guard)
251    }
252
253    /// Moves the cursor up to the parent node and returns its data components.
254    ///
255    /// Returns `None` and leaves the cursor unchanged if no parent exists.
256    pub fn parent(&mut self) -> Option<NodeGuard<'_, K, V, S, P>> {
257        self.current = self.current?.parent();
258        let current = self.current?;
259        let guard = NodeGuard::new(current);
260        Some(guard)
261    }
262
263    /// Moves the cursor down into the left child node and returns its data components.
264    ///
265    /// Returns `None` and leaves the cursor unchanged if no left child exists.
266    pub fn left(&mut self) -> Option<NodeGuard<'_, K, V, S, P>> {
267        self.current = self.current?.left();
268        let current = self.current?;
269        let guard = NodeGuard::new(current);
270        Some(guard)
271    }
272
273    /// Moves the cursor down into the right child node and returns its data components.
274    ///
275    /// Returns `None` and leaves the cursor unchanged if no right child exists.
276    pub fn right(&mut self) -> Option<NodeGuard<'_, K, V, S, P>> {
277        self.current = self.current?.right();
278        let current = self.current?;
279        let guard = NodeGuard::new(current);
280        Some(guard)
281    }
282
283    /// Removes the node currently pointed to by the cursor from the tree structure,
284    /// returning its owned key and value coordinates.
285    ///
286    /// This operation triggers full internal Red-Black tree rebalancing and augmented stat
287    /// updates along the tree lineage.
288    ///
289    /// Returns `None` if the cursor is already empty or invalid.
290    ///
291    pub fn remove(&mut self) -> Option<(K, V)> {
292        let node = self.current?;
293        let next_node = node.next_node();
294        self.current = next_node;
295        Some(self.layout.delete_node(node))
296    }
297}