commit 26d8ef84511c63c4762e2019deec16034292dedd Author: Nathan Stocks Date: Sat Jun 12 22:36:24 2021 -0600 Add example files diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2f7a7bf --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ + +# Generated by Cargo +# will have compiled files and executables +**/target/ + +# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries +# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html +**/Cargo.lock + +# These are backup files generated by rustfmt +**/*.rs.bk + +# Generated by VS Code +**/.vscode diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..fe6ee06 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[workspace] +members = [ + "examples/cafeteria", + "examples/hello", + "examples/kitchen", + "examples/puzzle_game", + "examples/puzzles", +] diff --git a/examples/cafeteria/.gitignore b/examples/cafeteria/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/examples/cafeteria/.gitignore @@ -0,0 +1 @@ +/target diff --git a/examples/cafeteria/Cargo.toml b/examples/cafeteria/Cargo.toml new file mode 100644 index 0000000..884ffca --- /dev/null +++ b/examples/cafeteria/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "cafeteria" +version = "0.1.0" +authors = ["Nathan Stocks "] +edition = "2018" + +[dependencies] +crossbeam = "0.8" diff --git a/examples/cafeteria/src/main.rs b/examples/cafeteria/src/main.rs new file mode 100644 index 0000000..4e5d3b4 --- /dev/null +++ b/examples/cafeteria/src/main.rs @@ -0,0 +1,57 @@ +use crossbeam::channel::{self, Receiver, Sender}; +use std::{thread, time::Duration}; + +#[derive(Debug)] +enum Lunch { + Soup, + Salad, + Sandwich, + HotDog, +} + +fn cafeteria_worker(name: &str, orders: Receiver<&str>, lunches: Sender) { + for order in orders { + println!("{} receives an order for {}", name, order); + let lunch = match &order { + x if x.contains("soup") => Lunch::Soup, + x if x.contains("salad") => Lunch::Salad, + x if x.contains("sandwich") => Lunch::Sandwich, + _ => Lunch::HotDog, + }; + for _ in 0..order.len() { + thread::sleep(Duration::from_secs_f32(0.1)) + } + println!("{} sends a {:?}", name, lunch); + if lunches.send(lunch).is_err() { + break; + } + } +} + +fn main() { + let (orders_tx, orders_rx) = channel::unbounded(); + let orders_rx2 = orders_rx.clone(); + let (lunches_tx, lunches_rx) = channel::unbounded(); + let lunches_tx2 = lunches_tx.clone(); + + let alice_handle = thread::spawn(|| cafeteria_worker("alice", orders_rx2, lunches_tx2)); + let zack_handle = thread::spawn(|| cafeteria_worker("zack", orders_rx, lunches_tx)); + + for order in vec![ + "polish dog", + "caesar salad", + "onion soup", + "reuben sandwich", + ] { + println!("ORDER: {}", order); + let _ = orders_tx.send(order); + } + drop(orders_tx); + + for lunch in lunches_rx { + println!("Order Up! -> {:?}", lunch); + } + + let _ = alice_handle.join(); + let _ = zack_handle.join(); +} diff --git a/examples/hello/Cargo.toml b/examples/hello/Cargo.toml new file mode 100644 index 0000000..0a92cb2 --- /dev/null +++ b/examples/hello/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "hello" +version = "0.1.0" +authors = ["Nathan Stocks "] +edition = "2018" + +[dependencies] + +[dev-dependencies] +criterion = { version = "0.3", features = ["html_reports"] } + +[[bench]] +name = "snuggle_speed" +harness = false diff --git a/examples/hello/benches/snuggle_speed.rs b/examples/hello/benches/snuggle_speed.rs new file mode 100644 index 0000000..f174480 --- /dev/null +++ b/examples/hello/benches/snuggle_speed.rs @@ -0,0 +1,9 @@ +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use hello::snuggle; + +pub fn snuggle_benchmark(c: &mut Criterion) { + c.bench_function("snuggle 2", |b| b.iter(|| snuggle(black_box(2)))); +} + +criterion_group!(benches, snuggle_benchmark); +criterion_main!(benches); diff --git a/examples/hello/src/lib.rs b/examples/hello/src/lib.rs new file mode 100644 index 0000000..0b1690f --- /dev/null +++ b/examples/hello/src/lib.rs @@ -0,0 +1,35 @@ +/// # Example +/// +/// ``` +/// # use hello::snuggle; +/// let bunnies = snuggle(5); +/// assert_eq!(bunnies, 40); +/// ``` +pub fn snuggle(bunnies: u128) -> u128 { + bunnies << 3 +} + +#[cfg(test)] +mod test { + use std::num::ParseIntError; + + use super::*; + + #[test] + fn snuggling_bunnies_multiply() { + assert_eq!(snuggle(2), 16); + } + + #[should_panic] + #[test] + fn scared_bunny() { + panic!("Hop hoppity hop!"); + } + + #[test] + fn bunny_result() -> Result<(), ParseIntError> { + let num_bunnies: u64 = "4".parse()?; + assert_eq!(num_bunnies, 4); + Ok(()) + } +} diff --git a/examples/hello/src/main.rs b/examples/hello/src/main.rs new file mode 100644 index 0000000..b378a5e --- /dev/null +++ b/examples/hello/src/main.rs @@ -0,0 +1,10 @@ +fn main() {} + +#[cfg(test)] +mod test { + + #[test] + fn the_bin_test() { + assert_eq!(1 + 1, 2); + } +} diff --git a/examples/hello/tests/anything.rs b/examples/hello/tests/anything.rs new file mode 100644 index 0000000..2d4ccdb --- /dev/null +++ b/examples/hello/tests/anything.rs @@ -0,0 +1,6 @@ +use hello::snuggle; + +#[test] +fn it_works_from_outside() { + assert!(snuggle(4) == 32); +} diff --git a/examples/kitchen/Cargo.toml b/examples/kitchen/Cargo.toml new file mode 100644 index 0000000..2eb60c9 --- /dev/null +++ b/examples/kitchen/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "kitchen" +version = "0.1.0" +authors = ["Nathan Stocks "] +edition = "2018" + +[dependencies] +log = "0.4" +env_logger = "0.8" diff --git a/examples/kitchen/src/main.rs b/examples/kitchen/src/main.rs new file mode 100644 index 0000000..17031ab --- /dev/null +++ b/examples/kitchen/src/main.rs @@ -0,0 +1,43 @@ +use log::{error, info}; +use std::{thread, time::Duration}; + +fn sleep(seconds: f32) { + thread::sleep(Duration::from_secs_f32(seconds)); +} + +pub mod dad { + use super::{info, sleep}; + + pub fn cook_spaghetti() -> bool { + info!("Cooking the spaghetti..."); + sleep(4.0); + info!("Spaghetti is ready!"); + true + } +} + +pub mod mom { + use super::{info, sleep}; + + pub fn cook_sauce_and_set_table() { + sleep(1.0); + info!("Cooking the sauce..."); + sleep(2.0); + info!("Sauce is ready! Setting the table..."); + sleep(2.0); + info!("Table is set!"); + } +} + +fn main() { + env_logger::init(); + let handle = thread::spawn(|| dad::cook_spaghetti()); + + mom::cook_sauce_and_set_table(); + + if handle.join().unwrap_or(false) { + info!("Spaghetti time! Yum!") + } else { + error!("Dad messed up the spaghetti. Order pizza instead?"); + } +} diff --git a/examples/puzzle_game/.gitignore b/examples/puzzle_game/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/examples/puzzle_game/.gitignore @@ -0,0 +1 @@ +/target diff --git a/examples/puzzle_game/Cargo.toml b/examples/puzzle_game/Cargo.toml new file mode 100644 index 0000000..2f8b91b --- /dev/null +++ b/examples/puzzle_game/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "puzzle_game" +version = "0.1.0" +authors = ["Nathan Stocks "] +edition = "2018" + +[dependencies] +anyhow = "1.0" +puzzles = { path = "../puzzles" } +log = "0.4" +env_logger = "0.8" diff --git a/examples/puzzle_game/puzzle.dat b/examples/puzzle_game/puzzle.dat new file mode 100644 index 0000000..76ade0f --- /dev/null +++ b/examples/puzzle_game/puzzle.dat @@ -0,0 +1 @@ +this is a puzzle diff --git a/examples/puzzle_game/src/main.rs b/examples/puzzle_game/src/main.rs new file mode 100644 index 0000000..591d97c --- /dev/null +++ b/examples/puzzle_game/src/main.rs @@ -0,0 +1,21 @@ +use anyhow::{Context, Result}; +use log::info; +use puzzles::Puzzle; +use std::fs::File; + +fn get_puzzle(filename: &str) -> Result { + let fh = File::open(filename) + .with_context(|| format!("couldn't open the puzzle file {}", filename))?; + let puzzle = Puzzle::from_file(fh).context("couldn't convert data into a puzzle")?; + Ok(puzzle) +} + +fn main() -> Result<()> { + env_logger::init(); + let puzzle = match get_puzzle("puzzle.dat").context("Couldn't get the first puzzle") { + Ok(p) => p, + Err(_) => Puzzle::new(), + }; + info!("Playing puzzle: {}", puzzle.name); + Ok(()) +} diff --git a/examples/puzzles/.gitignore b/examples/puzzles/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/examples/puzzles/.gitignore @@ -0,0 +1 @@ +/target diff --git a/examples/puzzles/Cargo.toml b/examples/puzzles/Cargo.toml new file mode 100644 index 0000000..caa54c9 --- /dev/null +++ b/examples/puzzles/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "puzzles" +version = "0.1.0" +authors = ["Nathan Stocks "] +edition = "2018" + +[dependencies] +thiserror = "1.0" +log = "0.4" diff --git a/examples/puzzles/src/lib.rs b/examples/puzzles/src/lib.rs new file mode 100644 index 0000000..7e95733 --- /dev/null +++ b/examples/puzzles/src/lib.rs @@ -0,0 +1,183 @@ +use log::{error, info}; +use std::fs::File; +use thiserror::Error; + +/// Number of pieces in the puzzle +/// +/// # History +/// +/// This is a separate paragraph. +/// - Clickable link: [PUZZLE_PIECES] +/// - We tried `7`, but this is better +pub const PUZZLE_PIECES: u32 = 42; + +/// This is a Puzzle! +#[derive(Clone, Debug)] +pub struct Puzzle { + /// Number of pieces + pub num_pieces: u32, + /// Descriptive name + pub name: String, +} + +impl Puzzle { + /// Make a new puzzle! + pub fn new() -> Self { + let puzzle = Default::default(); + info!("Created a puzzle with new(): {:?}", puzzle); + puzzle + } + /// Load a puzzle from a file + pub fn from_file(_fh: File) -> Result { + error!("This file is missing a piece!"); + Err(PuzzleError::MissingPiece) + } +} + +impl Default for Puzzle { + fn default() -> Self { + Puzzle { + num_pieces: PUZZLE_PIECES, + name: "Forest Lake".to_string(), + } + } +} + +impl PartialEq for Puzzle { + fn eq(self: &Puzzle, other: &Puzzle) -> bool { + (self.num_pieces == other.num_pieces) + && (self.name.to_lowercase() == other.name.to_lowercase()) + } +} + +impl From<&Puzzle> for String { + fn from(puzzle: &Puzzle) -> Self { + puzzle.name.clone() + } +} + +pub fn show>(s: T) { + println!("{}", s.into()); +} + +pub fn blah() { + let puzzle = Puzzle::default(); + show(&puzzle); + // puzzle is still available! +} + +#[derive(Clone, Copy)] +pub enum PuzzleType { + Jigsaw, +} + +// struct Vehicle; +// enum TransformerError { +// Whatever, +// } + +// struct Transformer; +// impl Transformer { +// pub fn new() -> Self { +// Self {} +// } +// pub fn stand(self) -> Result { +// Ok(self) +// } +// pub fn transform(self) -> Result { +// Ok(self) +// } +// pub fn rollout(self) -> Result { +// Ok(self) +// } +// pub fn chase(self) -> Result { +// Ok(self) +// } +// } + +// pub fn autobots_rollout() -> Result { +// let optimus = Transformer::new(); +// try!(try!(try!(try!(optimus.stand()).transform()).rollout()).chase()) +// // optimus.stand()?.transform()?.rollout()?.chase()? +// } + +// optimus.stand()?.transform()?.rollout()?.chase()? + +// let stand = match optimus.stand() { +// Ok(x) => x, +// Err(e) => return Err(e), +// }; +// let transform = match stand.transform() { +// Ok(x) => x, +// Err(e) => return Err(e), +// }; +// let rollout = match transform.rollout() { +// Ok(x) => x, +// Err(e) => return Err(e), +// }; +// match transform.chase() { +// Ok(x) => x, +// Err(e) => return Err(e), +// }; + +// match { +// match { +// match { +// match optimus.stand() { +// Ok(x) => x, +// Err(e) => return Err(e), +// } +// } +// .transform() +// { +// Ok(x) => x, +// Err(e) => return Err(e), +// } +// } +// .rollout() +// { +// Ok(x) => x, +// Err(e) => return Err(e), +// } +// } +// .chase() +// { +// Ok(x) => x, +// Err(e) => return Err(e), +// } +// } + +// #[derive(Debug)] // #5: Debug + Display + Exception +// #[non_exhaustive] // #4: Non-Exhaustive +// pub enum PuzzleError { +// // #1: enum +// WontFit(u16), // #2: Group Errors +// MissingPiece, // #3: Only YOUR Errors +// } + +#[derive(Debug, Error)] +#[non_exhaustive] +pub enum PuzzleError { + #[error("Piece {0} doesn't fit!")] + WontFit(u16), + #[error("Missing a piece")] + MissingPiece, +} + +// impl Display for PuzzleError { +// // #5: Debug + Display + Exception +// fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { +// use PuzzleError::*; +// match self { +// MissingPiece => write!(f, "Missing a piece"), +// WontFit(n) => write!(f, "Piece {} doesn't fit!", n), +// } +// } +// } + +// impl Error for PuzzleError { +// // #5: Debug + Display + Exception +// fn source(&self) -> Option<&(dyn Error + 'static)> { +// None +// } +// } diff --git a/examples/puzzles/src/main.rs b/examples/puzzles/src/main.rs new file mode 100644 index 0000000..bf48330 --- /dev/null +++ b/examples/puzzles/src/main.rs @@ -0,0 +1,7 @@ +use std::fmt::{Debug, Display}; + +use puzzles::{blah, Puzzle, PuzzleError}; + +fn main() { + blah(); +}