daily pastebin goal
22%
SHARE
TWEET

Untitled

a guest Dec 14th, 2018 53 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. use std::error::Error;
  2.  
  3. trait ChainError {
  4.     fn new(
  5.         line: u32,
  6.         filename: &'static str,
  7.         description: String,
  8.         error_cause: Box<dyn Error + 'static>,
  9.     ) -> Self;
  10.  
  11.     fn root_cause(&self) -> Option<&(dyn Error + 'static)>;
  12.     fn find_cause<T: Error + 'static>(&self) -> Option<&(dyn Error + 'static)>;
  13. }
  14.  
  15. #[macro_export]
  16. macro_rules! chain_error {
  17.     ( $t:ident, $v:expr $(, $more:expr)* ) => {
  18.         |e| $t :: new(line!(), file!(), format!($v, $( $more )*), e.into())
  19.     };
  20. }
  21.  
  22. #[macro_export]
  23. macro_rules! new_chain_error {
  24.     ($e:ident) => {
  25.         struct $e {
  26.             line: u32,
  27.             filename: &'static str,
  28.             description: String,
  29.             error_cause: Box<dyn Error + 'static>,
  30.         }
  31.  
  32.         impl ChainError for $e {
  33.             fn new(
  34.                 line: u32,
  35.                 filename: &'static str,
  36.                 description: String,
  37.                 error_cause: Box<dyn Error + 'static>,
  38.             ) -> Self {
  39.                 $e {
  40.                     line,
  41.                     filename,
  42.                     description,
  43.                     error_cause,
  44.                 }
  45.             }
  46.  
  47.             fn root_cause(&self) -> Option<&(dyn Error + 'static)> {
  48.                 let mut cause = self.error_cause.as_ref();
  49.                 while let Some(c) = cause.source() {
  50.                     cause = c;
  51.                 }
  52.                 Some(cause)
  53.             }
  54.  
  55.             fn find_cause<T: Error + 'static>(&self) -> Option<&(dyn Error + 'static)> {
  56.                 let mut cause = self as &(dyn Error + 'static);
  57.                 loop {
  58.                     if cause.is::<T>() {
  59.                         return Some(cause);
  60.                     }
  61.  
  62.                     match cause.source() {
  63.                         Some(c) => cause = c,
  64.                         None => return None,
  65.                     }
  66.                 }
  67.             }
  68.         }
  69.  
  70.         impl Error for $e {
  71.             fn description(&self) -> &str {
  72.                 &self.description
  73.             }
  74.  
  75.             fn source(&self) -> Option<&(dyn Error + 'static)> {
  76.                 Some(self.error_cause.as_ref())
  77.             }
  78.         }
  79.  
  80.         impl ::std::fmt::Display for $e {
  81.             fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
  82.                 writeln!(f, "{}", self.description)?;
  83.                 if let Some(e) = self.source() {
  84.                     writeln!(f, "\nCaused by:")?;
  85.                     ::std::fmt::Display::fmt(&e, f)?;
  86.                 }
  87.                 Ok(())
  88.             }
  89.         }
  90.  
  91.         impl ::std::fmt::Debug for $e {
  92.             fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
  93.                 writeln!(f, "{}:{}: {}", self.filename, self.line, self.description)?;
  94.                 if let Some(e) = self.source() {
  95.                     writeln!(f, "\nCaused by:")?;
  96.                     ::std::fmt::Debug::fmt(&e, f)?;
  97.                 }
  98.                 Ok(())
  99.             }
  100.         }
  101.     };
  102. }
  103.  
  104. //////////////////////////////////////////////////////////
  105.  
  106. new_chain_error!(MyError);
  107. new_chain_error!(MyMainError);
  108.  
  109. fn throw_error() -> Result<(), MyError> {
  110.     let directory = String::from("ldfhgdfkgjdf");
  111.     ::std::fs::remove_dir(&directory).map_err(chain_error!(
  112.         MyError,
  113.         "Could not remove directory '{}'!",
  114.         &directory
  115.     ))?;
  116.     Ok(())
  117. }
  118.  
  119. fn main() -> Result<(), Box<Error>> {
  120.     let res = throw_error().map_err(chain_error!(MyMainError, "I has an error."));
  121.  
  122.     if let Err(ref my_err) = res {
  123.         if let Some(source) = my_err.source() {
  124.             assert!(source.is::<MyError>());
  125.         }
  126.         println!("\nRoot cause is {:#?}\n", my_err.root_cause());
  127.  
  128.         assert!(my_err.root_cause().unwrap().is::<::std::io::Error>());
  129.         assert!(my_err.find_cause::<::std::io::Error>().is_some());
  130.  
  131.         if my_err.find_cause::<::std::io::Error>().is_some() {
  132.             println!("Has cause io::Error");
  133.         }
  134.         if my_err.find_cause::<MyError>().is_some() {
  135.             println!("Has cause MyError");
  136.         }
  137.  
  138.         println!("-----------");
  139.         println!("Display Error:\n{}", my_err);
  140.         println!("-----------");
  141.         println!("Debug Error:  \n{:#?}", my_err);
  142.         println!("-----------");
  143.     };
  144.     res?;
  145.     Ok(())
  146. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top