Add example files

This commit is contained in:
Nathan Stocks
2021-06-12 22:36:24 -06:00
commit 26d8ef8451
20 changed files with 448 additions and 0 deletions

14
.gitignore vendored Normal file
View File

@@ -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

8
Cargo.toml Normal file
View File

@@ -0,0 +1,8 @@
[workspace]
members = [
"examples/cafeteria",
"examples/hello",
"examples/kitchen",
"examples/puzzle_game",
"examples/puzzles",
]

1
examples/cafeteria/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/target

View File

@@ -0,0 +1,8 @@
[package]
name = "cafeteria"
version = "0.1.0"
authors = ["Nathan Stocks <nathan@agileperception.com>"]
edition = "2018"
[dependencies]
crossbeam = "0.8"

View File

@@ -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<Lunch>) {
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();
}

14
examples/hello/Cargo.toml Normal file
View File

@@ -0,0 +1,14 @@
[package]
name = "hello"
version = "0.1.0"
authors = ["Nathan Stocks <nathan@agileperception.com>"]
edition = "2018"
[dependencies]
[dev-dependencies]
criterion = { version = "0.3", features = ["html_reports"] }
[[bench]]
name = "snuggle_speed"
harness = false

View File

@@ -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);

35
examples/hello/src/lib.rs Normal file
View File

@@ -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(())
}
}

View File

@@ -0,0 +1,10 @@
fn main() {}
#[cfg(test)]
mod test {
#[test]
fn the_bin_test() {
assert_eq!(1 + 1, 2);
}
}

View File

@@ -0,0 +1,6 @@
use hello::snuggle;
#[test]
fn it_works_from_outside() {
assert!(snuggle(4) == 32);
}

View File

@@ -0,0 +1,9 @@
[package]
name = "kitchen"
version = "0.1.0"
authors = ["Nathan Stocks <nathan@agileperception.com>"]
edition = "2018"
[dependencies]
log = "0.4"
env_logger = "0.8"

View File

@@ -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?");
}
}

1
examples/puzzle_game/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/target

View File

@@ -0,0 +1,11 @@
[package]
name = "puzzle_game"
version = "0.1.0"
authors = ["Nathan Stocks <nathan@agileperception.com>"]
edition = "2018"
[dependencies]
anyhow = "1.0"
puzzles = { path = "../puzzles" }
log = "0.4"
env_logger = "0.8"

View File

@@ -0,0 +1 @@
this is a puzzle

View File

@@ -0,0 +1,21 @@
use anyhow::{Context, Result};
use log::info;
use puzzles::Puzzle;
use std::fs::File;
fn get_puzzle(filename: &str) -> Result<Puzzle> {
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(())
}

1
examples/puzzles/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/target

View File

@@ -0,0 +1,9 @@
[package]
name = "puzzles"
version = "0.1.0"
authors = ["Nathan Stocks <nathan@agileperception.com>"]
edition = "2018"
[dependencies]
thiserror = "1.0"
log = "0.4"

183
examples/puzzles/src/lib.rs Normal file
View File

@@ -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<Self, PuzzleError> {
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<T: Into<String>>(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<Transformer, TransformerError> {
// Ok(self)
// }
// pub fn transform(self) -> Result<Transformer, TransformerError> {
// Ok(self)
// }
// pub fn rollout(self) -> Result<Transformer, TransformerError> {
// Ok(self)
// }
// pub fn chase(self) -> Result<Transformer, TransformerError> {
// Ok(self)
// }
// }
// pub fn autobots_rollout() -> Result<Vehicle, TransformerError> {
// 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
// }
// }

View File

@@ -0,0 +1,7 @@
use std::fmt::{Debug, Display};
use puzzles::{blah, Puzzle, PuzzleError};
fn main() {
blah();
}