I have a tree structure like:
pub struct Tree {
children: Vec<Tree>
}
-
I am using
Cursor
to do read-only tree traversals. The cursor maintains the current position in the tree by storing traversal state in a stack. I like the design and it's working well. -
I would also like
CursorMut
to do read-write tree traversals. This cursor implementation is not passing the borrow checker. Storing mutable ancestors references in the traversal stack seems impossible. I think I understand each individual compiler error that I get, but maybe there's a way around the problems that I just can't figure out. -
I have managed to get read-write tree traversals in
CursorUnsafeMut
. There I store raw pointers in the stack to get around the borrowing problems. This seems to work, though I haven't tested much beyond getting it to compile, and it's using unsafe code.
My questions...
-
Is there some way to
CursorMut
work without unsafe code? -
If not then is it reasonable to store raw pointers in the stack as
CursorUnsafeMut
is doing?
pub struct Tree {
children: Vec<Tree>,
}
// 1. Working, but read-only
pub struct Cursor<'a> {
root: &'a Tree,
stack: Vec<&'a Tree>,
}
// 2. Not compiling
pub struct CursorMut<'a> {
root: &'a mut Tree,
stack: Vec<&'a mut Tree>,
}
// 3. Working, but using unsafe code
pub struct CursorUnsafeMut<'a> {
root: &'a mut Tree,
stack: Vec<*mut Tree>,
}
impl<'a> Cursor<'a> {
fn first_leaf(&mut self) -> &Tree {
let parent = self.stack.last().unwrap_or(&self.root);
if let Some(child) = parent.children.first() {
self.stack.push(child);
self.first_leaf()
} else {
parent
}
}
}
impl<'a> CursorMut<'a> {
fn first_leaf_mut(&mut self) -> &mut Tree {
let parent = self.stack.last_mut().unwrap_or(&mut self.root);
if let Some(child) = parent.children.first_mut() {
self.stack.push(child);
self.first_leaf_mut()
} else {
parent
}
}
}
impl<'a> CursorUnsafeMut<'a> {
fn first_leaf_mut(&mut self) -> &mut Tree {
let mut root_prt = self.root as *mut Tree;
let parent = self.stack.last_mut().unwrap_or(&mut root_prt);
if let Some(child) = unsafe { (**parent).children.first_mut() } {
self.stack.push(child);
self.first_leaf_mut()
} else {
unsafe { &mut **parent }
}
}
}