# Rust Tutorial ###### tags: `Active` ## checkpoint 1 ```=Rust use std::num::ParseIntError; #[derive(PartialEq, Debug)] enum ParsePosNonzeroError { Creation(CreationError), ParseInt(ParseIntError) } impl ParsePosNonzeroError { fn from_creation(err: CreationError) -> ParsePosNonzeroError { todo!() } } fn parse_pos_nonzero(s: &str) -> Result<PositiveNonzeroInteger, ParsePosNonzeroError> { todo!() } #[derive(PartialEq, Debug)] struct PositiveNonzeroInteger(u64); #[derive(PartialEq, Debug)] enum CreationError { Negative, Zero, } impl PositiveNonzeroInteger { fn new(value: i64) -> Result<PositiveNonzeroInteger, CreationError> { todo!() } } #[cfg(test)] mod test { use super::*; #[test] fn test_parse_error() { // We can't construct a ParseIntError, so we have to pattern match. assert!(matches!( parse_pos_nonzero("not a number"), Err(ParsePosNonzeroError::ParseInt(_)) )); } #[test] fn test_negative() { assert_eq!( parse_pos_nonzero("-555"), Err(ParsePosNonzeroError::Creation(CreationError::Negative)) ); } #[test] fn test_zero() { assert_eq!( parse_pos_nonzero("0"), Err(ParsePosNonzeroError::Creation(CreationError::Zero)) ); } #[test] fn test_positive() { let x = PositiveNonzeroInteger::new(42); assert!(x.is_ok()); assert_eq!(parse_pos_nonzero("42"), Ok(x.unwrap())); } } ``` ## checkpoint 2 ```=Rust trait AppendBar { fn append_bar(self) -> Self; } #[cfg(test)] mod tests { use super::*; #[test] fn is_foo_bar() { assert_eq!(String::from("Foo").append_bar(), String::from("FooBar")); } #[test] fn is_bar_bar() { assert_eq!( String::from("").append_bar().append_bar(), String::from("BarBar") ); } #[test] fn test_string() { let s = String::from("Foo"); let s = s.append_bar(); println!("s: {}", s); } #[test] fn is_vec_pop_eq_bar() { let mut foo = vec![String::from("Foo")].append_bar(); assert_eq!(foo.pop().unwrap(), String::from("Bar")); assert_eq!(foo.pop().unwrap(), String::from("Foo")); } } ``` ## checkpoint3 ```=Rust /// A counter type #[derive(Debug)] struct AtomicCounter; // add fields to me! impl AtomicCounter { fn new(init: i32) -> Self { todo!() // initialize } fn add(&self) -> i32 { todo!() // add 1 } fn sub(&self) -> i32 { todo!() // subtract 1 } fn get(&self) -> i32 { todo!() // get the counter value } } #[cfg(test)] mod test { use crate::AtomicCounter; use std::thread; use std::sync::Arc; #[test] fn t1() { let ctr = AtomicCounter::new(0); assert_eq!(1, ctr.add()) } #[test] fn t2() { let ctr = Arc::new(AtomicCounter::new(0)); let x = ctr.clone(); let _ = thread::spawn(move || { assert_eq!(1, x.add()); }).join(); assert_eq!(0, ctr.sub()); } #[test] fn t3() { let ctr = Arc::new(AtomicCounter::new(0)); assert_eq!(0, ctr.get()); (0..10).map(|_| { let x = ctr.clone(); thread::spawn(move || { x.add(); }) }).for_each(|x| x.join().unwrap()); assert_eq!(10, ctr.get()); } } ```