@@ -17,7 +17,6 @@ use core::num::NonZeroU32;
1717/// In order to be compatible with `std` and `no_std`, this type has two
1818/// possible implementations: with `std` a boxed `Error` trait object is stored,
1919/// while with `no_std` we merely store an error code.
20- #[ derive( Debug ) ]
2120pub struct Error {
2221 #[ cfg( feature="std" ) ]
2322 inner : Box < dyn std:: error:: Error + Send + Sync + ' static > ,
@@ -32,6 +31,7 @@ impl Error {
3231 ///
3332 /// See also `From<NonZeroU32>`, which is available with and without `std`.
3433 #[ cfg( feature="std" ) ]
34+ #[ inline]
3535 pub fn new < E > ( err : E ) -> Self
3636 where E : Into < Box < dyn std:: error:: Error + Send + Sync + ' static > >
3737 {
@@ -43,6 +43,7 @@ impl Error {
4343 /// When configured with `std`, this is a trivial operation and never
4444 /// panics. Without `std`, this method is simply unavailable.
4545 #[ cfg( feature="std" ) ]
46+ #[ inline]
4647 pub fn inner ( & self ) -> & ( dyn std:: error:: Error + Send + Sync + ' static ) {
4748 & * self . inner
4849 }
@@ -52,15 +53,45 @@ impl Error {
5253 /// When configured with `std`, this is a trivial operation and never
5354 /// panics. Without `std`, this method is simply unavailable.
5455 #[ cfg( feature="std" ) ]
56+ #[ inline]
5557 pub fn take_inner ( self ) -> Box < dyn std:: error:: Error + Send + Sync + ' static > {
5658 self . inner
5759 }
5860
61+ /// Codes below this point represent OS Errors (i.e. positive i32 values).
62+ /// Codes at or above this point, but below [`Error::CUSTOM_START`] are
63+ /// reserved for use by the `rand` and `getrandom` crates.
64+ pub const INTERNAL_START : u32 = 1 << 31 ;
65+
66+ /// Codes at or above this point can be used by users to define their own
67+ /// custom errors.
68+ pub const CUSTOM_START : u32 = ( 1 << 31 ) + ( 1 << 30 ) ;
69+
70+ /// Extract the raw OS error code (if this error came from the OS)
71+ ///
72+ /// This method is identical to `std::io::Error::raw_os_error()`, except
73+ /// that it works in `no_std` contexts. If this method returns `None`, the
74+ /// error value can still be formatted via the `Diplay` implementation.
75+ #[ inline]
76+ pub fn raw_os_error ( & self ) -> Option < i32 > {
77+ #[ cfg( feature="std" ) ] {
78+ if let Some ( e) = self . inner . downcast_ref :: < std:: io:: Error > ( ) {
79+ return e. raw_os_error ( ) ;
80+ }
81+ }
82+ match self . code ( ) {
83+ Some ( code) if u32:: from ( code) < Self :: INTERNAL_START =>
84+ Some ( u32:: from ( code) as i32 ) ,
85+ _ => None ,
86+ }
87+ }
88+
5989 /// Retrieve the error code, if any.
6090 ///
6191 /// If this `Error` was constructed via `From<NonZeroU32>`, then this method
6292 /// will return this `NonZeroU32` code (for `no_std` this is always the
6393 /// case). Otherwise, this method will return `None`.
94+ #[ inline]
6495 pub fn code ( & self ) -> Option < NonZeroU32 > {
6596 #[ cfg( feature="std" ) ] {
6697 self . inner . downcast_ref :: < ErrorCode > ( ) . map ( |c| c. 0 )
@@ -71,18 +102,36 @@ impl Error {
71102 }
72103}
73104
105+ impl fmt:: Debug for Error {
106+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
107+ #[ cfg( feature="std" ) ] {
108+ write ! ( f, "Error {{ inner: {:?} }}" , self . inner)
109+ }
110+ #[ cfg( all( feature="getrandom" , not( feature="std" ) ) ) ] {
111+ getrandom:: Error :: from ( self . code ) . fmt ( f)
112+ }
113+ #[ cfg( not( feature="getrandom" ) ) ] {
114+ write ! ( f, "Error {{ code: {} }}" , self . code)
115+ }
116+ }
117+ }
118+
74119impl fmt:: Display for Error {
75120 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
76121 #[ cfg( feature="std" ) ] {
77122 write ! ( f, "{}" , self . inner)
78123 }
79- #[ cfg( not( feature="std" ) ) ] {
124+ #[ cfg( all( feature="getrandom" , not( feature="std" ) ) ) ] {
125+ getrandom:: Error :: from ( self . code ) . fmt ( f)
126+ }
127+ #[ cfg( not( feature="getrandom" ) ) ] {
80128 write ! ( f, "error code {}" , self . code)
81129 }
82130 }
83131}
84132
85133impl From < NonZeroU32 > for Error {
134+ #[ inline]
86135 fn from ( code : NonZeroU32 ) -> Self {
87136 #[ cfg( feature="std" ) ] {
88137 Error { inner : Box :: new ( ErrorCode ( code) ) }
@@ -95,6 +144,7 @@ impl From<NonZeroU32> for Error {
95144
96145#[ cfg( feature="getrandom" ) ]
97146impl From < getrandom:: Error > for Error {
147+ #[ inline]
98148 fn from ( error : getrandom:: Error ) -> Self {
99149 #[ cfg( feature="std" ) ] {
100150 Error { inner : Box :: new ( error) }
@@ -107,15 +157,21 @@ impl From<getrandom::Error> for Error {
107157
108158#[ cfg( feature="std" ) ]
109159impl std:: error:: Error for Error {
160+ #[ inline]
110161 fn source ( & self ) -> Option < & ( dyn std:: error:: Error + ' static ) > {
111162 self . inner . source ( )
112163 }
113164}
114165
115166#[ cfg( feature="std" ) ]
116167impl From < Error > for std:: io:: Error {
168+ #[ inline]
117169 fn from ( error : Error ) -> Self {
118- std:: io:: Error :: new ( std:: io:: ErrorKind :: Other , error)
170+ if let Some ( code) = error. raw_os_error ( ) {
171+ std:: io:: Error :: from_raw_os_error ( code)
172+ } else {
173+ std:: io:: Error :: new ( std:: io:: ErrorKind :: Other , error)
174+ }
119175 }
120176}
121177
0 commit comments