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 日 |
441 在 Rust 模式 中
每月 461 次下载
在 2 个 crate 中使用(通过 tighterror-build)
61KB
86 行
tighterror - 紧凑的错误类型 + 代码生成
tighterror 是一个用于 Rust 中错误表示的简约框架。
它深受标准 std::io::Error
的启发,该标准使用单个 Rust 类型表示一组错误。这一概念进一步发展,使得一个 tighterror 可以在单个 Rust 类型中表示多个错误组。
目标
tighterror 努力实现以下目标
- 在保持支持惯用错误报告的同时,最小化错误类型的大小。
- 最小化错误路径上的运行时开销。默认情况下,不进行动态内存分配。
- 最小化匹配一组错误的运行时开销。
- 最小化编码工作量
- 使用标记语言定义错误,并自动生成 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会选择最小的底层类型,该类型足以容纳在规范文件中定义的类别和错误数量。支持的底层类型有u8
、u16
、u32
和u64
。
示例
以下是一个适合不需要文档的项目的基础示例。更多配置选项请参阅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.yaml
和src/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 License,版本2.0(LICENSE-APACHE或http://www.apache.org/licenses/LICENSE-2.0)
- MIT许可证(LICENSE-MIT或http://opensource.org/licenses/MIT)
。
贡献
除非您明确表示,否则根据Apache-2.0许可证定义,您有意提交以包含在工作中的任何贡献,将根据上述方式双许可,不附加任何其他条款或条件。
标签
error
kind
minimal
error reporting
lean
error handling
error-kind
error-code
code