one_err

Crates.ioone_err
lib.rsone_err
version0.0.8
sourcesrc
created_at2021-09-07 22:33:14.96692
updated_at2022-12-13 17:12:47.578735
descriptionOneErr to rule them all
homepage
repositoryhttps://github.com/neonphog/one_err
max_upload_size
id448261
size89,116
David Braden (neonphog)

documentation

https://docs.rs/one_err

README

one_err

OneErr to rule them all.

There are some great error helper crates out there. My favorites are thiserror and anyhow.

But sometimes you just need something different. The thiserror crate can over time lead to giant trees of nested error enums, while anyhow is difficult to match on.

Sometimes you need to interoperate with std::io::Error, but that type is awkward to construct, not Clone, and cannot be serialized.

OneErr is a newtype over std::io::Error, but makes it clonable, serializable, and hopefully more ergonomic.

std::io::ErrorKind Matching

use one_err::*;

for res in [
    Ok("not-error"),
    Err(OneErr::from(std::io::ErrorKind::InvalidInput)),
    Err(OneErr::from(std::io::ErrorKind::ConnectionRefused)),
] {
    match res.map_err(|e| e.kind()) {
        Ok(ok) => assert_eq!("not-error", ok),
        Err(std::io::ErrorKind::InvalidInput) => (),
        Err(std::io::ErrorKind::ConnectionRefused) => (),
        oth => panic!("unexpected: {:?}", oth),
    }
}

ErrNo Matching

use one_err::*;

for res in [
    Ok("not-error"),
    Err(OneErr::from(ErrNo::NoData)),
    Err(OneErr::from(ErrNo::Proto)),
] {
    match res.map_err(|e| e.errno()) {
        Ok(ok) => assert_eq!("not-error", ok),
        Err(ErrNo::NoData) => (),
        Err(ErrNo::Proto) => (),
        oth => panic!("unexpected: {:?}", oth),
    }
}

Custom Matching

use one_err::*;

const ERR_FOO: &str = "FOO";
const ERR_BAR: &str = "BAR";

for res in [
    Ok("not-error"),
    Err(OneErr::with_message(ERR_FOO, "foo test")),
    Err(OneErr::with_message(ERR_BAR, "bar test")),
] {
    match res.as_ref().map_err(|e| (e.str_kind(), e)) {
        Ok(ok) => assert_eq!("not-error", *ok),
        Err((ERR_FOO, e)) => assert_eq!("foo test", e.get_message().unwrap()),
        Err((ERR_BAR, e)) => assert_eq!("bar test", e.get_message().unwrap()),
        oth => panic!("unexpected: {:?}", oth),
    }
}

std::io Interoperability

use one_err::*;
use std::io::Read;

const CUSTOM_ERR: &str = "CustomError";

/// My custom Read that always errors.
pub struct ErrReader;

impl Read for ErrReader {
    fn read(&mut self, _buf: &mut [u8]) -> std::io::Result<usize> {
        Err(OneErr::new(CUSTOM_ERR).into())
    }
}

assert_eq!(
    r#"{"error":"CustomError"}"#,
    &ErrReader.read(&mut []).unwrap_err().to_string(),
);

Serialization and Parsing

use one_err::*;

const CUSTOM_ERR: &str = "CustomError";

let err = OneErr::new(CUSTOM_ERR);
let enc = err.to_string();

assert_eq!(
    r#"{"error":"CustomError"}"#,
    &enc,
);

let dec: OneErr = enc.parse().unwrap();
assert_eq!(err, dec);

License: Apache-2.0

Commit count: 21

cargo fmt