rust_programming_book 0.1.1

Programming works from THE RUST PROGRAMMING LANGUAGE
Documentation
use std::vec;
#[derive(Debug, PartialEq)]
pub enum ShirtColor {
    Blue,
    Red,
}
#[allow(dead_code)]
#[derive(Debug)]
pub struct Inventory {
    pub shirts: Vec<ShirtColor>,
}

impl Inventory {
    #[allow(dead_code)]
    pub fn giveaway(&self, user_preference: Option<ShirtColor>) -> ShirtColor {
        user_preference.unwrap_or_else(|| self.highest_stocked())
    }

    #[allow(dead_code)]
    fn highest_stocked(&self) -> ShirtColor {
        let mut blue_count = 0;
        let mut red_count = 0;

        for shirt in &self.shirts {
            match shirt {
                ShirtColor::Blue => blue_count += 1,
                ShirtColor::Red => red_count += 1,
            }
        }

        if blue_count > red_count {
            ShirtColor::Blue
        } else {
            ShirtColor::Red
        }
    }
}

#[allow(dead_code, unused_variables)]
pub fn capturing_reference() {
    let mut list = vec![1, 2, 3];

    // borrows immutable reference(closure implements Fn trait)
    let borrows = || println!("inside closure, list:{:#?}", list);

    // no error
    borrows();
    println!("after borrowing, list: {:#?}", list);

    // borrows mutable reference(closure implements FnMut trait)
    let mut mutable_borrow = || list.push(7);
    // no error
    mutable_borrow();
    println!("after borrowing, list: {:#?}", list);

    // moved ownership(closure automatically implements FnOnce trait)
    let move_ownership = move || list.push(8);
    // error as list is destroyed due to transfer of ownership to closure.
    // move_ownership();
    // println!("after borrowing, list: {:#?}", list);
}

/*
 * Moving captured values out of the closure and Fn traits
 * Closure automatically implement of the the 3 Fn traits(Fn, FnMut, FnOnce) and on the captured value handling style of the
 * the closure.
 * But while using generics we have to use trait bounds to specify what type of closures are allowed
 */
#[derive(Debug)]
#[allow(dead_code)]
struct Rect {
    x: i32,
    y: i32,
}
impl Rect {
    pub fn new(x: i32, y: i32) -> Self {
        Self { x, y }
    }
}

#[allow(dead_code)]
pub fn fn_mut_example() {
    let mut rectangles = vec![Rect::new(2, 3), Rect::new(5, 7), Rect::new(1, 2)];

    let mut count = 0;

    rectangles.sort_by_key(|val| {
        count += 1;
        val.y
    });

    println!(
        "sorted array: {:?}\n closure called {:?} times",
        rectangles, count
    );
}

#[allow(dead_code)]
pub fn get_square<T, F>(item: T, squarer: F) -> T
where
    F: FnOnce(T) -> T,
{
    squarer(item)
}

#[allow(dead_code)]
#[test]
pub fn fn_once_for_scalar_type() {
    let x = 10;
    let squarer = move |item: i32| item * item;
    let output = get_square(x, squarer);

    println!("input: {}, output: {:?}", x, output);
    assert_eq!(x * x, output);
}