diff options
Diffstat (limited to 'rust-book/smart-pointers/src/main.rs')
-rwxr-xr-x | rust-book/smart-pointers/src/main.rs | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/rust-book/smart-pointers/src/main.rs b/rust-book/smart-pointers/src/main.rs new file mode 100755 index 0000000..5a59f52 --- /dev/null +++ b/rust-book/smart-pointers/src/main.rs @@ -0,0 +1,234 @@ +use List::{Cons, Nil}; +use std::cell::RefCell; +use std::ops::Deref; +use std::rc::{Rc, Weak}; + +//enum List { +// Cons(i32, Rc<List>), +// Nil, +//} + +//#[derive(Debug)] +//enum List { +// Cons(Rc<RefCell<i32>>, Rc<List>), +// Nil, +//} + +#[derive(Debug)] +enum List { + Cons(i32, RefCell<Rc<List>>), + Nil, +} + +impl List { + fn tail(&self) -> Option<&RefCell<Rc<List>>> { + match self { + Cons(_, item) => Some(item), + Nil => None, + } + } +} + +//enum List { +// Cons(i32, Box<List>), +// Nil, +//} + +struct MyBox<T>(T); + +impl<T> MyBox<T> { + fn new(x: T) -> MyBox<T> { + MyBox(x) + } +} + +impl<T> Deref for MyBox<T> { + type Target = T; + fn deref(&self) -> &T { + &self.0 + } +} + +struct CustomSmartPointer { + data: String, +} + +impl Drop for CustomSmartPointer { + fn drop(&mut self) { + println!("Dropped `{}`", self.data); + } +} + +#[derive(Debug)] +struct Node { + value: i32, + parent: RefCell<Weak<Node>>, + children: RefCell<Vec<Rc<Node>>>, +} + +fn main() { +// let x = 5; +// let y = MyBox::new(x); +// +// assert_eq!(5, x); +// assert_eq!(5, *y); + +// let m = MyBox::new(String::from("world")); +// hello(&m); + +// let c = CustomSmartPointer { data: String::from("my stuff") }; +// drop(c); +// let d = CustomSmartPointer { data: String::from("other stuff") }; +// println!("created."); + +// let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil))))); +// dbg!(Rc::strong_count(&a)); +// let b = Cons(3, Rc::clone(&a)); +// dbg!(Rc::strong_count(&a)); +// { +// let c = Cons(4, Rc::clone(&a)); +// dbg!(Rc::strong_count(&a)); +// } +// dbg!(Rc::strong_count(&a)); + +// let value = Rc::new(RefCell::new(5)); +// +// let a = Rc::new(Cons(Rc::clone(&value), Rc::new(Nil))); +// +// let b = Cons(Rc::new(RefCell::new(6)), Rc::clone(&a)); +// let c = Cons(Rc::new(RefCell::new(10)), Rc::clone(&a)); +// +// *value.borrow_mut() += 10; +// +// dbg!(a); +// dbg!(b); +// dbg!(c); + +// let a = Rc::new(Cons(5, RefCell::new(Rc::new(Nil)))); +// dbg!(Rc::strong_count(&a)); +// dbg!(a.tail()); +// let b = Rc::new(Cons(10, RefCell::new(Rc::clone(&a)))); +// dbg!(Rc::strong_count(&a)); +// dbg!(Rc::strong_count(&b)); +// dbg!(b.tail()); +// +// if let Some(link) = a.tail() { +// *link.borrow_mut() = Rc::clone(&b); +// } +// +// dbg!(Rc::strong_count(&b)); +// dbg!(Rc::strong_count(&a)); + + //dbg!(a.tail()); // stack overflow + + let leaf = Rc::new(Node { + value: 3, + parent: RefCell::new(Weak::new()), + children: RefCell::new(vec![]), + }); + + println!("leaf strong = {}, weak = {}", + Rc::strong_count(&leaf), + Rc::weak_count(&leaf),); + + { + let branch = Rc::new(Node { + value: 5, + parent: RefCell::new(Weak::new()), + children: RefCell::new(vec![Rc::clone(&leaf)]), + }); + + *leaf.parent.borrow_mut() = Rc::downgrade(&branch); + + println!( + "branch strong = {}, weak = {}", + Rc::strong_count(&branch), + Rc::weak_count(&branch), + ); + + println!( + "leaf strong = {}, weak = {}", + Rc::strong_count(&leaf), + Rc::weak_count(&leaf), + ); + } + + println!("leaf parent = {:?}", leaf.parent.borrow().upgrade()); + println!( + "leaf strong = {}, weak = {}", + Rc::strong_count(&leaf), + Rc::weak_count(&leaf), + ); +} + +fn hello(name: &str) { + println!("hiya {}", name); +} + +pub trait Messenger { + fn send(&self, msg: &str); +} + +pub struct LimitTracker<'a, T: 'a + Messenger> { + messenger: &'a T, + value: usize, + max: usize, +} + +impl<'a, T> LimitTracker<'a, T> where T: Messenger { + pub fn new(messenger: &T, max: usize) -> LimitTracker<T> { + LimitTracker { + messenger, + value: 0, + max, + } + } + + pub fn set_value(&mut self, value: usize) { + self.value = value; + + let percentage_of_max = self.value as f64 / self.max as f64; + + if percentage_of_max >= 1.0 { + self.messenger.send("over quota"); + } + else if percentage_of_max >= 0.9 { + self.messenger.send("90% of quota"); + } + else if percentage_of_max >= 0.75 { + self.messenger.send("75% of quota"); + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::cell::RefCell; + + struct MockMessenger { + sent_messages: RefCell<Vec<String>>, + } + + impl MockMessenger { + fn new() -> MockMessenger { + MockMessenger { sent_messages: RefCell::new(vec![]) } + } + } + + impl Messenger for MockMessenger { + fn send(&self, message: &str) { + self.sent_messages.borrow_mut().push(String::from(message)); + } + } + + #[test] + fn sends_75() { + let mock_messenger = MockMessenger::new(); + let mut limit_tracker = LimitTracker::new(&mock_messenger, 100); + + limit_tracker.set_value(80); + + assert_eq!(mock_messenger.sent_messages.borrow().len(), 1); + } +} |