Skip to content
Snippets Groups Projects
Select Git revision
  • 81f8a31173075792f47ce578d55a414ea44c71fd
  • main default protected
  • update_2024
  • fix_formatting
4 results

main.rs

Blame
  • Forked from orestis.malaspin / rust-101
    Source project has a limited visibility.
    main.rs 3.37 KiB
    /* ANCHOR: all */
    
    /*!
    Part04 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 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 is 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 */