mirror of
https://github.com/haraldh/chainerror.git
synced 2025-01-31 00:56:41 +01:00
rename cherr()
to context()
This commit is contained in:
parent
2af5fb7ad6
commit
ed710fada3
|
@ -23,7 +23,5 @@ is-it-maintained-issue-resolution = { repository = "haraldh/chainerror" }
|
||||||
is-it-maintained-open-issues = { repository = "haraldh/chainerror" }
|
is-it-maintained-open-issues = { repository = "haraldh/chainerror" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = [ "location", "debug-cause" ]
|
default = []
|
||||||
location = []
|
|
||||||
display-cause = []
|
display-cause = []
|
||||||
debug-cause = []
|
|
||||||
|
|
23
README.md
23
README.md
|
@ -22,18 +22,9 @@ Debug information is worth it!
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
`default = [ "location", "debug-cause" ]`
|
|
||||||
|
|
||||||
`location`
|
|
||||||
: store the error location
|
|
||||||
|
|
||||||
`display-cause`
|
`display-cause`
|
||||||
: turn on printing a backtrace of the errors in `Display`
|
: turn on printing a backtrace of the errors in `Display`
|
||||||
|
|
||||||
`debug-cause`
|
|
||||||
: print a backtrace of the errors in `Debug`
|
|
||||||
|
|
||||||
|
|
||||||
## Tutorial
|
## Tutorial
|
||||||
|
|
||||||
Read the [Tutorial](https://haraldh.github.io/chainerror/tutorial1.html)
|
Read the [Tutorial](https://haraldh.github.io/chainerror/tutorial1.html)
|
||||||
|
@ -101,12 +92,12 @@ fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
|
|
||||||
fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
|
fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
let filename = "foo.txt";
|
let filename = "foo.txt";
|
||||||
do_some_io().cherr(format!("Error reading '{}'", filename))?;
|
do_some_io().context(format!("Error reading '{}'", filename))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
|
fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
func2().cherr("func1 error")?;
|
func2().context("func1 error")?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,14 +130,14 @@ fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
|
|
||||||
fn func3() -> Result<(), Box<dyn Error + Send + Sync>> {
|
fn func3() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
let filename = "foo.txt";
|
let filename = "foo.txt";
|
||||||
do_some_io().cherr(format!("Error reading '{}'", filename))?;
|
do_some_io().context(format!("Error reading '{}'", filename))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
derive_str_cherr!(Func2Error);
|
derive_str_context!(Func2Error);
|
||||||
|
|
||||||
fn func2() -> ChainResult<(), Func2Error> {
|
fn func2() -> ChainResult<(), Func2Error> {
|
||||||
func3().cherr(Func2Error("func2 error: calling func3".into()))?;
|
func3().context(Func2Error("func2 error: calling func3".into()))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,9 +162,9 @@ impl ::std::fmt::Debug for Func1Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn func1() -> ChainResult<(), Func1Error> {
|
fn func1() -> ChainResult<(), Func1Error> {
|
||||||
func2().cherr(Func1Error::Func2)?;
|
func2().context(Func1Error::Func2)?;
|
||||||
let filename = String::from("bar.txt");
|
let filename = String::from("bar.txt");
|
||||||
do_some_io().cherr(Func1Error::IO(filename))?;
|
do_some_io().context(Func1Error::IO(filename))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ this only
|
||||||
prints out the last `Error`.
|
prints out the last `Error`.
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
Error: StringError("func1 error")
|
Error: "func1 error"
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
The next chapters of this tutorial show how `chainerror` adds more information
|
The next chapters of this tutorial show how `chainerror` adds more information
|
||||||
|
|
|
@ -5,8 +5,8 @@ To cope with different kind of errors, we introduce the kind of an error `Func1E
|
||||||
Because we derive `Debug` and implement `Display` our `Func1ErrorKind` enum, this enum can be used as
|
Because we derive `Debug` and implement `Display` our `Func1ErrorKind` enum, this enum can be used as
|
||||||
a `std::error::Error`.
|
a `std::error::Error`.
|
||||||
|
|
||||||
Not using `String` errors anymore, the `cherr!()` macro seen in the beginning of
|
Not using `String` errors anymore, the `context()` function seen in the beginning of
|
||||||
the tutorial has to be used again.
|
the tutorial can be used again.
|
||||||
|
|
||||||
Only returning `Func1ErrorKind` in `func1()` now let us get rid of `Result<(), Box<Error + Send + Sync>>` and we can
|
Only returning `Func1ErrorKind` in `func1()` now let us get rid of `Result<(), Box<Error + Send + Sync>>` and we can
|
||||||
use `ChainResult<(), Func1ErrorKind>`.
|
use `ChainResult<(), Func1ErrorKind>`.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# Simple Chained String Errors
|
# Simple Chained String Errors
|
||||||
|
|
||||||
With relatively small changes and the help of the `cherr!` macro of the `chainerror` crate
|
With relatively small changes and the help of the `context()` method of the `chainerror` crate
|
||||||
the `String` errors are now chained together.
|
the `&str` errors are now chained together.
|
||||||
|
|
||||||
Press the play button in the upper right corner and see the nice debug output.
|
Press the play button in the upper right corner and see the nice debug output.
|
||||||
|
|
||||||
|
@ -19,14 +19,13 @@ Press the play button in the upper right corner and see the nice debug output.
|
||||||
{{#include ../examples/tutorial2.rs:13:15}}
|
{{#include ../examples/tutorial2.rs:13:15}}
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
The macro `cherr!(olderror, newerror)` stores `olderror` as the source/cause of `newerror`
|
The function `context(newerror)` stores `olderror` as the source/cause of `newerror`
|
||||||
along with the filename (`file!()`) and line number (`line!()`)
|
along with the `Location` of the `context()` call and returns `Err(newerror)`.
|
||||||
and returns `newerror`.
|
|
||||||
|
|
||||||
`Err()?` then returns the inner error applying `.into()`, so that we
|
`?` then returns the inner error applying `.into()`, so that we
|
||||||
again have a `Err(Box<Error + Send + Sync>)` as a result.
|
again have a `Err(Box<Error + Send + Sync>)` as a result.
|
||||||
|
|
||||||
The `Debug` implementation of `ChainError<T>` (which is returned by `cherr!()`)
|
The `Debug` implementation of `ChainError<T>` (which is returned by `context()`)
|
||||||
prints the `Debug` of `T` prefixed with the stored filename and line number.
|
prints the `Debug` of `T` prefixed with the stored filename and line number.
|
||||||
|
|
||||||
`ChainError<T>` in our case is `ChainError<String>`.
|
`ChainError<T>` in our case is `ChainError<&str>`.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Mapping Errors
|
# Mapping Errors
|
||||||
|
|
||||||
Now let's get more rust idiomatic by using `.map_err()`.
|
Now let's get more rust idiomatic by using `.context()` directly on the previous `Result`.
|
||||||
|
|
||||||
~~~rust
|
~~~rust
|
||||||
{{#include ../examples/tutorial3.rs}}
|
{{#include ../examples/tutorial3.rs}}
|
||||||
|
|
|
@ -1,12 +1,7 @@
|
||||||
# Saving coding chars
|
# More information
|
||||||
|
|
||||||
Because decorating an error with more information should not
|
To give more context to the error, you want to use `format!`
|
||||||
let you jump through hoops, `chainerror` has a quick macro for that.
|
to extend the information in the context string.
|
||||||
|
|
||||||
`mstrerror!()` fits right into `.map_err()` letting you quickly add
|
|
||||||
more debug strings.
|
|
||||||
|
|
||||||
`mstrerror!()` even understands `format!()` syntax like `println!()`.
|
|
||||||
|
|
||||||
~~~rust
|
~~~rust
|
||||||
{{#include ../examples/tutorial4.rs}}
|
{{#include ../examples/tutorial4.rs}}
|
||||||
|
|
|
@ -4,8 +4,8 @@ To distinguish the errors occuring in various places, we can define named string
|
||||||
"new type" pattern.
|
"new type" pattern.
|
||||||
|
|
||||||
~~~rust,ignore
|
~~~rust,ignore
|
||||||
derive_str_cherr!(Func2Error);
|
derive_str_context!(Func2Error);
|
||||||
derive_str_cherr!(Func1Error);
|
derive_str_context!(Func1Error);
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
Instead of `ChainError<String>` we now have `struct Func1Error(String)` and `ChainError<Func1Error>`.
|
Instead of `ChainError<String>` we now have `struct Func1Error(String)` and `ChainError<Func1Error>`.
|
||||||
|
|
|
@ -11,14 +11,14 @@ fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
|
|
||||||
fn func3() -> Result<(), Box<dyn Error + Send + Sync>> {
|
fn func3() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
let filename = "foo.txt";
|
let filename = "foo.txt";
|
||||||
do_some_io().cherr(format!("Error reading '{}'", filename))?;
|
do_some_io().context(format!("Error reading '{}'", filename))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
derive_str_cherr!(Func2Error);
|
derive_str_context!(Func2Error);
|
||||||
|
|
||||||
fn func2() -> ChainResult<(), Func2Error> {
|
fn func2() -> ChainResult<(), Func2Error> {
|
||||||
func3().cherr(Func2Error(format!("func2 error: calling func3")))?;
|
func3().context(Func2Error(format!("func2 error: calling func3")))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,9 +43,9 @@ impl ::std::fmt::Debug for Func1Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn func1() -> ChainResult<(), Func1Error> {
|
fn func1() -> ChainResult<(), Func1Error> {
|
||||||
func2().cherr(Func1Error::Func2)?;
|
func2().context(Func1Error::Func2)?;
|
||||||
let filename = String::from("bar.txt");
|
let filename = String::from("bar.txt");
|
||||||
do_some_io().cherr(Func1Error::IO(filename))?;
|
do_some_io().context(Func1Error::IO(filename))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,11 +8,11 @@ fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
derive_str_cherr!(Func2Error);
|
derive_str_context!(Func2Error);
|
||||||
|
|
||||||
fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
|
fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
let filename = "foo.txt";
|
let filename = "foo.txt";
|
||||||
do_some_io().cherr(Func2Error(format!("Error reading '{}'", filename)))?;
|
do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,9 +33,9 @@ impl ::std::fmt::Display for Func1ErrorKind {
|
||||||
impl ::std::error::Error for Func1ErrorKind {}
|
impl ::std::error::Error for Func1ErrorKind {}
|
||||||
|
|
||||||
fn func1() -> ChainResult<(), Func1ErrorKind> {
|
fn func1() -> ChainResult<(), Func1ErrorKind> {
|
||||||
func2().cherr(Func1ErrorKind::Func2)?;
|
func2().context(Func1ErrorKind::Func2)?;
|
||||||
let filename = String::from("bar.txt");
|
let filename = String::from("bar.txt");
|
||||||
do_some_io().cherr(Func1ErrorKind::IO(filename))?;
|
do_some_io().context(Func1ErrorKind::IO(filename))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,6 +53,8 @@ fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
eprintln!("\nDebug Error:\n{:?}", e);
|
eprintln!("\nDebug Error:\n{:?}", e);
|
||||||
|
|
||||||
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,11 +8,11 @@ fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
derive_str_cherr!(Func2Error);
|
derive_str_context!(Func2Error);
|
||||||
|
|
||||||
fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
|
fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
let filename = "foo.txt";
|
let filename = "foo.txt";
|
||||||
do_some_io().cherr(Func2Error(format!("Error reading '{}'", filename)))?;
|
do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,9 +39,9 @@ impl ::std::fmt::Debug for Func1ErrorKind {
|
||||||
impl ::std::error::Error for Func1ErrorKind {}
|
impl ::std::error::Error for Func1ErrorKind {}
|
||||||
|
|
||||||
fn func1() -> ChainResult<(), Func1ErrorKind> {
|
fn func1() -> ChainResult<(), Func1ErrorKind> {
|
||||||
func2().cherr(Func1ErrorKind::Func2)?;
|
func2().context(Func1ErrorKind::Func2)?;
|
||||||
let filename = String::from("bar.txt");
|
let filename = String::from("bar.txt");
|
||||||
do_some_io().cherr(Func1ErrorKind::IO(filename))?;
|
do_some_io().context(Func1ErrorKind::IO(filename))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +59,8 @@ fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
eprintln!("\nDebug Error:\n{:?}", e);
|
eprintln!("\nDebug Error:\n{:?}", e);
|
||||||
|
|
||||||
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,11 +8,11 @@ fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
derive_str_cherr!(Func2Error);
|
derive_str_context!(Func2Error);
|
||||||
|
|
||||||
fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
|
fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
let filename = "foo.txt";
|
let filename = "foo.txt";
|
||||||
do_some_io().cherr(Func2Error(format!("Error reading '{}'", filename)))?;
|
do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,9 +39,9 @@ impl ::std::fmt::Debug for Func1ErrorKind {
|
||||||
impl ::std::error::Error for Func1ErrorKind {}
|
impl ::std::error::Error for Func1ErrorKind {}
|
||||||
|
|
||||||
fn func1() -> ChainResult<(), Func1ErrorKind> {
|
fn func1() -> ChainResult<(), Func1ErrorKind> {
|
||||||
func2().cherr(Func1ErrorKind::Func2)?;
|
func2().context(Func1ErrorKind::Func2)?;
|
||||||
let filename = String::from("bar.txt");
|
let filename = String::from("bar.txt");
|
||||||
do_some_io().cherr(Func1ErrorKind::IO(filename))?;
|
do_some_io().context(Func1ErrorKind::IO(filename))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,6 +70,8 @@ fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
eprintln!("\nDebug Error:\n{:?}", e);
|
eprintln!("\nDebug Error:\n{:?}", e);
|
||||||
|
|
||||||
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,11 +7,11 @@ pub mod mycrate {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
derive_str_cherr!(Func2Error);
|
derive_str_context!(Func2Error);
|
||||||
|
|
||||||
fn func2() -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
fn func2() -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
let filename = "foo.txt";
|
let filename = "foo.txt";
|
||||||
do_some_io().cherr(Func2Error(format!("Error reading '{}'", filename)))?;
|
do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,9 +35,9 @@ pub mod mycrate {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn func1() -> Result<()> {
|
pub fn func1() -> Result<()> {
|
||||||
func2().cherr(ErrorKind::Func2)?;
|
func2().context(ErrorKind::Func2)?;
|
||||||
let filename = String::from("bar.txt");
|
let filename = String::from("bar.txt");
|
||||||
do_some_io().cherr(ErrorKind::IO(filename))?;
|
do_some_io().context(ErrorKind::IO(filename))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,6 +72,8 @@ fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
eprintln!("\nDebug Error:\n{:?}", e);
|
eprintln!("\nDebug Error:\n{:?}", e);
|
||||||
|
|
||||||
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ pub mod mycrate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! mcherr {
|
macro_rules! mcontext {
|
||||||
( $k:expr ) => {{
|
( $k:expr ) => {{
|
||||||
|e| {
|
|e| {
|
||||||
Error(
|
Error(
|
||||||
|
@ -92,7 +92,7 @@ pub mod mycrate {
|
||||||
|
|
||||||
pub fn func2() -> std::result::Result<(), Error> {
|
pub fn func2() -> std::result::Result<(), Error> {
|
||||||
let filename = "foo.txt";
|
let filename = "foo.txt";
|
||||||
do_some_io().map_err(mcherr!(ErrorKind::IO(format!(
|
do_some_io().map_err(mcontext!(ErrorKind::IO(format!(
|
||||||
"Error reading '{}'",
|
"Error reading '{}'",
|
||||||
filename
|
filename
|
||||||
))))?;
|
))))?;
|
||||||
|
@ -115,7 +115,7 @@ pub mod mycrate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! mcherr {
|
macro_rules! mcontext {
|
||||||
( $k:expr ) => {{
|
( $k:expr ) => {{
|
||||||
|e| {
|
|e| {
|
||||||
Error(
|
Error(
|
||||||
|
@ -175,9 +175,9 @@ pub mod mycrate {
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
|
|
||||||
pub fn func1() -> Result<()> {
|
pub fn func1() -> Result<()> {
|
||||||
func2().map_err(mcherr!(ErrorKind::Func2))?;
|
func2().map_err(mcontext!(ErrorKind::Func2))?;
|
||||||
let filename = String::from("bar.txt");
|
let filename = String::from("bar.txt");
|
||||||
do_some_io().map_err(mcherr!(ErrorKind::IO(filename)))?;
|
do_some_io().map_err(mcontext!(ErrorKind::IO(filename)))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -212,6 +212,8 @@ fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
eprintln!("\nDebug Error:\n{:?}", e);
|
eprintln!("\nDebug Error:\n{:?}", e);
|
||||||
|
|
||||||
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,11 +8,11 @@ pub mod mycrate {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
derive_str_cherr!(Func2Error);
|
derive_str_context!(Func2Error);
|
||||||
|
|
||||||
fn func2() -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
fn func2() -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
let filename = "foo.txt";
|
let filename = "foo.txt";
|
||||||
do_some_io(filename).cherr(Func2Error(format!("Error reading '{}'", filename)))?;
|
do_some_io(filename).context(Func2Error(format!("Error reading '{}'", filename)))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,15 +85,15 @@ pub mod mycrate {
|
||||||
|
|
||||||
let filename = "bar.txt";
|
let filename = "bar.txt";
|
||||||
|
|
||||||
do_some_io(filename).map_cherr(|e| ErrorKind::from_io_error(&e, filename.into()))?;
|
do_some_io(filename).map_context(|e| ErrorKind::from_io_error(&e, filename.into()))?;
|
||||||
do_some_io(filename).map_cherr(|_| ErrorKind::IO(filename.into()))?;
|
do_some_io(filename).map_context(|_| ErrorKind::IO(filename.into()))?;
|
||||||
do_some_io(filename).map_cherr(|e| ErrorKind::from(e))?;
|
do_some_io(filename).map_context(|e| ErrorKind::from(e))?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn super_func1() -> Result<()> {
|
pub fn super_func1() -> Result<()> {
|
||||||
func1().map_cherr(|e| ErrorKind::from(e))?;
|
func1().map_context(|e| ErrorKind::from(e))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,6 +130,8 @@ fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
eprintln!("\nDebug Error:\n{:?}", e);
|
eprintln!("\nDebug Error:\n{:?}", e);
|
||||||
|
|
||||||
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,14 +11,14 @@ fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
|
|
||||||
fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
|
fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
if let Err(e) = do_some_io() {
|
if let Err(e) = do_some_io() {
|
||||||
Err(e).cherr("func2 error")?;
|
Err(e).context("func2 error")?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
|
fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
if let Err(e) = func2() {
|
if let Err(e) = func2() {
|
||||||
Err(e).cherr("func1 error")?;
|
Err(e).context("func1 error")?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,18 +10,19 @@ fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
|
fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
do_some_io().cherr("func2 error")?;
|
do_some_io().context("func2 error")?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
|
fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
func2().cherr("func1 error")?;
|
func2().context("func1 error")?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
if let Err(e) = func1() {
|
if let Err(e) = func1() {
|
||||||
eprintln!("{:?}", e);
|
eprintln!("{:?}", e);
|
||||||
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,18 +10,19 @@ fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
|
|
||||||
fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
|
fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
let filename = "foo.txt";
|
let filename = "foo.txt";
|
||||||
do_some_io().cherr(format!("Error reading '{}'", filename))?;
|
do_some_io().context(format!("Error reading '{}'", filename))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
|
fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
func2().cherr("func1 error")?;
|
func2().context("func1 error")?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
if let Err(e) = func1() {
|
if let Err(e) = func1() {
|
||||||
eprintln!("{:?}", e);
|
eprintln!("{:?}", e);
|
||||||
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
|
|
||||||
fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
|
fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
let filename = "foo.txt";
|
let filename = "foo.txt";
|
||||||
do_some_io().cherr(format!("Error reading '{}'", filename))?;
|
do_some_io().context(format!("Error reading '{}'", filename))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
if let Err(e) = func2() {
|
if let Err(e) = func2() {
|
||||||
if let Some(s) = e.source() {
|
if let Some(s) = e.source() {
|
||||||
eprintln!("func2 failed because of '{}'", s);
|
eprintln!("func2 failed because of '{}'", s);
|
||||||
Err(e).cherr("func1 error")?;
|
Err(e).context("func1 error")?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -27,6 +27,7 @@ fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
if let Err(e) = func1() {
|
if let Err(e) = func1() {
|
||||||
eprintln!("{}", e);
|
eprintln!("{}", e);
|
||||||
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,12 +10,12 @@ fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
|
|
||||||
fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
|
fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
let filename = "foo.txt";
|
let filename = "foo.txt";
|
||||||
do_some_io().cherr(format!("Error reading '{}'", filename))?;
|
do_some_io().context(format!("Error reading '{}'", filename))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
|
fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
func2().cherr("func1 error")?;
|
func2().context("func1 error")?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@ fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
}
|
}
|
||||||
s = c;
|
s = c;
|
||||||
}
|
}
|
||||||
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,12 +10,12 @@ fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
|
|
||||||
fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
|
fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
let filename = "foo.txt";
|
let filename = "foo.txt";
|
||||||
do_some_io().cherr(format!("Error reading '{}'", filename))?;
|
do_some_io().context(format!("Error reading '{}'", filename))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
|
fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
func2().cherr(format!("func1 error"))?;
|
func2().context(format!("func1 error"))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
eprintln!("The root cause was: std::io::Error: {:#?}", ioerror);
|
eprintln!("The root cause was: std::io::Error: {:#?}", ioerror);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,18 +8,18 @@ fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
derive_str_cherr!(Func2Error);
|
derive_str_context!(Func2Error);
|
||||||
|
|
||||||
fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
|
fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
let filename = "foo.txt";
|
let filename = "foo.txt";
|
||||||
do_some_io().cherr(Func2Error(format!("Error reading '{}'", filename)))?;
|
do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
derive_str_cherr!(Func1Error);
|
derive_str_context!(Func1Error);
|
||||||
|
|
||||||
fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
|
fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
func2().cherr(Func1Error(format!("func1 error")))?;
|
func2().context(Func1Error(format!("func1 error")))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
eprintln!("Debug Func2Error:\n{:?}", f2err);
|
eprintln!("Debug Func2Error:\n{:?}", f2err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,21 +8,21 @@ fn do_some_io() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
derive_str_cherr!(Func2Error);
|
derive_str_context!(Func2Error);
|
||||||
|
|
||||||
fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
|
fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
let filename = "foo.txt";
|
let filename = "foo.txt";
|
||||||
do_some_io().cherr(Func2Error(format!("Error reading '{}'", filename)))?;
|
do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
derive_str_cherr!(Func1ErrorFunc2);
|
derive_str_context!(Func1ErrorFunc2);
|
||||||
derive_str_cherr!(Func1ErrorIO);
|
derive_str_context!(Func1ErrorIO);
|
||||||
|
|
||||||
fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
|
fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
func2().cherr(Func1ErrorFunc2(format!("func1 error calling func2")))?;
|
func2().context(Func1ErrorFunc2(format!("func1 error calling func2")))?;
|
||||||
let filename = "bar.txt";
|
let filename = "bar.txt";
|
||||||
do_some_io().cherr(Func1ErrorIO(format!("Error reading '{}'", filename)))?;
|
do_some_io().context(Func1ErrorIO(format!("Error reading '{}'", filename)))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@ fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
if let Some(s) = e.downcast_chain_ref::<Func1ErrorFunc2>() {
|
if let Some(s) = e.downcast_chain_ref::<Func1ErrorFunc2>() {
|
||||||
eprintln!("Func1ErrorFunc2:\n{:?}", s);
|
eprintln!("Func1ErrorFunc2:\n{:?}", s);
|
||||||
}
|
}
|
||||||
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
110
src/lib.rs
110
src/lib.rs
|
@ -12,18 +12,9 @@
|
||||||
//!
|
//!
|
||||||
//! ## Features
|
//! ## Features
|
||||||
//!
|
//!
|
||||||
//! `default = [ "location", "debug-cause" ]`
|
|
||||||
//!
|
|
||||||
//! `location`
|
|
||||||
//! : store the error location
|
|
||||||
//!
|
|
||||||
//! `display-cause`
|
//! `display-cause`
|
||||||
//! : turn on printing a backtrace of the errors in `Display`
|
//! : turn on printing a backtrace of the errors in `Display`
|
||||||
//!
|
//!
|
||||||
//! `debug-cause`
|
|
||||||
//! : print a backtrace of the errors in `Debug`
|
|
||||||
//!
|
|
||||||
//!
|
|
||||||
//! # Tutorial
|
//! # Tutorial
|
||||||
//!
|
//!
|
||||||
//! Read the [Tutorial](https://haraldh.github.io/chainerror/tutorial1.html)
|
//! Read the [Tutorial](https://haraldh.github.io/chainerror/tutorial1.html)
|
||||||
|
@ -91,17 +82,16 @@
|
||||||
//!
|
//!
|
||||||
//! fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
|
//! fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
//! let filename = "foo.txt";
|
//! let filename = "foo.txt";
|
||||||
//! do_some_io().cherr(format!("Error reading '{}'", filename))?;
|
//! do_some_io().context(format!("Error reading '{}'", filename))?;
|
||||||
//! Ok(())
|
//! Ok(())
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
|
//! fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
//! func2().cherr("func1 error")?;
|
//! func2().context("func1 error")?;
|
||||||
//! Ok(())
|
//! Ok(())
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! if let Err(e) = func1() {
|
//! if let Err(e) = func1() {
|
||||||
//! # #[cfg(feature = "debug-cause")]
|
|
||||||
//! #[cfg(not(windows))]
|
//! #[cfg(not(windows))]
|
||||||
//! assert_eq!(
|
//! assert_eq!(
|
||||||
//! format!("\n{:?}\n", e),
|
//! format!("\n{:?}\n", e),
|
||||||
|
@ -133,14 +123,14 @@
|
||||||
//!
|
//!
|
||||||
//! fn func3() -> Result<(), Box<dyn Error + Send + Sync>> {
|
//! fn func3() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
//! let filename = "foo.txt";
|
//! let filename = "foo.txt";
|
||||||
//! do_some_io().cherr(format!("Error reading '{}'", filename))?;
|
//! do_some_io().context(format!("Error reading '{}'", filename))?;
|
||||||
//! Ok(())
|
//! Ok(())
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! derive_str_cherr!(Func2Error);
|
//! derive_str_context!(Func2Error);
|
||||||
//!
|
//!
|
||||||
//! fn func2() -> ChainResult<(), Func2Error> {
|
//! fn func2() -> ChainResult<(), Func2Error> {
|
||||||
//! func3().cherr(Func2Error("func2 error: calling func3".into()))?;
|
//! func3().context(Func2Error("func2 error: calling func3".into()))?;
|
||||||
//! Ok(())
|
//! Ok(())
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
|
@ -165,9 +155,9 @@
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! fn func1() -> ChainResult<(), Func1Error> {
|
//! fn func1() -> ChainResult<(), Func1Error> {
|
||||||
//! func2().cherr(Func1Error::Func2)?;
|
//! func2().context(Func1Error::Func2)?;
|
||||||
//! let filename = String::from("bar.txt");
|
//! let filename = String::from("bar.txt");
|
||||||
//! do_some_io().cherr(Func1Error::IO(filename))?;
|
//! do_some_io().context(Func1Error::IO(filename))?;
|
||||||
//! Ok(())
|
//! Ok(())
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
|
@ -196,7 +186,6 @@
|
||||||
//! eprintln!("\nThe root cause was: std::io::Error: {:#?}", io_error);
|
//! eprintln!("\nThe root cause was: std::io::Error: {:#?}", io_error);
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! # #[cfg(feature = "no-debug-cause")]
|
|
||||||
//! #[cfg(not(windows))]
|
//! #[cfg(not(windows))]
|
||||||
//! assert_eq!(
|
//! assert_eq!(
|
||||||
//! format!("\n{:?}\n", e),
|
//! format!("\n{:?}\n", e),
|
||||||
|
@ -229,15 +218,15 @@ pub mod prelude {
|
||||||
//! convenience prelude
|
//! convenience prelude
|
||||||
pub mod v1 {
|
pub mod v1 {
|
||||||
//! convenience prelude
|
//! convenience prelude
|
||||||
pub use crate::ChainErrorDown as _;
|
pub use super::super::ChainErrorDown as _;
|
||||||
pub use crate::ResultTrait as _;
|
pub use super::super::ResultTrait as _;
|
||||||
pub use crate::{derive_err_kind, derive_str_cherr, ChainError, ChainResult};
|
pub use super::super::{ChainError, ChainResult};
|
||||||
|
pub use crate::{derive_err_kind, derive_str_context};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// chains an inner error kind `T` with a causing error
|
/// chains an inner error kind `T` with a causing error
|
||||||
pub struct ChainError<T> {
|
pub struct ChainError<T> {
|
||||||
#[cfg(feature = "location")]
|
|
||||||
occurrence: Option<String>,
|
occurrence: Option<String>,
|
||||||
kind: T,
|
kind: T,
|
||||||
error_cause: Option<Box<dyn Error + 'static + Send + Sync>>,
|
error_cause: Option<Box<dyn Error + 'static + Send + Sync>>,
|
||||||
|
@ -247,8 +236,7 @@ pub struct ChainError<T> {
|
||||||
pub type ChainResult<O, E> = std::result::Result<O, ChainError<E>>;
|
pub type ChainResult<O, E> = std::result::Result<O, ChainError<E>>;
|
||||||
|
|
||||||
impl<T: 'static + Display + Debug> ChainError<T> {
|
impl<T: 'static + Display + Debug> ChainError<T> {
|
||||||
#[cfg(feature = "location")]
|
/// Use the `context()` or `map_context()` Result methods instead of calling this directly
|
||||||
/// Use the `cherr()` or `map_cherr()` Result methods instead of calling this directly
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
kind: T,
|
kind: T,
|
||||||
|
@ -262,17 +250,6 @@ impl<T: 'static + Display + Debug> ChainError<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "location"))]
|
|
||||||
/// Use the `cherr()` or `map_cherr()` Result methods instead of calling this directly
|
|
||||||
#[inline]
|
|
||||||
pub fn new(
|
|
||||||
kind: T,
|
|
||||||
error_cause: Option<Box<dyn Error + 'static + Send + Sync>>,
|
|
||||||
_occurrence: Option<String>,
|
|
||||||
) -> Self {
|
|
||||||
Self { kind, error_cause }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// return the root cause of the error chain, if any exists
|
/// return the root cause of the error chain, if any exists
|
||||||
pub fn root_cause(&self) -> Option<&(dyn Error + 'static)> {
|
pub fn root_cause(&self) -> Option<&(dyn Error + 'static)> {
|
||||||
self.iter().last()
|
self.iter().last()
|
||||||
|
@ -292,18 +269,18 @@ impl<T: 'static + Display + Debug> ChainError<T> {
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// derive_str_cherr!(Func2Error);
|
/// derive_str_context!(Func2Error);
|
||||||
///
|
///
|
||||||
/// fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
|
/// fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
/// let filename = "foo.txt";
|
/// let filename = "foo.txt";
|
||||||
/// do_some_io().cherr(Func2Error(format!("Error reading '{}'", filename)))?;
|
/// do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// derive_str_cherr!(Func1Error);
|
/// derive_str_context!(Func1Error);
|
||||||
///
|
///
|
||||||
/// fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
|
/// fn func1() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
/// func2().cherr(Func1Error("func1 error".into()))?;
|
/// func2().context(Func1Error("func1 error".into()))?;
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
|
@ -334,7 +311,7 @@ impl<T: 'static + Display + Debug> ChainError<T> {
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use chainerror::prelude::v1::*;
|
/// # use chainerror::prelude::v1::*;
|
||||||
/// # derive_str_cherr!(FooError);
|
/// # derive_str_context!(FooError);
|
||||||
/// # let err = ChainError::new(String::new(), None, None);
|
/// # let err = ChainError::new(String::new(), None, None);
|
||||||
/// // Instead of writing
|
/// // Instead of writing
|
||||||
/// err.find_cause::<ChainError<FooError>>();
|
/// err.find_cause::<ChainError<FooError>>();
|
||||||
|
@ -357,7 +334,7 @@ impl<T: 'static + Display + Debug> ChainError<T> {
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use chainerror::prelude::v1::*;
|
/// # use chainerror::prelude::v1::*;
|
||||||
/// # derive_str_cherr!(FooErrorKind);
|
/// # derive_str_context!(FooErrorKind);
|
||||||
/// # let err = ChainError::new(String::new(), None, None);
|
/// # let err = ChainError::new(String::new(), None, None);
|
||||||
/// // Instead of writing
|
/// // Instead of writing
|
||||||
/// err.find_cause::<ChainError<FooErrorKind>>();
|
/// err.find_cause::<ChainError<FooErrorKind>>();
|
||||||
|
@ -394,11 +371,11 @@ impl<T: 'static + Display + Debug> ChainError<T> {
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// derive_str_cherr!(Func2Error);
|
/// derive_str_context!(Func2Error);
|
||||||
///
|
///
|
||||||
/// fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
|
/// fn func2() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
/// let filename = "foo.txt";
|
/// let filename = "foo.txt";
|
||||||
/// do_some_io().cherr(Func2Error(format!("Error reading '{}'", filename)))?;
|
/// do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
|
@ -419,8 +396,8 @@ impl<T: 'static + Display + Debug> ChainError<T> {
|
||||||
/// # }
|
/// # }
|
||||||
///
|
///
|
||||||
/// fn func1() -> ChainResult<(), Func1ErrorKind> {
|
/// fn func1() -> ChainResult<(), Func1ErrorKind> {
|
||||||
/// func2().cherr(Func1ErrorKind::Func2)?;
|
/// func2().context(Func1ErrorKind::Func2)?;
|
||||||
/// do_some_io().cherr(Func1ErrorKind::IO("bar.txt".into()))?;
|
/// do_some_io().context(Func1ErrorKind::IO("bar.txt".into()))?;
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
|
@ -453,10 +430,10 @@ impl<T: 'static + Display + Debug> ChainError<T> {
|
||||||
/// Convenience methods for `Result<>` to turn the error into a decorated ChainError
|
/// Convenience methods for `Result<>` to turn the error into a decorated ChainError
|
||||||
pub trait ResultTrait<O, E: Into<Box<dyn Error + 'static + Send + Sync>>> {
|
pub trait ResultTrait<O, E: Into<Box<dyn Error + 'static + Send + Sync>>> {
|
||||||
/// Decorate the error with a `kind` of type `T` and the source `Location`
|
/// Decorate the error with a `kind` of type `T` and the source `Location`
|
||||||
fn cherr<T: 'static + Display + Debug>(self, kind: T) -> std::result::Result<O, ChainError<T>>;
|
fn context<T: 'static + Display + Debug>(self, kind: T) -> std::result::Result<O, ChainError<T>>;
|
||||||
|
|
||||||
/// Decorate the error with a `kind` of type `T` produced with a `FnOnce` and the source `Location`
|
/// Decorate the `error` with a `kind` of type `T` produced with a `FnOnce(&error)` and the source `Location`
|
||||||
fn map_cherr<T: 'static + Display + Debug, F: FnOnce(&E) -> T>(
|
fn map_context<T: 'static + Display + Debug, F: FnOnce(&E) -> T>(
|
||||||
self,
|
self,
|
||||||
op: F,
|
op: F,
|
||||||
) -> std::result::Result<O, ChainError<T>>;
|
) -> std::result::Result<O, ChainError<T>>;
|
||||||
|
@ -466,7 +443,7 @@ impl<O, E: Into<Box<dyn Error + 'static + Send + Sync>>> ResultTrait<O, E>
|
||||||
for std::result::Result<O, E>
|
for std::result::Result<O, E>
|
||||||
{
|
{
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn cherr<T: 'static + Display + Debug>(self, kind: T) -> std::result::Result<O, ChainError<T>> {
|
fn context<T: 'static + Display + Debug>(self, kind: T) -> std::result::Result<O, ChainError<T>> {
|
||||||
match self {
|
match self {
|
||||||
Ok(t) => Ok(t),
|
Ok(t) => Ok(t),
|
||||||
Err(error_cause) => Err(ChainError::new(
|
Err(error_cause) => Err(ChainError::new(
|
||||||
|
@ -478,7 +455,7 @@ impl<O, E: Into<Box<dyn Error + 'static + Send + Sync>>> ResultTrait<O, E>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn map_cherr<T: 'static + Display + Debug, F: FnOnce(&E) -> T>(
|
fn map_context<T: 'static + Display + Debug, F: FnOnce(&E) -> T>(
|
||||||
self,
|
self,
|
||||||
op: F,
|
op: F,
|
||||||
) -> std::result::Result<O, ChainError<T>> {
|
) -> std::result::Result<O, ChainError<T>> {
|
||||||
|
@ -741,22 +718,16 @@ impl<T: 'static + Display + Debug> Debug for ChainError<T> {
|
||||||
if f.alternate() {
|
if f.alternate() {
|
||||||
let mut f = f.debug_struct(&format!("ChainError<{}>", std::any::type_name::<T>()));
|
let mut f = f.debug_struct(&format!("ChainError<{}>", std::any::type_name::<T>()));
|
||||||
|
|
||||||
#[cfg(feature = "location")]
|
let f = f
|
||||||
let f = f.field("occurrence", &self.occurrence);
|
.field("occurrence", &self.occurrence)
|
||||||
|
.field("kind", &self.kind)
|
||||||
let f = f.field("kind", &self.kind);
|
.field("source", &self.source());
|
||||||
|
|
||||||
#[cfg(feature = "debug-cause")]
|
|
||||||
let f = f.field("source", &self.source());
|
|
||||||
|
|
||||||
f.finish()
|
f.finish()
|
||||||
} else {
|
} else {
|
||||||
#[cfg(feature = "location")]
|
|
||||||
{
|
|
||||||
if let Some(ref o) = self.occurrence {
|
if let Some(ref o) = self.occurrence {
|
||||||
write!(f, "{}: ", o)?;
|
write!(f, "{}: ", o)?;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if TypeId::of::<String>() == TypeId::of::<T>()
|
if TypeId::of::<String>() == TypeId::of::<T>()
|
||||||
|| TypeId::of::<&str>() == TypeId::of::<T>()
|
|| TypeId::of::<&str>() == TypeId::of::<T>()
|
||||||
|
@ -766,13 +737,10 @@ impl<T: 'static + Display + Debug> Debug for ChainError<T> {
|
||||||
Debug::fmt(&self.kind, f)?;
|
Debug::fmt(&self.kind, f)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "debug-cause")]
|
|
||||||
{
|
|
||||||
if let Some(e) = self.source() {
|
if let Some(e) = self.source() {
|
||||||
writeln!(f, "\nCaused by:")?;
|
writeln!(f, "\nCaused by:")?;
|
||||||
Debug::fmt(&e, f)?;
|
Debug::fmt(&e, f)?;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -825,18 +793,18 @@ where
|
||||||
/// # Err(io::Error::from(io::ErrorKind::NotFound))?;
|
/// # Err(io::Error::from(io::ErrorKind::NotFound))?;
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// derive_str_cherr!(Func2Error);
|
/// derive_str_context!(Func2Error);
|
||||||
///
|
///
|
||||||
/// fn func2() -> ChainResult<(), Func2Error> {
|
/// fn func2() -> ChainResult<(), Func2Error> {
|
||||||
/// let filename = "foo.txt";
|
/// let filename = "foo.txt";
|
||||||
/// do_some_io().cherr(Func2Error(format!("Error reading '{}'", filename)))?;
|
/// do_some_io().context(Func2Error(format!("Error reading '{}'", filename)))?;
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// derive_str_cherr!(Func1Error);
|
/// derive_str_context!(Func1Error);
|
||||||
///
|
///
|
||||||
/// fn func1() -> Result<(), Box<dyn Error>> {
|
/// fn func1() -> Result<(), Box<dyn Error>> {
|
||||||
/// func2().cherr(Func1Error("func1 error".into()))?;
|
/// func2().context(Func1Error("func1 error".into()))?;
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
/// # if let Err(e) = func1() {
|
/// # if let Err(e) = func1() {
|
||||||
|
@ -851,7 +819,7 @@ where
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! derive_str_cherr {
|
macro_rules! derive_str_context {
|
||||||
($e:ident) => {
|
($e:ident) => {
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct $e(pub String);
|
pub struct $e(pub String);
|
||||||
|
@ -928,9 +896,9 @@ macro_rules! derive_str_cherr {
|
||||||
/// let filename = "bar.txt";
|
/// let filename = "bar.txt";
|
||||||
///
|
///
|
||||||
/// do_some_io(filename)
|
/// do_some_io(filename)
|
||||||
/// .map_cherr(|e| ErrorKind::from_io_error(e, filename.into()))?;
|
/// .map_context(|e| ErrorKind::from_io_error(e, filename.into()))?;
|
||||||
/// do_some_io(filename).map_cherr(|e| ErrorKind::IO(filename.into()))?;
|
/// do_some_io(filename).map_context(|e| ErrorKind::IO(filename.into()))?;
|
||||||
/// do_some_io(filename).map_cherr(|e| ErrorKind::from(e))?;
|
/// do_some_io(filename).map_context(|e| ErrorKind::from(e))?;
|
||||||
/// Ok(())
|
/// Ok(())
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
|
@ -7,12 +7,12 @@ use std::io;
|
||||||
fn test_iter() -> Result<(), Box<dyn Error + Send + Sync>> {
|
fn test_iter() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
let err: Result<(), _> = Err(io::Error::from(io::ErrorKind::NotFound));
|
let err: Result<(), _> = Err(io::Error::from(io::ErrorKind::NotFound));
|
||||||
let err = err.cherr("1");
|
let err = err.context("1");
|
||||||
let err = err.cherr("2");
|
let err = err.context("2");
|
||||||
let err = err.cherr("3");
|
let err = err.context("3");
|
||||||
let err = err.cherr("4");
|
let err = err.context("4");
|
||||||
let err = err.cherr("5");
|
let err = err.context("5");
|
||||||
let err = err.cherr("6");
|
let err = err.context("6");
|
||||||
let err = err.err().unwrap();
|
let err = err.err().unwrap();
|
||||||
|
|
||||||
let mut res = String::new();
|
let mut res = String::new();
|
||||||
|
@ -36,12 +36,12 @@ fn test_iter() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_iter() -> Result<(), Box<dyn Error + Send + Sync>> {
|
fn test_iter() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
let err: Result<(), _> = Err(io::Error::from(io::ErrorKind::NotFound));
|
let err: Result<(), _> = Err(io::Error::from(io::ErrorKind::NotFound));
|
||||||
let err = err.cherr("1");
|
let err = err.context("1");
|
||||||
let err = err.cherr("2");
|
let err = err.context("2");
|
||||||
let err = err.cherr("3");
|
let err = err.context("3");
|
||||||
let err = err.cherr("4");
|
let err = err.context("4");
|
||||||
let err = err.cherr("5");
|
let err = err.context("5");
|
||||||
let err = err.cherr("6");
|
let err = err.context("6");
|
||||||
let err = err.err().unwrap();
|
let err = err.err().unwrap();
|
||||||
|
|
||||||
let res = err.to_string();
|
let res = err.to_string();
|
||||||
|
@ -61,12 +61,12 @@ fn test_iter() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_find_cause() -> Result<(), Box<dyn Error + Send + Sync>> {
|
fn test_find_cause() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
let err: Result<(), _> = Err(io::Error::from(io::ErrorKind::NotFound));
|
let err: Result<(), _> = Err(io::Error::from(io::ErrorKind::NotFound));
|
||||||
let err = err.cherr("1");
|
let err = err.context("1");
|
||||||
let err = err.cherr("2");
|
let err = err.context("2");
|
||||||
let err = err.cherr("3");
|
let err = err.context("3");
|
||||||
let err = err.cherr("4");
|
let err = err.context("4");
|
||||||
let err = err.cherr("5");
|
let err = err.context("5");
|
||||||
let err = err.cherr("6");
|
let err = err.context("6");
|
||||||
let err = err.err().unwrap();
|
let err = err.err().unwrap();
|
||||||
|
|
||||||
let io_error: Option<&io::Error> = err.find_cause::<io::Error>();
|
let io_error: Option<&io::Error> = err.find_cause::<io::Error>();
|
||||||
|
@ -79,12 +79,12 @@ fn test_find_cause() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_root_cause() -> Result<(), Box<dyn Error + Send + Sync>> {
|
fn test_root_cause() -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
let err: Result<(), _> = Err(io::Error::from(io::ErrorKind::NotFound));
|
let err: Result<(), _> = Err(io::Error::from(io::ErrorKind::NotFound));
|
||||||
let err = err.cherr("1");
|
let err = err.context("1");
|
||||||
let err = err.cherr("2");
|
let err = err.context("2");
|
||||||
let err = err.cherr("3");
|
let err = err.context("3");
|
||||||
let err = err.cherr("4");
|
let err = err.context("4");
|
||||||
let err = err.cherr("5");
|
let err = err.context("5");
|
||||||
let err = err.cherr("6");
|
let err = err.context("6");
|
||||||
let err = err.err().unwrap();
|
let err = err.err().unwrap();
|
||||||
|
|
||||||
let err: Option<&(dyn std::error::Error + 'static)> = err.root_cause();
|
let err: Option<&(dyn std::error::Error + 'static)> = err.root_cause();
|
||||||
|
|
Loading…
Reference in a new issue