
特定平台的sys::decode_error_kind函数负责把错误代码映射到ErrorKind枚举。所有的这些都意味着代码可以通过检查.kind()以跨平台方式来对错误类别进行处理一个std::io::Error还可以从一个ErrorKind构建:impl From for Error { fn from(kind: ErrorKind) -> Error { Error { repr: Repr::Simple(kind) } }}这提供了一种跨平台访问错误码风格的错误处理。如果你需要最快的错误处理,这很方便。最后,还有第三种,完全自定义的表示:impl Error { pub fn new(kind: ErrorKind, error: E) -> Error where E: Into>, { Self::_new(kind, error.into()) } fn _new( kind: ErrorKind, error: Box, ) -> Error { Error { repr: Repr::Custom(Box::new(Custom { kind, error })), } } pub fn get_ref( &self, ) -> Option<&(dyn error::Error + Send + Sync + 'static)> { match &self.repr { Repr::Os(..) => None, Repr::Simple(..) => None, Repr::Custom(c) => Some(&*c.error), } } pub fn into_inner( self, ) -> Option> { match self.repr { Repr::Os(..) => None, Repr::Simple(..) => None, Repr::Custom(c) => Some(c.error), } }}需要注意的是:通用的new函数委托给单态的_new函数,这改善了编译时间,因为在单态化的过程中需要重复的代码更少了。我认为这对运行时效率也有改善:_new函数没有标记为内联(inline),所以函数调用会在调用点生成。这是好事,因为错误构造比较冷门,节省指令缓存更受欢迎。Custom变量是 boxed——这样是为了保持整体的size_of更小。错误的栈上大小是重要的:即使没有错误也要承担开销。这两种类型都指向一个'static'错误:type A = &(dyn error::Error + Send + Sync + 'static);type B = Box在一个 dyn Trait + '_ 中,'_ 是'static 的省略, 除非 trait 对象藏于一个引用背后,这种情况下,会被缩写为 &'a dyn Trait + 'a。get_ref, get_mut 以及into_inner提供了对底层错误的完整访问。与os_error相似,抽象模糊了细节,但也提供了钩子获取原本的底层数据。类似的,Display的实现也揭示了关于内部表示的最重要的细节。impl fmt::Display for Error { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { match &self.repr { Repr::Os(code) => { let detail = sys::os::error_string(*code); write!(fmt, "{} (os error {})", detail, code) } Repr::Simple(kind) => write!(fmt, "{}", kind.as_str()), Repr::Custom(c) => c.error.fmt(fmt), } }}