I have a struct Region
which contains [Option<Rc<RefCell<Region>>>; 2]
as its subregions
and Option<Weak<RefCell<Region>>>
as its container
. I am writing a method to insert a new Region
between self
and self.container
, which requires me to clone the Rc to self
to include in the newly created Region
as one of its subregions
. When self.container
is Some
this is possible because I can walk up to the container and then clone its subregion
that matches self
, but when self
has None
as its container, I do not know how to get a clone of the Rc
of self
from the &mut self
that is passed into the method.
Here is some code to make it clearer.
struct Region {
subregions: [Option<Rc<RefCell<Region>>>; 2],
container: Option<Weak<RefCell<Region>>>,
}
impl Region {
fn clone_from_container(&self) -> Option<Rc<RefCell<Region>>> {
Some(Rc::clone(&self.container
.as_ref()?
.upgrade()
.unwrap()
.borrow()
.subregions[self.from()]
.as_ref()
.unwrap()))
}
pub fn insert_above(&mut self) -> Rc<RefCell<Region>> {
let new = Rc::new(RefCell::new(Region {
subregion: [self.clone_from_container(),None],
container: self.container.clone(),
}));
self.replace(new.clone());
self.container = Some(Rc::downgrade(&new.clone()));
new
}
}
In my actual code there are a few more functions, but these are just aliases for long method chains to unbox the Rc
s and RefCell
s to allow me to actually get at the data. I've tried to keep it to the important details only.
The methods I've excluded, Region::replace
and Region::from
are pretty simple and their implementation don't matter. replace
walks up to the container
and replaces the reference to self
with the new region (very similar to clone_from_container
but to mutate the Region
), and from
simply finds the index of the Region
within its container
's subregions
(0 or 1)
When setting the subregion
of new
within, I would like to be able to say something like self.clone_from_container().or(Rc::clone(self))
, but obviously this isn't possible given the type that self
is passed as.
I figure it may just be necessary to have this be a static factory function, rather than an instance method, so we can pass self
with type Rc<RefCell<Region>>
, but I also thought it may be possible to use Rc::new_cyclic
; however, that function is somewhat confusing and I'm not quite sure how to employ it.
To simplify, I'm gonna say Rc<Region>
instead of Rc<RefCell<Region>>
If I understood correctly, this is your situation:
let region = Region::new()
let rc = Rc::new(region)
And you have a method such as:
impl Region {
fn my_function(&mut self) {
// Here you want to somehow get a reference to `rc` (the Rc that contains this region)
}
}
This is not possible, because Region
doesn't know that it is inside an Rc
. You have to somehow tell it that it is inside an Rc
.
One possible solution is to not use self
. For example:
impl Region {
fn my_function(value: Rc<Self>) {
// Now you have access to `rc`
}
}
Another option, as PitaJ suggested, is to make a trait for Rc<Region>
, in that case, self
would be Rc<Region>
, so you'd have access to Rc
.