@@ -45,7 +45,7 @@ pub struct BorrowedHandle<'handle> {
4545/// Note that it *may* have the value `INVALID_HANDLE_VALUE` (-1), which is
4646/// sometimes a valid handle value. See [here] for the full story. For APIs
4747/// 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>`.
4949///
5050/// `OwnedHandle` uses [`CloseHandle`] to close its handle on drop. As such,
5151/// it must not be used with handles to open registry keys which need to be
@@ -61,36 +61,32 @@ pub struct OwnedHandle {
6161 handle : NonNull < c_void > ,
6262}
6363
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.
6768///
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.
7173///
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.
7875#[ repr( transparent) ]
7976#[ unstable( feature = "io_safety" , issue = "87074" ) ]
80- pub struct OptionFileHandle {
81- handle : RawHandle ,
82- }
77+ #[ derive( Debug ) ]
78+ pub struct HandleOrInvalid ( Option < OwnedHandle > ) ;
8379
8480// The Windows [`HANDLE`] type may be transferred across and shared between
8581// thread boundaries (despite containing a `*mut void`, which in general isn't
8682// `Send` or `Sync`).
8783//
8884// [`HANDLE`]: std::os::windows::raw::HANDLE
8985unsafe impl Send for OwnedHandle { }
90- unsafe impl Send for OptionFileHandle { }
86+ unsafe impl Send for HandleOrInvalid { }
9187unsafe impl Send for BorrowedHandle < ' _ > { }
9288unsafe impl Sync for OwnedHandle { }
93- unsafe impl Sync for OptionFileHandle { }
89+ unsafe impl Sync for HandleOrInvalid { }
9490unsafe impl Sync for BorrowedHandle < ' _ > { }
9591
9692impl BorrowedHandle < ' _ > {
@@ -114,54 +110,31 @@ impl BorrowedHandle<'_> {
114110 }
115111}
116112
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 {
127114 type Error = ( ) ;
128115
129116 #[ 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 ( ( ) )
139132 } 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)
152134 }
153135 }
154136}
155137
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-
165138impl AsRawHandle for BorrowedHandle < ' _ > {
166139 #[ inline]
167140 fn as_raw_handle ( & self ) -> RawHandle {
@@ -188,7 +161,7 @@ impl IntoRawHandle for OwnedHandle {
188161impl FromRawHandle for OwnedHandle {
189162 /// Constructs a new instance of `Self` from the given raw handle.
190163 ///
191- /// Use `OptionFileHandle ` instead of `Option<OwnedHandle>` for APIs that
164+ /// Use `HandleOrInvalid ` instead of `Option<OwnedHandle>` for APIs that
192165 /// use `INVALID_HANDLE_VALUE` to indicate failure.
193166 ///
194167 /// # Safety
@@ -212,12 +185,12 @@ impl FromRawHandle for OwnedHandle {
212185 }
213186}
214187
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
217190 /// from a Windows API that uses `INVALID_HANDLE_VALUE` to indicate
218191 /// failure, such as `CreateFileW`.
219192 ///
220- /// Use `Option<OwnedHandle>` instead of `OptionFileHandle ` for APIs that
193+ /// Use `Option<OwnedHandle>` instead of `HandleOrInvalid ` for APIs that
221194 /// use null to indicate failure.
222195 ///
223196 /// # Safety
@@ -230,8 +203,8 @@ impl FromRawHandle for OptionFileHandle {
230203 /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
231204 #[ inline]
232205 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) ) )
235208 }
236209}
237210
@@ -244,15 +217,6 @@ impl Drop for OwnedHandle {
244217 }
245218}
246219
247- impl Drop for OptionFileHandle {
248- #[ inline]
249- fn drop ( & mut self ) {
250- unsafe {
251- let _ = c:: CloseHandle ( self . handle ) ;
252- }
253- }
254- }
255-
256220impl fmt:: Debug for BorrowedHandle < ' _ > {
257221 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
258222 f. debug_struct ( "BorrowedHandle" ) . field ( "handle" , & self . handle ) . finish ( )
@@ -265,12 +229,6 @@ impl fmt::Debug for OwnedHandle {
265229 }
266230}
267231
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-
274232/// A trait to borrow the handle from an underlying object.
275233#[ unstable( feature = "io_safety" , issue = "87074" ) ]
276234pub trait AsHandle {
0 commit comments