summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Carpenter <53hornet@gmail.com>2019-03-13 10:02:15 -0400
committerAdam Carpenter <53hornet@gmail.com>2019-03-13 10:02:15 -0400
commit8a4d2fb922c2c5a9e900b4b836d7787a09a1fe90 (patch)
treeafb760597bf4cc78194892be910febde0209f7f3
parentb71e253b697bae079a0cf2526209334f4b81f9a5 (diff)
downloadlearning-rust-8a4d2fb922c2c5a9e900b4b836d7787a09a1fe90.tar.xz
learning-rust-8a4d2fb922c2c5a9e900b4b836d7787a09a1fe90.zip
Added concurrency, pointers, oop
-rw-r--r--add/Cargo.toml7
-rw-r--r--add/add-one/Cargo.toml8
-rw-r--r--add/add-one/src/lib.rs11
-rw-r--r--add/adder/Cargo.toml9
-rw-r--r--add/adder/src/main.rs6
-rw-r--r--blog/Cargo.toml7
-rw-r--r--blog/src/lib.rs127
-rw-r--r--blog/src/main.rs36
-rw-r--r--concurrency/Cargo.toml7
-rw-r--r--concurrency/src/main.rs137
-rwxr-xr-xguessing-game/Cargo.toml4
-rw-r--r--oop/Cargo.toml7
-rw-r--r--oop/src/lib.rs41
-rw-r--r--oop/src/main.rs56
-rw-r--r--smart-pointers/Cargo.toml7
-rw-r--r--smart-pointers/src/main.rs234
16 files changed, 703 insertions, 1 deletions
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<Box<dyn State>>,
+// 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<Self>) -> Box<dyn State>;
+// fn approve(self: Box<Self>) -> Box<dyn State>;
+// fn content<'a>(&self, post: &'a Post) -> &'a str {
+// ""
+// }
+//}
+//
+//struct Draft {}
+//
+//impl State for Draft {
+// fn request_review(self: Box<Self>) -> Box<dyn State> {
+// Box::new(PendingReview {})
+// }
+//
+// fn approve(self: Box<Self>) -> Box<dyn State> {
+// self
+// }
+//}
+//
+//struct PendingReview {}
+//
+//impl State for PendingReview {
+// fn request_review(self: Box<Self>) -> Box<dyn State> {
+// self
+// }
+//
+// fn approve(self: Box<Self>) -> Box<dyn State> {
+// Box::new(Published {})
+// }
+//}
+//
+//struct Published {}
+//
+//impl State for Published {
+// fn request_review(self: Box<Self>) -> Box<dyn State> {
+// self
+// }
+//
+// fn approve(self: Box<Self>) -> Box<dyn State> {
+// 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 <carpenat@ES.AD.ADP.COM>"]
+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<Box<dyn Draw>>,
+}
+
+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<String>,
+}
+
+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<i32>,
+ average: f64,
+}
+
+impl AveragedCollection {
+ pub fn add(&mut self, value: i32) {
+ self.list.push(value);
+ self.update_average();
+ }
+
+ pub fn remove(&mut self) -> Option<i32> {
+ 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<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);
+ }
+}