Last active
February 9, 2022 10:20
-
-
Save davidlopezre/99cca2e2a267a691f691ed07359cfde2 to your computer and use it in GitHub Desktop.
Demonstration of Rc and Weak references
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::cell::RefCell; | |
use std::rc::Weak; | |
#[derive(Debug)] | |
pub struct Node<T> { | |
data: T, | |
// must be a RefCell because we want to store non Copy type `Vec` | |
// while allowing interior mutability (necessary for this cyclic type) | |
// this doesn't necessarily need to be weak, it is just for learning | |
// purposes | |
edges: RefCell<Vec<Weak<Node<T>>>>, | |
} | |
impl<T> Node<T> { | |
pub fn new(new_data: T) -> Node<T> { | |
Node { | |
data: new_data, | |
edges: RefCell::new(vec![]), | |
} | |
} | |
pub fn new_with_children(new_data: T, children: Vec<Weak<Node<T>>>) -> Node<T> { | |
Node { | |
data: new_data, | |
edges: RefCell::new(children), | |
} | |
} | |
pub fn add_child(&self, node: Weak<Node<T>>) { | |
self.edges.borrow_mut().push(node); | |
} | |
pub fn find(&self, query: &T) -> bool | |
where | |
T: Eq, | |
{ | |
if self.data == *query { | |
return true; | |
} | |
for n in self.edges.borrow().iter() { | |
if let Some(i) = n.upgrade() { | |
if i.find(query) { | |
return true; | |
} | |
} else { | |
println!("no strong references to this value so it was dropped") | |
} | |
} | |
return false; | |
} | |
} | |
#[cfg(test)] | |
mod tests { | |
use crate::Node; | |
use std::rc::Rc; | |
#[test] | |
fn find_test() { | |
let n1 = Node::new(1); | |
let n3 = Node::new(3); | |
let rc3 = Rc::new(n3); | |
// the first element in `children` will not be upgradable because | |
// there is no strong references to it. The second element in | |
// children has `rc3` as a strong reference so it won't be dropped until | |
// the test function terminates | |
let graph = Rc::new(Node::new_with_children( | |
5, | |
vec![Rc::downgrade(&Rc::new(n1)), Rc::downgrade(&rc3)], | |
)); | |
println!("{:?}", graph); | |
let result = graph.find(&1); | |
assert_eq!(true, result); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment