Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use std::error::Error;
- pub struct ChainError {
- line: u32,
- filename: &'static str,
- description: String,
- error_cause: Box<dyn Error + 'static>,
- }
- impl ChainError {
- pub 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)
- }
- pub fn has_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 ChainError {
- fn description(&self) -> &str {
- &self.description
- }
- fn source(&self) -> Option<&(dyn Error + 'static)> {
- Some(self.error_cause.as_ref())
- }
- }
- impl ::std::fmt::Display for ChainError {
- 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 ChainError {
- 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(())
- }
- }
- pub fn chained_error(
- line: u32,
- filename: &'static str,
- description: String,
- error_cause: Box<dyn Error + 'static>,
- ) -> ChainError {
- ChainError {
- line,
- filename,
- description,
- error_cause,
- }
- }
- #[macro_export]
- macro_rules! chain_error {
- ($r:expr, $v:expr, $t:tt) => {
- $r.map_err(|e| $t(chained_error(line!(), file!(), $v, e.into())))
- };
- }
- #[macro_export]
- macro_rules! new_chain_error {
- ($e:ident) => {
- struct $e(ChainError);
- impl ::std::fmt::Display for $e {
- fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
- self.0.fmt(f)
- }
- }
- impl ::std::fmt::Debug for $e {
- fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
- self.0.fmt(f)
- }
- }
- impl ::std::ops::Deref for $e {
- type Target = ChainError;
- fn deref(&self) -> &ChainError {
- &self.0
- }
- }
- impl ::std::error::Error for $e {
- fn description(&self) -> &str {
- self.0.description()
- }
- fn source(&self) -> Option<&(dyn Error + 'static)> {
- self.0.source()
- }
- }
- };
- }
- new_chain_error!(MyError);
- new_chain_error!(MyMainError);
- fn throw_error() -> Result<(), MyError> {
- let directory = String::from("ldfhgdfkgjdf");
- chain_error!(
- ::std::fs::remove_dir(&directory),
- format!("Could not remove directory '{}'!", &directory),
- MyError
- )?;
- Ok(())
- }
- fn main() -> Result<(), MyMainError> {
- let res = chain_error!(throw_error(), "I has an error.".into(), MyMainError);
- if let Err(ref my_err) = res {
- if let Some(source) = my_err.source() {
- if source.is::<MyError>() {
- println!("\nSource is MyError!!\n");
- }
- }
- println!("\nRoot cause is {:#?}\n", my_err.root_cause());
- if my_err.has_cause::<::std::io::Error>().is_some() {
- println!("Has cause io::Error\n");
- }
- if my_err.has_cause::<MyError>().is_some() {
- println!("Has cause MyError\n");
- }
- 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