For my project, χrust, I need to create a fully navigable and mutable tree.
By 'fully navigable' I mean parent <-> child traversals, as well as traversing siblings.
By 'mutable' I mean that the tree must be created (by parsing a specification such as JSON or XML, so I don't know the structure ahead of time), and then there is a phase where nodes may be added or removed from the tree, for example removing nodes that only contain whitespace. The tree doesn't have to be fully navigable during this phase: just depth-first traversal. After that phase, the tree can be made fully navigable but read-only.
Now, I've found a data structure that supports this use-case uses Weak references:
parent: Option<Weak<Node>>,
children: Vec<Rc<Node>>,
data: usize,
}
However, I can't work out how to create the tree structure without using interior mutability. I want to avoid interior mutability so that the last phase, read-only navigation, doesn't have a run-time penalty.
All my attempts to create the tree, without interior mutability, either run into borrow problems at compile-time, or fail at run-time in the get_mut function.
One example:
struct Node {
parent: Option<Weak<Node>>,
children: Vec<Rc<Node>>,
data: usize,
}
impl Node {
fn new(data: usize) -> Rc<Node> {
Rc::new(Node{parent: None, children: vec![], data})
}
}
trait NodeOps {
fn add_child(&mut self, n: &mut Rc<Node>);
}
impl NodeOps for Rc<Node> {
fn add_child(&mut self, n: &mut Rc<Node>) {
match Rc::get_mut(n) {
Some(m) => {
m.parent = Some(Rc::downgrade(self))
}
None => panic!("cannot get_mut child")
}
// get_mut of self fails because there is 1 strong reference and 1 weak reference
match Rc::get_mut(self) {
Some(m) => {
m.children.push(n.clone())
}
None => panic!("cannot get_mut parent")
}
}
}
fn main() {
let mut top = Node::new(1);
top.add_child(&mut Node::new(2));
println!("all good");
}
I've tried creating the child first, and then hooking it up to the parent. I've also tried creating children first, and then subsequently adding the Weak parent pointers. They all fail due to the same problem of not being able to get_mut something that already has Weak pointers to it.
So how can I create the tree without resorting to interior mutability?
Regards,
Steve Ball