mirror of
				https://github.com/haraldh/chainerror.git
				synced 2025-10-31 14:41:37 +01:00 
			
		
		
		
	add more traits and macros
Namely: * ChainErrorFrom * IntoChainError * minto_cherr! * into_cherr! * strerr! Also make derive_str_cherr! struct public
This commit is contained in:
		
							parent
							
								
									f972b5f703
								
							
						
					
					
						commit
						a040044529
					
				
					 4 changed files with 104 additions and 5 deletions
				
			
		|  | @ -1,6 +1,6 @@ | ||||||
| [package] | [package] | ||||||
| name = "chainerror" | name = "chainerror" | ||||||
| version = "0.2.0" | version = "0.3.0" | ||||||
| authors = ["Harald Hoyer <harald@redhat.com>"] | authors = ["Harald Hoyer <harald@redhat.com>"] | ||||||
| edition = "2018" | edition = "2018" | ||||||
| license = "MIT/Apache-2.0" | license = "MIT/Apache-2.0" | ||||||
|  |  | ||||||
|  | @ -30,6 +30,7 @@ impl ::std::fmt::Display for Func1ErrorKind { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | impl ::std::error::Error for Func1ErrorKind {} | ||||||
| 
 | 
 | ||||||
| fn func1() -> ChainResult<(), Func1ErrorKind> { | fn func1() -> ChainResult<(), Func1ErrorKind> { | ||||||
|     func2().map_err(|e| cherr!(e, Func1ErrorKind::Func2))?; |     func2().map_err(|e| cherr!(e, Func1ErrorKind::Func2))?; | ||||||
|  |  | ||||||
|  | @ -36,6 +36,8 @@ impl ::std::fmt::Debug for Func1ErrorKind { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | impl ::std::error::Error for Func1ErrorKind {} | ||||||
|  | 
 | ||||||
| fn func1() -> ChainResult<(), Func1ErrorKind> { | fn func1() -> ChainResult<(), Func1ErrorKind> { | ||||||
|     func2().map_err(|e| cherr!(e, Func1ErrorKind::Func2))?; |     func2().map_err(|e| cherr!(e, Func1ErrorKind::Func2))?; | ||||||
|     let filename = String::from("bar.txt"); |     let filename = String::from("bar.txt"); | ||||||
|  |  | ||||||
							
								
								
									
										104
									
								
								src/lib.rs
									
										
									
									
									
								
							
							
						
						
									
										104
									
								
								src/lib.rs
									
										
									
									
									
								
							|  | @ -369,7 +369,7 @@ impl<T: 'static + Display + Debug> ChainError<T> { | ||||||
|     ~~~ |     ~~~ | ||||||
| 
 | 
 | ||||||
|     **/ |     **/ | ||||||
|     pub fn kind<'a>(&'a self) -> &'a T { |     pub fn kind(&self) -> &T { | ||||||
|         &self.kind |         &self.kind | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -395,7 +395,10 @@ impl<U: 'static + Display + Debug> ChainErrorDown for ChainError<U> { | ||||||
| 
 | 
 | ||||||
|     fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> { |     fn downcast_chain_ref<T: 'static + Display + Debug>(&self) -> Option<&ChainError<T>> { | ||||||
|         if self.is_chain::<T>() { |         if self.is_chain::<T>() { | ||||||
|             unsafe { Some(&*(self as *const dyn Error as *const &ChainError<T>)) } |             #[allow(clippy::cast_ptr_alignment)] | ||||||
|  |             unsafe { | ||||||
|  |                 Some(&*(self as *const dyn Error as *const &ChainError<T>)) | ||||||
|  |             } | ||||||
|         } else { |         } else { | ||||||
|             None |             None | ||||||
|         } |         } | ||||||
|  | @ -403,7 +406,10 @@ impl<U: 'static + Display + Debug> ChainErrorDown for ChainError<U> { | ||||||
| 
 | 
 | ||||||
|     fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> { |     fn downcast_chain_mut<T: 'static + Display + Debug>(&mut self) -> Option<&mut ChainError<T>> { | ||||||
|         if self.is_chain::<T>() { |         if self.is_chain::<T>() { | ||||||
|             unsafe { Some(&mut *(self as *mut dyn Error as *mut &mut ChainError<T>)) } |             #[allow(clippy::cast_ptr_alignment)] | ||||||
|  |             unsafe { | ||||||
|  |                 Some(&mut *(self as *mut dyn Error as *mut &mut ChainError<T>)) | ||||||
|  |             } | ||||||
|         } else { |         } else { | ||||||
|             None |             None | ||||||
|         } |         } | ||||||
|  | @ -523,6 +529,48 @@ impl<T: 'static + Display + Debug> Debug for ChainError<T> { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | pub trait ChainErrorFrom<T>: Sized { | ||||||
|  |     fn chain_error_from(_: T, line_filename: Option<(u32, &'static str)>) -> ChainError<Self>; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub trait IntoChainError<T>: Sized { | ||||||
|  |     fn into_chain_error(self, line_filename: Option<(u32, &'static str)>) -> ChainError<T>; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<T, U> IntoChainError<U> for T | ||||||
|  | where | ||||||
|  |     U: ChainErrorFrom<T>, | ||||||
|  | { | ||||||
|  |     fn into_chain_error(self, line_filename: Option<(u32, &'static str)>) -> ChainError<U> { | ||||||
|  |         U::chain_error_from(self, line_filename) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<T, U> ChainErrorFrom<T> for U | ||||||
|  | where | ||||||
|  |     T: Into<U>, | ||||||
|  |     U: 'static + Display + Debug, | ||||||
|  | { | ||||||
|  |     fn chain_error_from(t: T, line_filename: Option<(u32, &'static str)>) -> ChainError<Self> { | ||||||
|  |         let e: U = t.into(); | ||||||
|  |         ChainError::<_>::new(e, None, line_filename) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[macro_export] | ||||||
|  | macro_rules! minto_cherr { | ||||||
|  |     ( ) => { | ||||||
|  |         |e| e.into_chain_error(Some((line!(), file!()))) | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[macro_export] | ||||||
|  | macro_rules! into_cherr { | ||||||
|  |     ( $t:expr ) => { | ||||||
|  |         $t.into_chain_error(Some((line!(), file!()))) | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /** creates a new `ChainError<T>`
 | /** creates a new `ChainError<T>`
 | ||||||
| 
 | 
 | ||||||
| # Examples | # Examples | ||||||
|  | @ -719,6 +767,54 @@ macro_rules! mstrerr { | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /** convenience macro for cherr!(T(format!(…))) where T(String)
 | ||||||
|  | ~~~rust | ||||||
|  | # use crate::chainerror::*; | ||||||
|  | # use std::error::Error; | ||||||
|  | # use std::result::Result; | ||||||
|  | # | ||||||
|  | derive_str_cherr!(Func2Error); | ||||||
|  | 
 | ||||||
|  | fn func2() -> ChainResult<(), Func2Error> { | ||||||
|  |     let filename = "foo.txt"; | ||||||
|  |     Err(strerr!(Func2Error, "Error reading '{}'", filename)) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | derive_str_cherr!(Func1Error); | ||||||
|  | 
 | ||||||
|  | fn func1() -> Result<(), Box<Error>> { | ||||||
|  |     func2().map_err(mstrerr!(Func1Error, "func1 error"))?; | ||||||
|  |     Ok(()) | ||||||
|  | } | ||||||
|  | # | ||||||
|  | # fn main() { | ||||||
|  | #     if let Err(e) = func1() { | ||||||
|  | #         if let Some(f1err) = e.downcast_chain_ref::<Func1Error>() { | ||||||
|  | #             assert!(f1err.find_cause::<ChainError<Func2Error>>().is_some()); | ||||||
|  | #             assert!(f1err.find_chain_cause::<Func2Error>().is_some()); | ||||||
|  | #         } else { | ||||||
|  | #             panic!(); | ||||||
|  | #         } | ||||||
|  | #     } else { | ||||||
|  | #         unreachable!(); | ||||||
|  | #     } | ||||||
|  | # } | ||||||
|  | ~~~ | ||||||
|  | 
 | ||||||
|  | **/ | ||||||
|  | #[macro_export] | ||||||
|  | macro_rules! strerr { | ||||||
|  |     ( $t:ident, $v:expr $(, $more:expr)* ) => { | ||||||
|  |         cherr!($t (format!($v, $( $more , )* ))) | ||||||
|  |     }; | ||||||
|  |     ( $t:path, $v:expr $(, $more:expr)* ) => { | ||||||
|  |         cherr!($t (format!($v, $( $more , )* ))) | ||||||
|  |     }; | ||||||
|  |     ( $v:expr $(, $more:expr)* ) => { | ||||||
|  |         cherr!(format!($v, $( $more , )* )) | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /** convenience macro to create a "new type" T(String) and implement Display + Debug for T
 | /** convenience macro to create a "new type" T(String) and implement Display + Debug for T
 | ||||||
| 
 | 
 | ||||||
| ~~~rust | ~~~rust | ||||||
|  | @ -765,7 +861,7 @@ fn func1() -> Result<(), Box<Error>> { | ||||||
| #[macro_export] | #[macro_export] | ||||||
| macro_rules! derive_str_cherr { | macro_rules! derive_str_cherr { | ||||||
|     ($e:ident) => { |     ($e:ident) => { | ||||||
|         struct $e(String); |         pub struct $e(pub String); | ||||||
|         impl ::std::fmt::Display for $e { |         impl ::std::fmt::Display for $e { | ||||||
|             fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { |             fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { | ||||||
|                 write!(f, "{}", self.0) |                 write!(f, "{}", self.0) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Harald Hoyer
						Harald Hoyer