Some macros to help with dynamic error handling/logging.\
The goal of this crate is to unify all error types without compromising type safety.\
\
The main features of this crate are the dynerr!
and dynmatch!
macros. when used alongside the return type DynResult<T>
, they allows you to return multiple error types from a function then easily match for them during your error handling. Using dynerr, theres no need to ever wrap errors.
rust
fn example(x: u32) -> DynResult<u32> { //returns a dynamic result
match x {
1 => Ok(x), //Ok()
2..=4 => dynerr!(ExampleError1::ThisError(x)), //custom error
5..=10 => dynerr!(ExampleError2::ThatError(x)), //different custom error
_ => {
std::env::current_dir()?; //an error not even defined by you!
Ok(x)
}
}
}
\
DynError
is an alias for Box<dyn error::Error>
. Any error that implements error::Error
can be turned into a DynError
.\
DynResult<T>
is just an alias for Result<T, DynError>
so anything that works on a Result<T>
will still work on a DynResult<T>
.\
Dynerr works with any error type from any crate, as long as the type being returned implements std::error::Error
then DynResult<T>
should be able to handle it.\
To directly return a custom error its recommended to use the dynerr!
macro instead of Err()
.\
To match against the DynError contained in DynResult<T>
, use the dynmatch!
macro.\
dynmatch!
usage looks similar to this:
rust
let i = match example(9) { //returns dyn error
Ok(i) => i,
Err(e) => {
dynmatch!(e, //the error to match
type ExampleError1 { //enum error type
arm ExampleError1::ThisError(2) => panic!("it was 2!"), //arm [pattern] => {code}
_ => panic!("{}",e) //_ => {code}
},
type ExampleError2 { //another enum error type
arm ExampleError2::ThatError(8) => panic!("it was 8!"), //more arms to match against
arm ExampleError2::ThatError(9) => 9,
_ => panic!("{}",e) //a final exhaustive match
},
_ => panic!("{}",e) //final exhaustive match if type not found
)
}
};
\
Aside from its main features, dynerr also has some simple macros to help with lazy logging.\
log!
will log an event to the supplied file. Defaults to event.log if no log file supplied.\
logged_panic!
will log an event to file then panic. Defaults to event.log if no log file supplied.\
check!
will call .unwrap_or_else(|e| logged_panic!(e))
on a result. Defaults to event.log if no log file supplied.\
If the supplied file doesn't exist then these macros will attempt to create the file.\
These macros all rely on the log
function. log
is capable of panicking but shouldn't ever need to under normal circumstances.
\
\
A complete example:
```rust use dynerr::*; use std::{fmt, error};
//THIS SECTION IS CREATING THE FIRST CUSTOM ERROR ///a custom error type
enum ExampleError1 { ThisError(u32), } //impl display formatting for error impl fmt::Display for ExampleError1 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { ExampleError1::ThisError(i) => write!(f, "ExampleError1::ThisError: {}",i), } } } //impl error conversion for error impl error::Error for ExampleError1 {}
//THIS SECTION IS CREATING THE SECOND CUSTOM ERROR
enum ExampleError2 { ThatError(u32), } impl fmt::Display for ExampleError2 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { ExampleError2::ThatError(i) => write!(f, "ExampleError2::ThatError: {}",i), } } } impl error::Error for ExampleError2 {}
///THIS SECTION IS USING IT
///shows error handling capabilities using DynError
fn example(x: u32) -> DynResult
fn main() -> DynResult<()> { log!("this is a test", "test.log"); let i = match example(2) { Ok(i) => i, Err(e) => { dynmatch!(e, //the DynError to be matched type ExampleError1 { //an error type arm ExampleError1::ThisError(2) => loggedpanic!("it was 2!"), //arm [pattern] => {code} _ => panic!("{}",e) //_ => {code} }, type ExampleError2 { arm ExampleError2::ThatError(8) => loggedpanic!("it was 8!", "test.log"), arm ExampleError2::ThatError(9) => 9, _ => panic!("{}",e) }, type std::io::Error { //an error type not defined by you arm i if i.kind() == std::io::ErrorKind::NotFound => panic!("not found"), //a match guard included in the match _ => panic!("{}", e) }, _ => panic!("{}",e) //what to do if error type isn't found ) } }; log!("do loggedpanic! if error"); let _i = check!(example(11)); let _i = check!(example(9), "test.log"); Ok(()) } ```