How do I deal with multiple errors in function?

So I decided that I would like to write some code in Rust on my own. However I got stuck at simple deal with multiple errors. The program does compile. But how do I get the result from get(), parse() functions and return error message from the function in case if something fails?

struct Size
{
    width: u32,
    height: u32
}

fn get_size(args: &Vec<String>) -> Result<Size, &'static str>
{
    if args.len() > 1
    {
        let x = args.get(0).unwrap().parse().unwrap(); // May fail
        let y = args.get(1).unwrap().parse().unwrap(); // May fail
        Ok(Size{width: x, height: y})
    }
    else
    {
        Err("Invalid arguments")
    }
}

fn main()
{
    let args: Vec<String> = std::env::args().skip(1).collect();
    let size = match get_size(&args)
    {
        Ok(sz) => sz,
        Err(er) =>
        {
            writeln!(std::io::stderr(), "{}", er).unwrap();
            std::process::exit(1);
        }
    };

    let size = get_size(&args).unwrap();
    println!("{} : {}", size.width, size.height);
}

Here's one way to write it:

fn get_size(args: &Vec<String>) -> Result<Size, Box<std::error::Error>> {
    let mut iter = args.iter();
    match (iter.next(), iter.next()) {
        (Some(x), Some(y)) => Ok(Size {
            width: x
                .parse()
                .map_err(|e| format!("Failed to parse x due to {}: {}", e, x))?,
            height: y
                .parse()
                .map_err(|e| format!("Failed to parse y due to {}: {}", e, y))?,
        }),
        _ => Err("Invalid arguments".into()),
    }
}

The ? operator can be thought of as an early return from the function if the Result it's being applied to is an Err. Rust docs should have more info on it if you're curious.

The Err type is switched to Box<std::error::Error>, which is basically a type erased Error implementation. Since the caller doesn't care about the precise error type and since an allocation on the error path isn't important here, this is the most convenient/flexible return type there.

1 Like