one_err 0.0.4

OneErr to rule them all
Documentation
# one_err

OneErr to rule them all.

There are some great error helper crates out there.
My favorites are [thiserror](https://crates.io/crates/thiserror) and
[anyhow](https://crates.io/crates/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

```rust
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

```rust
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

```rust
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

```rust
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

```rust
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