tooling

src/lib.rs

#![allow(unused)]
fn main() {
// ANCHOR: crate
//! This is an example of Rust crate comments (or inner comments).
//! They will be rendered in the front page of your (crate) library.
//!
//! # How to generate the documentation
//!
//! In this program we wrote an algorithm that computes the minimum of
//! a sequence of integers.
//!
//! To create the documentation run the command
//! ```bash
//! cargo doc
//! ```
//! The generated documentation can be found in the `target/doc/tooling/index.html` directory
//!
//! To view the documentation type
//! ```bash
//! cargo doc --open
//! ```
//! which will open the browser and show you the documentation.
//!
//! The documentation supports the Common Markdown syntax.
//!
//! Below we will use the `///` comments that will comment the code directly below.
//! We can also use `//` but they will not be rendered.
//! All the lines written here could be enclosed in `/*! ... */` instead of being prefixed by `//!`.
//!
//! For more information about writing documentation [follow that link](https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html).
//!
//! # Tooling
//!
//! Also Rust comes with great tooling.
//! - [Clippy](https://doc.rust-lang.org/stable/clippy/): The official Rust linter.
//! - [Rustfmt](https://github.com/rust-lang/rustfmt): The official Rust code formatter.
// ANCHOR_END: crate

// ANCHOR: size
/// The SIZE constant allows using statically sized arrays
const SIZE: usize = 9;
// ANCHOR_END: size

// ANCHOR: lib_modules
pub mod io;
pub mod minimum;
pub mod something_or_nothing;
// ANCHOR_END: lib_modules

// ANCHOR: test_creation
#[test]
fn test_creation() {
    use something_or_nothing::SomethingOrNothing;

    let n1: SomethingOrNothing<i32> = SomethingOrNothing::default();
    assert!(n1 == SomethingOrNothing::Nothing);
    let n2: SomethingOrNothing<i32> = SomethingOrNothing::Something(1);
    assert!(n2 == SomethingOrNothing::Something(1));
}
// ANCHOR_END: test_creation

// ANCHOR: cfg_test
#[cfg(test)]
mod tests {
    use crate::minimum::Minimum;
    use crate::something_or_nothing::{SomethingOrNothing, find_min};

    // ANCHOR: should_panic
    #[test]
    #[should_panic]
    fn test_failure_creation() {
        let n2: SomethingOrNothing<i32> = SomethingOrNothing::Something(1);
        assert!(n2 == SomethingOrNothing::Nothing);
        assert!(n2 == SomethingOrNothing::Something(2));
    }
    // ANCHOR_END: should_panic

    #[test]
    fn test_min() {
        let a = [1, 5, -1, 2, 0, 10, 11, 0, 3];
        let min = find_min(&a);
        assert!(min == SomethingOrNothing::Something(-1));
    }

    #[test]
    fn test_min_something_or_nothing() {
        let x = SomethingOrNothing::Something(5i32);
        let y = SomethingOrNothing::Something(10i32);
        let z = SomethingOrNothing::Nothing;
        assert!(x.min(y) == x);
        assert!(y.min(x) == x);
        assert!(z.min(y) == y);
        assert!(y.min(z) == y);
        assert!(z.min(z) == z);
    }
}
// ANCHOR_END: cfg_test
}

src/main.rs

use tooling::io;
use tooling::something_or_nothing::find_min;

fn main() {
    let tab = io::read_command_line();
    println!("Among the Somethings in the list:");
    io::print_tab(&tab);
    let min = find_min(&tab);
    min.print();
}

src/main_old.rs

// ANCHOR: crate
//! This is an example of Rust crate comments (or inner comments).
//! They will be rendered in the front page of your (crate) library.
//!
//! # How to generate the documentation
//!
//! In this program we wrote an algorithm that computes the minimum of
//! a sequence of integers.
//!
//! To create the documentation run the command
//! ```bash
//! cargo doc
//! ```
//! The obtain documentation can be found in the `target/doc/tooling/index.html` directory
//!
//! To view the documentation type
//! ```bash
//! cargo doc --open
//! ```
//! which will open the browser and show you the documentation.
//!
//! The documentation supports the CommonMarkdown syntax.
//!
//! Below we will use the `///` comments that will comment the code directly below.
//! We can also sue `//` but they will not be rendered.
//! All the lines written here could be enclosed in `/*! ... */` instead of being prefixed by `//!`.
//!
//! For more informations about writing documentation [follow that link](https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html).
//!
//! # Tooling
//!
//! Also Rust comes with great tooling.
//! - Clippy: A linter.
//! - Rustfmt: A formatter.
// ANCHOR_END: crate

// ANCHOR: something_or_nothing
/// An generic enumerated type that has two variants that are [Clone]
/// and [Copy] using derive.
///
/// - Nothing
/// - Something
#[derive(Clone, Copy)]
enum SomethingOrNothing<T> {
    /// A [SomethingOrNothing::Nothing]
    Nothing,
    /// A [SomethingOrNothing::Something] encapsulating a T
    Something(T),
}
// ANCHOR_END: something_or_nothing

// ANCHOR: static_function
impl<T: std::fmt::Display> SomethingOrNothing<T> {
    /// A static function that prints the content of a SomethingOrNothing.
    fn print(&self) {
        match self {
            SomethingOrNothing::Nothing => println!("Nothing."),
            SomethingOrNothing::Something(val) => println!("Something is: {}", val),
        }
    }
}
// ANCHOR_END: static_function

// ANCHOR: default
impl<T> Default for SomethingOrNothing<T> {
    /// By Default a [SomethingOrNothing] is a nothing.
    fn default() -> Self {
        SomethingOrNothing::Nothing
    }
}
// ANCHOR_END: default

// ANCHOR: partial_eq
impl<T: PartialEq> PartialEq for SomethingOrNothing<T> {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (SomethingOrNothing::Nothing, SomethingOrNothing::Nothing) => true,
            (SomethingOrNothing::Something(lhs), SomethingOrNothing::Something(rhs)) => {
                *lhs == *rhs
            }
            _ => false,
        }
    }
}
// ANCHOR_END: partial_eq

// ANCHOR: minimum
/// The [Minimum] trait computes the minimum value between two values of a type
trait Minimum: Copy {
    fn min(self, rhs: Self) -> Self;
}
// ANCHOR_END: minimum

impl<T: Minimum> Minimum for SomethingOrNothing<T> {
    fn min(self, rhs: Self) -> Self {
        match (self, rhs) {
            (SomethingOrNothing::Nothing, SomethingOrNothing::Nothing) => {
                SomethingOrNothing::Nothing
            }
            (SomethingOrNothing::Something(lhs), SomethingOrNothing::Something(rhs)) => {
                SomethingOrNothing::Something(lhs.min(rhs))
            }
            (SomethingOrNothing::Nothing, SomethingOrNothing::Something(rhs)) => {
                SomethingOrNothing::Something(rhs)
            }
            (SomethingOrNothing::Something(lhs), SomethingOrNothing::Nothing) => {
                SomethingOrNothing::Something(lhs)
            }
        }
    }
}

// Since i32 is [Copy] we don't need to explicitly implement it for i32
impl Minimum for i32 {
    fn min(self, rhs: Self) -> Self {
        if self < rhs {
            self
        } else {
            rhs
        }
    }
}

// ANCHOR: size
/// A constant that is the size of
const SIZE: usize = 9;
// ANCHOR_END: size

// ANCHOR: function
/// Poorly emulates the parsing of a command line.
fn read_command_line() -> [i32; SIZE] {
    [10, 32, 12, 43, 52, 53, 83, 2, 9]
}
// ANCHOR_END: function

/// Prints all the elements of the `tab`.
/// Tab is borrowed here
fn print_tab(tab: &[i32; SIZE]) {
    for t in tab {
        print!("{} ", t);
    }
    println!();
}

/// Computes the minimum of an Array of a type T which implements the [Minimum] trait.
/// Returns a [SomethingOrNothing::Something] containing the the minimum value
/// or [SomethingOrNothing::Nothing] if no minimum value was found.
///
/// # Example
///
/// ```
/// # fn main() {
/// let tab = [10, 32, 12, 43, 52, 53, 83, 2, 9];
/// let min = find_min(&tab);
/// assert!(min == SomethingOrNothing::Something(2));
/// # }
/// ```
fn find_min<T: Minimum>(tab: &[T; SIZE]) -> SomethingOrNothing<T> {
    let mut minimum = SomethingOrNothing::Nothing;
    // Here is T is Copyable. Which means that t is not moved in the loop
    for t in tab {
        minimum = minimum.min(SomethingOrNothing::Something(*t));
    }
    minimum
}

fn main() {
    let tab = read_command_line();
    println!("Among the Somethings in the list:");
    print_tab(&tab);
    // There are alternatives to access fields of tuples
    let min = find_min(&tab);
    // The first field is not used therefore we can replace it with "_"
    min.print();
}

src/io.rs

#![allow(unused)]
fn main() {
// ANCHOR: io_module
//! Contains functions to interact with the user, either
//! by reading inputs from the terminal, either by writing values
//! in it.
//ANCHOR_END: io_module

// ANCHOR: function
/// Poorly emulates the parsing of a command line.
pub fn read_command_line() -> [i32; crate::SIZE] {
    [10, 32, 12, 43, 52, 53, 83, 2, 9]
}
// ANCHOR_END: function

/// Prints all the elements of the `tab`.
/// Tab is borrowed here
pub fn print_tab(tab: &[i32; crate::SIZE]) {
    for t in tab {
        print!("{} ", t);
    }
    println!();
}
}

src/minimum.rs

#![allow(unused)]
fn main() {
// ANCHOR: min
//! Contains a generic trait implementation for computing the minimum between two
//! values. It is the equivalent of the `<` operator.
//!
//! # Examples
//!
//! For integers this would look like
//!
//! ```
//! # use tooling::minimum::Minimum;
//! let one = 1;
//! let two = 2;
//! assert!(Minimum::min(one, two) == one);
//! ```
// ANCHOR_END: min

// ANCHOR: minimum
/// The [Minimum] trait computes the minimum value between two values of a type
pub trait Minimum: Copy {
    fn min(self, rhs: Self) -> Self;
}
// ANCHOR_END: minimum

impl Minimum for i32 {
    fn min(self, rhs: Self) -> Self {
        if self < rhs { self } else { rhs }
    }
}

// ANCHOR: cfg_test_min
#[cfg(test)]
mod tests {
    use crate::minimum::Minimum;

    #[test]
    fn test_min_i32() {
        let x = 5;
        let y = 10;
        assert_eq!(Minimum::min(x, y), x);
        assert_eq!(Minimum::min(y, x), x);
        assert_eq!(Minimum::min(x, x), x);
        assert_eq!(Minimum::min(y, y), y);
    }
}
// ANCHOR_END: cfg_test_min
}

src/something_or_nothing.rs

//! Contains the core logic of the library, allowing to store generic values
//! (or their absence) and manipulate them.

use crate::minimum::Minimum;

// ANCHOR: something_or_nothing
/// A generic enumerated type that has two variants.
///
/// - Nothing
/// - Something
#[derive(Clone, Copy)]
pub enum SomethingOrNothing<T> {
    /// A [SomethingOrNothing::Nothing]
    Nothing,
    /// A [SomethingOrNothing::Something] encapsulating a T
    Something(T),
}
// ANCHOR_END: something_or_nothing

// ANCHOR: method
impl<T: std::fmt::Display> SomethingOrNothing<T> {
    /// A method that prints the content of a SomethingOrNothing.
    pub fn print(&self) {
        match self {
            SomethingOrNothing::Nothing => println!("Nothing."),
            SomethingOrNothing::Something(val) => println!("Something is: {}", val),
        }
    }
}
// ANCHOR_END: method

// ANCHOR: default
/// Implementation of the [Default] trait that creates a [SomethingOrNothing]
/// that is a `Nothing` variant.
///
/// # Example
///
/// ```
/// # use tooling::something_or_nothing::SomethingOrNothing;
/// # fn main() {
/// let def: SomethingOrNothing<i32> = SomethingOrNothing::default();
/// assert!(def == SomethingOrNothing::Nothing);
/// # }
/// ```
impl<T> Default for SomethingOrNothing<T> {
    /// By Default a [SomethingOrNothing] is a nothing.
    fn default() -> Self {
        SomethingOrNothing::Nothing
    }
}
// ANCHOR_END: default

// ANCHOR: partial_eq
/// Implementation of the [PartialEq] trait that is useful for tests.
impl<T: PartialEq> PartialEq for SomethingOrNothing<T> {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (SomethingOrNothing::Nothing, SomethingOrNothing::Nothing) => true,
            (SomethingOrNothing::Something(lhs), SomethingOrNothing::Something(rhs)) => {
                *lhs == *rhs
            }
            _ => false,
        }
    }
}
// ANCHOR_END: partial_eq

/// Implementation of the [Minimum] trait used for comparing values
/// in this crate.
impl<T: Minimum> Minimum for SomethingOrNothing<T> {
    fn min(self, rhs: Self) -> Self {
        match (self, rhs) {
            (SomethingOrNothing::Nothing, SomethingOrNothing::Nothing) => {
                SomethingOrNothing::Nothing
            }
            (SomethingOrNothing::Something(lhs), SomethingOrNothing::Something(rhs)) => {
                SomethingOrNothing::Something(lhs.min(rhs))
            }
            (SomethingOrNothing::Nothing, SomethingOrNothing::Something(rhs)) => {
                SomethingOrNothing::Something(rhs)
            }
            (SomethingOrNothing::Something(lhs), SomethingOrNothing::Nothing) => {
                SomethingOrNothing::Something(lhs)
            }
        }
    }
}

// ANCHOR: find_min
/// Computes the minimum of an Array of a type T which implements the [Minimum] trait.
/// Returns a [SomethingOrNothing::Something] containing the minimum value
/// or [SomethingOrNothing::Nothing] if no minimum value was found.
///
/// # Example
///
/// ```
/// # use tooling::something_or_nothing::{SomethingOrNothing, find_min};
/// # fn main() {
/// let tab = [10, 32, 12, 43, 52, 53, 83, 2, 9];
/// let min = find_min(&tab);
/// assert!(min == SomethingOrNothing::Something(2));
/// # }
/// ```
pub fn find_min<T: Minimum>(tab: &[T; crate::SIZE]) -> SomethingOrNothing<T> {
    let mut minimum = SomethingOrNothing::Nothing;
    // Here, if T is Copyable, t is not moved in the loop
    for t in tab {
        minimum = minimum.min(SomethingOrNothing::Something(*t));
    }
    minimum
}
// ANCHOR_END: find_min