# utils-results
The easiest and most intuitive error handling solution.
[![Github Forks][github-forks]][github-url]
[![Github Stars][github-stars]][github-url]
[![Crates.io][crates-badge]][crates-url]
[![Licensed][license-badge]][license-url]
[![CI][ci-badge]][ci-url]
[![Twitter][twitter-badge]][twitter-url]
[github-forks]: https://img.shields.io/github/forks/just-do-halee/utils-results?style=flat&logo=starship&color=dec968&labelColor=383636
[github-stars]: https://img.shields.io/github/stars/just-do-halee/utils-results?style=flat&logo=starship&color=dec968&labelColor=383636
[crates-badge]: https://img.shields.io/crates/v/utils-results.svg?labelColor=383636
[ci-badge]: https://github.com/just-do-halee/utils-results/actions/workflows/ci.yml/badge.svg
[twitter-badge]: https://img.shields.io/twitter/follow/do_halee?style=flat&logo=twitter&color=4a4646&labelColor=333131&label=just-do-halee
[license-badge]: https://img.shields.io/crates/l/utils-results?labelColor=383636
[twitter-url]: https://twitter.com/do_halee
[github-url]: https://github.com/just-do-halee/utils-results
[crates-url]: https://crates.io/crates/utils-results
[ci-url]: https://github.com/just-do-halee/utils-results/actions
[license-url]: https://github.com/just-do-halee/utils-results
| [Docs](https://docs.rs/utils-results) | [Latest Note](https://github.com/just-do-halee/utils-results/blob/main/CHANGELOG.md) |
```toml
[dependencies]
utils_results = "5.3.0"
```
## No-std
Disable default feature(allocator is needed).
```toml
[dependencies]
utils_results = { version = "5.3.0", default-features = false }
```
## Overview
First, You should make your own an error set.
```rust
err! {
BrokenHeader => "broken header."
AnotherHeader => "not matched header."
FileNotFound => "file not found."
EmptyArgument => "empty argument."
UnexpectedEof => "unexpected eof."
OutOfBounds => "index out of bounds."
NotMatched => "btw not matched."
}
```
And just errbang!
```rust
errbang!(err::BrokenHeader)
```
# More Examples
```rust
fn foo() -> Result { // Our Master Result Type
let bar = 2;
match bar {
0 => Ok(true),
1 => Ok(false),
_ => errbang!(err::NotMatched, "{} is {}", "bar", bar),
}
}
fn main() -> Result<()> {
let _is_bar_zero = foo()?;
Ok(())
}
```
```rust
errbang!("error.");
errbang!(err::MyError1);
errbang!(err::MyError2, "cannot find.");
errbang!(err::MyError3, "{} is {}", "bar", 2);
```
| Result
```
[src/main.rs 40:1] unexpected eof. bar is 2
```
unwrapping error input data. also can easily compare them.
```rust
fn foo() -> Result<()> {
// example
return errbang!(err::Bar, "this is input.");
}
assert_eq!(
errunwrap!(foo(), err::Bar), "this is input."
);
```
# ***Important***
- 1. One result type(`anyhow`).
- 2. All casted errors have their own chaining error' information(all the previous errors).
if you follow below rules, you can easily debug all your projects.
### errbang -> errcast -> errcast -> ... -> errcast -> errextract
---
## * Quick Overview
```rust
use utils_results::*;
err! {
One => "this error is first one."
Two => "this error is second one."
Three => "this error is third one."
Well => "is this?"
}
fn aaa() -> Result {
return errbang!(err::One, "{}.error bang!", 1);
}
fn bbb() -> Result {
let n = errcast!(aaa(), err::Two, "{}.two <- one.", 2);
Ok(n)
}
fn ccc() -> Result {
Ok(errcast!(bbb(), err::Three, "{}.three <- two.", 3))
}
fn main() -> Result<()> {
let c = errextract!(ccc(), err::Well => 127);
eprintln!("1/{} is cosmological constant.", c);
Ok(())
}
```
| Result
```
Error:
[src/main.rs 11:12] this error is first one. 1.error bang! aaa()
⎺↴
[src/main.rs 14:13] this error is second one. 2.two <- one. bbb()
⎺↴
[src/main.rs 18:8] this error is third one. 3.three <- two.
```
If the matching error has changed,
```rust
// Well to Three
let c = errextract!(ccc(), err::Three => 127);
```
| Result
```
1/127 is cosmological constant.
```
---
# ***errcast***
Any type of error can be converted into our Master Error. **(non panic unwraping)**
##### \ = *errcast!* (\, \, \);
```rust
// example
let num_read = errcast!(file.read(&mut buf), err::ReadErr, "this is {} data.", "meta");
```
---
# Simply just do this!
```rust
let file = errcast!(File::open("test"), err::FileOpenError)
```
## or...
```rust
// Master `Result` can take any errors
let file = File::open("test")?;
// if cfg!(no_std),
let file = io_to_err!(File::open("test"))?;
```
But, *errcast* -> ***errextract*** combo is always good choice.
```rust
fn exe(path: &str) -> Result {
let file = errcast!(File::open("test"), err::FileOpenError);
// .....
// ...
Ok(num)
}
fn main() -> Result<()> {
/// non panic unwraping
/// and specific error can return
/// matching block
let num = errextract!(exe(path),
err::FileOpenError => 0);
/// other errors will go out -> Result
Ok(())
}
```
---
Well, we can also handle io::Error more idiomatic way. (feature = "std")
## ***Matching `io::Error`***
```rust
io_err! {
// io::ErrorKind => err::MyError
UnexpectedEof => err::MyError1
Interrupted => err::MyError2
NotFound => err::MyError3
// ...
}
```
Declare matching macro and just handle that.
```rust
io_to_err!(file.seek(SeekFrom::End(0)))?;
err_to_io!(my_seek(0))?;
```
---
# ***Master Result***
* Please use our Master ***Result***\
instead std::result::Result or io::Result etc..
* this is `anyhow` Result.
---
###### ***utils-results/lib.rs*** Definition
```rust
/// Master Result
pub type Result = anyhow::Result;
```
---
### just put this in your project.
```rust
pub use utils_results::*;
```
## You can also convert any type of `Result`
```rust
// to our Master Result
resultcast!(handle.join().unwrap())?;
```