Add example files
This commit is contained in:
14
.gitignore
vendored
Normal file
14
.gitignore
vendored
Normal 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
8
Cargo.toml
Normal 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
1
examples/cafeteria/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
8
examples/cafeteria/Cargo.toml
Normal file
8
examples/cafeteria/Cargo.toml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[package]
|
||||||
|
name = "cafeteria"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Nathan Stocks <nathan@agileperception.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
crossbeam = "0.8"
|
||||||
57
examples/cafeteria/src/main.rs
Normal file
57
examples/cafeteria/src/main.rs
Normal 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
14
examples/hello/Cargo.toml
Normal 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
|
||||||
9
examples/hello/benches/snuggle_speed.rs
Normal file
9
examples/hello/benches/snuggle_speed.rs
Normal 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
35
examples/hello/src/lib.rs
Normal 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(())
|
||||||
|
}
|
||||||
|
}
|
||||||
10
examples/hello/src/main.rs
Normal file
10
examples/hello/src/main.rs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
fn main() {}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn the_bin_test() {
|
||||||
|
assert_eq!(1 + 1, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
6
examples/hello/tests/anything.rs
Normal file
6
examples/hello/tests/anything.rs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
use hello::snuggle;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn it_works_from_outside() {
|
||||||
|
assert!(snuggle(4) == 32);
|
||||||
|
}
|
||||||
9
examples/kitchen/Cargo.toml
Normal file
9
examples/kitchen/Cargo.toml
Normal 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"
|
||||||
43
examples/kitchen/src/main.rs
Normal file
43
examples/kitchen/src/main.rs
Normal 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
1
examples/puzzle_game/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
11
examples/puzzle_game/Cargo.toml
Normal file
11
examples/puzzle_game/Cargo.toml
Normal 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"
|
||||||
1
examples/puzzle_game/puzzle.dat
Normal file
1
examples/puzzle_game/puzzle.dat
Normal file
@@ -0,0 +1 @@
|
|||||||
|
this is a puzzle
|
||||||
21
examples/puzzle_game/src/main.rs
Normal file
21
examples/puzzle_game/src/main.rs
Normal 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
1
examples/puzzles/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
9
examples/puzzles/Cargo.toml
Normal file
9
examples/puzzles/Cargo.toml
Normal 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
183
examples/puzzles/src/lib.rs
Normal 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
|
||||||
|
// }
|
||||||
|
// }
|
||||||
7
examples/puzzles/src/main.rs
Normal file
7
examples/puzzles/src/main.rs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
use std::fmt::{Debug, Display};
|
||||||
|
|
||||||
|
use puzzles::{blah, Puzzle, PuzzleError};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
blah();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user