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}