summaryrefslogtreecommitdiff
path: root/rust-book/smart-pointers/src
diff options
context:
space:
mode:
Diffstat (limited to 'rust-book/smart-pointers/src')
-rwxr-xr-xrust-book/smart-pointers/src/main.rs234
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);
+ }
+}