Lab 4: Errors

The code we wrote live:

use std::fs::read_to_string;
use std::io;
use std::process::exit;
use std::num::ParseIntError;
use thiserror::Error;

#[derive(Debug, Error)]
pub enum MainError {
    #[error("an io error occured: {0}")]
    IoError(#[from] io::Error),
    #[error("an divide error occured: {0}")]
    DivideError(#[from] DivideError),
    #[error("couldn't parse int: {0}")]
    ParseIntError(#[from] ParseIntError),
    #[error("not enough parts on line")]
    NotEnoughParts
}

#[derive(Debug, Error)]
pub enum DivideError {
    #[error("divide 1 failed")]
    FirstFailed,
    #[error("divide 2 failed")]
    SecondFailed,
}

pub fn divide_three(a: u64, b: u64, c: u64) -> Result<u64, DivideError> {
    let r1 = divide(a, b).ok_or(DivideError::FirstFailed)?;
    let r2 = divide(r1, c).ok_or(DivideError::SecondFailed)?;

    Ok(r2)
}

pub fn divide(a: u64, b: u64) -> Option<u64> {
    if b == 0 {
        None
    } else {
        Some(a / b)
    }
}

fn process_integers(inputs: &[(u64, u64, u64)]) -> Result<Vec<u64>, DivideError> {
    let mut res = Vec::new();

    for &(a, b, c) in inputs {
        let answer = divide_three(a, b, c);
        match answer {
            Ok(i) => res.push(i),
            Err(e) => {
                return Err(e);
            }
        }
    }

    Ok(res)
}

fn read_and_process() -> Result<(), MainError> {
    // numbers.csv contains:
    // 20, 2, 3
    // 12, 0, 5
    // 58, 3, 0
    let contents = read_to_string("src/numbers.csv")?;
    let mut numbers = Vec::new();

    for i in contents.lines() {
        let mut splitter = i.split(',');

        let first = splitter.next().ok_or(MainError::NotEnoughParts)?;
        let second = splitter.next().ok_or(MainError::NotEnoughParts)?;
        let third = splitter.next().ok_or(MainError::NotEnoughParts)?;

        let first_int = first.trim().parse()?;
        let second_int = second.trim().parse()?;
        let third_int = third.trim().parse()?;

        numbers.push((first_int, second_int, third_int));
    }

    let res = process_integers(&numbers)?;
    println!("{res:?}");


    Ok(())
}

#[test]
fn test_right_error() {
    assert_eq!(Err(DivideError::FirstFailed), process_integers(&[(1, 0, 4)]))
}

fn main() {
    if let Err(e) = read_and_process() {
        eprintln!("{}", e);
        exit(1);
    }
}