#错误 #上下文 #thiserror #枚举 #字符串 #生成

thiserror_string_context

为使用 thiserror 生成的错误枚举添加上下文字符串

2 个版本

新版本 0.1.1 2024 年 8 月 24 日
0.1.0 2024 年 8 月 23 日

858Rust 模式

Download history 61/week @ 2024-08-17

每月 71 次下载

MIT/Apache

7KB

此软件包扩展了 thiserror,使其能够向错误枚举添加字符串上下文。

典型用法是使用文件名对 io::Error 进行注解,但它可以在需要字符串错误注解的任何情况下使用。

与其他类似软件包的关系

此软件包在添加上下文方面不如 anyhowsnafu 灵活,但它具有可忽略的开销,并且使用起来更加方便。它仅服务于单一目的:向使用 thiserror 生成的错误枚举添加解释性字符串。它不适用于除枚举之外的任何错误类型,也不支持除字符串之外的其他上下文类型。

与具有类似目的的其他软件包相比 - thiserror-context,此软件包不会强制用户创建具有和没有上下文的两个不同的错误类型。相反,将隐藏的上下文变体添加到错误枚举本身,这使得此解决方案更加优雅,并且维护起来更加容易。

用法

用法非常简单

use thiserror::Error;
use thiserror_string_context::*;

// Annotate your error enum with `string_context` attribute.
// This will allow to use `MyError::with_context()` method
// to add a string annotation to your errors.
// You may add a custom error message where `{0}` 
// is your original error variant.
#[string_context("Custom context message: {0}")]
#[derive(Error,Debug)]
enum MyError {
   #[error("Slight underflow happened!")]
   Underflow,
   #[error("slight overflow happened!")]
   Overflow,
   #[error("too far from correct!")]
   TooFar,
}

fn check_number(n: i32) -> Result<(),MyError> {
   match n {
       42 => println!("Correct number!"),
       41 => return Err(MyError::Underflow),
       43 => return Err(MyError::Overflow),
       _ => return Err(MyError::TooFar),
   }
   Ok(())
}

fn initiate_error() -> anyhow::Result<()> {
   // Here we add a context message
   check_number(41).with_context(|| "Crashing with value 41")?;
   Ok(())
}

# fn main() {
#     initiate_error().unwrap();
# }

此代码会崩溃,并显示以下消息

Custom context message: Crashing with value 41

Caused by:
    Slight underflow happened!

匹配带有上下文的错误枚举

当上下文添加到错误枚举中时,会向其中添加一个隐藏的变体,这使得枚举变体的匹配变得有些繁琐。方法 unwrap_context 返回一个元组,其中第一个元素是包含上下文(如果有)的 Option<String>,第二个是“去皮”后的枚举本身。这允许非常简单的匹配

if let Err(err) = initiate_error() {
    // Run different actions on different error variants
    match err.unwrap_context() {
        // Different actions could be performed on the same
        // variant with and without the context
        (Some(ctx),MyError::Underflow) => {...},
        (None,MyError::Underflow) => {...},
        // The context could be ignored
        (_,MyError::Overflow) => {...},
        // The wildcard pattern is required
        _ => {...},
    }
}

依赖关系

~0.4–0.8MB
~20K SLoC