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