@@ -9,6 +9,7 @@ use crate::{alloc::AllocError, str::CStr};
99use alloc:: alloc:: LayoutError ;
1010
1111use core:: fmt;
12+ use core:: num:: NonZeroI32 ;
1213use core:: num:: TryFromIntError ;
1314use core:: str:: Utf8Error ;
1415
@@ -20,7 +21,11 @@ pub mod code {
2021 $(
2122 #[ doc = $doc]
2223 ) *
23- pub const $err: super :: Error = super :: Error ( -( crate :: bindings:: $err as i32 ) ) ;
24+ pub const $err: super :: Error =
25+ match super :: Error :: try_from_errno( -( crate :: bindings:: $err as i32 ) ) {
26+ Some ( err) => err,
27+ None => panic!( "Invalid errno in `declare_err!`" ) ,
28+ } ;
2429 } ;
2530 }
2631
@@ -88,7 +93,7 @@ pub mod code {
8893///
8994/// The value is a valid `errno` (i.e. `>= -MAX_ERRNO && < 0`).
9095#[ derive( Clone , Copy , PartialEq , Eq ) ]
91- pub struct Error ( core :: ffi :: c_int ) ;
96+ pub struct Error ( NonZeroI32 ) ;
9297
9398impl Error {
9499 /// Creates an [`Error`] from a kernel error code.
@@ -107,45 +112,59 @@ impl Error {
107112
108113 // INVARIANT: The check above ensures the type invariant
109114 // will hold.
110- Error ( errno)
115+ // SAFETY: `errno` is checked above to be in a valid range.
116+ unsafe { Error :: from_errno_unchecked ( errno) }
117+ }
118+
119+ /// Creates an [`Error`] from a kernel error code.
120+ ///
121+ /// Returns [`None`] if `errno` is out-of-range.
122+ const fn try_from_errno ( errno : core:: ffi:: c_int ) -> Option < Error > {
123+ if errno < -( bindings:: MAX_ERRNO as i32 ) || errno >= 0 {
124+ return None ;
125+ }
126+
127+ // SAFETY: `errno` is checked above to be in a valid range.
128+ Some ( unsafe { Error :: from_errno_unchecked ( errno) } )
111129 }
112130
113131 /// Creates an [`Error`] from a kernel error code.
114132 ///
115133 /// # Safety
116134 ///
117135 /// `errno` must be within error code range (i.e. `>= -MAX_ERRNO && < 0`).
118- unsafe fn from_errno_unchecked ( errno : core:: ffi:: c_int ) -> Error {
136+ const unsafe fn from_errno_unchecked ( errno : core:: ffi:: c_int ) -> Error {
119137 // INVARIANT: The contract ensures the type invariant
120138 // will hold.
121- Error ( errno)
139+ // SAFETY: The caller guarantees `errno` is non-zero.
140+ Error ( unsafe { NonZeroI32 :: new_unchecked ( errno) } )
122141 }
123142
124143 /// Returns the kernel error code.
125144 pub fn to_errno ( self ) -> core:: ffi:: c_int {
126- self . 0
145+ self . 0 . get ( )
127146 }
128147
129148 #[ cfg( CONFIG_BLOCK ) ]
130149 pub ( crate ) fn to_blk_status ( self ) -> bindings:: blk_status_t {
131150 // SAFETY: `self.0` is a valid error due to its invariant.
132- unsafe { bindings:: errno_to_blk_status ( self . 0 ) }
151+ unsafe { bindings:: errno_to_blk_status ( self . 0 . get ( ) ) }
133152 }
134153
135154 /// Returns the error encoded as a pointer.
136155 pub fn to_ptr < T > ( self ) -> * mut T {
137156 #[ cfg_attr( target_pointer_width = "32" , allow( clippy:: useless_conversion) ) ]
138157 // SAFETY: `self.0` is a valid error due to its invariant.
139158 unsafe {
140- bindings:: ERR_PTR ( self . 0 . into ( ) ) as * mut _
159+ bindings:: ERR_PTR ( self . 0 . get ( ) . into ( ) ) as * mut _
141160 }
142161 }
143162
144163 /// Returns a string representing the error, if one exists.
145164 #[ cfg( not( testlib) ) ]
146165 pub fn name ( & self ) -> Option < & ' static CStr > {
147166 // SAFETY: Just an FFI call, there are no extra safety requirements.
148- let ptr = unsafe { bindings:: errname ( -self . 0 ) } ;
167+ let ptr = unsafe { bindings:: errname ( -self . 0 . get ( ) ) } ;
149168 if ptr. is_null ( ) {
150169 None
151170 } else {
0 commit comments