I'm studying rust and I'm stuck on a question about Rc, Weak and RefCell. The use case is to implement a fully functioning tree, where each node has one parent and a list of children. The documentation provides a good starting point:
use std::cell::RefCell;
use std::rc::{Rc, Weak};
#[derive(Debug)]
struct Node {
value: i32,
parent: RefCell<Weak<Node>>,
children: RefCell<Vec<Rc<Node>>>,
}
fn main() {
let leaf = Rc::new(Node {
value: 3,
parent: RefCell::new(Weak::new()),
children: RefCell::new(vec![]),
});
println!("leaf parent = {:?}", leaf.parent.borrow().upgrade());
let branch = Rc::new(Node {
value: 5,
parent: RefCell::new(Weak::new()),
children: RefCell::new(vec![Rc::clone(&leaf)]),
});
*leaf.parent.borrow_mut() = Rc::downgrade(&branch);
println!("leaf parent = {:?}", leaf.parent.borrow().upgrade());
}
But. When I try to expand upon this, there's a problem with the design. I cannot add a new node to an already consisting one. The branch
node has a child, but this I think is only possible because we already know leaf
is going to be the one and only child before branch
is created. If this is not the case, can we somehow change branch
after it already has been created inside an Rc
and add leaf
as a child?
Or should I leave this design and adopt a design that looks more like:
#[derive(Debug)]
struct Node {
value: i32,
parent: Weak<RefCell<Node>>,
children: Vec<Rc<RefCell<Node>>>,
}