9次发布

0.1.24 2020年9月18日
0.1.23 2020年9月18日

2141Rust模式

Download history 69/week @ 2024-07-22

69 每月下载

MIT 许可证

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


DynErrorBox<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! 宏。
这些宏都依赖于 logclean_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(())
}

无运行时依赖