17 个稳定版本
1.9.2 | 2021 年 4 月 11 日 |
---|---|
1.9.1 | 2021 年 4 月 8 日 |
1.8.0 | 2020 年 9 月 15 日 |
1.7.1 | 2019 年 7 月 30 日 |
1.3.0 | 2018 年 11 月 18 日 |
#308 in Rust 模式
10,486 每月下载次数
在 90 个 crate (69 个直接使用) 中使用
41KB
761 行
Rust 自定义错误
这个包包含一个宏,可以让你更容易地定义自定义错误,而无需编写大量样板代码。
这个包中包含的 custom_error!
宏接受一个类型名和一系列可能的错误,并为所有情况生成一个 Rust 枚举,同时生成实现 std::error::Error
和 std::fmt::Display
的所需 impl
块。
如果你只有一个错误情况,你也可以生成一个结构体而不是枚举。
现在你可以这样写
extern crate custom_error;
use custom_error::custom_error;
// Note the use of braces rather than parentheses.
custom_error!{MyError
Unknown{code:u8} = "unknown error with code {code}.",
Err41 = "Sit by a lake"
}
而不是
#[derive(Debug)]
enum MyError {
Unknown { code: u8 },
Err41,
}
impl std::error::Error for MyError {}
impl std::fmt::Display for MyError {
fn fmt(&self, f: &mut std::fmt::Formatter)
-> std::fmt::Result {
match self {
MyError::Unknown { code } => write!(f, "unknown error with code {}." , code),
MyError::Err41 => write!(f, "Sit by a lake")
}
}
}
如果你只有一个错误情况,你也可以生成一个结构体
extern crate custom_error;
use custom_error::custom_error;
custom_error!{MyError{code:u8} = "error with code {code}."}
简单错误
要定义简单错误,你只需要指出以下三件事
- 你自定义错误类型的名称,
- 不同错误情况的名称,
- 每个情况的文本描述。
extern crate custom_error;
use custom_error::custom_error;
custom_error!{MyError
Bad = "Something bad happened",
Terrible = "This is a very serious error!!!"
}
带参数的自定义错误
你可以在错误中存储数据。为了做到这一点,请在错误类型后面的大括号内指定要存储的字段的名称和类型。
extern crate custom_error;
use custom_error::custom_error;
custom_error!{SantaError
BadChild{name:String, foolishness:u8} = "{name} has been bad {foolishness} times this year",
TooFar = "The location you indicated is too far from the north pole",
InvalidReindeer{legs:u8} = "The reindeer has {legs} legs"
}
assert_eq!(
"Thomas has been bad 108 times this year",
SantaError::BadChild{name: "Thomas".into(), foolishness: 108}.to_string());
错误消息可以使用大括号({parameter_name}
)引用你的参数。如果你需要一些自定义逻辑来显示你的参数,你可以使用 高级自定义错误消息。
包装其他错误类型
如果你的错误原因是另一个较低级别的错误,你可以在你的一个错误情况中添加一个特殊的 source
字段来表示这一点。
因此,你可以让你的自定义错误包装其他错误类型,并且从这些外部错误类型到自定义错误类型的转换将自动实现。
#[macro_use] extern crate custom_error;
use std::{io, io::Read, fs::File, result::Result, num::ParseIntError};
custom_error! {FileParseError
Io{source: io::Error} = "unable to read from the file",
Format{source: ParseIntError} = "the file does not contain a valid integer",
TooLarge{value:u8} = "the number in the file ({value}) is too large"
}
fn parse_hex_file(filename: &str) -> Result<u8, FileParseError> {
let mut contents = String::new();
// The '?' notation can convert from generic errors to our custom error type
File::open(filename)?.read_to_string(&mut contents)?;
let value = u8::from_str_radix(&contents, 16)?;
if value > 42 {
Err(FileParseError::TooLarge { value })
} else {
Ok(value)
}
}
fn main() {
let parse_result = parse_hex_file("/i'm not a file/");
assert_eq!("unable to read from the file", parse_result.unwrap_err().to_string());
}
可见性
你可以在声明开头添加 pub
关键字来使错误类型公开。
custom_error!{pub MyError A="error a", B="error b"}
属性
您可以通过在宏调用开头添加属性来为错误类型推导属性。
custom_error!{#[derive(PartialEq,PartialOrd)] MyError A="error a", B="error b"}
assert!(MyError::A < MyError::B);
由于文档注释只是对#[doc = "..."]
的语法糖,因此您也可以使用它们。
custom_error!{
/// This is the documentation for my error type
pub MyError A="error a", B="error b"
}
高级自定义错误消息
如果您想使用无法用简单格式化字符串表达的错误消息,您可以使用自定义代码生成错误消息。
在以下示例中,我们使用此功能根据底层IO错误的起因显示不同的错误消息。
custom_error!{ pub MyError
Io{source: Error} = @{
match source.kind() {
NotFound => "The file does not exist",
TimedOut => "The operation timed out",
_ => "unknown error",
}
},
Unknown = "unknown error"
}
nostd
此crate支持no-std
:它可以在不使用rust标准库的情况下构建。要使用no-std版本,请在您的Cargo.toml
中禁用此crate的std功能。
[dependencies]
custom_error = { version = "1", default-features = false } # nostd compatible
unstable
还有一个名为unstable
的功能,它在no-std中实现了对AllocError
和TryReserveError
的nostd错误特质的实现。
最低支持的Rust版本
此crate与Rust >= 1.36兼容并经过测试