Skip to content

Instantly share code, notes, and snippets.

@yongkyuns
Created December 30, 2020 01:42
Show Gist options
  • Save yongkyuns/859bf6f78d4a637f0caaf51d93c9a436 to your computer and use it in GitHub Desktop.
Save yongkyuns/859bf6f78d4a637f0caaf51d93c9a436 to your computer and use it in GitHub Desktop.
Modelling child that holds partial reference to parent's data using Rc,RefCell
use std::cell::RefCell;
use std::rc::Rc;
use std::rc::Weak;
pub type RefPoint = Rc<RefCell<Point>>;
pub type WeakPoint = Weak<RefCell<Point>>;
#[derive(Debug)]
pub struct Point {
x: f32,
y: f32,
}
#[derive(Debug)]
pub struct Object {
pub position: RefPoint,
pub origin: Option<WeakPoint>,
}
impl Object {
pub fn new() -> Self {
Self {
position: Rc::new(RefCell::new(Point { x: 0.0, y: 0.0 })),
origin: None,
}
}
pub fn set_origin(&mut self, parent: RefPoint) {
self.origin = Some(Rc::downgrade(&parent));
}
pub fn move_by(&mut self, x: f32, y: f32) {
self.position.borrow_mut().x += x;
self.position.borrow_mut().y += y;
}
pub fn get_origin(&self) -> Option<Point> {
if let Some(origin) = &self.origin {
if let Some(point) = origin.upgrade() {
let p = point.borrow();
Some(Point { x: p.x, y: p.y })
} else {
None
}
} else {
None
}
}
}
impl HasRefPosition for Object {
fn position(&self) -> RefPoint {
Rc::clone(&self.position)
}
}
pub trait HasRefPosition {
fn position(&self) -> RefPoint;
fn move_by(&mut self, x: f32, y: f32) {
let point = self.position();
let mut p = point.borrow_mut();
p.x += x;
p.y += y;
}
}
fn main() {
let mut child = Object::new();
{
let mut parent = Object::new();
child.set_origin(Rc::clone(&parent.position));
parent.move_by(5.0, 5.0);
dbg!("{:?}", child.get_origin()); // Here, child's origin is properly pointing to parent's mutated position
}
dbg!("{:?}", child.get_origin()); // After parent goes out of scope, child's reference to parent becomes `None`
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment