21 个版本

0.0.21 2024 年 7 月 20 日
0.0.17 2024 年 6 月 29 日
0.0.13 2024 年 3 月 23 日
0.0.4 2023 年 12 月 30 日
0.0.1 2023 年 10 月 27 日

441Rust 模式

Download history 125/week @ 2024-04-21 19/week @ 2024-04-28 1/week @ 2024-05-05 118/week @ 2024-05-12 80/week @ 2024-05-19 6/week @ 2024-05-26 3/week @ 2024-06-02 1/week @ 2024-06-09 126/week @ 2024-06-16 146/week @ 2024-06-23 149/week @ 2024-06-30 28/week @ 2024-07-07 308/week @ 2024-07-14 59/week @ 2024-07-21 42/week @ 2024-07-28

每月 461 次下载
2 个 crate 中使用(通过 tighterror-build

MIT/Apache

61KB
86

tighterror - 紧凑的错误类型 + 代码生成

crates.io docs.rs

tighterror 是一个用于 Rust 中错误表示的简约框架。

它深受标准 std::io::Error 的启发,该标准使用单个 Rust 类型表示一组错误。这一概念进一步发展,使得一个 tighterror 可以在单个 Rust 类型中表示多个错误组。

目标

tighterror 努力实现以下目标

  1. 在保持支持惯用错误报告的同时,最小化错误类型的大小。
  2. 最小化错误路径上的运行时开销。默认情况下,不进行动态内存分配。
  3. 最小化匹配一组错误的运行时开销。
  4. 最小化编码工作量
    • 使用标记语言定义错误,并自动生成 Rust 模板代码
    • 优化的错误报告

特性

  • YAML 规范
  • TOML 规范
  • 分类
    • 隐式
    • 扁平类型
  • 模块
    • 隐式
    • 单独的文件
  • 错误类型变体
  • 分类错误类型
  • 标志
  • 位置
  • 回溯

介绍

tighterror 采用声明式方法,其中用户项目在其用标记语言(YAML 或 TOML)编写的规范文件中维护其错误集合。从规范文件生成 Rust 源代码是通过框架提供的专用工具完成的。

在基本形式下,tighterror 是围绕一个小型无符号整数的一个 newtype,例如 u8,其值是错误的一个唯一标识符,即 错误类型

#[repr(transparent)]
pub struct ErrorKind(u8);

#[repr(transparent)]
pub struct Error(ErrorKind);  // <-- the type to use in Result<T, E>

错误类型 通过两个部分按位构建:错误分类错误变体错误分类 逻辑地分组几个错误,并允许通过单个匹配臂处理整个组。 错误变体 是错误在其 分类 中的唯一标识符。 分类变体 一起构成了给定 tighterror 实例化中错误的唯一标识符。

以下图例展示了错误类型的示例布局。此布局可以表示最多4个类别,每个类别最多32个错误。

            ┌───┬───┬───┬───┬───┬───┬───┬───┐                      
            │   │   │   │   │   │   │   │   │ (0-4) 5 variant bits 
          u8│ 7 │ 6 │ 5 │ 4 │ 3 │ 2 │ 1 │ 0 │ (5-6) 2 category bits
            │   │   │   │   │   │   │   │   │ (7-7) 1 reserved bit 
            └───┼───┴───┼───┴───┴───┴───┴───┤                      
                │  cat  │      variant      │                      

默认情况下,tighterror会选择最小的底层类型,该类型足以容纳在规范文件中定义的类别和错误数量。支持的底层类型有u8u16u32u64

示例

以下是一个适合不需要文档的项目的基础示例。更多配置选项请参阅crate 文档

在您项目的根目录中的tighterror.yaml文件中定义错误

---
errors:
  - BAD_ARG
  - BAD_FILE_PATH

[!NOTE] 上面的示例只定义了错误列表,没有指定任何类别。在这种情况下,tighterror将创建一个隐式的General类别。

当只有一个类别时,类别位数为0。

tighterror添加到您的Cargo.toml文件

cargo add tighterror

安装cargo插件

cargo install cargo-tighterror

运行插件以在src/errors.rs中生成Rust模块

cargo tighterror -o src/errors.rs

将生成的模块包含到您的项目中,就像任何其他手动编写的Rust模块一样,例如mod errors;

[!NOTE] 建议将tighterror.yamlsrc/errors.rs都放入源代码管理中,以便于可见性和变更跟踪。

以下是对生成的模块的简化视图

#[repr(transparent)]
pub struct ErrorCategory(u8);

#[repr(transparent)]
pub struct ErrorKind(u8);

#[repr(transparent)]
pub struct Error(ErrorKind);

impl tighterror::Category for ErrorCategory { ... }
impl tighterror::Kind for ErrorKind { ... }
impl tighterror::Error for Error { ... }

pub mod categories {
   use super::ErrorCategory;
   pub const GENERAL: ErrorCategory = ErrorCategory::new(0);
}

pub mod kinds {
   use super::categories::*;
   use super::ErrorKind;
   pub const BAD_ARG: ErrorKind = ErrorKind::new(GENERAL, 0);
   pub const BAD_FILE_PATH: ErrorKind = ErrorKind::new(GENERAL, 1);
}

Error是用于Result<T, E>的类型。它可以如下创建

let e = Error::from(BAD_ARG);
let e: Error = BAD_ARG.into();

// ErrorKind is convertible to Result<T, Error>
fn foo() -> Result<(), Error> {
  BAD_FILE_PATH.into()
}
assert!(foo().is_err_and(|e| e.kind() == BAD_FILE_PATH));

文档

完整文档在docs.rs上。

许可证

根据您的选择,许可协议为

贡献

除非您明确表示,否则根据Apache-2.0许可证定义,您有意提交以包含在工作中的任何贡献,将根据上述方式双许可,不附加任何其他条款或条件。

标签

error kind minimal error reporting lean error handling error-kind error-code code

无运行时依赖