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