@@ -17,7 +17,6 @@ use core::num::NonZeroU32;
17
17
/// In order to be compatible with `std` and `no_std`, this type has two
18
18
/// possible implementations: with `std` a boxed `Error` trait object is stored,
19
19
/// while with `no_std` we merely store an error code.
20
- #[ derive( Debug ) ]
21
20
pub struct Error {
22
21
#[ cfg( feature="std" ) ]
23
22
inner : Box < dyn std:: error:: Error + Send + Sync + ' static > ,
@@ -32,6 +31,7 @@ impl Error {
32
31
///
33
32
/// See also `From<NonZeroU32>`, which is available with and without `std`.
34
33
#[ cfg( feature="std" ) ]
34
+ #[ inline]
35
35
pub fn new < E > ( err : E ) -> Self
36
36
where E : Into < Box < dyn std:: error:: Error + Send + Sync + ' static > >
37
37
{
@@ -43,6 +43,7 @@ impl Error {
43
43
/// When configured with `std`, this is a trivial operation and never
44
44
/// panics. Without `std`, this method is simply unavailable.
45
45
#[ cfg( feature="std" ) ]
46
+ #[ inline]
46
47
pub fn inner ( & self ) -> & ( dyn std:: error:: Error + Send + Sync + ' static ) {
47
48
& * self . inner
48
49
}
@@ -52,15 +53,45 @@ impl Error {
52
53
/// When configured with `std`, this is a trivial operation and never
53
54
/// panics. Without `std`, this method is simply unavailable.
54
55
#[ cfg( feature="std" ) ]
56
+ #[ inline]
55
57
pub fn take_inner ( self ) -> Box < dyn std:: error:: Error + Send + Sync + ' static > {
56
58
self . inner
57
59
}
58
60
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
+
59
89
/// Retrieve the error code, if any.
60
90
///
61
91
/// If this `Error` was constructed via `From<NonZeroU32>`, then this method
62
92
/// will return this `NonZeroU32` code (for `no_std` this is always the
63
93
/// case). Otherwise, this method will return `None`.
94
+ #[ inline]
64
95
pub fn code ( & self ) -> Option < NonZeroU32 > {
65
96
#[ cfg( feature="std" ) ] {
66
97
self . inner . downcast_ref :: < ErrorCode > ( ) . map ( |c| c. 0 )
@@ -71,18 +102,36 @@ impl Error {
71
102
}
72
103
}
73
104
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
+
74
119
impl fmt:: Display for Error {
75
120
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
76
121
#[ cfg( feature="std" ) ] {
77
122
write ! ( f, "{}" , self . inner)
78
123
}
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" ) ) ] {
80
128
write ! ( f, "error code {}" , self . code)
81
129
}
82
130
}
83
131
}
84
132
85
133
impl From < NonZeroU32 > for Error {
134
+ #[ inline]
86
135
fn from ( code : NonZeroU32 ) -> Self {
87
136
#[ cfg( feature="std" ) ] {
88
137
Error { inner : Box :: new ( ErrorCode ( code) ) }
@@ -95,6 +144,7 @@ impl From<NonZeroU32> for Error {
95
144
96
145
#[ cfg( feature="getrandom" ) ]
97
146
impl From < getrandom:: Error > for Error {
147
+ #[ inline]
98
148
fn from ( error : getrandom:: Error ) -> Self {
99
149
#[ cfg( feature="std" ) ] {
100
150
Error { inner : Box :: new ( error) }
@@ -107,15 +157,21 @@ impl From<getrandom::Error> for Error {
107
157
108
158
#[ cfg( feature="std" ) ]
109
159
impl std:: error:: Error for Error {
160
+ #[ inline]
110
161
fn source ( & self ) -> Option < & ( dyn std:: error:: Error + ' static ) > {
111
162
self . inner . source ( )
112
163
}
113
164
}
114
165
115
166
#[ cfg( feature="std" ) ]
116
167
impl From < Error > for std:: io:: Error {
168
+ #[ inline]
117
169
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
+ }
119
175
}
120
176
}
121
177
0 commit comments