Given Rc<RefCell<T>>, can I get an Rc<RefCell<>> to some data owned by T?

I'm trying to create a trait in the vein of serde's serialize but want to be able to modify data and then reserialize it within the trait. For the ability to read and modify, without thinking too hard, I decided to try to use Rc<RefCell<...>> as a kind of model.

The problem is I need to be able to call a function for "child" fields or parts of data that also implement this trait. I'm aware of map and map_mut on RefCell but these won't help because I need the Rc because the data needs to live for 'static as it could be used in event listeners registered elsewhere.

I have this psuedo code. Have any ideas or data types that could be more useful?

struct A { b: B }
struct B { foo: String }

impl MyTrait for A {
  fn my_fn(handle: Rc<RefCell<Self>>) {
    let b_handle = /* possible to get Rc<RefCell<B>>? */

    B::my_fn(b_handle)
  }
}

impl MyTrait for B {
  fn my_fn(handle: Rc<RefCell<Self>>) {
    // ...
  }
}

This is probably dumb but I'm playing around with a side project and wanted to use Rc<RefCell<...>> because its quick and easy.

One possibility:

struct A { b: Rc<RefCell<B>> }

I should have clarified I want to eventually use this in a derive macro and want to keep it more generic/abstracted away from any type definition. I wish it were as easy as that haha

You could add a method to A that returns a new struct that contains the refcell lock to A and implements Deref<Target = B>. This wouldn't be static though, and you could run into runtime problems if you are not careful, but it would work.

Other than that, you could add yet another struct that would contain the Rc to A, and that struct would return the previous struct which implements Deref<Target = B>. Now this struct is static but you need to call two methods to get to B.

No, Rc doesn't support offsets to its insides. There's OffsetArc in the triomphe crate.

And RefCell doesn't have a "mapped" version. There's MappedRwLockGuard in parking_lot.

Aaand these two won't work together, because the guard is a new object and not something stored in the Rc/Arc.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.