Skip to main content

std/os/windows/io/
handle.rs

1//! Owned and borrowed OS handles.
2
3#![stable(feature = "io_safety", since = "1.63.0")]
4
5use super::raw::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle};
6use crate::alloc::Allocator;
7use crate::marker::PhantomData;
8use crate::mem::ManuallyDrop;
9use crate::sys::{AsInner, FromInner, IntoInner, cvt};
10use crate::{fmt, fs, io, ptr, sys};
11
12/// A borrowed handle.
13///
14/// This has a lifetime parameter to tie it to the lifetime of something that
15/// owns the handle.
16///
17/// This uses `repr(transparent)` and has the representation of a host handle,
18/// so it can be used in FFI in places where a handle is passed as an argument,
19/// it is not captured or consumed.
20///
21/// Note that it *may* have the value `-1`, which in `BorrowedHandle` always
22/// represents a valid handle value, such as [the current process handle], and
23/// not `INVALID_HANDLE_VALUE`, despite the two having the same value. See
24/// [here] for the full story.
25///
26/// And, it *may* have the value `NULL` (0), which can occur when consoles are
27/// detached from processes, or when `windows_subsystem` is used.
28///
29/// This type's `.to_owned()` implementation returns another `BorrowedHandle`
30/// rather than an `OwnedHandle`. It just makes a trivial copy of the raw
31/// handle, which is then borrowed under the same lifetime.
32///
33/// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
34/// [the current process handle]: https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getcurrentprocess#remarks
35#[derive(Copy, Clone)]
36#[repr(transparent)]
37#[stable(feature = "io_safety", since = "1.63.0")]
38pub struct BorrowedHandle<'handle> {
39    handle: RawHandle,
40    _phantom: PhantomData<&'handle OwnedHandle>,
41}
42
43/// An owned handle.
44///
45/// This closes the handle on drop.
46///
47/// Note that it *may* have the value `-1`, which in `OwnedHandle` always
48/// represents a valid handle value, such as [the current process handle], and
49/// not `INVALID_HANDLE_VALUE`, despite the two having the same value. See
50/// [here] for the full story.
51///
52/// And, it *may* have the value `NULL` (0), which can occur when consoles are
53/// detached from processes, or when `windows_subsystem` is used.
54///
55/// `OwnedHandle` uses [`CloseHandle`] to close its handle on drop. As such,
56/// it must not be used with handles to open registry keys which need to be
57/// closed with [`RegCloseKey`] instead.
58///
59/// [`CloseHandle`]: https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-closehandle
60/// [`RegCloseKey`]: https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regclosekey
61///
62/// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
63/// [the current process handle]: https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getcurrentprocess#remarks
64#[repr(transparent)]
65#[stable(feature = "io_safety", since = "1.63.0")]
66pub struct OwnedHandle {
67    handle: RawHandle,
68}
69
70/// FFI type for handles in return values or out parameters, where `NULL` is used
71/// as a sentry value to indicate errors, such as in the return value of `CreateThread`. This uses
72/// `repr(transparent)` and has the representation of a host handle, so that it can be used in such
73/// FFI declarations.
74///
75/// The only thing you can usefully do with a `HandleOrNull` is to convert it into an
76/// `OwnedHandle` using its [`TryFrom`] implementation; this conversion takes care of the check for
77/// `NULL`. This ensures that such FFI calls cannot start using the handle without
78/// checking for `NULL` first.
79///
80/// This type may hold any handle value that [`OwnedHandle`] may hold. As with `OwnedHandle`, when
81/// it holds `-1`, that value is interpreted as a valid handle value, such as
82/// [the current process handle], and not `INVALID_HANDLE_VALUE`.
83///
84/// If this holds a non-null handle, it will close the handle on drop.
85///
86/// [the current process handle]: https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getcurrentprocess#remarks
87#[repr(transparent)]
88#[stable(feature = "io_safety", since = "1.63.0")]
89#[derive(Debug)]
90pub struct HandleOrNull(RawHandle);
91
92/// FFI type for handles in return values or out parameters, where `INVALID_HANDLE_VALUE` is used
93/// as a sentry value to indicate errors, such as in the return value of `CreateFileW`. This uses
94/// `repr(transparent)` and has the representation of a host handle, so that it can be used in such
95/// FFI declarations.
96///
97/// The only thing you can usefully do with a `HandleOrInvalid` is to convert it into an
98/// `OwnedHandle` using its [`TryFrom`] implementation; this conversion takes care of the check for
99/// `INVALID_HANDLE_VALUE`. This ensures that such FFI calls cannot start using the handle without
100/// checking for `INVALID_HANDLE_VALUE` first.
101///
102/// This type may hold any handle value that [`OwnedHandle`] may hold, except that when it holds
103/// `-1`, that value is interpreted to mean `INVALID_HANDLE_VALUE`.
104///
105/// If holds a handle other than `INVALID_HANDLE_VALUE`, it will close the handle on drop.
106#[repr(transparent)]
107#[stable(feature = "io_safety", since = "1.63.0")]
108#[derive(Debug)]
109pub struct HandleOrInvalid(RawHandle);
110
111// The Windows [`HANDLE`] type may be transferred across and shared between
112// thread boundaries (despite containing a `*mut void`, which in general isn't
113// `Send` or `Sync`).
114//
115// [`HANDLE`]: std::os::windows::raw::HANDLE
116#[stable(feature = "io_safety", since = "1.63.0")]
117unsafe impl Send for OwnedHandle {}
118#[stable(feature = "io_safety", since = "1.63.0")]
119unsafe impl Send for HandleOrNull {}
120#[stable(feature = "io_safety", since = "1.63.0")]
121unsafe impl Send for HandleOrInvalid {}
122#[stable(feature = "io_safety", since = "1.63.0")]
123unsafe impl Send for BorrowedHandle<'_> {}
124#[stable(feature = "io_safety", since = "1.63.0")]
125unsafe impl Sync for OwnedHandle {}
126#[stable(feature = "io_safety", since = "1.63.0")]
127unsafe impl Sync for HandleOrNull {}
128#[stable(feature = "io_safety", since = "1.63.0")]
129unsafe impl Sync for HandleOrInvalid {}
130#[stable(feature = "io_safety", since = "1.63.0")]
131unsafe impl Sync for BorrowedHandle<'_> {}
132
133impl BorrowedHandle<'_> {
134    /// Returns a `BorrowedHandle` holding the given raw handle.
135    ///
136    /// # Safety
137    ///
138    /// The resource pointed to by `handle` must be a valid open handle, it
139    /// must remain open for the duration of the returned `BorrowedHandle`.
140    ///
141    /// Note that it *may* have the value `INVALID_HANDLE_VALUE` (-1), which is
142    /// sometimes a valid handle value. See [here] for the full story.
143    ///
144    /// And, it *may* have the value `NULL` (0), which can occur when consoles are
145    /// detached from processes, or when `windows_subsystem` is used.
146    ///
147    /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
148    #[inline]
149    #[rustc_const_stable(feature = "io_safety", since = "1.63.0")]
150    #[stable(feature = "io_safety", since = "1.63.0")]
151    pub const unsafe fn borrow_raw(handle: RawHandle) -> Self {
152        Self { handle, _phantom: PhantomData }
153    }
154
155    /// Converts a `BorrowedHandle` into a reference to a file-like type.
156    ///
157    #[cfg_attr(windows, doc = "```no_run")]
158    #[cfg_attr(not(windows), doc = "```ignore (needs windows)")]
159    /// # #![feature(fd_view)]
160    /// # use std::fs::File;
161    /// # use std::io;
162    /// # use std::os::windows::io::AsHandle;
163    /// let meta = io::stdout().as_handle().to_view::<File>().metadata().unwrap();
164    /// if meta.is_file() {
165    ///     println!("stdout is a regular file");
166    /// }
167    /// ```
168    #[unstable(feature = "fd_view", issue = "160402")]
169    pub fn to_view<T>(&self) -> &T
170    where
171        Self: AsRef<T>,
172    {
173        self.as_ref()
174    }
175}
176
177#[stable(feature = "io_safety", since = "1.63.0")]
178impl TryFrom<HandleOrNull> for OwnedHandle {
179    type Error = NullHandleError;
180
181    #[inline]
182    fn try_from(handle_or_null: HandleOrNull) -> Result<Self, NullHandleError> {
183        let handle_or_null = ManuallyDrop::new(handle_or_null);
184        if handle_or_null.is_valid() {
185            // SAFETY: The handle is not null.
186            Ok(unsafe { OwnedHandle::from_raw_handle(handle_or_null.0) })
187        } else {
188            Err(NullHandleError(()))
189        }
190    }
191}
192
193#[stable(feature = "io_safety", since = "1.63.0")]
194impl Drop for HandleOrNull {
195    #[inline]
196    fn drop(&mut self) {
197        if self.is_valid() {
198            unsafe {
199                let _ = sys::c::CloseHandle(self.0);
200            }
201        }
202    }
203}
204
205impl OwnedHandle {
206    /// Creates a new `OwnedHandle` instance that shares the same underlying
207    /// object as the existing `OwnedHandle` instance.
208    #[stable(feature = "io_safety", since = "1.63.0")]
209    pub fn try_clone(&self) -> io::Result<Self> {
210        self.as_handle().try_clone_to_owned()
211    }
212}
213
214impl BorrowedHandle<'_> {
215    /// Creates a new `OwnedHandle` instance that shares the same underlying
216    /// object as the existing `BorrowedHandle` instance.
217    #[stable(feature = "io_safety", since = "1.63.0")]
218    pub fn try_clone_to_owned(&self) -> io::Result<OwnedHandle> {
219        self.duplicate(0, false, sys::c::DUPLICATE_SAME_ACCESS)
220    }
221
222    pub(crate) fn duplicate(
223        &self,
224        access: u32,
225        inherit: bool,
226        options: u32,
227    ) -> io::Result<OwnedHandle> {
228        let handle = self.as_raw_handle();
229
230        // `Stdin`, `Stdout`, and `Stderr` can all hold null handles, such as
231        // in a process with a detached console. `DuplicateHandle` would fail
232        // if we passed it a null handle, but we can treat null as a valid
233        // handle which doesn't do any I/O, and allow it to be duplicated.
234        if handle.is_null() {
235            return unsafe { Ok(OwnedHandle::from_raw_handle(handle)) };
236        }
237
238        let mut ret = ptr::null_mut();
239        cvt(unsafe {
240            let cur_proc = sys::c::GetCurrentProcess();
241            sys::c::DuplicateHandle(
242                cur_proc,
243                handle,
244                cur_proc,
245                &mut ret,
246                access,
247                inherit as sys::c::BOOL,
248                options,
249            )
250        })?;
251        unsafe { Ok(OwnedHandle::from_raw_handle(ret)) }
252    }
253}
254
255#[stable(feature = "io_safety", since = "1.63.0")]
256impl TryFrom<HandleOrInvalid> for OwnedHandle {
257    type Error = InvalidHandleError;
258
259    #[inline]
260    fn try_from(handle_or_invalid: HandleOrInvalid) -> Result<Self, InvalidHandleError> {
261        let handle_or_invalid = ManuallyDrop::new(handle_or_invalid);
262        if handle_or_invalid.is_valid() {
263            // SAFETY: The handle is not invalid.
264            Ok(unsafe { OwnedHandle::from_raw_handle(handle_or_invalid.0) })
265        } else {
266            Err(InvalidHandleError(()))
267        }
268    }
269}
270
271#[stable(feature = "io_safety", since = "1.63.0")]
272impl Drop for HandleOrInvalid {
273    #[inline]
274    fn drop(&mut self) {
275        if self.is_valid() {
276            unsafe {
277                let _ = sys::c::CloseHandle(self.0);
278            }
279        }
280    }
281}
282
283/// This is the error type used by [`HandleOrNull`] when attempting to convert
284/// into a handle, to indicate that the value is null.
285// The empty field prevents constructing this, and allows extending it in the future.
286#[stable(feature = "io_safety", since = "1.63.0")]
287#[derive(Debug, Clone, PartialEq, Eq)]
288pub struct NullHandleError(());
289
290#[stable(feature = "io_safety", since = "1.63.0")]
291impl fmt::Display for NullHandleError {
292    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
293        "A HandleOrNull could not be converted to a handle because it was null".fmt(fmt)
294    }
295}
296
297#[stable(feature = "io_safety", since = "1.63.0")]
298impl crate::error::Error for NullHandleError {}
299
300/// This is the error type used by [`HandleOrInvalid`] when attempting to
301/// convert into a handle, to indicate that the value is
302/// `INVALID_HANDLE_VALUE`.
303// The empty field prevents constructing this, and allows extending it in the future.
304#[stable(feature = "io_safety", since = "1.63.0")]
305#[derive(Debug, Clone, PartialEq, Eq)]
306pub struct InvalidHandleError(());
307
308#[stable(feature = "io_safety", since = "1.63.0")]
309impl fmt::Display for InvalidHandleError {
310    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
311        "A HandleOrInvalid could not be converted to a handle because it was INVALID_HANDLE_VALUE"
312            .fmt(fmt)
313    }
314}
315
316#[stable(feature = "io_safety", since = "1.63.0")]
317impl crate::error::Error for InvalidHandleError {}
318
319#[stable(feature = "io_safety", since = "1.63.0")]
320impl AsRawHandle for BorrowedHandle<'_> {
321    #[inline]
322    fn as_raw_handle(&self) -> RawHandle {
323        self.handle
324    }
325}
326
327#[stable(feature = "io_safety", since = "1.63.0")]
328impl AsRawHandle for OwnedHandle {
329    #[inline]
330    fn as_raw_handle(&self) -> RawHandle {
331        self.handle
332    }
333}
334
335#[stable(feature = "io_safety", since = "1.63.0")]
336impl IntoRawHandle for OwnedHandle {
337    #[inline]
338    fn into_raw_handle(self) -> RawHandle {
339        ManuallyDrop::new(self).handle
340    }
341}
342
343#[stable(feature = "io_safety", since = "1.63.0")]
344impl FromRawHandle for OwnedHandle {
345    #[inline]
346    unsafe fn from_raw_handle(handle: RawHandle) -> Self {
347        Self { handle }
348    }
349}
350
351impl HandleOrNull {
352    /// Constructs a new instance of `Self` from the given `RawHandle` returned
353    /// from a Windows API that uses null to indicate failure, such as
354    /// `CreateThread`.
355    ///
356    /// Use `HandleOrInvalid` instead of `HandleOrNull` for APIs that
357    /// use `INVALID_HANDLE_VALUE` to indicate failure.
358    ///
359    /// # Safety
360    ///
361    /// The passed `handle` value must either satisfy the safety requirements
362    /// of [`FromRawHandle::from_raw_handle`], or be null. Note that not all
363    /// Windows APIs use null for errors; see [here] for the full story.
364    ///
365    /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
366    #[stable(feature = "io_safety", since = "1.63.0")]
367    #[inline]
368    pub unsafe fn from_raw_handle(handle: RawHandle) -> Self {
369        Self(handle)
370    }
371
372    fn is_valid(&self) -> bool {
373        !self.0.is_null()
374    }
375}
376
377impl HandleOrInvalid {
378    /// Constructs a new instance of `Self` from the given `RawHandle` returned
379    /// from a Windows API that uses `INVALID_HANDLE_VALUE` to indicate
380    /// failure, such as `CreateFileW`.
381    ///
382    /// Use `HandleOrNull` instead of `HandleOrInvalid` for APIs that
383    /// use null to indicate failure.
384    ///
385    /// # Safety
386    ///
387    /// The passed `handle` value must either satisfy the safety requirements
388    /// of [`FromRawHandle::from_raw_handle`], or be
389    /// `INVALID_HANDLE_VALUE` (-1). Note that not all Windows APIs use
390    /// `INVALID_HANDLE_VALUE` for errors; see [here] for the full story.
391    ///
392    /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
393    #[stable(feature = "io_safety", since = "1.63.0")]
394    #[inline]
395    pub unsafe fn from_raw_handle(handle: RawHandle) -> Self {
396        Self(handle)
397    }
398
399    fn is_valid(&self) -> bool {
400        self.0 != sys::c::INVALID_HANDLE_VALUE
401    }
402}
403
404#[stable(feature = "io_safety", since = "1.63.0")]
405impl Drop for OwnedHandle {
406    #[inline]
407    fn drop(&mut self) {
408        unsafe {
409            let _ = sys::c::CloseHandle(self.handle);
410        }
411    }
412}
413
414#[stable(feature = "io_safety", since = "1.63.0")]
415impl fmt::Debug for BorrowedHandle<'_> {
416    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
417        f.debug_struct("BorrowedHandle").field("handle", &self.handle).finish()
418    }
419}
420
421#[stable(feature = "io_safety", since = "1.63.0")]
422impl fmt::Debug for OwnedHandle {
423    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
424        f.debug_struct("OwnedHandle").field("handle", &self.handle).finish()
425    }
426}
427
428macro_rules! impl_is_terminal {
429    ($($t:ty),*$(,)?) => {$(
430        #[stable(feature = "is_terminal", since = "1.70.0")]
431        impl io::IsTerminal for $t {
432            #[inline]
433            fn is_terminal(&self) -> bool {
434                crate::sys::io::is_terminal(self)
435            }
436        }
437    )*}
438}
439
440impl_is_terminal!(BorrowedHandle<'_>, OwnedHandle);
441
442/// A trait to borrow the handle from an underlying object.
443#[stable(feature = "io_safety", since = "1.63.0")]
444pub trait AsHandle {
445    /// Borrows the handle.
446    ///
447    /// # Example
448    ///
449    #[cfg_attr(windows, doc = "```no_run")]
450    #[cfg_attr(not(windows), doc = "```ignore (needs windows)")]
451    /// use std::fs::File;
452    /// # use std::io;
453    /// use std::os::windows::io::{AsHandle, BorrowedHandle};
454    ///
455    /// let mut f = File::open("foo.txt")?;
456    /// let borrowed_handle: BorrowedHandle<'_> = f.as_handle();
457    /// # Ok::<(), io::Error>(())
458    /// ```
459    #[stable(feature = "io_safety", since = "1.63.0")]
460    fn as_handle(&self) -> BorrowedHandle<'_>;
461}
462
463#[stable(feature = "io_safety", since = "1.63.0")]
464impl<T: AsHandle + ?Sized> AsHandle for &T {
465    #[inline]
466    fn as_handle(&self) -> BorrowedHandle<'_> {
467        T::as_handle(self)
468    }
469}
470
471#[stable(feature = "io_safety", since = "1.63.0")]
472impl<T: AsHandle + ?Sized> AsHandle for &mut T {
473    #[inline]
474    fn as_handle(&self) -> BorrowedHandle<'_> {
475        T::as_handle(self)
476    }
477}
478
479#[stable(feature = "as_windows_ptrs", since = "1.71.0")]
480/// This impl allows implementing traits that require `AsHandle` on Arc.
481/// ```
482/// # #[cfg(windows)] mod group_cfg {
483/// # use std::os::windows::io::AsHandle;
484/// use std::fs::File;
485/// use std::sync::Arc;
486///
487/// trait MyTrait: AsHandle {}
488/// impl MyTrait for Arc<File> {}
489/// impl MyTrait for Box<File> {}
490/// # }
491/// ```
492impl<T: AsHandle + ?Sized> AsHandle for crate::sync::Arc<T> {
493    #[inline]
494    fn as_handle(&self) -> BorrowedHandle<'_> {
495        (**self).as_handle()
496    }
497}
498
499#[stable(feature = "as_windows_ptrs", since = "1.71.0")]
500impl<T: AsHandle + ?Sized> AsHandle for crate::rc::Rc<T> {
501    #[inline]
502    fn as_handle(&self) -> BorrowedHandle<'_> {
503        (**self).as_handle()
504    }
505}
506
507#[unstable(feature = "unique_rc_arc", issue = "112566")]
508impl<T: AsHandle + ?Sized> AsHandle for crate::rc::UniqueRc<T> {
509    #[inline]
510    fn as_handle(&self) -> BorrowedHandle<'_> {
511        (**self).as_handle()
512    }
513}
514
515#[stable(feature = "as_windows_ptrs", since = "1.71.0")]
516impl<T: AsHandle + ?Sized, A: Allocator> AsHandle for Box<T, A> {
517    #[inline]
518    fn as_handle(&self) -> BorrowedHandle<'_> {
519        (**self).as_handle()
520    }
521}
522
523#[stable(feature = "io_safety", since = "1.63.0")]
524impl AsHandle for BorrowedHandle<'_> {
525    #[inline]
526    fn as_handle(&self) -> BorrowedHandle<'_> {
527        *self
528    }
529}
530
531#[stable(feature = "io_safety", since = "1.63.0")]
532impl AsHandle for OwnedHandle {
533    #[inline]
534    fn as_handle(&self) -> BorrowedHandle<'_> {
535        // Safety: `OwnedHandle` and `BorrowedHandle` have the same validity
536        // invariants, and the `BorrowedHandle` is bounded by the lifetime
537        // of `&self`.
538        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
539    }
540}
541
542#[stable(feature = "io_safety", since = "1.63.0")]
543impl AsHandle for fs::File {
544    #[inline]
545    fn as_handle(&self) -> BorrowedHandle<'_> {
546        self.as_inner().as_handle()
547    }
548}
549
550#[stable(feature = "io_safety", since = "1.63.0")]
551impl From<fs::File> for OwnedHandle {
552    /// Takes ownership of a [`File`](fs::File)'s underlying file handle.
553    #[inline]
554    fn from(file: fs::File) -> OwnedHandle {
555        file.into_inner().into_inner().into_inner()
556    }
557}
558
559#[stable(feature = "io_safety", since = "1.63.0")]
560impl From<OwnedHandle> for fs::File {
561    /// Returns a [`File`](fs::File) that takes ownership of the given handle.
562    #[inline]
563    fn from(owned: OwnedHandle) -> Self {
564        Self::from_inner(FromInner::from_inner(FromInner::from_inner(owned)))
565    }
566}
567
568#[stable(feature = "io_safety", since = "1.63.0")]
569impl AsHandle for io::Stdin {
570    #[inline]
571    fn as_handle(&self) -> BorrowedHandle<'_> {
572        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
573    }
574}
575
576#[stable(feature = "io_safety", since = "1.63.0")]
577impl<'a> AsHandle for io::StdinLock<'a> {
578    #[inline]
579    fn as_handle(&self) -> BorrowedHandle<'_> {
580        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
581    }
582}
583
584#[stable(feature = "io_safety", since = "1.63.0")]
585impl AsHandle for io::Stdout {
586    #[inline]
587    fn as_handle(&self) -> BorrowedHandle<'_> {
588        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
589    }
590}
591
592#[stable(feature = "io_safety", since = "1.63.0")]
593impl<'a> AsHandle for io::StdoutLock<'a> {
594    #[inline]
595    fn as_handle(&self) -> BorrowedHandle<'_> {
596        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
597    }
598}
599
600#[stable(feature = "io_safety", since = "1.63.0")]
601impl AsHandle for io::Stderr {
602    #[inline]
603    fn as_handle(&self) -> BorrowedHandle<'_> {
604        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
605    }
606}
607
608#[stable(feature = "io_safety", since = "1.63.0")]
609impl<'a> AsHandle for io::StderrLock<'a> {
610    #[inline]
611    fn as_handle(&self) -> BorrowedHandle<'_> {
612        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
613    }
614}
615
616#[stable(feature = "io_safety", since = "1.63.0")]
617impl AsHandle for crate::process::ChildStdin {
618    #[inline]
619    fn as_handle(&self) -> BorrowedHandle<'_> {
620        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
621    }
622}
623
624#[stable(feature = "io_safety", since = "1.63.0")]
625impl From<crate::process::ChildStdin> for OwnedHandle {
626    /// Takes ownership of a [`ChildStdin`](crate::process::ChildStdin)'s file handle.
627    #[inline]
628    fn from(child_stdin: crate::process::ChildStdin) -> OwnedHandle {
629        unsafe { OwnedHandle::from_raw_handle(child_stdin.into_raw_handle()) }
630    }
631}
632
633#[stable(feature = "io_safety", since = "1.63.0")]
634impl AsHandle for crate::process::ChildStdout {
635    #[inline]
636    fn as_handle(&self) -> BorrowedHandle<'_> {
637        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
638    }
639}
640
641#[stable(feature = "io_safety", since = "1.63.0")]
642impl From<crate::process::ChildStdout> for OwnedHandle {
643    /// Takes ownership of a [`ChildStdout`](crate::process::ChildStdout)'s file handle.
644    #[inline]
645    fn from(child_stdout: crate::process::ChildStdout) -> OwnedHandle {
646        unsafe { OwnedHandle::from_raw_handle(child_stdout.into_raw_handle()) }
647    }
648}
649
650#[stable(feature = "io_safety", since = "1.63.0")]
651impl AsHandle for crate::process::ChildStderr {
652    #[inline]
653    fn as_handle(&self) -> BorrowedHandle<'_> {
654        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
655    }
656}
657
658#[stable(feature = "io_safety", since = "1.63.0")]
659impl From<crate::process::ChildStderr> for OwnedHandle {
660    /// Takes ownership of a [`ChildStderr`](crate::process::ChildStderr)'s file handle.
661    #[inline]
662    fn from(child_stderr: crate::process::ChildStderr) -> OwnedHandle {
663        unsafe { OwnedHandle::from_raw_handle(child_stderr.into_raw_handle()) }
664    }
665}
666
667#[stable(feature = "io_safety", since = "1.63.0")]
668impl<T> AsHandle for crate::thread::JoinHandle<T> {
669    #[inline]
670    fn as_handle(&self) -> BorrowedHandle<'_> {
671        unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
672    }
673}
674
675#[stable(feature = "io_safety", since = "1.63.0")]
676impl<T> From<crate::thread::JoinHandle<T>> for OwnedHandle {
677    #[inline]
678    fn from(join_handle: crate::thread::JoinHandle<T>) -> OwnedHandle {
679        join_handle.into_inner().into_handle().into_inner()
680    }
681}
682
683#[stable(feature = "anonymous_pipe", since = "1.87.0")]
684impl AsHandle for io::PipeReader {
685    fn as_handle(&self) -> BorrowedHandle<'_> {
686        self.0.as_handle()
687    }
688}
689
690#[stable(feature = "anonymous_pipe", since = "1.87.0")]
691impl From<io::PipeReader> for OwnedHandle {
692    fn from(pipe: io::PipeReader) -> Self {
693        pipe.into_inner().into_inner()
694    }
695}
696
697#[stable(feature = "anonymous_pipe", since = "1.87.0")]
698impl AsHandle for io::PipeWriter {
699    fn as_handle(&self) -> BorrowedHandle<'_> {
700        self.0.as_handle()
701    }
702}
703
704/// Implements `AsRef<$t>` conversions from `BorrowedHandle` to the specified types.
705///
706/// # Safety
707///
708/// It must be sound to transmute `&BorrowedHandle` to `&$t`.
709///
710/// This typically implies that:
711///
712/// - $t must be a wrapper with `BorrowedHandle`, `OwnedHandle` or `RawHandle` being the single non-ZST-field.
713///   Nominally it also requires repr(transparent), but std can cheat because we can stay in
714///   sync with rustc's layout implementation details.
715/// - `&$t` must not have any methods that would allow closing the file descriptor.
716/// - `&$t` impls must tolerate instances being created from any kind of file-descriptor without
717///   going through some dedicated constructor function, akin to `From<OwnedHandle>` being a noop
718///   conversion.
719pub(crate) macro unsafe_impl_handle_asrefs {
720    ($($t:ty),*$(,)?) => {$(
721        #[unstable(feature = "fd_view", issue = "160402")]
722        #[unstable_feature_bound(fd_view)]
723        impl AsRef<$t> for BorrowedHandle<'_> {
724            #[inline]
725            fn as_ref(&self) -> &$t {
726                use core::mem;
727
728                // These are neither necessary nor sufficient, but generally
729                // a type that implements them is more likely to have the required behavior.
730                fn type_check<T: From<OwnedHandle> + Into<OwnedHandle> + AsHandle>() {}
731
732                // sanity check in case layouts change
733                const {
734                    assert!(mem::size_of::<RawHandle>() == mem::size_of::<$t>());
735                    assert!(mem::size_of::<RawHandle>() == mem::size_of::<BorrowedHandle<'_>>());
736                }
737                type_check::<$t>();
738                // SAFETY: See macro-level requirements.
739                unsafe { mem::transmute::<&BorrowedHandle<'_>, &$t>(self) }
740            }
741        }
742    )*}
743}
744
745unsafe_impl_handle_asrefs!(crate::fs::File, io::PipeWriter, io::PipeReader,);
746
747#[stable(feature = "anonymous_pipe", since = "1.87.0")]
748impl From<io::PipeWriter> for OwnedHandle {
749    fn from(pipe: io::PipeWriter) -> Self {
750        pipe.into_inner().into_inner()
751    }
752}
753
754#[stable(feature = "anonymous_pipe", since = "1.87.0")]
755impl From<OwnedHandle> for io::PipeReader {
756    fn from(owned_handle: OwnedHandle) -> Self {
757        Self::from_inner(FromInner::from_inner(owned_handle))
758    }
759}
760
761#[stable(feature = "anonymous_pipe", since = "1.87.0")]
762impl From<OwnedHandle> for io::PipeWriter {
763    fn from(owned_handle: OwnedHandle) -> Self {
764        Self::from_inner(FromInner::from_inner(owned_handle))
765    }
766}