bases1bases2types_avancesgen_types_composesproprietemodules_visibilitetoolinggestion_erreursclosuresiterateurscollectionslifetimescliunsafemin_list

bases1

src/main.rs

/// Rust basics:
///     - basic types (usize, i32, str)
///     - const, let, let mut
///     - control structures (for, if)
///     - collection: arrays, indexing
///     - macros for IO and errors

// No functions, only types used are i32, usize and [i32; SIZE].
// Indexing of array, for and if else control structures.
// Macros: panic! for error handling, print! and println! for I/O.
// Clippy does not like the code at all.

fn main() {
    const SIZE: usize = 9;
    let tab: [i32; SIZE] = [10, 32, 12, 43, 52, 53, 83, 2, 9];

    if SIZE == 0 {
        panic!("Size is of tab = 0.");
    }

    println!("Among the numbers in the list:");
    for i in 0..SIZE {
        print!("{} ", tab[i]);
    }
    println!();

    let mut min = tab[0];
    for i in 1..SIZE {
        if min > tab[i] {
            min = tab[i];
        }
    }

    println!("The minimal value is: {}", min);
}

bases2

src/main.rs

/// Rust basics:
///     - Functions
///     - Arguments are "moved"
///     - if is an expression
///     - for loops revisited

const SIZE: usize = 9;

fn read_command_line() -> [i32; SIZE] {
    [10, 32, 12, 43, 52, 53, 83, 2, 9]
}

// Check if the size is large enough (more that 1 element)
fn check_size(size: usize) {
    if size == 0 {
        panic!("Size is of tab = 0.");
    }
}

// Prints tab and returns tab.
// Tab would be destructed at the end of the function otherwise.
fn print_tab(tab: [i32; SIZE]) {
    for t in tab {
        print!("{} ", t);
    }
    println!();
}

fn min_i32(lhs: i32, rhs: i32) -> i32 {
    if lhs < rhs { lhs } else { rhs }
}

fn find_min(tab: [i32; SIZE]) -> i32 {
    check_size(SIZE);
    let mut min = i32::MAX;
    for t in tab {
        min = min_i32(min, t);
    }
    min
}

fn main() {
    let tab = read_command_line();
    println!("Among the numbers in the list:");
    print_tab(tab);
    let min = find_min(tab);
    println!("The minimal value is: {}", min);
}

types_avances

src/main.rs

/// In types_avances we introduce `Enums` (also known as `Algebraic Data Types`), `Pattern Matching`,
/// associated functions and methods.

enum NumberOrNothing {
    Nothing,
    Number(i32),
}

impl NumberOrNothing {
    fn new(val: i32) -> Self {
        NumberOrNothing::Number(val)
    }

    // Method (takes `self`)
    fn print(self) {
        match self {
            NumberOrNothing::Nothing => println!("No number."),
            NumberOrNothing::Number(val) => println!("The number is: {}", val),
        }
    }
}

const SIZE: usize = 9;

fn read_command_line() -> [i32; SIZE] {
    [10, 32, 12, 43, 52, 53, 83, 2, 9]
}

// Prints tab and returns tab.
// Tab would be destructed at the end of the function otherwise.
fn print_tab(tab: [i32; SIZE]) {
    for t in tab {
        print!("{} ", t);
    }
    println!();
}

fn min_i32(lhs: i32, rhs: i32) -> i32 {
    if lhs < rhs { lhs } else { rhs }
}

fn find_min(tab: [i32; SIZE]) -> NumberOrNothing {
    let mut min = NumberOrNothing::Nothing;
    for t in tab {
        match min {
            NumberOrNothing::Nothing => min = NumberOrNothing::new(t),
            NumberOrNothing::Number(val) => min = NumberOrNothing::new(min_i32(val, t)),
        }
    }
    min
}

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

gen_types_composes

src/main.rs

/* ANCHOR: all */

/// In gen_types_composes we introduce genericity through traits and in particular, [Copy],
/// [Clone], [std::fmt::Display] .
// ANCHOR: something_or_nothing
enum SomethingOrNothing<T> {
    Nothing,
    Something(T),
}
// ANCHOR_END: something_or_nothing

// ANCHOR: new
impl<T> SomethingOrNothing<T> {
    fn new(val: T) -> SomethingOrNothing<T> {
        SomethingOrNothing::Something(val)
    }
}
// ANCHOR_END: new

// ANCHOR: print
// Print function
// We know the generic type T must be Displayable
fn print<T: std::fmt::Display>(val: SomethingOrNothing<T>) {
    match val {
        SomethingOrNothing::Nothing => println!("Nothing."),
        SomethingOrNothing::Something(val) => println!("Something is: {}", val),
    }
}
// ANCHOR_END: print

// ANCHOR: clone
impl<T: Clone> Clone for SomethingOrNothing<T> {
    fn clone(&self) -> Self {
        match self {
            SomethingOrNothing::Nothing => SomethingOrNothing::Nothing,
            SomethingOrNothing::Something(val) => SomethingOrNothing::new(val.clone()),
        }
    }
}
// ANCHOR_END: clone

// ANCHOR: copy
impl<T: Copy> Copy for SomethingOrNothing<T> {}
// ANCHOR_END: copy

// If we remove Copy, we have a problem with the t in tab
// in the computation of the minimum.
// ANCHOR: minimum
trait Minimum: Copy {
    fn min(self, rhs: Self) -> Self;
}
// ANCHOR_END: minimum

// ANCHOR: minimum_impl
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::new(lhs.min(rhs))
            }
            (SomethingOrNothing::Nothing, SomethingOrNothing::Something(rhs)) => {
                SomethingOrNothing::new(rhs)
            }
            (SomethingOrNothing::Something(lhs), SomethingOrNothing::Nothing) => {
                SomethingOrNothing::new(lhs)
            }
        }
    }
}
// ANCHOR_END: minimum_impl

// i32 is Copy, like other primitive types (f32, f64, etc.).
// Fixed-size arrays [T; N] are also Copy when T is Copy.
// ANCHOR: minimum_i32
impl Minimum for i32 {
    fn min(self, rhs: Self) -> Self {
        if self < rhs { self } else { rhs }
    }
}
// ANCHOR_END: minimum_i32

const SIZE: usize = 9;

fn read_command_line() -> [i32; SIZE] {
    [10, 32, 12, 43, 52, 53, 83, 2, 9]
}

// Prints tab and returns tab.
// Tab would be destructed at the end of the function otherwise.
// ANCHOR: print_tab
fn print_tab<T: std::fmt::Display>(tab: [T; SIZE]) {
    for t in tab {
        print!("{} ", t);
    }
    println!();
}
// ANCHOR_END: print_tab

// ANCHOR: find_min
fn find_min<T: Minimum>(tab: [T; SIZE]) -> SomethingOrNothing<T> {
    let mut current_minimum = SomethingOrNothing::Nothing;
    // Here, if T is not Copyable, tab is consumed and cannot be returned
    for t in tab {
        current_minimum = current_minimum.min(SomethingOrNothing::new(t));
    }
    current_minimum
}
// ANCHOR_END: find_min

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

/* ANCHOR_END: all */

propriete

src/main.rs

/* ANCHOR: all */

/*!
propriete illustrates the concepts of **Ownership** and **Borrowing**. It also
presents the manual implementation of [Clone] and [Copy].
*/
// ANCHOR: something_or_nothing
enum SomethingOrNothing<T> {
    Nothing,
    Something(T),
}
impl<T> SomethingOrNothing<T> {
    fn new(val: T) -> SomethingOrNothing<T> {
        SomethingOrNothing::Something(val)
    }
}
// ANCHOR_END: something_or_nothing

// ANCHOR: print
fn print<T: std::fmt::Display>(val: &SomethingOrNothing<T>) {
    match val {
        SomethingOrNothing::Nothing => println!("Nothing."),
        SomethingOrNothing::Something(val) => println!("Something is: {}", val),
    }
}
// ANCHOR_END: print

// Manual implementation of [Clone]
impl<T: Clone> Clone for SomethingOrNothing<T> {
    fn clone(&self) -> Self {
        match self {
            SomethingOrNothing::Nothing => SomethingOrNothing::Nothing,
            SomethingOrNothing::Something(val) => SomethingOrNothing::Something(val.clone()),
        }
    }
}

// Manual implementation of [Copy]
impl<T: Copy> Copy for SomethingOrNothing<T> {}

// If we remove Copy, we have a problem with the t in tab
// in the computation of the minimum.
// ANCHOR: minimum
trait Minimum: Copy {
    fn min(self, rhs: Self) -> Self;
}
// ANCHOR_END: minimum

// ANCHOR: minimum_impl
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_END: minimum_impl

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

const SIZE: usize = 9;

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

// Prints all the elements of the `tab`.
// Tab is borrowed here
// ANCHOR: print_tab
fn print_tab<T: std::fmt::Display>(tab: &[T; SIZE]) {
    for t in tab {
        print!("{} ", t);
    }
    println!();
}
// ANCHOR_END: print_tab

// Computes the minimum of a borrowed 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.
// ANCHOR: find_min
fn find_min<T: Minimum>(tab: &[T; SIZE]) -> SomethingOrNothing<T> {
    let mut current_minimum = SomethingOrNothing::Nothing;
    // Here, if T is not Copyable, tab is consumed and cannot be returned
    for t in tab {
        current_minimum = current_minimum.min(SomethingOrNothing::new(*t));
    }
    current_minimum
}
// ANCHOR_END: find_min

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

/* ANCHOR_END: all */

modules_visibilite

src/lib.rs

#![allow(unused)]
fn main() {
// ANCHOR: lib_modules
/*!
modules_visibilite illustrates the concepts of **modules** and **visibility**.
*/

// The size of the tab
const SIZE: usize = 9;

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

src/main.rs

// ANCHOR: main_imports
use modules_visibilite::io;
use modules_visibilite::something_or_nothing::find_min;
// ANCHOR_END: main_imports

fn main() {
    // modules_visibilite::io is imported but not read_command_line
    let tab = io::read_command_line();
    println!("Among the Somethings in the list:");
    // modules_visibilite::io is imported but not print_tab
    io::print_tab(&tab);
    // modules_visibilite::something_or_nothing::find_min is imported and can be used directly
    let min = find_min(&tab);
    min.print();
}

src/io.rs

#![allow(unused)]
fn main() {
// 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]
}

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

src/minimum.rs

#![allow(unused)]
fn main() {
// ANCHOR: trait
pub trait Minimum: Copy {
    fn min(self, rhs: Self) -> Self;
}
// ANCHOR_END: trait

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

src/something_or_nothing.rs

#![allow(unused)]
fn main() {
// ANCHOR: minimum
use crate::minimum::Minimum;
// ANCHOR_END: minimum

// ANCHOR: pub_enum
#[derive(Clone, Copy)]
pub enum SomethingOrNothing<T> {
    Nothing,
    Something(T),
}
// ANCHOR_END: pub_enum

// ANCHOR: pub_method
impl<T: std::fmt::Display> SomethingOrNothing<T> {
    pub fn print(&self) {
        match self {
            SomethingOrNothing::Nothing => println!("Nothing."),
            SomethingOrNothing::Something(val) => println!("Something is: {}", val),
        }
    }
}
// ANCHOR_END: pub_method

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)
            }
        }
    }
}

// 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.
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
}
}

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

gestion_erreurs

src/lib.rs

#![allow(unused)]
fn main() {
//! This crate shows us different ways of dealing with errors in a Rust program.
//! You will find examples of [Option], [Result] and [panic!].

pub mod find_minimum;
pub mod io;
pub mod minimum;

#[cfg(test)]
mod tests {
    use crate::find_minimum::{
        find_min_amongst_arrays_by_hand, find_min_amongst_arrays_qm_op, find_min_with_option,
        find_min_with_panic, find_min_with_result,
    };
    const TAB: [i32; 9] = [10, 32, 12, 43, 52, 53, 83, 2, 9];
    const TAB_B: [i32; 9] = [22, 34, 11, 4, 52, 99, 71, 13, 43];
    const TAB_EMPTY: [i32; 0] = [];
    const MIN_TAB: i32 = 2;

    #[test]
    fn test_find_min_option() {
        let min = find_min_with_option(&TAB);

        assert!(min == Some(MIN_TAB));
    }

    #[test]
    fn test_find_min_option_empty() {
        let min = find_min_with_option(&TAB_EMPTY);

        assert!(min.is_none());
    }

    #[test]
    fn test_find_min_result() {
        let min = find_min_with_result(&TAB);

        assert!(min == Ok(MIN_TAB));
    }

    #[test]
    fn test_find_min_result_empty() {
        let min = find_min_with_result(&TAB_EMPTY);

        assert!(min.is_err());
    }

    #[test]
    fn test_find_min_panic() {
        let min = find_min_with_panic(&TAB);

        assert!(min == MIN_TAB);
    }

    #[test]
    #[should_panic]
    fn test_find_min_panic_empty() {
        let _min = find_min_with_panic(&TAB_EMPTY);
    }

    #[test]
    fn test_find_min_amongst_arrays_bh() {
        let min = find_min_amongst_arrays_by_hand(&TAB, &TAB_B);

        assert!(min == Ok(MIN_TAB));
    }

    #[test]
    fn test_find_min_amongst_arrays_qm() {
        let min = find_min_amongst_arrays_qm_op(&TAB, &TAB_B);

        assert!(min == Ok(MIN_TAB));
    }

    #[test]
    fn test_find_min_amongst_arrays_bh_empty() {
        let min = find_min_amongst_arrays_by_hand(&TAB, &TAB_EMPTY);

        assert!(min.is_err());
    }

    #[test]
    fn test_find_min_amongst_arrays_qm_empty() {
        let min = find_min_amongst_arrays_qm_op(&TAB, &TAB_EMPTY);

        assert!(min.is_err());
    }
}
}

src/main.rs

use gestion_erreurs::find_minimum::{
    FindMinError::EmptyList, FindMinError::UnsupportedError, find_min_amongst_arrays_qm_op,
    find_min_with_option, find_min_with_result,
};
use gestion_erreurs::io;

fn main() {
    let tab = io::read_command_line_correct();
    println!("Among the elements in the list:");
    io::print_tab(&tab);
    let min = find_min_with_option(&tab);
    match min {
        Some(val) => print!("The minimum value is {}", val),
        None => eprintln!("There is no minimum since the list is empty"),
    }
    println!("");
    println!("");

    let tab_empty = io::read_empty_command_line();
    println!("Among the elements in the list:");
    io::print_tab(&tab_empty);

    //ANCHOR: parse_result
    let min = find_min_with_result(&tab_empty);
    match min {
        Ok(val) => print!("The minimum value is {}", val),
        Err(EmptyList) => eprintln!("The array is empty"),
        Err(UnsupportedError(msg)) => panic!("Unsupported error : {}", msg),
    }
    //ANCHOR_END: parse_result

    println!("Among the elements in the lists:");
    io::print_tab(&tab);
    io::print_tab(&tab_empty);
    let min = find_min_amongst_arrays_qm_op(&tab, &tab_empty);
    match min {
        Ok(val) => print!("The minimum value is {}", val),
        Err(EmptyList) => eprintln!("One or both arrays are empty"),
        Err(UnsupportedError(msg)) => panic!("Unsupported error : {}", msg),
    }
}

src/find_minimum.rs

//! Contains the core logic of the library, allowing to store generic values
//! (or their absence) and manipulate them.
//! We demonstrates three kind of way to deal with errors

use crate::minimum::Minimum;

// ANCHOR: find_min_error
#[derive(PartialEq)]
pub enum FindMinError {
    EmptyList,
    UnsupportedError(String),
}
// ANCHOR_END: find_min_error

use crate::find_minimum::FindMinError::EmptyList;

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

/// Computes the minimum of an Array of a type T which implements the [Minimum] trait.
/// Returns a [Result::Ok] containing the minimum value
/// or an [Result::Err] containing the error, if no minimum value was found.
///
/// # Example
///
/// ```
/// # use gestion_erreurs::find_minimum::{find_min_with_result};
/// # fn main() {
/// let tab = [10, 32, 12, 43, 52, 53, 83, 2, 9];
/// let min = find_min_with_result(&tab);
/// assert!(min == Ok(2));
/// # }
/// ```
///
/// ```
/// # use gestion_erreurs::find_minimum::{find_min_with_result};
/// # fn main() {
/// let tab : [i32; 0] = [];
/// let min = find_min_with_result(&tab);
/// assert!(min.is_err());
/// # }
/// ```
// ANCHOR: min_with_result
pub fn find_min_with_result<T: Minimum>(tab: &[T]) -> Result<T, FindMinError> {
    let mut minimum = None;
    // Here, if T is Copyable, t is not moved in the loop
    for t in tab {
        minimum = Minimum::min(minimum, Some(*t));
    }

    match minimum {
        Some(val) => Ok(val),
        None => Err(EmptyList),
    }
}
// ANCHOR_END: min_with_result

/// Computes the minimum of an Array of a type T which implements the [Minimum] trait.
/// Returns a T which is the minimum value
/// or panics if no minimum value was found.
///
/// # Example
///
/// ```
/// # use gestion_erreurs::find_minimum::{find_min_with_panic};
/// # fn main() {
/// let tab = [10, 32, 12, 43, 52, 53, 83, 2, 9];
/// let min = find_min_with_panic(&tab);
/// assert!(min == 2);
/// # }
/// ```
///
/// ```should_panic
/// # use gestion_erreurs::find_minimum::{find_min_with_panic};
/// # fn main() {
/// let tab : [i32; 0] = [];
/// let _min = find_min_with_panic(&tab);
/// # }
/// ```
// ANCHOR: min_with_panic
pub fn find_min_with_panic<T: Minimum>(tab: &[T]) -> T {
    let mut minimum = None;
    // Here, if T is Copyable, t is not moved in the loop
    for t in tab {
        minimum = Minimum::min(minimum, Some(*t));
    }

    // We decide that we cannot compute the minimum of an empty array
    match minimum {
        Some(val) => val,
        None => panic!("The array is empty"),
    }
}
// ANCHOR_END: min_with_panic

/// Computes the minimum amongst two Arrays of a type T which implements the [Minimum] trait.
/// Returns a [Result::Ok] containing the minimum value
/// or an [Result::Err] containing the error, if no minimum value was found.
///
/// We deal with errors in underlying function calls without the [?] operator.
///
/// # Example
///
/// ```
/// # use gestion_erreurs::find_minimum::{find_min_amongst_arrays_by_hand};
/// # fn main() {
/// let tab_a = [10, 32, 12, 43, 52, 53, 83, 2, 9];
/// let tab_b = [22, 34, 11, 4, 52, 99, 71, 13, 43];
/// let min = find_min_amongst_arrays_by_hand(&tab_a, &tab_b);
/// assert!(min == Ok(2));
/// # }
/// ```
///
/// ```
/// # use gestion_erreurs::find_minimum::{find_min_amongst_arrays_by_hand};
/// # fn main() {
/// let tab_a = [10, 32, 12, 43, 52, 53, 83, 2, 9];
/// let tab_b : [i32; 0] = [];
/// let min = find_min_amongst_arrays_by_hand(&tab_a, &tab_b);
/// assert!(min.is_err());
/// # }
/// ```
// ANCHOR: min_two_tabs_hand
pub fn find_min_amongst_arrays_by_hand<T: Minimum>(
    lhs: &[T],
    rhs: &[T],
) -> Result<T, FindMinError> {
    let min_result = find_min_with_result(lhs);
    let min_l = if let Ok(x) = min_result {
        x
    } else {
        // Since tmp is not Ok, we return the error to the caller
        return min_result;
    };

    let min_result = find_min_with_result(rhs);
    let min_r = if let Ok(x) = min_result {
        x
    } else {
        // Since tmp is not Ok, we return the error to the caller
        return min_result;
    };

    Ok(min_l.min(min_r))
}
// ANCHOR_END: min_two_tabs_hand

/// Computes the minimum amongst two Arrays of a type T which implements the [Minimum] trait.
/// Returns a [Result::Ok] containing the minimum value
/// or an [Result::Err] containing the error, if no minimum value was found.
///
/// We deal with errors in underlying function with the [?] operator.
///
/// # Example
///
/// ```
/// # use gestion_erreurs::find_minimum::{find_min_amongst_arrays_qm_op};
/// # fn main() {
/// let tab_a = [10, 32, 12, 43, 52, 53, 83, 2, 9];
/// let tab_b = [22, 34, 11, 4, 52, 99, 71, 13, 43];
/// let min = find_min_amongst_arrays_qm_op(&tab_a, &tab_b);
/// assert!(min == Ok(2));
/// # }
/// ```
///
/// ```
/// # use gestion_erreurs::find_minimum::{find_min_amongst_arrays_qm_op};
/// # fn main() {
/// let tab_a = [10, 32, 12, 43, 52, 53, 83, 2, 9];
/// let tab_b : [i32; 0] = [];
/// let min = find_min_amongst_arrays_qm_op(&tab_a, &tab_b);
/// assert!(min.is_err());
/// # }
/// ```
// ANCHOR: min_two_tabs_qm
pub fn find_min_amongst_arrays_qm_op<T: Minimum>(lhs: &[T], rhs: &[T]) -> Result<T, FindMinError> {
    // The question mark operator will unpack the value if the function returns [Result::Ok]
    // or end the function and return the [Result:Err] to the caller.
    let min_l = find_min_with_result(lhs)?;
    let min_r = find_min_with_result(rhs)?;

    Ok(min_l.min(min_r))
}
// ANCHOR_END: min_two_tabs_qm

src/io.rs

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

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

/// Poorly emulates the parsing of a command line.
pub fn read_empty_command_line() -> [i32; 0] {
    []
}

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

src/minimum.rs

#![allow(unused)]
fn main() {
//! 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 gestion_erreurs::minimum::Minimum;
//! let one = 1;
//! let two = 2;
//! assert!(Minimum::min(one, two) == one);
//! ```

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

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

// ANCHOR: min_for_option
impl<T: Minimum> Minimum for Option<T> {
    fn min(self, rhs: Self) -> Self {
        match self {
            Some(val_l) => Some(match rhs {
                Some(val_r) => val_l.min(val_r),
                None => val_l,
            }),
            None => match rhs {
                Some(val_r) => Some(val_r),
                None => None,
            },
        }
    }
}
// ANCHOR_END: min_for_option

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

closures

src/lib.rs

#![allow(unused)]
fn main() {
//! This crate shows us different ways of dealing with errors in a Rust program.
//! You will find examples of [Option], [Result] and [panic!].

pub mod binary_operator;
pub mod find;
pub mod io;

#[cfg(test)]
mod tests {
    use crate::binary_operator::*;
    use crate::find::find_with_hof;
    const TAB: [i32; 9] = [10, 32, 12, 43, 52, 53, 83, 2, 9];
    const TAB_EMPTY: [i32; 0] = [];
    const MIN_TAB: i32 = 2;
    const MAX_TAB: i32 = 83;

    #[test]
    fn test_find_with_option_min() {
        let min: Option<i32> = find_with_hof(&TAB, |x: i32, y: i32| if x <= y { x } else { y });

        assert!(min == Some(MIN_TAB));
    }

    #[test]
    fn test_find_with_option_max() {
        let max: Option<i32> = find_with_hof(&TAB, |x: i32, y: i32| if x >= y { x } else { y });

        assert!(max == Some(MAX_TAB));
    }

    #[test]
    fn test_find_with_option_empty() {
        let min: Option<i32> =
            find_with_hof(&TAB_EMPTY, |x: i32, y: i32| if x <= y { x } else { y });

        assert!(min.is_none());
    }

    #[test]
    fn test_minimum_operator() {
        let f = minimum_operator::<i32>();

        assert!(f(5, 10) == 5);
    }

    #[test]
    fn test_maximum_operator() {
        let f = maximum_operator::<i32>();

        assert!(f(5, 10) == 10);
    }

    #[test]
    fn test_sum_operator() {
        let f = sum_operator::<i32>();

        assert!(f(5, 10) == 15);
    }

    #[test]
    fn test_mul_operator() {
        let f = mul_operator::<i32>();

        assert!(f(5, 10) == 50);
    }
}
}

src/main.rs

use closures::binary_operator::{minimum_operator, sum_operator};
use closures::find::find_with_hof;
use closures::io;

fn main() {
    let tab = io::read_command_line_correct();
    println!("Among the elements in the list:");
    io::print_tab(&tab);

    //ANCHOR: min_usage
    let min = find_with_hof(&tab, minimum_operator());
    match min {
        Some(val) => println!("The minimum value is {}", val),
        None => eprintln!("There is no minimum"),
    }
    //ANCHOR_END: min_usage

    //ANCHOR: max_variable
    let max_op: fn(i32, i32) -> i32 = |x, y| if x >= y { x } else { y };
    //ANCHOR_END: max_variable

    //ANCHOR: option_filter
    let max_val: Option<i32> = find_with_hof(&tab, max_op);
    let odd_max: Option<i32> = max_val.filter(|x| x % 2 == 1);
    match odd_max {
        Some(_) => println!("The maximum value is an odd number"),
        None => {
            if max_val.is_some() {
                println!("The maximum value is an even number")
            } else {
                eprintln!("There is no maximum")
            }
        }
    }
    //ANCHOR_END: option_filter

    //ANCHOR: option_map
    let two: f32 = 2.0f32;

    let sum: Option<i32> = find_with_hof(&tab, sum_operator());
    let half: Option<f32> = sum.map(|x: i32| (x as f32) / two);
    match half {
        Some(val) => println!("The sum of the elements divided by two is {}", val),
        None => eprintln!("There is no sum"),
    }
    //ANCHOR_END: option_map
}

src/binary_operator.rs

// ANCHOR: binary_operator
pub type BinaryOperator<T> = fn(T, T) -> T;
// ANCHOR_END: binary_operator

/// Returns a closure that computes the minimum
/// between two elements of type T.
/// # Example
///
/// ```
/// # use closures::binary_operator::{minimum_operator};
/// # fn main() {
/// let f = minimum_operator();
/// assert!(f(1,2) == 1);
/// # }
/// ```
// ANCHOR: minimum_operator
pub fn minimum_operator<T: PartialOrd>() -> BinaryOperator<T> {
    |x: T, y: T| if x <= y { x } else { y }
}
// ANCHOR_END: minimum_operator

/// Returns a closure that computes the maximum
/// between two elements of type T.
/// # Example
///
/// ```
/// # use closures::binary_operator::{maximum_operator};
/// # fn main() {
/// let f = maximum_operator();
/// assert!(f(1,2) == 2);
/// # }
/// ```
// ANCHOR: maximum_operator
pub fn maximum_operator<T: PartialOrd>() -> BinaryOperator<T> {
    |x: T, y: T| if x >= y { x } else { y }
}
// ANCHOR_END: maximum_operator

/// Returns a closure that computes the sum
/// of two elements of type T.
/// # Example
///
/// ```
/// # use closures::binary_operator::{sum_operator};
/// # fn main() {
/// let f = sum_operator();
/// assert!(f(1,2) == 3);
/// # }
/// ```
// ANCHOR: sum_operator
pub fn sum_operator<T: std::ops::Add<Output = T>>() -> BinaryOperator<T> {
    |x: T, y: T| x + y
}
// ANCHOR_END: sum_operator

/// Returns a closure that computes the product
/// of two elements of type T.
/// # Example
///
/// ```
/// # use closures::binary_operator::{mul_operator};
/// # fn main() {
/// let f = mul_operator();
/// assert!(f(1,2) == 2);
/// # }
/// ```
// ANCHOR: mul_operator
pub fn mul_operator<T: std::ops::Mul<Output = T>>() -> BinaryOperator<T> {
    |x: T, y: T| x * y
}
// ANCHOR_END: mul_operator

src/find.rs

//! Contains the core logic of the library, allowing to store generic values
//! (or their absence) and manipulate them.
//! We demonstrates three kind of way to deal with errors

use crate::binary_operator::BinaryOperator;

/// Computes the result of a binary reduction of an Array of a type T.
/// Take the binary operation as a function.
/// Returns a [Option::Some] containing the result value
/// or [Option::None] if the array was empty.
///
/// # Example
///
/// ```
/// # use closures::find::{find_with_hof};
/// # fn main() {
/// let tab = [10, 32, 12, 43, 52, 53, 83, 2, 9];
/// let min = find_with_hof(&tab,|x, y| if x <= y { x } else { y });
/// assert!(min == Some(2));
/// # }
/// ```
// ANCHOR: find_with_hof
pub fn find_with_hof<T: Copy>(tab: &[T], op: BinaryOperator<T>) -> Option<T> {
    let mut res = None;
    // Here, if T is Copyable, t is not moved in the loop
    for t in tab {
        if let Some(val) = res {
            res = Some(op(val, *t))
        } else {
            res = Some(*t)
        }
    }
    res
}
// ANCHOR_END: find_with_hof

src/io.rs

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

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

/// Poorly emulates the parsing of a command line.
pub fn read_empty_command_line() -> [i32; 0] {
    []
}

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

iterateurs

src/lib.rs

#![allow(unused)]
fn main() {
//! This crate shows us different ways of dealing with errors in a Rust program.
//! You will find examples of [Option], [Result] and [panic!].

pub mod find;
pub mod io;

#[cfg(test)]
mod tests {
    use crate::find::{find_absolute_minimum, find_minimum};
    const VEC: [i32; 9] = [10, 32, 12, 43, 52, 53, 83, 2, 9];
    const VEC_2: [i32; 9] = [-10, 32, 12, -43, 52, -53, 83, -2, 9];
    const MIN_VEC: i32 = 2;
    const ABS_MIN_VEC_2: i32 = -2;

    #[test]
    fn test_find_minimum() {
        let min: Option<i32> = find_minimum(&(VEC.to_vec()));

        assert!(min == Some(MIN_VEC));
    }

    #[test]
    fn test_find_absolute_minimum() {
        let min: Option<i32> = find_absolute_minimum(&(VEC_2.to_vec()));

        assert!(min == Some(ABS_MIN_VEC_2));
    }
}
}

src/main.rs

use iterateurs::find::{find_absolute_minimum, find_even_minimum, find_minimum};
use iterateurs::io;

fn main() {
    let v = io::read_command_line_correct();
    println!("Among the elements in the list:");
    io::print_vec(&v);

    let min = find_minimum(&v);
    match min {
        Some(val) => println!("The minimum value is {}", val),
        None => eprintln!("There is no minimum"),
    }

    let min = find_absolute_minimum(&v);
    match min {
        Some(val) => println!("The minimum by absolute value is {}", val),
        None => eprintln!("There is no minimum"),
    }

    let min = find_even_minimum(&v);
    match min {
        Some(val) => println!("The smallest even value is {}", val),
        None => eprintln!("There is no minimum"),
    }
}

src/find.rs

//! Contains the core logic of the library, allowing to store generic values
//! (or their absence) and manipulate them.
//! We demonstrate several ways to process collections with iterators.

/// Computes the minimum of a vector of i32.
/// Returns a [Option::Some] containing the minimum value
/// or [Option::None] if the vec was empty.
///
/// # Example
///
/// ```
/// # use iterateurs::find::{find_minimum};
/// # fn main() {
/// let v = vec![-2, 5, 18, 65, 22, 56, -30];
/// let min = find_minimum(&v);
/// assert!(min == Some(-30));
/// # }
/// ```
// ANCHOR: find_minimum
pub fn find_minimum(v: &Vec<i32>) -> Option<i32> {
    v.iter().fold(None, |acc, current| {
        let next_acc = if let Some(val) = acc {
            if val <= *current { val } else { *current }
        } else {
            *current
        };
        Some(next_acc)
    })
}
// ANCHOR_END: find_minimum

/// Computes the smallest even number in a vector of i32.
/// Returns a [Option::Some] containing the smallest even number
/// or [Option::None] if the vec was empty.
///
/// # Example
///
/// ```
/// # use iterateurs::find::{find_even_minimum};
/// # fn main() {
/// let v = vec![15, 64, 47, 2, 1, 53, 22];
/// let min = find_even_minimum(&v);
/// assert!(min == Some(2));
/// # }
/// ```
// ANCHOR: find_even_minimum
pub fn find_even_minimum(v: &Vec<i32>) -> Option<i32> {
    v.iter().filter(|i| *i % 2 == 0).fold(None, |acc, current| {
        let next_acc = if let Some(val) = acc {
            if val <= *current { val } else { *current }
        } else {
            *current
        };
        Some(next_acc)
    })
}
// ANCHOR_END: find_even_minimum

/// Computes the minimum absolute value of a vector of i32.
/// Returns a [Option::Some] containing the minimum abs value
/// or [Option::None] if the vec was empty.
///
/// # Example
///
/// ```
/// # use iterateurs::find::{find_absolute_minimum};
/// # fn main() {
/// let v = vec![-2, 5, 18, 65, 22, 56, -30];
/// let min = find_absolute_minimum(&v);
/// assert!(min == Some(-2));
/// # }
/// ```
// ANCHOR: find_absolute_minimum
pub fn find_absolute_minimum(v: &Vec<i32>) -> Option<i32> {
    // ANCHOR: find_absolute_minimum_1
    let signs = v.iter().map(|i| i.signum());
    let abs_values = v.iter().map(|i| i.abs());
    // ANCHOR_END: find_absolute_minimum_1
    // ANCHOR: find_absolute_minimum_2
    signs
        .zip(abs_values)
        // ANCHOR_END: find_absolute_minimum_2
        // ANCHOR: find_absolute_minimum_3
        .fold(None, |acc, (c_sign, c_abs_v)| {
            let next_acc = if let Some((sign, abs_v)) = acc {
                if abs_v <= c_abs_v {
                    (sign, abs_v)
                } else {
                    (c_sign, c_abs_v)
                }
            } else {
                (c_sign, c_abs_v)
            };
            Some(next_acc)
        })
        // ANCHOR_END: find_absolute_minimum_3
        // ANCHOR: find_absolute_minimum_4
        .map(|(sign, abs_v)| sign * abs_v)
    // ANCHOR_END: find_absolute_minimum_4
}
// ANCHOR_END: find_absolute_minimum

src/io.rs

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

/// Poorly emulates the parsing of a command line.
pub fn read_command_line_correct() -> Vec<i32> {
    vec![-10, 32, 12, -43, 52, -53, 83, -2, 9]
}

/// Poorly emulates the parsing of a command line.
pub fn read_empty_command_line() -> Vec<i32> {
    vec![]
}

/// Prints all the elements of the vector.
/// vector is borrowed here
pub fn print_vec(v: &Vec<i32>) {
    print!("[ ");
    for t in v {
        print!("{} ", t);
    }
    println!("]");
}
}

collections

src/lib.rs

#![allow(unused)]
fn main() {
//! 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/collections/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.

pub mod io;
pub mod minimum;
pub mod something_or_nothing;

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

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

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

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

src/main.rs

use collections::io;
use collections::something_or_nothing::find_min;

fn main() -> Result<(), String> {
    //ANCHOR: vec
    let tab: Vec<i32> = io::read_command_line(10usize);
    println!("Among the Somethings in the list:");
    io::print_tab(&tab);
    let min = find_min(&tab);
    min.print();
    //ANCHOR_END: vec

    let tab = io::read_command_line_str()?;
    println!("Among the Somethings in the list:");
    io::print_tab(&tab);
    let min = find_min(&tab);
    min.print();

    //ANCHOR: ref
    println!("Among the Somethings in the list:");
    io::print_tab(&tab[1..9]);
    let min = find_min(&tab[1..9]);
    min.print();
    //ANCHOR_END: ref

    //ANCHOR: tab
    let tab = [1, 2, 3, 4, 5, 6];
    println!("Among the Somethings in the list:");
    io::print_tab(&tab);
    let min = find_min(&tab);
    min.print();
    //ANCHOR_END: tab

    Ok(())
}

src/io.rs

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

// ANCHOR: read_command_line
/// Poorly emulates the parsing of a command line.
pub fn read_command_line(len: usize) -> Vec<i32> {
    let mut rng = rand::rng();
    // ANCHOR: vec_new
    let mut v: Vec<i32> = Vec::new();
    // ANCHOR_END: vec_new
    // ANCHOR: vec_for
    for _i in 0..len {
        // ANCHOR: vec_push
        v.push(rng.random());
        // ANCHOR_END: vec_push
    }
    // ANCHOR_END: vec_for
    v
}
// ANCHOR_END: read_command_line

// ANCHOR: read_command_line_str
/// Poorly emulates the parsing of a command line.
pub fn read_command_line_str() -> Result<Vec<i32>, String> {
    // ANCHOR: from
    let mut s = String::from("20 10 48 58 29 0 58 -10 39 5485 394");
    // ANCHOR_END: from
    // ANCHOR: push_str
    s.push_str(" -100");
    // ANCHOR_END: push_str
    // ANCHOR: push_char
    s.push(' ');
    s.push('1');
    s.push('2');
    // ANCHOR_END: push_char
    // ANCHOR: split
    let s: Vec<&str> = s.split_ascii_whitespace().collect();
    // ANCHOR_END: split

    // ANCHOR: string_for
    let mut v = Vec::new();
    for i in 0..s.len() {
        v.push(
            // ANCHOR: conversion
            s.get(i)
                .ok_or(String::from("Unable to index"))?
                .parse()
                .map_err(|_| format!("Unable to parse {}", s[i]))?,
            // ANCHOR_END: conversion
        );
    }
    // ANCHOR_END: string_for
    Ok(v)
}
// ANCHOR_END: read_command_line_str

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

src/minimum.rs

#![allow(unused)]
fn main() {
//! 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 collections::minimum::Minimum;
//! let one = 1;
//! let two = 2;
//! assert!(Minimum::min(one, two) == one);
//! ```

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

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

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

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;

/// 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),
}

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),
        }
    }
}

/// Implementation of the [Default] trait that creates a [SomethingOrNothing]
/// that is a `Nothing` variant.
///
/// # Example
///
/// ```
/// # use collections::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
    }
}

/// 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,
        }
    }
}

/// 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)
            }
        }
    }
}

/// 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 collections::something_or_nothing::{SomethingOrNothing, find_min};
/// # fn main() {
/// let tab = vec![10, 32, 12, 43, 52, 53, 83, 2, 9];
/// let min = find_min(&tab);
/// assert!(min == SomethingOrNothing::Something(2));
/// # }
/// ```
// ANCHOR: find_min
pub fn find_min<T: Minimum>(tab: &[T]) -> 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

lifetimes

src/lib.rs

#![allow(unused)]
fn main() {
/*!
lifetimes illustrates the use of [Vec] and the Error Handling with [Option] and [Result].
It also showcases struct enums.
*/

pub mod custom_int;
pub mod io;
mod minimum;
pub mod something_or_nothing;

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

    #[test]
    fn test_creation() {
        let n1: SomethingOrNothing<i32> = SomethingOrNothing::default();
        assert!(n1 == SomethingOrNothing::default());
        let n2: SomethingOrNothing<i32> = SomethingOrNothing::new(1);
        assert!(n2 == SomethingOrNothing::new(1));
    }

    #[test]
    #[should_panic]
    fn test_failure_creation() {
        let n2: SomethingOrNothing<i32> = SomethingOrNothing::new(1);
        assert!(n2 == SomethingOrNothing::default());
        assert!(n2 == SomethingOrNothing::new(2));
    }

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

    #[test]
    fn test_min_empty() {
        let a: Vec<i32> = vec![];
        let min = find_min(&a);
        assert!(min == SomethingOrNothing::default());
    }

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

    #[test]
    fn test_min_something_or_nothing() {
        let x = SomethingOrNothing::new(5i32);
        let y = SomethingOrNothing::new(10i32);
        let z = SomethingOrNothing::default();
        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);
    }
}
}

src/main.rs

use lifetimes::custom_int::CustomInt;
use lifetimes::io;
use lifetimes::something_or_nothing::find_min;

// ANCHOR: main
fn main() -> Result<(), String> {
    let v1 = vec![1, 3, 6, 9];
    let v2 = vec![2, 4, 2, 1];
    let v3 = vec![7, 4, 5, 3];
    let v4 = vec![4, 1, 1, 1];
    let v5 = vec![2, 5, 1, 8];
    let v6 = vec![5, 1, 5, 2];
    let v7 = vec![7, 6, 6, 7];
    let v8 = vec![8, 2, 2, 2];
    let lhs = vec![
        CustomInt::try_new(&v1, 1)?,
        CustomInt::try_new(&v2, -1)?,
        CustomInt::try_new(&v3, 1)?,
        CustomInt::try_new(&v4, -1)?,
        CustomInt::try_new(&v5, 1)?,
        CustomInt::try_new(&v6, 1)?,
        CustomInt::try_new(&v7, 1)?,
        CustomInt::try_new(&v8, 1)?,
    ];

    println!("Among the custom ints in the list:");
    io::print_tab_custom_int(&lhs);
    let min = find_min(&lhs);
    println!("The minimum is {min}");
    Ok(())
}
// ANCHOR_END: main

src/custom_int.rs

#![allow(unused)]
fn main() {
use std::cmp::Ordering;

use crate::minimum::Minimum;

/// Larger ints based on a [Vec] of [u8] to represent arbitrary lengthy numbers.
/// The number has a sign as well.
// ANCHOR: custom_int
#[derive(Debug)]
pub struct CustomInt<'a> {
    /// The data contains the unsigned integers that are read from right to left
    /// The number 1337 is stored as vec![7, 3, 3, 1]. Each number must be in the range [0,9]
    /// and no trailing 0s are allowed.
    data: &'a Vec<u8>,
    /// Contains the sign of the number +/-1;
    sign: i8,
}
// ANCHOR_END: custom_int

// ANCHOR: custom_int_impl
impl<'a> CustomInt<'a>
// ANCHOR_END: custom_int_impl
{
    /// Tries to create a new [CustomInt]. If the number is valid it returns
    /// an Ok(CustomInt) an Error otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// use lifetimes::custom_int::CustomInt;
    /// let v1 = vec![1, 2, 3, 4];
    /// let num = CustomInt::try_new(&v1, 1);
    /// assert!(num.is_ok());
    /// let num = CustomInt::try_new(&v1, -1);
    /// assert!(num.is_ok());
    /// let num = CustomInt::try_new(&v1, 10);
    /// assert!(num.is_err());
    /// let num = CustomInt::try_new(&v1, -10);
    /// assert!(num.is_err());
    /// let v1 = vec![];
    /// let num = CustomInt::try_new(&v1, -1);
    /// assert!(num.is_err());
    /// ```
    ///
    // ANCHOR: try_new
    pub fn try_new(data: &'a Vec<u8>, sign: i8) -> Result<Self, String> {
        if data.is_empty() {
            Err(String::from("Data is empty."))
        } else if sign == 1 || sign == -1 {
            Ok(CustomInt { data, sign })
        } else {
            Err(String::from("Invalid sign."))
        }
    }
    // ANCHOR_END: try_new
}

// ANCHOR: minimum
impl<'a> Minimum<'a> for CustomInt<'a>
// ANCHOR_END: minimum
{
    // ANCHOR: min
    fn min(&'a self, rhs: &'a Self) -> &'a Self {
        match self.sign.cmp(&rhs.sign) {
            Ordering::Less => return self,
            Ordering::Greater => return rhs,
            Ordering::Equal => match self.data.len().cmp(&rhs.data.len()) {
                Ordering::Less => {
                    if self.sign == 1 {
                        return self;
                    } else {
                        return rhs;
                    }
                }
                Ordering::Greater => {
                    if self.sign == 1 {
                        return rhs;
                    } else {
                        return self;
                    }
                }
                Ordering::Equal => {
                    for (l, r) in self.data.iter().rev().zip(rhs.data.iter().rev()) {
                        let ls = (*l as i8) * self.sign;
                        let rs = (*r as i8) * self.sign;
                        match ls.cmp(&rs) {
                            Ordering::Less => return self,
                            Ordering::Greater => return rhs,
                            Ordering::Equal => {}
                        }
                    }
                }
            },
        }
        self
    }
    // ANCHOR_END: min
}

// ANCHOR: partialeq
impl<'a> PartialEq for CustomInt<'a>
// ANCHOR_END: partialeq
{
    fn eq(&self, other: &Self) -> bool {
        if self.sign == other.sign && self.data.len() == other.data.len() {
            self.data
                .iter()
                .zip(other.data.iter())
                .try_fold(true, |_, (l, r)| if *l == *r { Some(true) } else { None })
                .is_some()
        } else {
            false
        }
    }
}

// ANCHOR: display
impl<'a> std::fmt::Display for CustomInt<'a>
// ANCHOR_END: display
{
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        // This could be replaced by an `?`
        if self.sign == -1 {
            write!(f, "-")?;
        }

        // This could be replaced by an `?`
        let res = self
            .data
            .iter()
            .rev()
            .try_fold((), |_, t| write!(f, "{}", t));
        res
    }
}

#[cfg(test)]
mod tests {
    use crate::custom_int::CustomInt;
    use crate::minimum::Minimum;
    use crate::something_or_nothing::find_min;

    #[test]
    fn test_creation() {
        let v1 = vec![1, 2, 3, 4];
        CustomInt::try_new(&v1, 1).unwrap();
        CustomInt::try_new(&v1, -1).unwrap();
    }

    #[test]
    #[should_panic]
    fn test_failure_creation_sign() {
        let v1 = vec![1, 2, 3, 4];
        CustomInt::try_new(&v1, 10).unwrap();
    }

    #[test]
    #[should_panic]
    fn test_failure_creation_sign2() {
        let v1 = vec![1, 2, 3, 4];
        CustomInt::try_new(&v1, 0).unwrap();
    }

    #[test]
    #[should_panic]
    fn test_failure_creation_data() {
        let v1 = vec![];
        CustomInt::try_new(&v1, 1).unwrap();
    }

    #[test]
    fn test_min() {
        let mut v = Vec::new();
        let v1 = vec![1, 2, 3, 4];
        let v2 = vec![1, 2, 3];
        let lhs = CustomInt::try_new(&v1, 1).unwrap();
        let rhs = CustomInt::try_new(&v2, 1).unwrap();
        assert!(rhs == *lhs.min(&rhs));
        v.push(lhs);
        v.push(rhs);
        let lhs = CustomInt::try_new(&v1, -1).unwrap();
        let rhs = CustomInt::try_new(&v2, -1).unwrap();
        assert!(lhs == *lhs.min(&rhs));
        v.push(lhs);
        v.push(rhs);
        let v1 = vec![1, 2, 3, 4];
        let v2 = vec![1, 2, 5, 4];
        let lhs = CustomInt::try_new(&v1, -1).unwrap();
        let rhs = CustomInt::try_new(&v2, -1).unwrap();
        assert!(rhs == *lhs.min(&rhs));
        v.push(lhs);
        v.push(rhs);
        let lhs = CustomInt::try_new(&v1, 1).unwrap();
        let rhs = CustomInt::try_new(&v2, 1).unwrap();
        assert!(lhs == *lhs.min(&rhs));
        let min = find_min(&v);
        assert_eq!(*min.unwrap(), CustomInt::try_new(&v2, -1).unwrap());
    }
}
}

src/io.rs

#![allow(unused)]
fn main() {
use crate::custom_int::CustomInt;

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

/// Prints all the elements of the `tab`.
/// Tab is borrowed here
pub fn print_tab_custom_int(tab: &Vec<CustomInt>) {
    for i in tab {
        println!("{i} ");
    }
    println!();
}
}

src/minimum.rs

#![allow(unused)]
fn main() {
// ANCHOR: minimum
pub trait Minimum<'a> {
    fn min(&'a self, rhs: &'a Self) -> &'a Self;
}
// ANCHOR_END: minimum

// ANCHOR: min
impl<'a> Minimum<'a> for i32 {
    fn min(&'a self, rhs: &'a Self) -> &'a Self {
        if self < rhs { self } else { rhs }
    }
}
// ANCHOR_END: min
}

src/something_or_nothing.rs

use std::fmt::Display;

use crate::minimum::Minimum;

/// A generic newtype that wraps an Option<T>.
// ANCHOR: newtype
#[derive(Debug)]
pub struct SomethingOrNothing<T>(Option<T>);
// ANCHOR_END: newtype

impl<T> SomethingOrNothing<T> {
    pub fn new(val: T) -> Self {
        SomethingOrNothing(Some(val))
    }

    // ANCHOR: newtype_unwrap
    pub fn unwrap(self) -> T {
        self.0.unwrap()
    }
    // ANCHOR_END: newtype_unwrap
}

// ANCHOR: newtype_display
impl<T: Display> std::fmt::Display for SomethingOrNothing<T> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match &self {
            SomethingOrNothing(None) => write!(f, "Nothing.")?,
            SomethingOrNothing(Some(val)) => write!(f, "Something is: {}", val)?,
        }
        Ok(())
    }
}
// ANCHOR_END: newtype_display

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

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

// ANCHOR: min
// ANCHOR: impl_min
impl<'a, T: Minimum<'a> + PartialEq> Minimum<'a> for SomethingOrNothing<T>
// ANCHOR_END: impl_min
{
    fn min(&'a self, rhs: &'a Self) -> &'a Self {
        match (self, rhs) {
            (SomethingOrNothing(None), SomethingOrNothing(None)) => self,
            (SomethingOrNothing(Some(l)), SomethingOrNothing(Some(r))) => {
                if *l == *l.min(r) {
                    self
                } else {
                    rhs
                }
            }
            (SomethingOrNothing(None), SomethingOrNothing(Some(_))) => rhs,
            (SomethingOrNothing(Some(_)), SomethingOrNothing(None)) => self,
        }
    }
}
// ANCHOR_END: min

/// Computes the minimum of an Array of a type T which implements the [Minimum] trait.
/// Returns a [Something] containing the minimum value
/// or [Nothing] if no minimum value was found.
///
/// # Examples
///
/// ```
/// # use lifetimes::something_or_nothing::{SomethingOrNothing, find_min};
/// # fn main() {
/// let tab = vec![10, 32, 12, 43, 52, 53, 83, 2, 9];
/// let min = find_min(&tab);
/// assert!(*min.unwrap() == 2);
/// # }
/// ```
///
/// ```
/// # use lifetimes::something_or_nothing::{SomethingOrNothing, find_min};
/// # fn main() {
/// let tab: Vec<i32> = vec![];
/// let min = find_min(&tab);
/// assert!(min == SomethingOrNothing::default());
/// # }
/// ```
// ANCHOR: find_min
pub fn find_min<'a, T: Minimum<'a>>(tab: &'a [T]) -> SomethingOrNothing<&'a T> {
    // A very elegant fold applied on an iterator
    tab.iter().fold(SomethingOrNothing::default(), |res, x| {
        let r = match res {
            SomethingOrNothing(None) => x,
            SomethingOrNothing(Some(r)) => r.min(x),
        };
        SomethingOrNothing::new(r)
    })
}
// ANCHOR_END: find_min

/// Finds the minimum values contained in two slices and returns the reference
/// towards the slice that contains it.
///
/// # Examples
///
/// ```
/// # use lifetimes::something_or_nothing::{SomethingOrNothing, vec_with_min};
/// # fn main() {
/// let tab1 = vec![10, 32, 12, 43, 52, 53, 83, 2, 9];
/// let tab2 = vec![10, 32, 12, 43, -2, 53, 83, 2, 9];
///
/// let min = vec_with_min(&tab1, &tab2).unwrap();
/// assert!(min == &tab2);
/// # }
/// ```
pub fn vec_with_min<'a, T: Minimum<'a> + PartialEq>(
    lhs: &'a [T],
    rhs: &'a [T],
) -> SomethingOrNothing<&'a [T]> {
    match (find_min(lhs), find_min(rhs)) {
        (SomethingOrNothing(None), SomethingOrNothing(None)) => SomethingOrNothing::default(),
        (SomethingOrNothing(None), SomethingOrNothing(Some(_))) => SomethingOrNothing::new(rhs),
        (SomethingOrNothing(Some(_)), SomethingOrNothing(None)) => SomethingOrNothing::new(lhs),
        (SomethingOrNothing(Some(l)), SomethingOrNothing(Some(r))) => {
            if *l == *l.min(r) {
                SomethingOrNothing::new(lhs)
            } else {
                SomethingOrNothing::new(rhs)
            }
        }
    }
}

cli

src/lib.rs

#![allow(unused)]
fn main() {
/*!
cli illustrates the use of [Vec] and the Error Handling with [Option] and [Result].
It also showcases struct enums.
*/

pub mod io;
mod minimum;
pub mod something_or_nothing;

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

    #[test]
    fn test_creation() {
        let n1: SomethingOrNothing<i32> = SomethingOrNothing::default();
        assert!(n1 == SomethingOrNothing::default());
        let n2: SomethingOrNothing<i32> = SomethingOrNothing::new(1);
        assert!(n2 == SomethingOrNothing::new(1));
    }

    #[test]
    #[should_panic]
    fn test_failure_creation() {
        let n2: SomethingOrNothing<i32> = SomethingOrNothing::new(1);
        assert!(n2 == SomethingOrNothing::default());
        assert!(n2 == SomethingOrNothing::new(2));
    }

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

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

    #[test]
    fn test_min_something_or_nothing() {
        let x = SomethingOrNothing::new(5i32);
        let y = SomethingOrNothing::new(10i32);
        let z = SomethingOrNothing::default();
        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);
    }
}
}

src/main.rs

use cli::io;

fn main() -> Result<(), String> {
    io::read_command_line_builder()?;
    Ok(())
}

src/io.rs

#![allow(unused)]
fn main() {
use std::{
    fs::File,
    io::{BufReader, Read, Write},
};

// ANCHOR: use_clap
use clap::{Arg, Command, Parser, value_parser};
// ANCHOR_END: use_clap

// ANCHOR: consts
const COMMAND: &str = "cli";
const AUTHOR: &str = "Orestis Malaspinas";
const VERSION: &str = "0.1.0";
// ANCHOR_END: consts

use crate::something_or_nothing::find_min;

// ANCHOR: read_from_urandom
fn read_from_urandom(count: usize) -> Result<Vec<i32>, String> {
    // ANCHOR: open
    let file = File::open("/dev/urandom").map_err(|_| "Could not open /dev/urandom")?;
    // ANCHOR_END: open
    // ANCHOR: read
    let mut buf_reader = BufReader::new(file);
    let mut numbers = vec![0; count * 4];
    buf_reader
        .read_exact(&mut numbers)
        .map_err(|_| "Could not read numbers")?;
    // ANCHOR_END: read
    // ANCHOR: convert_to_i32
    Ok(numbers
        .chunks(4)
        .map(|i| i32::from_be_bytes(i.try_into().unwrap()))
        .collect::<Vec<_>>())
    // ANCHOR_END: convert_to_i32
}
// ANCHOR_END: read_from_urandom

// ANCHOR: write_to_file
fn write_to_file(output: &str, numbers: &[i32]) -> Result<(), String> {
    // ANCHOR: create
    let mut file = File::create(output).map_err(|_| format!("Failed to create {output}"))?;
    // ANCHOR_END: create
    // ANCHOR: write
    writeln!(file, "Among the Somethings in the list:")
        .map_err(|_| "Failed to write header into file.")?;
    for n in numbers {
        write!(file, "{n} ").map_err(|_| format!("Failed to write {n} into file."))?;
    }
    writeln!(file,).map_err(|_| "Failed to write carriage return into file.")?;
    writeln!(file, "{}", find_min(numbers).to_string())
        .map_err(|_| "Failed to write minimum value into file.")?;
    // ANCHOR_END: write
    Ok(())
}
// ANCHOR_END: write_to_file

/// Reads i32 from the command line and returns a [Vec] containing
/// these numbers. Returns errors when the parsing fails.
pub fn read_command_line_builder() -> Result<(), String> {
    // ANCHOR: matches
    let matches =
    // ANCHOR: new_command
        Command::new(COMMAND)
            .author(AUTHOR)
            .version(VERSION)
    // ANCHOR_END: new_command
    // ANCHOR: new_args
            .arg(
                Arg::new("numbers") // id
                    .short('n')         // version courte -n
                    .long("numbers")    // ou longue --numbers
                    .help("A list of i32 numbers") // l'aide
                    .num_args(1..) // combien il y a d'entrées
                    .allow_negative_numbers(true) // on peut avoir des négatifs
                    .value_parser(value_parser!(i32)) // on veut s'assurer que ça soit des nombres
                    .required(false), // optionnel
            )
            .arg(
                Arg::new("count")
                    .short('c')
                    .long("count")
                    .help("How many random numbers we want?")
                    .value_parser(value_parser!(usize))
                    .conflicts_with("numbers") // impossible d'avoir -c et -n
                    .required(false),
            )
            .arg(
                Arg::new("output")
                    .short('o')
                    .long("output")
                    .help("Should we write output in a file?")
                    .required(false),
            )
    // ANCHOR: new_args
            .get_matches();
    // ANCHOR_END: matches

    // ANCHOR: numbers_matches
    let numbers = if let Some(count) =
        // ANCHOR: get_one_matches
        matches.get_one::<usize>("count")
    // ANCHOR_END: get_one_matches
    {
        read_from_urandom(*count)?
    } else if let Some(numbers) =
        // ANCHOR: get_many_matches
        matches.get_many::<i32>("numbers")
    // ANCHOR_END: get_many_matches
    {
        numbers.copied().collect()
    } else {
        Vec::new()
    };
    // ANCHOR_END: numbers_matches

    // ANCHOR: output_matches
    if let Some(output) =
        // ANCHOR: get_one_string_matches
        matches.get_one::<String>("output")
    // ANCHOR_END: get_one_string_matches
    {
        write_to_file(output, &numbers)?;
    } else {
        println!("Among the Somethings in the list:");
        print_tab(&numbers);
        println!("{}", find_min(&numbers).to_string());
    }
    // ANCHOR_END: output_matches

    Ok(())
}

/// Does not compile without the feature derive
// ANCHOR: derive
#[derive(Parser)]
// ANCHOR: command
#[command(author, version, about, long_about = None)]
// ANCHOR_END: command
struct CliMin {
    // ANCHOR: arg
    #[arg(short, long, help = "A list of i32 numbers", num_args=1.., allow_negative_numbers=true, value_parser = clap::value_parser!(i32))]
    numbers: Option<Vec<i32>>,
    // ANCHOR_END: arg
    #[arg(short, long, help = "How many random numbers we want?", value_parser = clap::value_parser!(usize), conflicts_with = "numbers")]
    count: Option<usize>,
    #[arg(short, long, help = "Filename for writing the numbers.")]
    output: Option<String>,
}
// ANCHOR_END: derive

/// Reads i32 from the command line and returns a [Vec] containing
/// these numbers. Returns errors when the parsing fails.
// ANCHOR: read_command_line_derive
pub fn read_command_line_derive() -> Result<(), String> {
    // ANCHOR: parse
    let cli = CliMin::parse();
    // ANCHOR_END: parse
    let numbers = if let Some(count) = cli.count {
        read_from_urandom(count)?
    } else if let Some(numbers) = cli.numbers {
        numbers
    } else {
        Vec::new()
    };
    if let Some(output) = cli.output {
        write_to_file(&output, &numbers)?;
    } else {
        println!("Among the Somethings in the list:");
        print_tab(&numbers);
        println!("{}", find_min(&numbers).to_string());
    }
    Ok(())
}
// ANCHOR_END: read_command_line_derive

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

src/minimum.rs

#![allow(unused)]
fn main() {
// If we remove Copy, we have a problem with the t in tab
// in the computation of the minimum.
pub trait Minimum: Copy {
    fn min(self, rhs: Self) -> Self;
}

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

src/something_or_nothing.rs

use std::fmt::Display;

use crate::minimum::Minimum;

/// A generic newtype that wraps an Option<T>.
#[derive(Clone, Copy)]
pub struct SomethingOrNothing<T>(Option<T>);

impl<T: Minimum + Display> SomethingOrNothing<T> {
    pub fn new(val: T) -> Self {
        SomethingOrNothing(Some(val))
    }
    /// A method that returns the content of a SomethingOrNothing as a String.
    pub fn to_string(&self) -> String {
        match self.0 {
            None => String::from("Nothing."),
            Some(val) => format!("Something is: {}", val),
        }
    }
}

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

impl<T: PartialEq + Minimum> PartialEq for SomethingOrNothing<T> {
    fn eq(&self, other: &Self) -> bool {
        match (self.0, other.0) {
            (None, None) => true,
            (Some(lhs), Some(rhs)) => lhs == rhs,
            _ => false,
        }
    }
}

impl<T: Minimum + Display> Minimum for SomethingOrNothing<T> {
    fn min(self, rhs: Self) -> Self {
        match (self.0, rhs.0) {
            (None, None) => SomethingOrNothing(None),
            (Some(lhs), Some(rhs)) => SomethingOrNothing::new(lhs.min(rhs)),
            (None, Some(rhs)) => SomethingOrNothing::new(rhs),
            (Some(lhs), None) => SomethingOrNothing::new(lhs),
        }
    }
}

/// Computes the minimum of an Array of a type T which implements the [Minimum] trait.
/// Returns a [Some] containing the minimum value
/// or [None] if no minimum value was found.
///
/// # Examples
///
/// ```
/// # use cli::something_or_nothing::{SomethingOrNothing, find_min};
/// # fn main() {
/// let tab = vec![10, 32, 12, 43, 52, 53, 83, 2, 9];
/// let min = find_min(&tab);
/// assert!(min == SomethingOrNothing::new(2));
/// # }
/// ```
///
/// ```
/// # use cli::something_or_nothing::{SomethingOrNothing, find_min};
/// # fn main() {
/// let tab: Vec<i32> = vec![];
/// let min = find_min(&tab);
/// assert!(min == SomethingOrNothing::default());
/// # }
/// ```
pub fn find_min<T: Minimum + Display>(tab: &[T]) -> SomethingOrNothing<T> {
    let mut minimum: SomethingOrNothing<T> = SomethingOrNothing(None);
    // Here, if T is Copyable, t is not moved in the loop
    for t in tab {
        minimum = minimum.min(SomethingOrNothing::new(*t));
    }
    minimum
}

unsafe

src/lib.rs

#![allow(unused)]
fn main() {
pub mod immutable_linked_list;
pub mod safe_linked_list;
pub mod unsafe_linked_list;
}

src/main.rs

use linked_list::immutable_linked_list::LinkedList as ImmutableList;
use linked_list::safe_linked_list::LinkedList as SafeList;
use linked_list::unsafe_linked_list::LinkedList as UnsafeList;

fn create_lists() -> (ImmutableList, SafeList, UnsafeList) {
    (ImmutableList::new(), SafeList::new(), UnsafeList::new())
}

fn main() {
    let (immutable_list, mut safe_list, mut unsafe_list) = create_lists();

    // Populate lists
    let immutable_list = immutable_list.push(1);
    let immutable_list = immutable_list.push(2);
    let immutable_list = immutable_list.push(3);

    safe_list.push(1);
    safe_list.push(2);
    safe_list.push(3);

    unsafe_list.push(1);
    unsafe_list.push(2);
    unsafe_list.push(3);

    let (i_val, immutable_list) = immutable_list.pop();
    let s_val = safe_list.pop();
    let u_val = unsafe_list.pop();

    assert_eq!(i_val, s_val);
    assert_eq!(i_val, u_val);
    assert_eq!(s_val, u_val);

    let immutable_list = immutable_list.push(4);
    safe_list.push(4);
    unsafe_list.push(4);

    immutable_list.print();
    safe_list.print();
    unsafe_list.print();

    for _j in 1..5 {
        let mut ul = UnsafeList::new();
        for i in 1..1_000_000 {
            ul.push(i);
        }
    }

    unsafe_list.print();
}

src/immutable_linked_list/mod.rs

#![allow(unused)]
fn main() {
// ANCHOR: element
struct Element {
    data: i32,
    next: Option<Box<Element>>,
}
// ANCHOR_END: element

impl Element {
    fn new(data: i32, next: Option<Box<Element>>) -> Self {
        Element { data, next }
    }
}

// ANCHOR: linked_list
pub struct LinkedList {
    head: Option<Box<Element>>,
}
// ANCHOR_END: linked_list

impl LinkedList {
    // ANCHOR: new
    pub fn new() -> Self {
        Self { head: None }
    }
    // ANCHOR_END: new

    // ANCHOR: is_empty
    pub fn is_empty(self) -> (bool, Self) {
        match self.head {
            None => (true, self),
            _ => (false, self),
        }
    }
    // ANCHOR_END: is_empty

    // ANCHOR: push
    pub fn push(self, data: i32) -> Self {
        let elem = Box::new(Element::new(data, self.head));
        Self { head: Some(elem) }
    }
    // ANCHOR_END: push

    // ANCHOR: pop
    pub fn pop(self) -> (Option<i32>, Self) {
        if let Some(elem) = self.head {
            (Some(elem.data), Self { head: elem.next })
        } else {
            (None, Self { head: None })
        }
    }
    // ANCHOR_END: pop

    // ANCHOR: print
    pub fn print(self) -> Self {
        // Attention : new_list est reconstruite en ré-empilant chaque élément en
        // tête, elle est donc renvoyée dans l'ordre inverse de `self`.
        let mut new_list = Self::new();
        // ANCHOR: while
        let mut current = self.head;
        while let Some(tmp) = current {
            print!("{} --> ", tmp.data);
            new_list = new_list.push(tmp.data);
            current = tmp.next;
        }
        println!("∅");
        // ANCHOR_END: while
        new_list
    }
    // ANCHOR_END: print

    #[allow(dead_code)]
    // ANCHOR: clear
    pub fn clear(self) {
        let mut current = self.head;
        while let Some(tmp) = current {
            current = tmp.next;
        }
    }
    // ANCHOR_END: clear
}

#[cfg(test)]
mod tests {
    use super::LinkedList;

    #[test]
    fn new() {
        let (is_empty, _) = LinkedList::new().is_empty();
        assert!(is_empty);
    }

    #[test]
    fn push() {
        let list = LinkedList::new();
        let list = list.push(1);
        let (is_empty, list) = list.is_empty();
        assert!(!is_empty);
        assert_eq!(list.head.as_ref().unwrap().data, 1);

        let list = list.push(2);
        assert_eq!(list.head.unwrap().data, 2);
    }

    #[test]
    fn pop() {
        let list = LinkedList::new();
        let (e, list) = list.pop();
        assert_eq!(e, None);

        let list = list.push(1);
        let (e, list) = list.pop();
        assert_eq!(e, Some(1));

        let (e, list) = list.pop();
        assert_eq!(e, None);

        let list = list.push(2);
        let list = list.push(3);
        let list = list.push(4);

        assert_eq!(list.head.as_ref().unwrap().data, 4);

        let (e, list) = list.pop();
        assert_eq!(list.head.as_ref().unwrap().data, 3);
        assert_eq!(e, Some(4));
        let (_, list) = list.pop();
        let (_, list) = list.pop();
        let (is_empty, _) = list.is_empty();
        assert!(is_empty);
    }
}
}

src/safe_linked_list/mod.rs

#![allow(unused)]
fn main() {
// ANCHOR: element
struct Element {
    data: i32,
    next: Option<Box<Element>>,
}
// ANCHOR_END: element

impl Element {
    fn new(data: i32, next: Option<Box<Element>>) -> Self {
        Element { data, next }
    }
}

// ANCHOR: linked_list
pub struct LinkedList {
    head: Option<Box<Element>>,
}
// ANCHOR_END: linked_list

impl LinkedList {
    // ANCHOR: new
    pub fn new() -> Self {
        Self { head: None }
    }
    // ANCHOR_END: new

    // ANCHOR: is_empty
    pub fn is_empty(&self) -> bool {
        self.head.is_none()
    }
    // ANCHOR_END: is_empty

    // ANCHOR: push
    pub fn push(&mut self, data: i32) {
        // let new_element = Box::new(Element::new(data, self.head));
        // Cela ne peut pas fonctionner, parce qu'on est derrière une référence partagée
        // et donc on ne peut pas "move" self.head

        // ANCHOR: take
        let new_head = Box::new(Element::new(data, self.head.take()));
        // ANCHOR_END: take
        // take retourne la valeur qui se trouve dans Some et laisse un None
        // à la place de l'option.
        // C'est strictement équivalent au replace (ci-dessous)
        self.head = Some(new_head);
    }
    // ANCHOR_END: push

    // ANCHOR: push_replace
    pub fn push_replace(&mut self, data: i32) {
        // ANCHOR: replace
        let old_head = std::mem::replace(&mut self.head, None);
        let new_head = Box::new(Element::new(data, old_head));
        // ANCHOR_END: replace
        // replace retourne self.head et remplace l'ancienne valeur par None (comme ça le compilateur est content)
        self.head = Some(new_head);
    }
    // ANCHOR_END: push_replace

    // ANCHOR: push_unsafe
    pub fn push_unsafe(&mut self, data: i32) {
        let old_head = unsafe {
            // De la documentation:
            // `read` crée une copie bit à bit de `T`, que `T` soit [`Copy`] ou non.
            // Si `T` n'est pas [`Copy`], utiliser à la fois la valeur renvoyée et la valeur de
            // `*src` peut violer la sécurité de la mémoire. Notez que l'assignation à `*src` compte comme une
            // utilisation parce qu'elle tentera de `drop` la valeur à `*src`.
            let result = std::ptr::read(&self.head);
            std::ptr::write(&mut self.head, None);
            // Ce `write` est en fait un "truc" pour enlever l'aliasing entre
            // self.head et result. Il écrase la valeur à self.head avec None
            // sans `drop` self.head et donc result.
            result
        };
        let new_head = Box::new(Element::new(data, old_head));
        self.head = Some(new_head);
    }
    // ANCHOR_END: push_unsafe

    // ANCHOR: pop
    pub fn pop(&mut self) -> Option<i32> {
        // map prend la valeur dans Some, lui applique la fonction anonyme
        // et remballe la valeur obtenue dans un Some. Si l'Option
        // originale est None, il se passe rien.
        self.head.take().map(|element| {
            self.head = element.next;
            element.data
        })
    }
    // ANCHOR_END: pop

    // ANCHOR: print
    pub fn print(&self) {
        let mut current = &self.head;
        while let Some(tmp) = &current {
            print!("{} --> ", tmp.data);
            current = &tmp.next;
        }
        println!("∅");
    }
    // ANCHOR_END: print
}

impl Drop for LinkedList {
    fn drop(&mut self) {
        let mut current = self.head.take();
        while let Some(mut tmp) = current {
            current = tmp.next.take();
        }
    }
}

#[cfg(test)]
mod test {
    use super::LinkedList;

    #[test]
    fn new() {
        assert!(LinkedList::new().is_empty());
    }

    #[test]
    fn push() {
        let mut list = LinkedList::new();
        list.push(1);
        assert_eq!(list.head.as_ref().unwrap().data, 1);
        list.push(2);
        assert_eq!(list.head.as_ref().unwrap().data, 2);
    }

    #[test]
    fn pop() {
        let mut list = LinkedList::new();
        let e = list.pop();
        assert_eq!(e, None);

        list.push(1);
        let e = list.pop();
        assert_eq!(e, Some(1));

        let e = list.pop();
        assert_eq!(e, None);

        list.push(2);
        list.push(3);
        list.push(4);

        assert_eq!(list.head.as_ref().unwrap().data, 4);

        let e = list.pop();
        assert_eq!(list.head.as_ref().unwrap().data, 3);
        assert_eq!(e, Some(4));
        list.push(5);
        list.push(6);
        let e = list.pop();
        assert_eq!(list.head.as_ref().unwrap().data, 5);
        assert_eq!(e, Some(6));
    }
}
}

src/unsafe_linked_list/mod.rs

#![allow(unused)]
fn main() {
use std::alloc::{Layout, alloc, dealloc, handle_alloc_error};
use std::ptr;

// ANCHOR: element
struct Element {
    data: i32,
    next: *mut Element,
}
// ANCHOR_END: element

impl Element {
    // ANCHOR: new
    fn new(data: i32, next: *mut Element) -> *mut Element {
        let layout = Layout::new::<Element>();
        let e = unsafe { alloc(layout) as *mut Element };
        if e.is_null() {
            handle_alloc_error(layout);
        }
        // On écrit dans la mémoire fraîchement allouée, encore non initialisée.
        // L'opérateur `=` tenterait normalement de `drop` l'ancienne valeur du champ :
        // c'est sans danger ici, `i32` et `*mut Element` n'ayant pas de destructeur.
        // Pour un champ avec destructeur, il faudrait passer par `ptr::write`.
        unsafe {
            (*e).data = data;
            (*e).next = next;
        }
        e
    }
    // ANCHOR_END: new
}

//ANCHOR: drop
impl Drop for Element {
    fn drop(&mut self) {
        let elem = self as *mut Element;
        if !elem.is_null() {
            let layout = Layout::new::<Element>();
            unsafe {
                dealloc(elem as *mut u8, layout);
            }
        }
    }
}
//ANCHOR_END: drop

// ANCHOR: linked_list
pub struct LinkedList {
    head: *mut Element,
}
// ANCHOR_END: linked_list

impl LinkedList {
    // ANCHOR: ll_new
    pub fn new() -> LinkedList {
        LinkedList {
            head: ptr::null_mut(),
        }
    }
    // ANCHOR_END: ll_new

    // ANCHOR: is_empty
    fn is_empty(&self) -> bool {
        self.head.is_null()
    }
    // ANCHOR_END: is_empty

    // ANCHOR: push
    pub fn push(&mut self, data: i32) {
        let new_head = Element::new(data, self.head);
        self.head = new_head;
    }
    // ANCHOR_END: push

    // ANCHOR: pop
    pub fn pop(&mut self) -> Option<i32> {
        if self.is_empty() {
            None
        } else {
            let old_head = self.head;
            unsafe {
                self.head = (*self.head).next;
            }
            let val = unsafe { (*old_head).data };
            unsafe {
                old_head.drop_in_place();
            }
            Some(val)
        }
    }
    // ANCHOR_END: pop

    // ANCHOR: print
    pub fn print(&self) {
        let mut current_head = self.head;
        while !current_head.is_null() {
            unsafe {
                print!("{} --> ", (*current_head).data);
                current_head = (*current_head).next;
            }
        }
        println!("∅");
    }
    // ANCHOR_END: print
}

// ANCHOR: ll_drop
impl Drop for LinkedList {
    fn drop(&mut self) {
        while !self.is_empty() {
            let _ = self.pop();
        }
    }
}
// ANCHOR_END: ll_drop

#[cfg(test)]
mod tests {
    use super::LinkedList;

    #[test]
    fn new() {
        assert!(LinkedList::new().is_empty());
    }

    #[test]
    fn push() {
        let mut list = LinkedList::new();
        list.push(1);
        assert_eq!(unsafe { (*list.head).data }, 1);
        list.push(2);
        assert_eq!(unsafe { (*list.head).data }, 2);
    }

    #[test]
    fn pop() {
        let mut list = LinkedList::new();
        let e = list.pop();
        assert_eq!(e, None);

        list.push(1);
        let e = list.pop();
        assert_eq!(e, Some(1));

        let e = list.pop();
        assert_eq!(e, None);

        list.push(2);
        list.push(3);
        list.push(4);

        assert_eq!(unsafe { (*list.head).data }, 4);

        let e = list.pop();
        assert_eq!(unsafe { (*list.head).data }, 3);
        assert_eq!(e, Some(4));
        list.push(5);
        list.push(6);
        let e = list.pop();
        assert_eq!(unsafe { (*list.head).data }, 5);
        assert_eq!(e, Some(6));
    }
}
}

min_list (C)

min_list.c

#include <errno.h>
#include <inttypes.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_INT 100

typedef enum _result { ok, err_invalid_size, err_is_null } result;

const char *usage_msg =
    "Error wrong number of arguments.\n"
    "Usage: ./min_list <num1> <num2> ...\n"
    "       where <num1>, <num2>, ... must be valid integers.\n";

// Copies the value of the smallest value in the tab array in the min variable.
// Returns the pointer to a newly allocated value of the minimum value of the
// array if everything went fine. Returns NULL otherwise
int *list_find_min(int32_t *tab, int size);

// Prints all the element in the tab array.
// Returns err_invalid_size if size <= 0
// Returns err_is_null if tab is NULL
// Returns ok if everything went fine
result list_print(int32_t *tab, int size);

// Exits if the error code shows invalidity
void error_handling(result error_code, int32_t **tab);

// Parses a string to an integer.
// Returns a pointer to newly allocated data.
// Returns NULL if conversion failed.
int *parse_int32(char *arg_to_transform);

// Reads the command line inputs and stores them
// in a newly allocated array.
// Returns the array with the parsed numbers or NULL if allocation failed or an
// invalid number was parsed.
int *read_input(int size, char *char_num[]) {
    int32_t *tab = malloc(size * sizeof(*tab));
    if (NULL == tab) {
        fprintf(stderr, "Memory allocation failed\n");
        return NULL;
    }
    for (int i = 0; i < size; ++i) {
        int *num = parse_int32(char_num[i]);
        if (NULL == num) {
            free(tab);
            fprintf(stderr, "Tried to parse %s which is not a valid integer.\n",
                    char_num[i]);
            return NULL;
        }
        tab[i] = *num;
        free(num);
    }
    return tab;
}

int main(int argc, char *argv[]) {
    if (argc == 1) {
        fprintf(stderr, "%s", usage_msg);
        return EXIT_FAILURE;
    }

    int size = argc - 1;
    int32_t *tab = read_input(size, &argv[1]);
    if (NULL == tab) {
        fprintf(stderr, "Failure during argument parsing.\n");
        return EXIT_FAILURE;
    }

    printf("Among the numbers in the list:\n");
    error_handling(list_print(tab, size), &tab);
    int *min = list_find_min(tab, size);
    if (NULL == min) {
        fprintf(stderr, "Could not find the minimum of the array.\n");
        free(tab);
        tab = NULL;
        return EXIT_FAILURE;
    }
    printf("The value of the minimum of the numbers is: %d\n", *min);

    free(min);
    free(tab);
    tab = NULL;

    return EXIT_SUCCESS;
}

int min_i32(int32_t lhs, int32_t rhs) {
    if (lhs < rhs) {
        return lhs;
    } else {
        return rhs;
    }
}

// Checks if size is valid and tab is not NULL
result list_is_valid(int32_t *tab, int size) {
    if (size <= 0) {
        return err_invalid_size;
    }
    if (NULL == tab) {
        return err_is_null;
    }
    return ok;
}

result list_print(int32_t *tab, int size) {
    result code = list_is_valid(tab, size);
    if (code != ok) {
        return code;
    }

    for (int i = 0; i < size; ++i) {
        printf("%d ", tab[i]);
    }
    printf("\n");
    return code;
}

int32_t *list_find_min(int32_t *tab, int size) {
    result code = list_is_valid(tab, size);
    if (code != ok) {
        return NULL;
    }

    int32_t *min = malloc(sizeof(*min));
    *min = tab[0];
    for (int i = 1; i < size; ++i) {
        *min = min_i32(*min, tab[i]);
    }
    return min;
}

void error_handling(result error_code, int32_t **tab) {
    switch (error_code) {
        case err_invalid_size:
            fprintf(stderr, "Return value, %d. Size is <= 0.\n", error_code);
            free(*tab);
            *tab = NULL;
            exit(EXIT_FAILURE);
            break;
        case err_is_null:
            fprintf(stderr, "Tab is NULL.\n");
            free(*tab);
            *tab = NULL;
            exit(EXIT_FAILURE);
            break;
        case ok:
            break;
    }
}

int32_t *parse_int32(char *arg_to_transform) {
    if (strlen(arg_to_transform) == 0) {
        return NULL;  // empty string to parse
    }
    char *remaining;
    errno = 0;  // errno == 0 (defined in errno.h) means everything went fine
    long arg = strtol(arg_to_transform, &remaining,
                      10);  // number is parsed in base 10
    if (*remaining != '\0' || errno != 0) {
        return NULL;  // Empty string parsed or an error occurred
    }

    if (arg < INT_MIN || arg > INT_MAX) {
        return NULL;  // Not within the limits of an int
    }
    int32_t *num = malloc(sizeof(*num));
    *num = (int32_t)arg;
    return num;
}