From 8a4d2fb922c2c5a9e900b4b836d7787a09a1fe90 Mon Sep 17 00:00:00 2001 From: Adam Carpenter <53hornet@gmail.com> Date: Wed, 13 Mar 2019 10:02:15 -0400 Subject: Added concurrency, pointers, oop --- add/Cargo.toml | 7 ++ add/add-one/Cargo.toml | 8 ++ add/add-one/src/lib.rs | 11 +++ add/adder/Cargo.toml | 9 ++ add/adder/src/main.rs | 6 ++ blog/Cargo.toml | 7 ++ blog/src/lib.rs | 127 ++++++++++++++++++++++++ blog/src/main.rs | 36 +++++++ concurrency/Cargo.toml | 7 ++ concurrency/src/main.rs | 137 ++++++++++++++++++++++++++ guessing-game/Cargo.toml | 4 +- oop/Cargo.toml | 7 ++ oop/src/lib.rs | 41 ++++++++ oop/src/main.rs | 56 +++++++++++ smart-pointers/Cargo.toml | 7 ++ smart-pointers/src/main.rs | 234 +++++++++++++++++++++++++++++++++++++++++++++ 16 files changed, 703 insertions(+), 1 deletion(-) create mode 100644 add/Cargo.toml create mode 100644 add/add-one/Cargo.toml create mode 100644 add/add-one/src/lib.rs create mode 100644 add/adder/Cargo.toml create mode 100644 add/adder/src/main.rs create mode 100644 blog/Cargo.toml create mode 100644 blog/src/lib.rs create mode 100644 blog/src/main.rs create mode 100644 concurrency/Cargo.toml create mode 100644 concurrency/src/main.rs create mode 100644 oop/Cargo.toml create mode 100644 oop/src/lib.rs create mode 100644 oop/src/main.rs create mode 100644 smart-pointers/Cargo.toml create mode 100644 smart-pointers/src/main.rs diff --git a/add/Cargo.toml b/add/Cargo.toml new file mode 100644 index 0000000..37b9688 --- /dev/null +++ b/add/Cargo.toml @@ -0,0 +1,7 @@ +[workspace] + +members = [ + "adder", + "add-one", +] + diff --git a/add/add-one/Cargo.toml b/add/add-one/Cargo.toml new file mode 100644 index 0000000..88d65d1 --- /dev/null +++ b/add/add-one/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "add-one" +version = "0.1.0" +authors = ["Adam Carpenter <53hornet@gmail.com>"] +edition = "2018" + +[dependencies] +rand = "0.3.14" diff --git a/add/add-one/src/lib.rs b/add/add-one/src/lib.rs new file mode 100644 index 0000000..fe3583e --- /dev/null +++ b/add/add-one/src/lib.rs @@ -0,0 +1,11 @@ +pub fn add_one(x: i32) -> i32 { + x + 1 +} + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + assert_eq!(2 + 2, 4); + } +} diff --git a/add/adder/Cargo.toml b/add/adder/Cargo.toml new file mode 100644 index 0000000..1fefcc2 --- /dev/null +++ b/add/adder/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "adder" +version = "0.1.0" +authors = ["Adam Carpenter <53hornet@gmail.com>"] +edition = "2018" + +[dependencies] +add-one = { path = "../add-one" } + diff --git a/add/adder/src/main.rs b/add/adder/src/main.rs new file mode 100644 index 0000000..7099fb8 --- /dev/null +++ b/add/adder/src/main.rs @@ -0,0 +1,6 @@ +use add_one; + +fn main() { + let num = 10; + println!("{}", add_one::add_one(num)); +} diff --git a/blog/Cargo.toml b/blog/Cargo.toml new file mode 100644 index 0000000..0f971d3 --- /dev/null +++ b/blog/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "blog" +version = "0.1.0" +authors = ["Adam Carpenter <53hornet@gmail.com>"] +edition = "2018" + +[dependencies] diff --git a/blog/src/lib.rs b/blog/src/lib.rs new file mode 100644 index 0000000..8436a36 --- /dev/null +++ b/blog/src/lib.rs @@ -0,0 +1,127 @@ +//pub struct Post { +// state: Option>, +// content: String, +//} +// +//impl Post { +// pub fn new() -> Post { +// Post { +// state: Some(Box::new(Draft {})), +// content: String::new(), +// } +// } +// +// pub fn add_text(&mut self, text: &str) { +// self.content.push_str(text); +// } +// +// pub fn content(&self) -> &str { +// self.state.as_ref().unwrap().content(&self) +// } +// +// pub fn request_review(&mut self) { +// if let Some(s) = self.state.take() { +// self.state = Some(s.request_review()) +// } +// } +// +// pub fn approve(&mut self) { +// if let Some(s) = self.state.take() { +// self.state = Some(s.approve()) +// } +// } +//} +// +//trait State { +// fn request_review(self: Box) -> Box; +// fn approve(self: Box) -> Box; +// fn content<'a>(&self, post: &'a Post) -> &'a str { +// "" +// } +//} +// +//struct Draft {} +// +//impl State for Draft { +// fn request_review(self: Box) -> Box { +// Box::new(PendingReview {}) +// } +// +// fn approve(self: Box) -> Box { +// self +// } +//} +// +//struct PendingReview {} +// +//impl State for PendingReview { +// fn request_review(self: Box) -> Box { +// self +// } +// +// fn approve(self: Box) -> Box { +// Box::new(Published {}) +// } +//} +// +//struct Published {} +// +//impl State for Published { +// fn request_review(self: Box) -> Box { +// self +// } +// +// fn approve(self: Box) -> Box { +// self +// } +// +// fn content<'a>(&self, post: &'a Post) -> &'a str { +// &post.content +// } +//} + + + +pub struct Post { + content: String, +} + +pub struct DraftPost { + content: String, +} + +pub struct PendingReviewPost { + content: String, +} + +impl Post { + pub fn new() -> DraftPost { + DraftPost { + content: String::new(), + } + } + + pub fn content(&self) -> &str { + &self.content + } +} + +impl DraftPost { + pub fn add_text(&mut self, text: &str) { + self.content.push_str(text); + } + + pub fn request_review(self) -> PendingReviewPost { + PendingReviewPost { + content: self.content, + } + } +} + +impl PendingReviewPost { + pub fn approve(self) -> Post { + Post { + content: self.content, + } + } +} diff --git a/blog/src/main.rs b/blog/src/main.rs new file mode 100644 index 0000000..c976cd9 --- /dev/null +++ b/blog/src/main.rs @@ -0,0 +1,36 @@ +use blog::Post; + +fn main() { +// let mut post = Post::new(); +// +// post.add_text("salad"); +// assert_eq!("", post.content()); +// +// post.request_review(); +// assert_eq!("", post.content()); +// +// post.approve(); +// assert_eq!("salad", post.content()); + + + +// let mut post = Post::new(); +// post.add_text("salad"); +// assert_eq!("", post.content()); + + + + let mut post = Post::new(); + + post.add_text("salad"); + let post = post.request_review(); + let post = post.approve(); + + assert_eq!("salad", post.content()); + + + + + + println!("Done."); +} diff --git a/concurrency/Cargo.toml b/concurrency/Cargo.toml new file mode 100644 index 0000000..0bfe465 --- /dev/null +++ b/concurrency/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "concurrency" +version = "0.1.0" +authors = ["Adam Carpenter <53hornet@gmail.com>"] +edition = "2018" + +[dependencies] diff --git a/concurrency/src/main.rs b/concurrency/src/main.rs new file mode 100644 index 0000000..53417eb --- /dev/null +++ b/concurrency/src/main.rs @@ -0,0 +1,137 @@ +use std::sync::Arc; +use std::rc::Rc; +use std::sync::Mutex; +use std::thread; +use std::sync::mpsc; +use std::time::Duration; + +fn main() { +// let handle = thread::spawn(|| { +// for i in 1..10 { +// println!("spawned: {}", i); +// thread::sleep(Duration::from_millis(1)); +// } +// }); +// +// for i in 1..5 { +// println!("main: {}", i); +// thread::sleep(Duration::from_millis(1)); +// } +// +// handle.join().unwrap(); + + + +// let v = vec![1, 2, 3]; +// +// let handle = thread::spawn(move || { +// println!("Here's a vector: {:?}", v); +// }); +// +// drop(v); +// handle.join().unwrap(); + + + +// let (tx, rx) = mpsc::channel(); +// +// thread::spawn(move || { +// let val = String::from("hi"); +// tx.send(val).unwrap(); +// dbg!(val); +// }); +// +// let received = rx.recv().unwrap(); +// dbg!(received); + + + +// let (tx, rx) = mpsc::channel(); +// +// thread::spawn(move || { +// let vals = vec![ +// String::from("the"), +// String::from("walking"), +// String::from("thread"), +// ]; +// +// for val in vals { +// tx.send(val).unwrap(); +// thread::sleep(Duration::from_secs(1)); +// } +// }); +// +// for received in rx { +// println!("got {}", received); +// } + + + +// let (tx, rx) = mpsc::channel(); +// +// let tx1 = mpsc::Sender::clone(&tx); +// thread::spawn(move || { +// let vals = vec![ +// String::from("the"), +// String::from("walking"), +// String::from("thread"), +// ]; +// +// for val in vals { +// tx1.send(val).unwrap(); +// thread::sleep(Duration::from_secs(1)); +// } +// }); +// +// thread::spawn(move || { +// let vals = vec![ +// String::from("welcome"), +// String::from("to"), +// String::from("woodberry"), +// String::from("!"), +// ]; +// +// for val in vals { +// tx.send(val).unwrap(); +// thread::sleep(Duration::from_secs(1)); +// } +// }); +// +// for received in rx { +// dbg!(received); +// } + + + +// let m = Mutex::new(5); +// +// { +// let mut num = m.lock().unwrap(); +// *num = 6; +// } +// +// println!("m = {:?}", m); + + + + let counter = Arc::new(Mutex::new(0)); + let mut handles = vec![]; + + for _ in 0..10 { + let counter = Arc::clone(&counter); + let handle = thread::spawn(move || { + let mut num = counter.lock().unwrap(); + + *num += 1; + }); + handles.push(handle); + } + + for handle in handles { + handle.join().unwrap(); + } + + dbg!(*counter.lock().unwrap()); + + println!("Done."); +} diff --git a/guessing-game/Cargo.toml b/guessing-game/Cargo.toml index 8238fc5..08e8e30 100755 --- a/guessing-game/Cargo.toml +++ b/guessing-game/Cargo.toml @@ -1,8 +1,10 @@ [package] name = "guessing-game" version = "0.1.0" -authors = ["Adam Carpenter "] +authors = ["Adam Carpenter <53hornet@gmail.com>"] edition = "2018" +description = "A fun game where you guess what number the computer has chosen." +license = "MIT OR Apache-2.0" [dependencies] rand = "0.3.14" diff --git a/oop/Cargo.toml b/oop/Cargo.toml new file mode 100644 index 0000000..28311ff --- /dev/null +++ b/oop/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "oop" +version = "0.1.0" +authors = ["Adam Carpenter <53hornet@gmail.com>"] +edition = "2018" + +[dependencies] diff --git a/oop/src/lib.rs b/oop/src/lib.rs new file mode 100644 index 0000000..91ef2e8 --- /dev/null +++ b/oop/src/lib.rs @@ -0,0 +1,41 @@ +pub trait Draw { + fn draw(&self); +} + +pub struct Screen { + pub components: Vec>, +} + +impl Screen { + pub fn run(&self) { + for component in self.components.iter() { + component.draw(); + } + } +} + +pub struct Button { + pub width: u32, + pub height: u32, + pub label: String, +} + +impl Draw for Button { + fn draw(&self) { + dbg!("drew button"); + } +} + +pub struct SelectBox { + pub width: u32, + pub height: u32, + pub options: Vec, +} + +impl Draw for SelectBox { + fn draw(&self) { + dbg!("drew select box"); + } +} + + diff --git a/oop/src/main.rs b/oop/src/main.rs new file mode 100644 index 0000000..e92c07c --- /dev/null +++ b/oop/src/main.rs @@ -0,0 +1,56 @@ +use oop::{Screen, Button, SelectBox}; + +pub struct AveragedCollection { + list: Vec, + average: f64, +} + +impl AveragedCollection { + pub fn add(&mut self, value: i32) { + self.list.push(value); + self.update_average(); + } + + pub fn remove(&mut self) -> Option { + let result = self.list.pop(); + match result { + Some(value) => { + self.update_average(); + Some(value) + }, + None => None, + } + } + + pub fn average(&self) -> f64 { + self.average + } + + fn update_average(&mut self) { + let total: i32 = self.list.iter().sum(); + self.average = total as f64 / self.list.len() as f64; + } +} + +fn main() { + let screen = Screen { + components: vec![ + Box::new(SelectBox { + width: 75, + height: 10, + options: vec![ + String::from("Yes"), + String::from("Maybe"), + String::from("No") + ], + }), + Box::new(Button { + width: 50, + height: 10, + label: String::from("OK"), + }), + ], + }; + + screen.run(); +} diff --git a/smart-pointers/Cargo.toml b/smart-pointers/Cargo.toml new file mode 100644 index 0000000..0dcde9f --- /dev/null +++ b/smart-pointers/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "smart-pointers" +version = "0.1.0" +authors = ["Adam Carpenter <53hornet@gmail.com>"] +edition = "2018" + +[dependencies] diff --git a/smart-pointers/src/main.rs b/smart-pointers/src/main.rs new file mode 100644 index 0000000..5a59f52 --- /dev/null +++ b/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), +// Nil, +//} + +//#[derive(Debug)] +//enum List { +// Cons(Rc>, Rc), +// Nil, +//} + +#[derive(Debug)] +enum List { + Cons(i32, RefCell>), + Nil, +} + +impl List { + fn tail(&self) -> Option<&RefCell>> { + match self { + Cons(_, item) => Some(item), + Nil => None, + } + } +} + +//enum List { +// Cons(i32, Box), +// Nil, +//} + +struct MyBox(T); + +impl MyBox { + fn new(x: T) -> MyBox { + MyBox(x) + } +} + +impl Deref for MyBox { + 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>, + children: RefCell>>, +} + +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 { + 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>, + } + + 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); + } +} -- cgit v1.2.3