@@ -13,32 +13,21 @@ use core::num::NonZeroU32;
1313/// The [`Error::raw_os_error()`] will indicate if the error is from the OS, and
1414/// if so, which error code the OS gave the application. If such an error is
1515/// encountered, please consult with your system documentation.
16+ ///
17+ /// Internally this type is a NonZeroU32, with certain values reserved for
18+ /// certain purposes, see [`Error::INTERNAL_START`] and [`Error::CUSTOM_START`].
1619#[ derive( Copy , Clone , Eq , PartialEq ) ]
1720pub struct Error ( NonZeroU32 ) ;
1821
19- // This NonZeroU32 in Error has enough room for two types of errors:
20- // - OS Errors: in range [1, 1 << 31) (i.e. positive i32 values)
21- // - Custom Errors: in range [1 << 31, 1 << 32) (in blocks of 1 << 16)
22- const CUSTOM_START : u32 = 1 << 31 ;
23- const BLOCK_SIZE : u32 = 1 << 16 ;
24-
2522impl Error {
26- /// Create a new error from a raw OS error number (errno).
27- #[ inline]
28- pub fn from_os_error ( errno : i32 ) -> Self {
29- assert ! ( errno > 0 ) ;
30- Self ( NonZeroU32 :: new ( errno as u32 ) . unwrap ( ) )
31- }
23+ /// Codes below this point represent OS Errors (i.e. positive i32 values).
24+ /// Codes at or above this point, but below [`Error::CUSTOM_START`] are
25+ /// reserved for use by the `rand` and `getrandom` crates.
26+ pub const INTERNAL_START : u32 = 1 << 31 ;
3227
33- /// Crate a custom error in the provided block (group of 2^16 error codes).
34- /// The provided block must not be negative, and block 0 is reserved for
35- /// custom errors in the `getrandom` crate.
36- #[ inline]
37- pub fn custom_error ( block : i16 , code : u16 ) -> Self {
38- assert ! ( block >= 0 ) ;
39- let n = CUSTOM_START + ( block as u16 as u32 ) * BLOCK_SIZE + ( code as u32 ) ;
40- Self ( NonZeroU32 :: new ( n) . unwrap ( ) )
41- }
28+ /// Codes at or above this point can be used by users to define their own
29+ /// custom errors.
30+ pub const CUSTOM_START : u32 = ( 1 << 31 ) + ( 1 << 30 ) ;
4231
4332 /// Extract the raw OS error code (if this error came from the OS)
4433 ///
@@ -47,33 +36,21 @@ impl Error {
4736 /// error value can still be formatted via the `Diplay` implementation.
4837 #[ inline]
4938 pub fn raw_os_error ( & self ) -> Option < i32 > {
50- self . try_os_error ( ) . ok ( )
39+ if self . 0 . get ( ) < Self :: INTERNAL_START {
40+ Some ( self . 0 . get ( ) as i32 )
41+ } else {
42+ None
43+ }
5144 }
5245
5346 /// Extract the bare error code.
5447 ///
5548 /// This code can either come from the underlying OS, or be a custom error.
56- /// Use [`raw_os_error()`] to disambiguate.
49+ /// Use [`Error:: raw_os_error()`] to disambiguate.
5750 #[ inline]
5851 pub fn code ( & self ) -> NonZeroU32 {
5952 self . 0
6053 }
61-
62- /// Helper method for creating internal errors
63- #[ allow( dead_code) ]
64- pub ( crate ) fn internal ( code : u16 ) -> Self {
65- Self :: custom_error ( 0 , code)
66- }
67-
68- /// Returns either the OS error or a (block, code) pair
69- fn try_os_error ( & self ) -> Result < i32 , ( i16 , u16 ) > {
70- if self . 0 . get ( ) < CUSTOM_START {
71- Ok ( self . 0 . get ( ) as i32 )
72- } else {
73- let offset = self . 0 . get ( ) - CUSTOM_START ;
74- Err ( ( ( offset / BLOCK_SIZE ) as i16 , ( offset % BLOCK_SIZE ) as u16 ) )
75- }
76- }
7754}
7855
7956#[ cfg( any( unix, target_os = "redox" ) ) ]
@@ -96,44 +73,34 @@ fn os_err_desc(_errno: i32, _buf: &mut [u8]) -> Option<&str> {
9673impl fmt:: Debug for Error {
9774 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
9875 let mut dbg = f. debug_struct ( "Error" ) ;
99- match self . try_os_error ( ) {
100- Ok ( errno) => {
101- dbg. field ( "os_error" , & errno) ;
102- let mut buf = [ 0u8 ; 128 ] ;
103- if let Some ( desc) = os_err_desc ( errno, & mut buf) {
104- dbg. field ( "description" , & desc) ;
105- }
106- }
107- Err ( ( 0 , code) ) => {
108- dbg. field ( "internal_code" , & code) ;
109- if let Some ( desc) = internal_desc ( code) {
110- dbg. field ( "description" , & desc) ;
111- }
112- }
113- Err ( ( block, code) ) => {
114- dbg. field ( "block" , & block) ;
115- dbg. field ( "custom_code" , & code) ;
76+ if let Some ( errno) = self . raw_os_error ( ) {
77+ dbg. field ( "os_error" , & errno) ;
78+ let mut buf = [ 0u8 ; 128 ] ;
79+ if let Some ( desc) = os_err_desc ( errno, & mut buf) {
80+ dbg. field ( "description" , & desc) ;
11681 }
82+ } else if let Some ( desc) = internal_desc ( * self ) {
83+ dbg. field ( "internal_code" , & self . 0 . get ( ) ) ;
84+ dbg. field ( "description" , & desc) ;
85+ } else {
86+ dbg. field ( "unknown_code" , & self . 0 . get ( ) ) ;
11787 }
11888 dbg. finish ( )
11989 }
12090}
12191
12292impl fmt:: Display for Error {
12393 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
124- match self . try_os_error ( ) {
125- Ok ( errno) => {
126- let mut buf = [ 0u8 ; 128 ] ;
127- match os_err_desc ( errno, & mut buf) {
128- Some ( desc) => f. write_str ( desc) ,
129- None => write ! ( f, "OS Error: {}" , errno) ,
130- }
131- }
132- Err ( ( 0 , code) ) => match internal_desc ( code) {
94+ if let Some ( errno) = self . raw_os_error ( ) {
95+ let mut buf = [ 0u8 ; 128 ] ;
96+ match os_err_desc ( errno, & mut buf) {
13397 Some ( desc) => f. write_str ( desc) ,
134- None => write ! ( f, "Internal Error: {}" , code) ,
135- } ,
136- Err ( ( block, code) ) => write ! ( f, "Custom Error: block={}, code={}" , block, code) ,
98+ None => write ! ( f, "OS Error: {}" , errno) ,
99+ }
100+ } else if let Some ( desc) = internal_desc ( * self ) {
101+ f. write_str ( desc)
102+ } else {
103+ write ! ( f, "Unknown Error: {}" , self . 0 . get( ) )
137104 }
138105 }
139106}
@@ -145,19 +112,23 @@ impl From<NonZeroU32> for Error {
145112}
146113
147114/// Internal Error constants
148- pub ( crate ) const UNSUPPORTED : u16 = 0 ;
149- pub ( crate ) const UNKNOWN_IO_ERROR : u16 = 1 ;
150- pub ( crate ) const SEC_RANDOM_FAILED : u16 = 2 ;
151- pub ( crate ) const RTL_GEN_RANDOM_FAILED : u16 = 3 ;
152- pub ( crate ) const FAILED_RDRAND : u16 = 4 ;
153- pub ( crate ) const NO_RDRAND : u16 = 5 ;
154- pub ( crate ) const BINDGEN_CRYPTO_UNDEF : u16 = 6 ;
155- pub ( crate ) const BINDGEN_GRV_UNDEF : u16 = 7 ;
156- pub ( crate ) const STDWEB_NO_RNG : u16 = 8 ;
157- pub ( crate ) const STDWEB_RNG_FAILED : u16 = 9 ;
158-
159- fn internal_desc ( code : u16 ) -> Option < & ' static str > {
160- match code {
115+ pub ( crate ) const UNSUPPORTED : Error = internal_error ( 0 ) ;
116+ pub ( crate ) const UNKNOWN_IO_ERROR : Error = internal_error ( 1 ) ;
117+ pub ( crate ) const SEC_RANDOM_FAILED : Error = internal_error ( 2 ) ;
118+ pub ( crate ) const RTL_GEN_RANDOM_FAILED : Error = internal_error ( 3 ) ;
119+ pub ( crate ) const FAILED_RDRAND : Error = internal_error ( 4 ) ;
120+ pub ( crate ) const NO_RDRAND : Error = internal_error ( 5 ) ;
121+ pub ( crate ) const BINDGEN_CRYPTO_UNDEF : Error = internal_error ( 6 ) ;
122+ pub ( crate ) const BINDGEN_GRV_UNDEF : Error = internal_error ( 7 ) ;
123+ pub ( crate ) const STDWEB_NO_RNG : Error = internal_error ( 8 ) ;
124+ pub ( crate ) const STDWEB_RNG_FAILED : Error = internal_error ( 9 ) ;
125+
126+ const fn internal_error ( n : u16 ) -> Error {
127+ Error ( unsafe { NonZeroU32 :: new_unchecked ( Error :: INTERNAL_START + n as u32 ) } )
128+ }
129+
130+ fn internal_desc ( error : Error ) -> Option < & ' static str > {
131+ match error {
161132 UNSUPPORTED => Some ( "getrandom: this target is not supported" ) ,
162133 UNKNOWN_IO_ERROR => Some ( "Unknown std::io::Error" ) ,
163134 SEC_RANDOM_FAILED => Some ( "SecRandomCopyBytes: call failed" ) ,
0 commit comments