dynerr

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.\ To delete a log file use the clean! macro.\ These macros all rely on either the log or clean_log functions. these functions are 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

[derive(Debug)]

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

[derive(Debug)]

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 { match x { 1 => Ok(x), //Ok 2..=4 => dynerr!(ExampleError1::ThisError(x)), //custom error 5..=10 => dynerr!(ExampleError2::ThatError(x)), //different custom error _ => { std::fs::File::open("none")?; //an error not even defined by you! Ok(x) } } }

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(()) } ```