@@ -9,6 +9,7 @@ use crate::{alloc::AllocError, str::CStr};
9
9
use alloc:: alloc:: LayoutError ;
10
10
11
11
use core:: fmt;
12
+ use core:: num:: NonZeroI32 ;
12
13
use core:: num:: TryFromIntError ;
13
14
use core:: str:: Utf8Error ;
14
15
@@ -20,7 +21,11 @@ pub mod code {
20
21
$(
21
22
#[ doc = $doc]
22
23
) *
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
+ } ;
24
29
} ;
25
30
}
26
31
@@ -88,7 +93,7 @@ pub mod code {
88
93
///
89
94
/// The value is a valid `errno` (i.e. `>= -MAX_ERRNO && < 0`).
90
95
#[ derive( Clone , Copy , PartialEq , Eq ) ]
91
- pub struct Error ( core :: ffi :: c_int ) ;
96
+ pub struct Error ( NonZeroI32 ) ;
92
97
93
98
impl Error {
94
99
/// Creates an [`Error`] from a kernel error code.
@@ -107,45 +112,59 @@ impl Error {
107
112
108
113
// INVARIANT: The check above ensures the type invariant
109
114
// 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) } )
111
129
}
112
130
113
131
/// Creates an [`Error`] from a kernel error code.
114
132
///
115
133
/// # Safety
116
134
///
117
135
/// `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 {
119
137
// INVARIANT: The contract ensures the type invariant
120
138
// will hold.
121
- Error ( errno)
139
+ // SAFETY: The caller guarantees `errno` is non-zero.
140
+ Error ( unsafe { NonZeroI32 :: new_unchecked ( errno) } )
122
141
}
123
142
124
143
/// Returns the kernel error code.
125
144
pub fn to_errno ( self ) -> core:: ffi:: c_int {
126
- self . 0
145
+ self . 0 . get ( )
127
146
}
128
147
129
148
#[ cfg( CONFIG_BLOCK ) ]
130
149
pub ( crate ) fn to_blk_status ( self ) -> bindings:: blk_status_t {
131
150
// 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 ( ) ) }
133
152
}
134
153
135
154
/// Returns the error encoded as a pointer.
136
155
pub fn to_ptr < T > ( self ) -> * mut T {
137
156
#[ cfg_attr( target_pointer_width = "32" , allow( clippy:: useless_conversion) ) ]
138
157
// SAFETY: `self.0` is a valid error due to its invariant.
139
158
unsafe {
140
- bindings:: ERR_PTR ( self . 0 . into ( ) ) as * mut _
159
+ bindings:: ERR_PTR ( self . 0 . get ( ) . into ( ) ) as * mut _
141
160
}
142
161
}
143
162
144
163
/// Returns a string representing the error, if one exists.
145
164
#[ cfg( not( testlib) ) ]
146
165
pub fn name ( & self ) -> Option < & ' static CStr > {
147
166
// 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 ( ) ) } ;
149
168
if ptr. is_null ( ) {
150
169
None
151
170
} else {
0 commit comments