4 个版本
0.2.2 | 2024 年 5 月 18 日 |
---|---|
0.2.1 | 2024 年 5 月 18 日 |
0.2.0 | 2024 年 5 月 11 日 |
0.1.0 | 2024 年 5 月 11 日 |
#706 在 Rust 模式
每月 32 次下载
25KB
317 行
typederror
anyhow 的包装器,但具有“主要”错误类型。
动机
此库旨在成为 anyhow
和 thiserror
之间的粘合剂。它允许你为调用者应匹配的变体定义主要错误类型,同时仍然捕获途中可能发生的任何其他错误。
记录函数的错误类型
如果你简单地返回一个 anyhow::Error
,调用者不知道期望哪种错误。他们需要阅读你的代码来确定可能出现的错误类型。
通过使用 TError
,你可以指定调用者应匹配的主要错误类型。这有助于记录函数的主要错误类型。
fn my_fallible_function() -> typederror::Result<(), MyError> {
// Do something that might fail.
let s = std::fs::read_to_string("file.txt").map_err(|e| MyError::IoError(e))?;
// NOTE: if `MyError` implements `From<std::io::Error>`,
// you can do `std::fs::read_to_string("file.txt").terror()?` instead.
some_operation(s)?; // An error we don't need to match on.
Ok(())
}
主要错误类型可以是派生自 thiserror::Error
的枚举,其中只有有意义的错误被枚举捕获,而其他错误则被底层的 anyhow::Error
捕获。
你还可以实现 DefaultError
,以便将所有其他错误捕获在主要错误类型的特殊“通配符”变体中。
#[derive(Debug, thiserror::Error)]
enum MyError {
#[error("IO error: {0}")]
IoError(#[from] std::io::Error),
#[error("{0}")]
Misc(typederror::anyhow::Error)
}
impl DefaultError for MyError {
fn from_anyhow(err: typederror::anyhow::Error) -> Self {
Self::Misc(err)
}
}
向下转换为主要错误类型
由于 TError
已经知道主要错误类型,它可以提供向下转换为该类型的便利方法。这使得你可以更轻松地处理单一种类的错误,而无需在多个不同的错误类型上进行匹配。
if let Err(err) = my_fallible_function() { // returns Result<T, TError<MyError>>
match err.get() {
MyError::IoError(e) => { // e is of type `std::io::Error`
// Handle the error.
}
MyError::Misc(e) => { // e is of type `anyhow::Error`
// Handle the error.
}
}
}
如果需要,你还可以向下转换为其他类型,就像使用 anyhow
一样。
match err.downcast_ref::<serde::Error>() {
Ok(e) => {
// Handle serde error.
}
Err(e) => {
// Handle other error.
}
}
从简单开始,然后添加错误变体
为了帮助你开始,你可以使用 TError<()>
作为主要错误类型。或者使用 typederror::Result<T>
作为函数的返回类型。这将有效地与 anyhow
一样工作,让你可以在编写代码时不必担心错误类型。
fn do_something() -> typederror::Result<()> {
// Do something.
my_fallible_function()?;
Ok(())
}
稍后,当您想为函数创建特定的变体以便调用者更容易匹配时,您可以创建一个枚举,派生自thiserror::Error
,并使用它作为主要错误类型。您需要添加任何必要的转换,但只需添加您想要匹配的变体。
所有其他错误将按照anyhow
的行为捕获,或者它们可以通过在枚举上实现DefaultError
特质来捕获到枚举的特殊“通配符”变体。
注意事项
遗憾的是,?
运算符不能自动将错误类型转换为您的首选错误类型。
例如
#[derive(Debug, thiserror::Error)]
enum MyError {
#[error("IO error: {0}")]
IoError(#[from] std::io::Error),
#[error("{0}")]
Misc(anyhow::Error)
}
impl DefaultError for MyError {
fn from_anyhow(err: anyhow::Error) -> Self {
Self::Misc(err)
}
}
fn my_fallible_function() -> typederror::Result<(), MyError> {
let s = std::fs::read_to_string("file.txt")?;
// Do something else with s.
Ok(())
}
fn main() {
if let Err(e) = my_fallible_function() {
match e.get() {
// ...
}
}
}
在上面的示例中,?
运算符不会自动将std::io::Error
转换为MyError::IoError
,就像您直接使用MyError
作为错误类型时那样。错误将匹配为MyError::Misc
,在调用e.get()
时。
为了正确捕获IoError
,将函数的第一行改为
let s = std::fs::read_to_string("file.txt").terror()?;
最低支持的 Rust 版本
thirtyfour
的最低支持 Rust 版本目前是1.75,并将根据依赖项的需要进行更新。
许可证
根据您的选择,在Apache许可证版本2.0或MIT许可证下授权。除非您明确声明,否则任何贡献,根据Apache-2.0许可证定义,提交给此crate的,都应如上所述双许可,没有任何附加条款或条件。
`SPDX-License-Identifier: MIT OR Apache-2.0`
依赖项
~130KB