I'm new to Rust, so I'm sorry if this question has an absolutely obvious solution. I cannot find cleaner way to write the code below. I know this code cause panic
because of container
is already borrowed.
return match &container.borrow().parent {
Some(parent) => {
container.borrow_mut().active = false;
Layout::move_focus(parent, direction, f)
}
None => Rc::clone(container),
}
Problem there is preventing me from changing a container
attributes while I'm match
ing parent
. Because of match
ing parent
and changing active
state, that are independent in my code, I think this code is safe.
I also know this can be solved by moving mutable borrow out of match
and changing match
to if let
as is shown in the code below. Variable active
is set to true
at the beginning.
{
container.borrow_mut().active = false;
}
if let Some(parent) = &container.borrow().parent {
return Layout::move_focus(parent, direction, f);
}
container.borrow_mut().active = true;
Rc::clone(container)
Is there a more readable and cleaner way to write code with the same functionality?
If it is important for solving this problem the whole code implements nodes that have containers on widgets inside, where containers must know their parents.
Function declaration:
pub fn move_focus(
container: &Rc<RefCell<Container>>,
direction: Direction,
f: fn(&RcCon) -> Option<Rc<RefCell<Container>>>,
) -> Rc<RefCell<Container>>
Structs:
pub struct Container {
pub items: Vec<Item>,
pub layout: Layout,
pub direction: Direction,
pub parent: Option<Rc<RefCell<Container>>,
pub act_index: usize,
pub active: bool,
}
pub enum Item {
Container(RcCon),
Widget(Holder),
}
You can borrow whole container as mut
firstly, and then do operations on it.
let mut c = container.borrow_mut();
return match c.parent {
Some(parent) => {
c.active = false;
Layout::move_focus(parent, direction, f)
}
None => Rc::clone(container),
}
Also passing &Rc
as an argument is not idiomatic rust. Prefer passing Rc
directly.