mutcursor/mut_cursor_vec.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
extern crate alloc;
/// Similar to [MutCursor](crate::MutCursor), but allows for a dynamically growing stack
///
/// `MutCursorVec` is not available if the `no_std` feature is set
pub struct MutCursorVec<'root, T: ?Sized + 'root> {
top: &'root mut T,
stack: alloc::vec::Vec<*mut T>,
}
unsafe impl<'a, T> Sync for MutCursorVec<'a, T> where &'a mut T: Sync + Send, T: ?Sized {}
unsafe impl<'a, T> Send for MutCursorVec<'a, T> where &'a mut T: Sync + Send, T: ?Sized {}
impl<'root, T: ?Sized + 'root> MutCursorVec<'root, T> {
/// Returns a new `MutCursorVec` with a reference to the specified root
#[inline]
pub fn new(root: &'root mut T) -> Self {
Self {
top: root,
stack: alloc::vec::Vec::new(),
}
}
/// Returns a new `MutCursorVec` with a reference to the specified root, and an allocated buffer
/// for `capacity` references
#[inline]
pub fn new_with_capacity(root: &'root mut T, capacity: usize) -> Self {
Self {
top: root,
stack: alloc::vec::Vec::with_capacity(capacity),
}
}
/// Returns a const reference from the mutable reference on the top of the stack
#[inline]
pub fn top(&self) -> &T {
self.top
}
/// Returns the mutable reference on the top of the stack
#[inline]
pub fn top_mut(&mut self) -> &mut T {
self.top
}
/// Returns the mutable reference on the top of the stack, consuming the stack
#[inline]
pub fn into_mut(self) -> &'root mut T {
self.top
}
/// Consumes the stack and returns a mutable reference to an object with the `'root` lifetime,
/// if a closure returns `Ok`, otherwise returns the stack and a custom error value
///
/// NOTE: Usage is identical to [MutCursor::try_map_into_mut](crate::MutCursor::try_map_into_mut)
#[inline]
pub fn try_map_into_mut<U, E, F>(mut self, f: F) -> Result<&'root mut U, (Self, E)>
where for<'r> F: FnOnce(&'r mut T) -> Result<&'r mut U, E>
{
let top_ref = unsafe{ self.top_mut_internal() };
match f(top_ref) {
Ok(r) => Ok(r),
Err(e) => Err((self, e))
}
}
/// Returns the number of excess references stored in the stack, which corresponds to the number of
/// times [backtrack](Self::backtrack) may be called
#[inline]
pub fn depth(&self) -> usize {
self.stack.len()
}
/// Returns the number of references the stack is capable of holding without reallocation
#[inline]
pub fn capacity(&self) -> usize {
self.stack.capacity() + 1
}
/// Steps deeper into the traversal, pushing a new reference onto the top of the stack
///
/// If the `step_f` closure returns `Some()`, the contained reference is pushed onto the stack and
/// this method returns `true`. If the closure returns `None` then the stack is unmodified and this
/// method returns `false`.
#[inline]
pub fn advance<F>(&mut self, step_f: F) -> bool
where F: FnOnce(&'root mut T) -> Option<&'root mut T>
{
match step_f(unsafe{ self.top_mut_internal() }) {
Some(new_node) => {
unsafe{ self.push(new_node); }
true
},
None => false
}
}
/// Pops a reference from the stack, exposing the prior reference as the new [top](Self::top)
///
/// This method will panic if the stack contains only 1 entry
#[inline]
pub fn backtrack(&mut self) {
match self.stack.pop() {
Some(top_ptr) => {
self.top = unsafe{ &mut *top_ptr };
},
None => panic!("MutCursor must contain valid reference")
}
}
/// Pops all references from the stack, exposing the root reference as the [top](Self::top)
///
/// This method does nothing if the stack is already at the root
#[inline]
pub fn to_root(&mut self) {
if self.stack.len() > 0 {
self.stack.truncate(1);
let top_ptr = self.stack.pop().unwrap();
self.top = unsafe{ &mut *top_ptr };
}
}
/// Private
#[inline]
unsafe fn top_mut_internal(&mut self) -> &'root mut T {
unsafe{ &mut *(self.top as *mut T) }
}
/// Private
#[inline]
unsafe fn push(&mut self, t_ref: &'root mut T) {
self.stack.push(self.top as *mut T);
self.top = t_ref;
}
}
impl<'root, T: ?Sized> core::ops::Deref for MutCursorVec<'root, T> {
type Target = T;
fn deref(&self) -> &T {
self.top()
}
}
impl<'root, T: ?Sized> core::ops::DerefMut for MutCursorVec<'root, T> {
fn deref_mut(&mut self) -> &mut T {
self.top_mut()
}
}
#[cfg(test)]
mod test {
extern crate std;
use std::*;
use std::boxed::*;
use crate::*;
struct TreeNode {
val: usize,
next: Option<Box<TreeNode>>
}
impl TreeNode {
fn new(count: usize) -> Self {
if count > 0 {
Self {val: count, next: Some(Box::new(Self::new(count-1)))}
} else {
Self {val: 0, next: None}
}
}
fn traverse(&mut self) -> Option<&mut Self> {
self.next.as_mut().map(|boxed| &mut **boxed)
}
}
#[test]
fn basics_vec() {
let mut tree = TreeNode::new(10);
let mut node_stack = MutCursorVec::<TreeNode>::new(&mut tree);
while node_stack.advance(|node| {
node.traverse()
}) {}
assert_eq!(node_stack.top().val, 0);
assert_eq!(node_stack.depth(), 10);
node_stack.backtrack();
assert_eq!(node_stack.top().val, 1);
assert_eq!(node_stack.depth(), 9);
node_stack.backtrack();
node_stack.backtrack();
node_stack.backtrack();
assert_eq!(node_stack.top().val, 4);
assert_eq!(node_stack.depth(), 6);
while node_stack.advance(|node| {
node.traverse()
}) {}
assert_eq!(node_stack.top().val, 0);
assert_eq!(node_stack.depth(), 10);
node_stack.backtrack();
node_stack.backtrack();
node_stack.backtrack();
node_stack.backtrack();
node_stack.backtrack();
node_stack.backtrack();
assert_eq!(node_stack.top().val, 6);
assert_eq!(node_stack.depth(), 4);
assert_eq!(node_stack.into_mut().val, 6);
}
}