ErrorKind to the rescue
To cope with different kind of errors, we introduce the kind of an error Func1ErrorKind
with an enum.
Because we derive Debug
and implement Display
our Func1ErrorKind
enum, this enum can be used as
a std::error::Error
.
Not using String
errors anymore, the cherr!()
macro seen in the beginning of
the tutorial has to be used again.
Only returning Func1ErrorKind
in func1()
now let us get rid of Result<(), Box<Error + Send + Sync>>
and we can
use ChainResult<(), Func1ErrorKind>
.
In main
we can now directly use the methods of ChainError<T>
without downcasting the error first.
Also a nice match
on ChainError<T>.kind()
is now possible, which returns &T
, meaning
&Func1ErrorKind
here.
use chainerror::*; use std::error::Error; use std::io; use std::result::Result; fn do_some_io() -> Result<(), Box<Error + Send + Sync>> { Err(io::Error::from(io::ErrorKind::NotFound))?; Ok(()) } derive_str_cherr!(Func2Error); fn func2() -> Result<(), Box<Error + Send + Sync>> { let filename = "foo.txt"; do_some_io().map_err(mstrerr!(Func2Error, "Error reading '{}'", filename))?; Ok(()) } #[derive(Debug)] enum Func1ErrorKind { Func2, IO(String), } impl ::std::fmt::Display for Func1ErrorKind { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { match self { Func1ErrorKind::Func2 => write!(f, "func1 error calling func2"), Func1ErrorKind::IO(filename) => write!(f, "Error reading '{}'", filename), } } } impl ::std::error::Error for Func1ErrorKind {} fn func1() -> ChainResult<(), Func1ErrorKind> { func2().map_err(|e| cherr!(e, Func1ErrorKind::Func2))?; let filename = String::from("bar.txt"); do_some_io().map_err(|e| cherr!(e, Func1ErrorKind::IO(filename)))?; Ok(()) } fn main() -> Result<(), Box<Error + Send + Sync>> { if let Err(e) = func1() { match e.kind() { Func1ErrorKind::Func2 => eprintln!("Main Error Report: func1 error calling func2"), Func1ErrorKind::IO(filename) => { eprintln!("Main Error Report: func1 error reading '{}'", filename) } } if let Some(e) = e.find_chain_cause::<Func2Error>() { eprintln!("\nError reported by Func2Error: {}", e) } eprintln!("\nDebug Error:\n{:?}", e); } Ok(()) } #[allow(dead_code)] mod chainerror { {{#includecomment ../src/lib.rs}} }