top | item 28801611

(no title)

shaoner | 4 years ago

I faced the same kind of issue lately and thought that implementing a From trait for each type of error was kind of annoying.

Taking the article example, I ended up doing this:

    #[derive(Debug, Clone, Copy, Eq, PartialEq)]
    pub enum MyError {
        MyErr1,
        MyErr2,
        MyErr3,
    }

    fn read_number_from_file(filename: &str) -> Result<u64, MyError> {
        let mut file = File::open(filename).or(Err(MyError::MyErr1))?; // Error!

        let mut buffer = String::new();

        file.read_to_string(&mut buffer).or(Err(MyError::MyErr2))?; // Error

        let parsed: u64 = buffer.trim().parse().or(Err(MyError::MyErr3))?; // Error

        Ok(parsed)
    }

As I'm a beginner, I would love to hear some thoughts on this

discuss

order

sfvisser|4 years ago

Nothing wrong with that, although you could use ‘map_err’ instead of ‘or’ to preserve the original errors as well if you want to.

onei|4 years ago

I really like the thiserror crate for cutting down boilerplate and you can add annotations to automatically implement From. However, if you want to handle errors with more granularity, e.g. IO errors as noted elsewhere in the discussion, then you'll need to implement From yourself.

And as others noted, .map_err(...) is slightly better than .or(...) for wrapping errors.

loeg|4 years ago

The downside of this approach is that you have discarded the original error information. It’s also somewhat verbose at the error-handling site.

hota_mazi|4 years ago

The only downside of this approach is that you can't pass a dynamic string giving details on the error, but that's because Rust's enums are not powerful enough to express this (as opposed to Kotlin or Java).