9次发布
0.1.24 | 2020年9月18日 |
---|---|
0.1.23 | 2020年9月18日 |
2141 在 Rust模式
69 每月下载
22KB
146 行
dynerr
一些宏,用于帮助动态错误处理/日志记录。
该crate的目标是在不牺牲类型安全的情况下统一所有错误类型。
该crate的主要功能是dynerr!
和dynmatch!
宏。当与返回类型DynResult<T>
一起使用时,它们允许您从一个函数中返回多个错误类型,然后在错误处理期间轻松匹配它们。使用dynerr,您无需再包装错误。
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
是Box<dyn error::Error>
的别名。任何实现了error::Error
的错误都可以转换为DynError
。
DynResult<T>
只是Result<T, DynError>
的别名,因此任何在Result<T>
上工作的内容也可以在DynResult<T>
上工作。
Dynerr可以与任何crate中的任何错误类型一起工作,只要返回的类型实现了std::error::Error
,那么DynResult<T>
应该能够处理它。
为了直接返回自定义错误,建议使用dynerr!
宏而不是Err()
。
为了匹配DynResult<T>
中包含的DynError,请使用dynmatch!
宏。
dynmatch!
的使用方法如下
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
)
}
};
除了其主要功能外,dynerr还有一些简单的宏来帮助进行懒加载日志。
log!
将事件记录到指定的文件中。如果没有提供日志文件,则默认为 event.log。
logged_panic!
将事件记录到文件然后触发 panic。如果没有提供日志文件,则默认为 event.log。
check!
将在结果上调用 .unwrap_or_else(|e| logged_panic!(e))
。如果没有提供日志文件,则默认为 event.log。
如果提供的文件不存在,则这些宏将尝试创建该文件。
要删除日志文件,请使用 clean!
宏。
这些宏都依赖于 log
或 clean_log
函数。这些函数能够触发 panic,但在正常情况下通常不需要。
完整示例
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<u32> {
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) => logged_panic!("it was 2!"), //arm [pattern] => {code}
_ => panic!("{}",e) //_ => {code}
},
type ExampleError2 {
arm ExampleError2::ThatError(8) => logged_panic!("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 logged_panic! if error");
let _i = check!(example(11));
let _i = check!(example(9), "test.log");
Ok(())
}