generic_cursors/
simple.rs1use std::{future::Future, marker::PhantomData, pin::Pin};
2
3pub struct MutRefStack<'root, T: ?Sized> {
4 lifetime: PhantomData<&'root mut T>,
6 data: Vec<*mut T>,
8}
9
10pub enum MoveDecision<'root, 'this, T: ?Sized> {
11 Ascend,
12 Stay,
13 Descend(&'this mut T),
14 Inject(&'root mut T),
15}
16
17pub enum MoveError {
18 AscendAtRoot,
19}
20
21impl<'root, T: ?Sized> MutRefStack<'root, T> {
22 pub fn new(root: &'root mut T) -> Self {
25 Self {
26 lifetime: PhantomData,
27 data: vec![root],
28 }
29 }
30
31 fn raw_top(&self) -> *mut T {
33 self.data
34 .last()
35 .copied()
36 .expect("root pointer should never be popped")
37 }
38
39 pub fn top(&self) -> &T {
41 let ptr: *const T = self.raw_top();
42 unsafe { &(*ptr) }
43 }
44
45 pub fn top_mut(&mut self) -> &mut T {
47 let ptr: *mut T = self.raw_top();
48 unsafe { &mut (*ptr) }
49 }
50
51 pub fn is_at_root(&self) -> bool {
53 self.data.len() == 1
54 }
55
56 pub fn inject_top(&mut self, new_top: &'root mut T) -> &mut T {
59 self.data.push(new_top);
60 self.top_mut()
61 }
62
63 pub fn inject_with(
66 &mut self,
67 f: impl FnOnce(&mut T) -> Option<&'root mut T>,
68 ) -> Option<&mut T> {
69 let new_top = f(self.top_mut())?;
70 self.data.push(new_top);
71 Some(self.top_mut())
72 }
73
74 pub fn descend_with(
78 &mut self,
79 f: impl for<'node> FnOnce(&'node mut T) -> Option<&'node mut T>,
80 ) -> Option<&mut T> {
81 let old_top: *mut T = self.raw_top();
82 let new_top: &mut T = unsafe { f(&mut *old_top)? };
83 self.data.push(new_top);
84 Some(new_top)
85 }
86
87 pub fn ascend(&mut self) -> Option<&mut T> {
91 match self.data.len() {
92 0 => unreachable!("root pointer must always exist"),
93 1 => None,
94 _ => {
95 self.data.pop();
96 Some(self.top_mut())
97 }
98 }
99 }
100
101 pub fn ascend_while<P>(&mut self, mut predicate: P) -> &mut T
105 where
106 P: FnMut(&mut T) -> bool,
107 {
108 while !self.is_at_root() && predicate(self.top_mut()) {
109 let Some(_) = self.ascend() else {
110 unreachable!();
111 };
112 }
113 self.top_mut()
114 }
115
116 pub fn move_with<F>(&mut self, f: F) -> Result<&mut T, MoveError>
119 where
120 F: for<'a> FnOnce(&'a mut T) -> MoveDecision<'root, 'a, T>,
121 {
122 let top = self.top_mut();
123 let result = f(top);
124 match result {
125 MoveDecision::Ascend => self.ascend().ok_or(MoveError::AscendAtRoot),
126 MoveDecision::Stay => Ok(self.top_mut()),
127 MoveDecision::Inject(new_top) | MoveDecision::Descend(new_top) => {
128 let new_top: *mut T = new_top;
129 self.data.push(new_top);
130 Ok(self.top_mut())
131 }
132 }
133 }
134
135 pub async fn move_with_async<F>(&mut self, f: F) -> Result<&mut T, MoveError>
136 where
137 F: for<'a> FnOnce(
138 &'a mut T,
139 )
140 -> Pin<Box<dyn Future<Output = MoveDecision<'root, 'a, T>> + 'a>>,
141 {
142 let top = self.top_mut();
143 let result = f(top).await;
144 match result {
145 MoveDecision::Ascend => self.ascend().ok_or(MoveError::AscendAtRoot),
146 MoveDecision::Stay => Ok(self.top_mut()),
147 MoveDecision::Inject(new_top) | MoveDecision::Descend(new_top) => {
148 let new_top: *mut T = new_top;
149 self.data.push(new_top);
150 Ok(self.top_mut())
151 }
152 }
153 }
154
155 pub fn into_top(self) -> &'root mut T {
157 let ptr = self.data.last().copied().unwrap();
158 unsafe { &mut *ptr }
159 }
160
161 pub fn to_root(&mut self) -> &mut T {
163 self.data.truncate(1);
164 self.top_mut()
165 }
166}