-
Notifications
You must be signed in to change notification settings - Fork 50
Alternative solution to "fn layout needs to mut borrow several nodes" #40
Description
Hi! I've just seen your awesome talk about data-driven UI's in Rust, and got intrigued by the problem of traversing a ECS-style tree while borrowing nodes mutably.
I think I have a similar problem in other domain: structured editing of syntax trees. Don't want to go into details about it, but if you want to code stuff "find or create node X and add A, B and C children to it", you also sort-of want two mutable borrows of different indices.
I'd like to share my solution, which is different from yours "implement trampoline/state machine by hand". I think it is actually worse for your use case due to interactions with object safety, but it's still interesting.
The idea is that instead of passing a &mut Node, one uses &mut Tree, NodeId. That way, it's possible to reborrow &mut Node as &mut tree[node_id] several times, and use borrowing via other indices in between. Now, this does have to go a number of additional contortions to actually work for dyn Widget state: you need to explicitly separate widget's state and behavior, and then introduce an additional trait to make that object safe, but it does work out in the end, and result looks like this:
struct Counter;
impl Widget for Counter {
type Data = usize;
fn layout(
ctx: &mut LayoutCtx, // insead of passing &mut Self, we pass an index and `&mut Ctx`
me: TypedId<Self>,
children: &[Id]
) -> usize {
for &id in children.iter() {
let child_layout = ctx.layout(id);
*ctx.data_mut(me) += child_layout;
}
*ctx.data_mut(me)
}
}On to re watching Flutter rendering pipeline talk! :)