@@ -45,7 +45,7 @@ pub struct BorrowedHandle<'handle> {
45
45
/// Note that it *may* have the value `INVALID_HANDLE_VALUE` (-1), which is
46
46
/// sometimes a valid handle value. See [here] for the full story. For APIs
47
47
/// like `CreateFileW` which report errors with `INVALID_HANDLE_VALUE` instead
48
- /// of null, use [`OptionFileHandle `] instead of `Option<OwnedHandle>`.
48
+ /// of null, use [`HandleOrInvalid `] instead of `Option<OwnedHandle>`.
49
49
///
50
50
/// `OwnedHandle` uses [`CloseHandle`] to close its handle on drop. As such,
51
51
/// it must not be used with handles to open registry keys which need to be
@@ -61,36 +61,32 @@ pub struct OwnedHandle {
61
61
handle : NonNull < c_void > ,
62
62
}
63
63
64
- /// Similar to `Option<OwnedHandle>`, but intended for use in FFI interfaces
65
- /// where `INVALID_HANDLE_VALUE` is used as the sentry value, and null values
66
- /// are not used at all, such as in the return value of `CreateFileW`.
64
+ /// FFI type for handles in return values or out parameters, where `INVALID_HANDLE_VALUE` is used
65
+ /// as a sentry value to indicate errors, such as in the return value of `CreateFileW`. This uses
66
+ /// `repr(transparent)` and has the representation of a host handle, so that it can be used in such
67
+ /// FFI declarations.
67
68
///
68
- /// The main thing you can do with an `OptionFileHandle` is to convert it into
69
- /// an `OwnedHandle` using its [`TryFrom`] implementation, and this conversion
70
- /// takes care of the check for `INVALID_HANDLE_VALUE`.
69
+ /// The only thing you can usefully do with a `HandleOrInvalid` is to convert it into an
70
+ /// `OwnedHandle` using its [`TryFrom`] implementation; this conversion takes care of the check for
71
+ /// `INVALID_HANDLE_VALUE`. This ensures that such FFI calls cannot start using the handle without
72
+ /// checking for `INVALID_HANDLE_VALUE` first.
71
73
///
72
- /// If this holds an owned handle, it closes the handle on drop.
73
- ///
74
- /// This uses `repr(transparent)` and has the representation of a host handle,
75
- /// so it can be used in FFI in places where a non-null handle is passed as a
76
- /// consumed argument or returned as an owned value, or it is
77
- /// `INVALID_HANDLE_VALUE` indicating an error or an otherwise absent value.
74
+ /// If this holds a valid handle, it will close the handle on drop.
78
75
#[ repr( transparent) ]
79
76
#[ unstable( feature = "io_safety" , issue = "87074" ) ]
80
- pub struct OptionFileHandle {
81
- handle : RawHandle ,
82
- }
77
+ #[ derive( Debug ) ]
78
+ pub struct HandleOrInvalid ( Option < OwnedHandle > ) ;
83
79
84
80
// The Windows [`HANDLE`] type may be transferred across and shared between
85
81
// thread boundaries (despite containing a `*mut void`, which in general isn't
86
82
// `Send` or `Sync`).
87
83
//
88
84
// [`HANDLE`]: std::os::windows::raw::HANDLE
89
85
unsafe impl Send for OwnedHandle { }
90
- unsafe impl Send for OptionFileHandle { }
86
+ unsafe impl Send for HandleOrInvalid { }
91
87
unsafe impl Send for BorrowedHandle < ' _ > { }
92
88
unsafe impl Sync for OwnedHandle { }
93
- unsafe impl Sync for OptionFileHandle { }
89
+ unsafe impl Sync for HandleOrInvalid { }
94
90
unsafe impl Sync for BorrowedHandle < ' _ > { }
95
91
96
92
impl BorrowedHandle < ' _ > {
@@ -114,54 +110,31 @@ impl BorrowedHandle<'_> {
114
110
}
115
111
}
116
112
117
- impl OptionFileHandle {
118
- /// Return an empty `OptionFileHandle` with no resource.
119
- #[ inline]
120
- #[ unstable( feature = "io_safety" , issue = "87074" ) ]
121
- pub const fn none ( ) -> Self {
122
- Self { handle : c:: INVALID_HANDLE_VALUE }
123
- }
124
- }
125
-
126
- impl TryFrom < OptionFileHandle > for OwnedHandle {
113
+ impl TryFrom < HandleOrInvalid > for OwnedHandle {
127
114
type Error = ( ) ;
128
115
129
116
#[ inline]
130
- fn try_from ( option : OptionFileHandle ) -> Result < Self , ( ) > {
131
- let handle = option. handle ;
132
- forget ( option) ;
133
- if let Some ( non_null) = NonNull :: new ( handle) {
134
- if non_null. as_ptr ( ) != c:: INVALID_HANDLE_VALUE {
135
- Ok ( Self { handle : non_null } )
136
- } else {
137
- Err ( ( ) )
138
- }
117
+ fn try_from ( handle_or_invalid : HandleOrInvalid ) -> Result < Self , ( ) > {
118
+ // In theory, we ought to be able to assume that the pointer here is
119
+ // never null, use `OwnedHandle` rather than `Option<OwnedHandle>`, and
120
+ // obviate the the panic path here. Unfortunately, Win32 documentation
121
+ // doesn't explicitly guarantee this anywhere.
122
+ //
123
+ // APIs like [`CreateFileW`] itself have `HANDLE` arguments where a
124
+ // null handle indicates an absent value, which wouldn't work if null
125
+ // were a valid handle value, so it seems very unlikely that it could
126
+ // ever return null. But who knows?
127
+ //
128
+ // [`CreateFileW`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew
129
+ let owned_handle = handle_or_invalid. 0 . expect ( "A `HandleOrInvalid` was null!" ) ;
130
+ if owned_handle. handle . as_ptr ( ) == c:: INVALID_HANDLE_VALUE {
131
+ Err ( ( ) )
139
132
} else {
140
- // In theory, we ought to be able to assume that the pointer here
141
- // is never null, change `option.handle` to `NonNull`, and obviate
142
- // the the panic path here. Unfortunately, Win32 documentation
143
- // doesn't explicitly guarantee this anywhere.
144
- //
145
- // APIs like [`CreateFileW`] itself have `HANDLE` arguments where a
146
- // null handle indicates an absent value, which wouldn't work if
147
- // null were a valid handle value, so it seems very unlikely that
148
- // it could ever return null. But who knows?
149
- //
150
- // [`CreateFileW`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew
151
- panic ! ( "An `OptionFileHandle` was null!" ) ;
133
+ Ok ( owned_handle)
152
134
}
153
135
}
154
136
}
155
137
156
- impl From < OwnedHandle > for OptionFileHandle {
157
- #[ inline]
158
- fn from ( owned : OwnedHandle ) -> Self {
159
- let handle = owned. handle ;
160
- forget ( owned) ;
161
- Self { handle : handle. as_ptr ( ) }
162
- }
163
- }
164
-
165
138
impl AsRawHandle for BorrowedHandle < ' _ > {
166
139
#[ inline]
167
140
fn as_raw_handle ( & self ) -> RawHandle {
@@ -188,7 +161,7 @@ impl IntoRawHandle for OwnedHandle {
188
161
impl FromRawHandle for OwnedHandle {
189
162
/// Constructs a new instance of `Self` from the given raw handle.
190
163
///
191
- /// Use `OptionFileHandle ` instead of `Option<OwnedHandle>` for APIs that
164
+ /// Use `HandleOrInvalid ` instead of `Option<OwnedHandle>` for APIs that
192
165
/// use `INVALID_HANDLE_VALUE` to indicate failure.
193
166
///
194
167
/// # Safety
@@ -212,12 +185,12 @@ impl FromRawHandle for OwnedHandle {
212
185
}
213
186
}
214
187
215
- impl FromRawHandle for OptionFileHandle {
216
- /// Constructs a new instance of `Self` from the given raw handle returned
188
+ impl FromRawHandle for HandleOrInvalid {
189
+ /// Constructs a new instance of `Self` from the given `RawHandle` returned
217
190
/// from a Windows API that uses `INVALID_HANDLE_VALUE` to indicate
218
191
/// failure, such as `CreateFileW`.
219
192
///
220
- /// Use `Option<OwnedHandle>` instead of `OptionFileHandle ` for APIs that
193
+ /// Use `Option<OwnedHandle>` instead of `HandleOrInvalid ` for APIs that
221
194
/// use null to indicate failure.
222
195
///
223
196
/// # Safety
@@ -230,8 +203,8 @@ impl FromRawHandle for OptionFileHandle {
230
203
/// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
231
204
#[ inline]
232
205
unsafe fn from_raw_handle ( handle : RawHandle ) -> Self {
233
- assert ! ( !handle . is_null ( ) ) ;
234
- Self { handle }
206
+ // We require non-null here to catch errors earlier.
207
+ Self ( Some ( OwnedHandle :: from_raw_handle ( handle) ) )
235
208
}
236
209
}
237
210
@@ -244,15 +217,6 @@ impl Drop for OwnedHandle {
244
217
}
245
218
}
246
219
247
- impl Drop for OptionFileHandle {
248
- #[ inline]
249
- fn drop ( & mut self ) {
250
- unsafe {
251
- let _ = c:: CloseHandle ( self . handle ) ;
252
- }
253
- }
254
- }
255
-
256
220
impl fmt:: Debug for BorrowedHandle < ' _ > {
257
221
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
258
222
f. debug_struct ( "BorrowedHandle" ) . field ( "handle" , & self . handle ) . finish ( )
@@ -265,12 +229,6 @@ impl fmt::Debug for OwnedHandle {
265
229
}
266
230
}
267
231
268
- impl fmt:: Debug for OptionFileHandle {
269
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
270
- f. debug_struct ( "OptionFileHandle" ) . field ( "handle" , & self . handle ) . finish ( )
271
- }
272
- }
273
-
274
232
/// A trait to borrow the handle from an underlying object.
275
233
#[ unstable( feature = "io_safety" , issue = "87074" ) ]
276
234
pub trait AsHandle {
0 commit comments