
下面是std::io::Error的样子:
pub struct Error {
repr: Repr,
}
enum Repr {
Os(i32),
Simple(ErrorKind),
Custom(Box),
}
struct Custom {
kind: ErrorKind,
error: Box,
}
首先需要注意的是,它是一个内部的枚举,但这是一个隐藏得很好的实现细节。为了能够检查和处理各种错误情况,这里有一个单独的公开的无字段的 kind 枚举。
#[derive(Clone, Copy)]
#[non_exhaustive]
pub enum ErrorKind {
NotFound,
PermissionDenied,
Interrupted,
...
Other,
}
impl Error {
pub fn kind(&self) -> ErrorKind {
match &self.repr {
Repr::Os(code) => sys::decode_error_kind(*code),
Repr::Custom(c) => c.kind,
Repr::Simple(kind) => *kind,
}
}
}
尽管ErrorKind和Repr都是枚举,公开暴露的ErrorKind就那么恐怖了。 另一点需要注意的是#[non_exhaustive]的可拷贝的无字段枚举的设计——-没有合理的替代方案或兼容性问题。
一些io::Errors只是原生的 OS 错误代码:
impl Error {
pub fn from_raw_os_error(code: i32) -> Error {
Error { repr: Repr::Os(code) }
}
pub fn raw_os_error(&self) -> Option {
match self.repr {
Repr::Os(i) => Some(i),
Repr::Custom(..) => None,
Repr::Sim