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 */