Guest User

Untitled

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