#error #termination #derive-error #error-handling #derive #debugging

thistermination

受thiserror启发的库,用于为错误枚举添加Termination特质。

2个稳定版本

1.1.0 2023年10月8日
1.0.0 2023年10月5日

2219Rust模式

每月下载量21次

MIT许可证

40KB
492

thistermination

thistermination是一个受thiserror启发的库,用于为错误枚举添加std::process::Termination特质。

[dependencies]
thistermination = "1.0"

编译器支持:需要rustc 1.56+

为什么实现Termination特质?

实现std::process::Terminationstd::fmt::Debug特质的结构体或枚举可以被main函数返回,允许开发者打印程序退出的消息并设置退出码。

用法

要将std::process::Termination特质添加到枚举中,可以使用以下三个可能的derive宏之一:

  • #[derive(Termination)]:旨在与thiserror结合使用,此宏实现了std::process::Terminationstd::fmt::Debug特质。默认的exit_code为libc::EXIT_FAILURE,除非显式使用exit_codemsg设置,否则Debug消息与Display消息相同。

    use thistermination::{Termination};
    use thiserror::Error;
    
    #[derive(Error, Termination)]
    pub enum RequestError {
        #[error("request failed {0:?}")]
        RequestFailed(#[from] reqwest::Error),
        #[termination(msg("exiting wrong api key"))]
        #[error("wrong api key")]
        WrongAPIKey,
        #[termination(exit_code(3))]
        #[error("failed with status {0}")]
        RequestStatusError(u16),
        #[termination(exit_code(4), msg("exiting failed to load image {error:?}"))]
        #[error("failed to load image {error:?}")]
        ImageLoadError{#[from] error: image::ImageError},
    }
    
    fn main() -> Result<(), RequestError> {
        Err(RequestError::WrongAPIKey)
    }
    
  • #[derive(TerminationFull)]:此宏旨在不产生错误的情况下使用,实现了以下特质:std::process::Terminationstd::fmt::Debugstd::fmt::Displaystd::error::Error。默认的exit_codelibc::EXIT_FAILURE,而msg是必需的,并用于Display和Debug。

    use thistermination::{TerminationFull};
    
    #[derive(TerminationFull)]
    pub enum RequestError {
        #[termination(exit_code(1), msg("request failed {0:?}"))]
        RequestFailed(#[from] reqwest::Error),
        #[termination(exit_code(2), msg("wrong api key"))]
        WrongAPIKey,
        #[termination(exit_code(3), msg("failed with status {0}"))]
        RequestStatusError(u16),
        #[termination(exit_code(4), msg("failed to load image {error:?}"))]
        ImageLoadError{#[from] error: image::ImageError},
    }
    
    fn main() -> Result<(), RequestError> {
        Err(RequestError::WrongAPIKey)
    }
    
  • #[derive(TerminationNoDebug)]:是最基本的变体,仅实现了std::process::Termination特质。如果没有提供exit_code,则默认为libc::EXIT_FAILURE。然而,对于枚举类型在main函数中返回,需要实现std::fmt::Debug特质,这必须手动实现或使用Debug宏。

    use thistermination::{TerminationNoDebug};
    
    #[derive(TerminationNoDebug, Debug)]
    pub enum RequestError {
        #[termination(exit_code(1))]
        RequestFailed(reqwest::Error),
        WrongAPIKey,
        #[termination(exit_code(3))]
        RequestStatusError(u16),
        ImageLoadError{error: image::ImageError},
    }
    
    fn main() -> Result<(), RequestError> {
        Err(RequestError::WrongAPIKey)
    }
    

详细信息

  • thistermination没有出现在您的公共API中;宏只是实现了各种特质。

  • 这些宏可以为单元枚举、具有命名字段的枚举和枚举元组进行派生。

  • msg支持以格式字符串方式访问枚举的字段

    • #[termination(msg("{var}"))] ⟶ write!("{}", self.var)
    • #[termination(msg("{0}"))] ⟶ write!("{}", self.0)
    • #[termination(msg("{var:?}"))] ⟶ write!("{:?}", self.var)
    • #[termination(msg("{0:?}"))] ⟶ write!("{:?}", self.0)

    您还可以为msg指定额外的格式字符串参数。

    #[derive(TerminationFull)]
    pub enum RequestError {
        #[termination(exit_code(4), msg("failed to load image {0:?}"))]
        ImageLoadError(#[from] image::ImageError),
    }
    
  • 使用#[from]将生成特定变体的std::convert::From实现。带有#[from]的变体不允许包含任何其他字段,并且只能与#[derive(TerminationFull)]一起使用。

    #[derive(TerminationFull)]
    pub enum CLIError {
        #[termination(exit_code(4), msg("Invalid argument {0}, expected < {}", i16::MAX))]
        InvalidArgument(u16),
    }
    
  • 您还可以通过将辅助属性#[termination(...)]添加到枚举本身来更改exit_codemsg的默认值。

    #[derive(Error, Termination)]
    #[termination(exit_code(3), msg("Fatal Error"))]
    pub enum RequestError {
        #[error("request failed {0:?}")]
        RequestFailed(#[from] reqwest::Error),
        #[error("wrong api key")]
        WrongAPIKey,
        #[error("failed with status {0}")]
        RequestStatusError(u16),
        #[termination(exit_code(4), msg("exiting failed to load image {error:?}"))]
        #[error("failed to load image {error:?}")]
        ImageLoadError{#[from] error: image::ImageError},
    }
    

与thiserror的比较

#[derive(TerminationFull)] 可以用来替代 thiserror,因为它提供了许多 thiserror 的基本功能。然而,它缺少一些功能,如 #[source]#[backtrace]、自动检测堆栈跟踪的能力以及 #[error(transparent)]。如果需要这些功能中的任何一个,可以使用 thiserror 与 #[derive(Termination)] 结合使用。

依赖项

~2.4–4MB
~70K SLoC