Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use std::error::Error;
- trait ChainError {
- fn new(
- line: u32,
- filename: &'static str,
- description: String,
- error_cause: Box<dyn Error + 'static>,
- ) -> Self;
- fn root_cause(&self) -> Option<&(dyn Error + 'static)>;
- fn find_cause<T: Error + 'static>(&self) -> Option<&(dyn Error + 'static)>;
- }
- #[macro_export]
- macro_rules! chain_error {
- ( $t:ident, $v:expr $(, $more:expr)* ) => {
- |e| $t :: new(line!(), file!(), format!($v, $( $more )*), e.into())
- };
- }
- #[macro_export]
- macro_rules! new_chain_error {
- ($e:ident) => {
- struct $e {
- line: u32,
- filename: &'static str,
- description: String,
- error_cause: Box<dyn Error + 'static>,
- }
- impl ChainError for $e {
- fn new(
- line: u32,
- filename: &'static str,
- description: String,
- error_cause: Box<dyn Error + 'static>,
- ) -> Self {
- $e {
- line,
- filename,
- description,
- error_cause,
- }
- }
- fn root_cause(&self) -> Option<&(dyn Error + 'static)> {
- let mut cause = self.error_cause.as_ref();
- while let Some(c) = cause.source() {
- cause = c;
- }
- Some(cause)
- }
- fn find_cause<T: Error + 'static>(&self) -> Option<&(dyn Error + 'static)> {
- let mut cause = self as &(dyn Error + 'static);
- loop {
- if cause.is::<T>() {
- return Some(cause);
- }
- match cause.source() {
- Some(c) => cause = c,
- None => return None,
- }
- }
- }
- }
- impl Error for $e {
- fn description(&self) -> &str {
- &self.description
- }
- fn source(&self) -> Option<&(dyn Error + 'static)> {
- Some(self.error_cause.as_ref())
- }
- }
- impl ::std::fmt::Display for $e {
- fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
- writeln!(f, "{}", self.description)?;
- if let Some(e) = self.source() {
- writeln!(f, "\nCaused by:")?;
- ::std::fmt::Display::fmt(&e, f)?;
- }
- Ok(())
- }
- }
- impl ::std::fmt::Debug for $e {
- fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
- writeln!(f, "{}:{}: {}", self.filename, self.line, self.description)?;
- if let Some(e) = self.source() {
- writeln!(f, "\nCaused by:")?;
- ::std::fmt::Debug::fmt(&e, f)?;
- }
- Ok(())
- }
- }
- };
- }
- //////////////////////////////////////////////////////////
- new_chain_error!(MyError);
- new_chain_error!(MyMainError);
- fn throw_error() -> Result<(), MyError> {
- let directory = String::from("ldfhgdfkgjdf");
- ::std::fs::remove_dir(&directory).map_err(chain_error!(
- MyError,
- "Could not remove directory '{}'!",
- &directory
- ))?;
- Ok(())
- }
- fn main() -> Result<(), Box<Error>> {
- let res = throw_error().map_err(chain_error!(MyMainError, "I has an error."));
- if let Err(ref my_err) = res {
- if let Some(source) = my_err.source() {
- assert!(source.is::<MyError>());
- }
- println!("\nRoot cause is {:#?}\n", my_err.root_cause());
- assert!(my_err.root_cause().unwrap().is::<::std::io::Error>());
- assert!(my_err.find_cause::<::std::io::Error>().is_some());
- if my_err.find_cause::<::std::io::Error>().is_some() {
- println!("Has cause io::Error");
- }
- if my_err.find_cause::<MyError>().is_some() {
- println!("Has cause MyError");
- }
- println!("-----------");
- println!("Display Error:\n{}", my_err);
- println!("-----------");
- println!("Debug Error: \n{:#?}", my_err);
- println!("-----------");
- };
- res?;
- Ok(())
- }
Add Comment
Please, Sign In to add comment