2个稳定版本
1.2.1 | 2022年1月13日 |
---|
#1345 在 过程宏
79KB
1.5K SLoC
error_generator
一个用于生成Rust中完全限定错误所需样板代码的crate。
动机
想象一个复杂的方法,有多个可能的失败,比如解析外部资源。你需要
- 从外部服务器接收资源
- 将资源解析为领域对象
- 读取必要的值并检查其有效性
对这个任务的典型方法是为每个操作创建一个错误,如下所示
struct NetworkError { pub response_code: usize }
struct ParseError { pub line: usize }
struct InvalidValueError(pub f32)
为复杂操作创建错误,创建一个枚举,其变体包含单个错误值,如下所示
enum ComplexError {
Network(NetworkError),
Parsing(ParseError),
InvalidValue(InvalidValueError)
}
最终方法看起来像这样
fn complex_function() -> Result<f32, ComplexError> {
let file = receive_file()?; // maybe a NetworkError
let the_object = parse_file(file)?; // maybe a ParseError
let value = check_and_get_value(the_object)?; // maybe an InvalidValueError
value
}
问题:如果我们想有一个完全限定的错误,我们所有的错误都应该实现std::error::Error trait,这反过来又要求std::fmt::Debug和std::fmt::Display。'Debug'可以推导,但'Error'和'Display'必须手动实现。此外,要使用上面的问号运算符,我们需要为'ComplexError'实现三个额外的std::convert::From实现。
总共需要11个额外的impl-blocks(4 Error,4 Display,3 From)来模拟这个(仍然相当简单)示例。对于这个问题有解决方案,比如'quick_error' crate,但我想要一种更优雅的方式来生成这种样板代码。因为我习惯了像lombok这样的代码生成库,所以我想要创建一些类似的东西,结果就是'error'属性。
用法
关于如何使用此属性的一般说明已记录在属性本身中。现在,我只展示如何在前面示例中使用它。
要像下面那样使用我们的'complex_method',添加'error'属性如下
#[error(message = "The external server returned code {self.response_code} instead of 200.")]
struct NetworkError { pub response_code: usize }
#[error(message = "Syntax error in line {self.line}.")]
struct ParseError { pub line: usize }
#[error(message = "Invalid value, expected '42' but got {self.0}.")]
struct InvalidValueError(pub f32)
#[error(impl_from)]
enum ComplexError {
#[error(message = "Error while receiving the external file: {_0}")]
Network(NetworkError),
#[error(message = "Error while parsing the file: {_0}")]
Parsing(ParseError),
#[error(message = "Error while retreiving the value: {_0}")]
InvalidValue(InvalidValueError)
}
fn complex_function() -> Result<f32, ComplexError> {
let file = receive_file()?;
let the_object = parse_file(file)?;
let value = check_and_get_value(the_object)?;
value
}
这将使用更少的代码创建任何所需实现(Error,Display,From)。
缺点
- 缺乏IDE对这些类型宏的支持。IDE会警告你关于即将到来的编译器错误,有关未实现的特征。
未来计划
- 能够禁用"derive(Debug)"属性,如果您想手动实现Debug
依赖关系
~1.5MB
~36K SLoC