diff --git a/booksrc/tutorial12.md b/booksrc/tutorial12.md new file mode 100644 index 0000000..682eaa8 --- /dev/null +++ b/booksrc/tutorial12.md @@ -0,0 +1,12 @@ +# Deref for the ErrorKind + +Because ChainError implements Deref to &T, we can also match on `*e` instead of `e.kind()`. + +~~~rust +use crate::chainerror::*; +{{#include ../examples/tutorial12.rs:2:}} +# #[allow(dead_code)] +# mod chainerror { +{{#includecomment ../src/lib.rs}} +# } +~~~ diff --git a/examples/tutorial12.rs b/examples/tutorial12.rs new file mode 100644 index 0000000..38ff09e --- /dev/null +++ b/examples/tutorial12.rs @@ -0,0 +1,64 @@ +use chainerror::*; +use std::error::Error; +use std::io; +use std::result::Result; + +fn do_some_io() -> Result<(), Box> { + Err(io::Error::from(io::ErrorKind::NotFound))?; + Ok(()) +} + +derive_str_cherr!(Func2Error); + +fn func2() -> Result<(), Box> { + let filename = "foo.txt"; + do_some_io().map_err(mstrerr!(Func2Error, "Error reading '{}'", filename))?; + Ok(()) +} + +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::fmt::Debug for Func1ErrorKind { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + write!(f, "{}", self) + } +} + +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> { + if let Err(e) = func1() { + match *e { + Func1ErrorKind::Func2 => eprintln!("Main Error Report: func1 error calling func2"), + Func1ErrorKind::IO(ref filename) => { + eprintln!("Main Error Report: func1 error reading '{}'", filename) + } + } + + if let Some(e) = e.find_chain_cause::() { + eprintln!("\nError reported by Func2Error: {}", e) + } + + eprintln!("\nDebug Error:\n{:?}", e); + } + Ok(()) +} diff --git a/src/lib.rs b/src/lib.rs index 547e4f7..ca9d75e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -374,6 +374,14 @@ impl<'a> Iterator for ErrorIter<'a> { } } +impl std::ops::Deref for ChainError { + type Target = T; + + fn deref(&self) -> &Self::Target { + self.kind() + } +} + /// Convenience trait to hide the `ChainError` implementation internals pub trait ChainErrorDown { /// Test if of type `ChainError`