mutcursor/
mut_cursor_vec.rs1
2use core::ptr::NonNull;
3use core::marker::PhantomData;
4
5pub struct MutCursorVec<'root, T: ?Sized + 'root> {
10 top: NonNull<T>,
11 stack: alloc::vec::Vec<NonNull<T>>,
12 phantom: PhantomData<&'root mut T>, }
14
15unsafe impl<'a, T> Sync for MutCursorVec<'a, T> where T: Sync, T: ?Sized {}
16unsafe impl<'a, T> Send for MutCursorVec<'a, T> where T: Send, T: ?Sized {}
17
18impl<'root, T: ?Sized + 'root> MutCursorVec<'root, T> {
19 #[inline]
21 pub fn new(root: &'root mut T) -> Self {
22 Self {
23 top: root.into(),
24 stack: alloc::vec::Vec::new(),
25 phantom: PhantomData::default(),
26 }
27 }
28 #[inline]
31 pub fn new_with_capacity(root: &'root mut T, capacity: usize) -> Self {
32 Self {
33 top: root.into(),
34 stack: alloc::vec::Vec::with_capacity(capacity),
35 phantom: PhantomData::default(),
36 }
37 }
38 #[inline]
40 pub fn top(&self) -> &T {
41 unsafe{ self.top.as_ref() }
42 }
43 #[inline]
45 pub fn top_mut(&mut self) -> &mut T {
46 unsafe{ self.top.as_mut() }
47 }
48 #[inline]
50 pub fn into_mut(mut self) -> &'root mut T {
51 unsafe{ self.top.as_mut() }
52 }
53 #[inline]
58 pub fn try_map_into_mut<U, E, F>(mut self, f: F) -> Result<&'root mut U, (Self, E)>
59 where for<'r> F: FnOnce(&'r mut T) -> Result<&'r mut U, E>
60 {
61 let top_ref = unsafe{ self.top_mut_internal() };
62 match f(top_ref) {
63 Ok(r) => Ok(r),
64 Err(e) => Err((self, e))
65 }
66 }
67 #[inline]
70 pub fn depth(&self) -> usize {
71 self.stack.len()
72 }
73 #[inline]
75 pub fn capacity(&self) -> usize {
76 self.stack.capacity() + 1
77 }
78 #[inline]
84 pub fn advance<F>(&mut self, step_f: F) -> bool
85 where F: FnOnce(&mut T) -> Option<&mut T>
86 {
87 match step_f(unsafe{ self.top_mut_internal() }) {
88 Some(new_node) => {
89 unsafe{ self.push(new_node); }
90 true
91 },
92 None => false
93 }
94 }
95 #[inline]
99 pub fn backtrack(&mut self) {
100 match self.stack.pop() {
101 Some(top_ptr) => {
102 self.top = top_ptr;
103 },
104 None => panic!("MutCursor must contain valid reference")
105 }
106 }
107 #[inline]
111 pub fn to_root(&mut self) {
112 if self.stack.len() > 0 {
113 self.stack.truncate(1);
114 self.top = self.stack.pop().unwrap();
115 }
116 }
117 #[inline]
119 unsafe fn top_mut_internal(&mut self) -> &'root mut T {
120 unsafe{ self.top.as_mut() }
121 }
122 #[inline]
124 unsafe fn push(&mut self, t_ref: &'root mut T) {
125 let mut top_ptr: NonNull<T> = t_ref.into();
126 core::mem::swap(&mut top_ptr, &mut self.top);
127 self.stack.push(top_ptr);
128 }
129}
130
131impl<'root, T: ?Sized> core::ops::Deref for MutCursorVec<'root, T> {
132 type Target = T;
133 fn deref(&self) -> &T {
134 self.top()
135 }
136}
137
138impl<'root, T: ?Sized> core::ops::DerefMut for MutCursorVec<'root, T> {
139 fn deref_mut(&mut self) -> &mut T {
140 self.top_mut()
141 }
142}
143
144#[cfg(test)]
145mod test {
146 use std::*;
147 use std::boxed::*;
148
149 use crate::*;
150
151 struct TreeNode {
152 val: usize,
153 next: Option<Box<TreeNode>>
154 }
155 impl TreeNode {
156 fn new(count: usize) -> Self {
157 if count > 0 {
158 Self {val: count, next: Some(Box::new(Self::new(count-1)))}
159 } else {
160 Self {val: 0, next: None}
161 }
162 }
163 fn traverse(&mut self) -> Option<&mut Self> {
164 self.next.as_mut().map(|boxed| &mut **boxed)
165 }
166 }
167
168 #[test]
169 fn basics_vec() {
170 let mut tree = TreeNode::new(10);
171 let mut node_stack = MutCursorVec::<TreeNode>::new(&mut tree);
172
173 while node_stack.advance(|node| {
174 node.traverse()
175 }) {}
176
177 assert_eq!(node_stack.top().val, 0);
178 assert_eq!(node_stack.depth(), 10);
179
180 node_stack.backtrack();
181 assert_eq!(node_stack.top().val, 1);
182 assert_eq!(node_stack.depth(), 9);
183
184 node_stack.backtrack();
185 node_stack.backtrack();
186 node_stack.backtrack();
187 assert_eq!(node_stack.top().val, 4);
188 assert_eq!(node_stack.depth(), 6);
189
190 while node_stack.advance(|node| {
191 node.traverse()
192 }) {}
193 assert_eq!(node_stack.top().val, 0);
194 assert_eq!(node_stack.depth(), 10);
195
196 node_stack.backtrack();
197 node_stack.backtrack();
198 node_stack.backtrack();
199 node_stack.backtrack();
200 node_stack.backtrack();
201 node_stack.backtrack();
202 assert_eq!(node_stack.top().val, 6);
203 assert_eq!(node_stack.depth(), 4);
204
205 assert_eq!(node_stack.into_mut().val, 6);
206 }
207
208 #[test]
210 fn miri_tagging_issue() {
211 let x = &mut 0;
212 let mut c = MutCursorVec::new(x);
213 c.advance(|x| Some(x));
214 c.backtrack();
215 println!("{}", c.top());
216 }
217}