# 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());
}
}
```