handle.rs - source (original) (raw)
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:📑:PhantomData;
7use crate::mem::ManuallyDrop;
8use crate::sys::cvt;
9use crate::sys_common::{AsInner, FromInner, IntoInner};
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
156#[stable(feature = "io_safety", since = "1.63.0")]
157impl TryFrom<HandleOrNull> for OwnedHandle {
158 type Error = NullHandleError;
159
160 #[inline]
161 fn try_from(handle_or_null: HandleOrNull) -> Result<Self, NullHandleError> {
162 let handle_or_null = ManuallyDrop::new(handle_or_null);
163 if handle_or_null.is_valid() {
164 // SAFETY: The handle is not null.
165 Ok(unsafe { OwnedHandle::from_raw_handle(handle_or_null.0) })
166 } else {
167 Err(NullHandleError(()))
168 }
169 }
170}
171
172#[stable(feature = "io_safety", since = "1.63.0")]
173impl Drop for HandleOrNull {
174 #[inline]
175 fn drop(&mut self) {
176 if self.is_valid() {
177 unsafe {
178 let _ = sys::c::CloseHandle(self.0);
179 }
180 }
181 }
182}
183
184impl OwnedHandle {
185 /// Creates a new `OwnedHandle` instance that shares the same underlying
186 /// object as the existing `OwnedHandle` instance.
187 #[stable(feature = "io_safety", since = "1.63.0")]
188 pub fn try_clone(&self) -> crate::io::Result<Self> {
189 self.as_handle().try_clone_to_owned()
190 }
191}
192
193impl BorrowedHandle<'_> {
194 /// Creates a new `OwnedHandle` instance that shares the same underlying
195 /// object as the existing `BorrowedHandle` instance.
196 #[stable(feature = "io_safety", since = "1.63.0")]
197 pub fn try_clone_to_owned(&self) -> crate::io::Result<OwnedHandle> {
198 self.duplicate(0, false, sys::c::DUPLICATE_SAME_ACCESS)
199 }
200
201 pub(crate) fn duplicate(
202 &self,
203 access: u32,
204 inherit: bool,
205 options: u32,
206 ) -> io::Result<OwnedHandle> {
207 let handle = self.as_raw_handle();
208
209 // `Stdin`, `Stdout`, and `Stderr` can all hold null handles, such as
210 // in a process with a detached console. `DuplicateHandle` would fail
211 // if we passed it a null handle, but we can treat null as a valid
212 // handle which doesn't do any I/O, and allow it to be duplicated.
213 if handle.is_null() {
214 return unsafe { Ok(OwnedHandle::from_raw_handle(handle)) };
215 }
216
217 let mut ret = ptr::null_mut();
218 cvt(unsafe {
219 let cur_proc = sys::c::GetCurrentProcess();
220 sys::c::DuplicateHandle(
221 cur_proc,
222 handle,
223 cur_proc,
224 &mut ret,
225 access,
226 inherit as sys::c::BOOL,
227 options,
228 )
229 })?;
230 unsafe { Ok(OwnedHandle::from_raw_handle(ret)) }
231 }
232}
233
234#[stable(feature = "io_safety", since = "1.63.0")]
235impl TryFrom<HandleOrInvalid> for OwnedHandle {
236 type Error = InvalidHandleError;
237
238 #[inline]
239 fn try_from(handle_or_invalid: HandleOrInvalid) -> Result<Self, InvalidHandleError> {
240 let handle_or_invalid = ManuallyDrop::new(handle_or_invalid);
241 if handle_or_invalid.is_valid() {
242 // SAFETY: The handle is not invalid.
243 Ok(unsafe { OwnedHandle::from_raw_handle(handle_or_invalid.0) })
244 } else {
245 Err(InvalidHandleError(()))
246 }
247 }
248}
249
250#[stable(feature = "io_safety", since = "1.63.0")]
251impl Drop for HandleOrInvalid {
252 #[inline]
253 fn drop(&mut self) {
254 if self.is_valid() {
255 unsafe {
256 let _ = sys::c::CloseHandle(self.0);
257 }
258 }
259 }
260}
261
262/// This is the error type used by [`HandleOrNull`] when attempting to convert
263/// into a handle, to indicate that the value is null.
264// The empty field prevents constructing this, and allows extending it in the future.
265#[stable(feature = "io_safety", since = "1.63.0")]
266#[derive(Debug, Clone, PartialEq, Eq)]
267pub struct NullHandleError(());
268
269#[stable(feature = "io_safety", since = "1.63.0")]
270impl fmt::Display for NullHandleError {
271 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
272 "A HandleOrNull could not be converted to a handle because it was null".fmt(fmt)
273 }
274}
275
276#[stable(feature = "io_safety", since = "1.63.0")]
277impl crate::error::Error for NullHandleError {}
278
279/// This is the error type used by [`HandleOrInvalid`] when attempting to
280/// convert into a handle, to indicate that the value is
281/// `INVALID_HANDLE_VALUE`.
282// The empty field prevents constructing this, and allows extending it in the future.
283#[stable(feature = "io_safety", since = "1.63.0")]
284#[derive(Debug, Clone, PartialEq, Eq)]
285pub struct InvalidHandleError(());
286
287#[stable(feature = "io_safety", since = "1.63.0")]
288impl fmt::Display for InvalidHandleError {
289 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
290 "A HandleOrInvalid could not be converted to a handle because it was INVALID_HANDLE_VALUE"
291 .fmt(fmt)
292 }
293}
294
295#[stable(feature = "io_safety", since = "1.63.0")]
296impl crate::error::Error for InvalidHandleError {}
297
298#[stable(feature = "io_safety", since = "1.63.0")]
299impl AsRawHandle for BorrowedHandle<'_> {
300 #[inline]
301 fn as_raw_handle(&self) -> RawHandle {
302 self.handle
303 }
304}
305
306#[stable(feature = "io_safety", since = "1.63.0")]
307impl AsRawHandle for OwnedHandle {
308 #[inline]
309 fn as_raw_handle(&self) -> RawHandle {
310 self.handle
311 }
312}
313
314#[stable(feature = "io_safety", since = "1.63.0")]
315impl IntoRawHandle for OwnedHandle {
316 #[inline]
317 fn into_raw_handle(self) -> RawHandle {
318 ManuallyDrop::new(self).handle
319 }
320}
321
322#[stable(feature = "io_safety", since = "1.63.0")]
323impl FromRawHandle for OwnedHandle {
324 #[inline]
325 unsafe fn from_raw_handle(handle: RawHandle) -> Self {
326 Self { handle }
327 }
328}
329
330impl HandleOrNull {
331 /// Constructs a new instance of `Self` from the given `RawHandle` returned
332 /// from a Windows API that uses null to indicate failure, such as
333 /// `CreateThread`.
334 ///
335 /// Use `HandleOrInvalid` instead of `HandleOrNull` for APIs that
336 /// use `INVALID_HANDLE_VALUE` to indicate failure.
337 ///
338 /// # Safety
339 ///
340 /// The passed `handle` value must either satisfy the safety requirements
341 /// of [`FromRawHandle::from_raw_handle`], or be null. Note that not all
342 /// Windows APIs use null for errors; see [here] for the full story.
343 ///
344 /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
345 #[stable(feature = "io_safety", since = "1.63.0")]
346 #[inline]
347 pub unsafe fn from_raw_handle(handle: RawHandle) -> Self {
348 Self(handle)
349 }
350
351 fn is_valid(&self) -> bool {
352 !self.0.is_null()
353 }
354}
355
356impl HandleOrInvalid {
357 /// Constructs a new instance of `Self` from the given `RawHandle` returned
358 /// from a Windows API that uses `INVALID_HANDLE_VALUE` to indicate
359 /// failure, such as `CreateFileW`.
360 ///
361 /// Use `HandleOrNull` instead of `HandleOrInvalid` for APIs that
362 /// use null 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
368 /// `INVALID_HANDLE_VALUE` (-1). Note that not all Windows APIs use
369 /// `INVALID_HANDLE_VALUE` for errors; see [here] for the full story.
370 ///
371 /// [here]: https://devblogs.microsoft.com/oldnewthing/20040302-00/?p=40443
372 #[stable(feature = "io_safety", since = "1.63.0")]
373 #[inline]
374 pub unsafe fn from_raw_handle(handle: RawHandle) -> Self {
375 Self(handle)
376 }
377
378 fn is_valid(&self) -> bool {
379 self.0 != sys::c::INVALID_HANDLE_VALUE
380 }
381}
382
383#[stable(feature = "io_safety", since = "1.63.0")]
384impl Drop for OwnedHandle {
385 #[inline]
386 fn drop(&mut self) {
387 unsafe {
388 let _ = sys::c::CloseHandle(self.handle);
389 }
390 }
391}
392
393#[stable(feature = "io_safety", since = "1.63.0")]
394impl fmt::Debug for BorrowedHandle<'_> {
395 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
396 f.debug_struct("BorrowedHandle").field("handle", &self.handle).finish()
397 }
398}
399
400#[stable(feature = "io_safety", since = "1.63.0")]
401impl fmt::Debug for OwnedHandle {
402 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
403 f.debug_struct("OwnedHandle").field("handle", &self.handle).finish()
404 }
405}
406
407macro_rules! impl_is_terminal {
408 ($($t:ty),*$(,)?) => {$(
409 #[unstable(feature = "sealed", issue = "none")]
410 impl crate::sealed::Sealed for $t {}
411
412 #[stable(feature = "is_terminal", since = "1.70.0")]
413 impl crate::io::IsTerminal for $t {
414 #[inline]
415 fn is_terminal(&self) -> bool {
416 crate::sys::io::is_terminal(self)
417 }
418 }
419 )*}
420}
421
422impl_is_terminal!(BorrowedHandle<'_>, OwnedHandle);
423
424/// A trait to borrow the handle from an underlying object.
425#[stable(feature = "io_safety", since = "1.63.0")]
426pub trait AsHandle {
427 /// Borrows the handle.
428 ///
429 /// # Example
430 ///
431 /// ```rust,no_run
432 /// use std::fs::File;
433 /// # use std::io;
434 /// use std::os::windows::io::{AsHandle, BorrowedHandle};
435 ///
436 /// let mut f = File::open("foo.txt")?;
437 /// let borrowed_handle: BorrowedHandle<'_> = f.as_handle();
438 /// # Ok::<(), io::Error>(())
439 /// ```
440 #[stable(feature = "io_safety", since = "1.63.0")]
441 fn as_handle(&self) -> BorrowedHandle<'_>;
442}
443
444#[stable(feature = "io_safety", since = "1.63.0")]
445impl<T: AsHandle + ?Sized> AsHandle for &T {
446 #[inline]
447 fn as_handle(&self) -> BorrowedHandle<'_> {
448 T::as_handle(self)
449 }
450}
451
452#[stable(feature = "io_safety", since = "1.63.0")]
453impl<T: AsHandle + ?Sized> AsHandle for &mut T {
454 #[inline]
455 fn as_handle(&self) -> BorrowedHandle<'_> {
456 T::as_handle(self)
457 }
458}
459
460#[stable(feature = "as_windows_ptrs", since = "1.71.0")]
461/// This impl allows implementing traits that require `AsHandle` on Arc.
462/// ```
463/// # #[cfg(windows)] mod group_cfg {
464/// # use std::os::windows::io::AsHandle;
465/// use std::fs::File;
466/// use std::sync::Arc;
467///
468/// trait MyTrait: AsHandle {}
469/// impl MyTrait for Arc<File> {}
470/// impl MyTrait for Box<File> {}
471/// # }
472/// ```
473impl<T: AsHandle + ?Sized> AsHandle for crate::sync::Arc<T> {
474 #[inline]
475 fn as_handle(&self) -> BorrowedHandle<'_> {
476 (**self).as_handle()
477 }
478}
479
480#[stable(feature = "as_windows_ptrs", since = "1.71.0")]
481impl<T: AsHandle + ?Sized> AsHandle for crate::rc::Rc<T> {
482 #[inline]
483 fn as_handle(&self) -> BorrowedHandle<'_> {
484 (**self).as_handle()
485 }
486}
487
488#[unstable(feature = "unique_rc_arc", issue = "112566")]
489impl<T: AsHandle + ?Sized> AsHandle for crate::rc::UniqueRc<T> {
490 #[inline]
491 fn as_handle(&self) -> BorrowedHandle<'_> {
492 (**self).as_handle()
493 }
494}
495
496#[stable(feature = "as_windows_ptrs", since = "1.71.0")]
497impl<T: AsHandle + ?Sized> AsHandle for Box<T> {
498 #[inline]
499 fn as_handle(&self) -> BorrowedHandle<'_> {
500 (**self).as_handle()
501 }
502}
503
504#[stable(feature = "io_safety", since = "1.63.0")]
505impl AsHandle for BorrowedHandle<'_> {
506 #[inline]
507 fn as_handle(&self) -> BorrowedHandle<'_> {
508 *self
509 }
510}
511
512#[stable(feature = "io_safety", since = "1.63.0")]
513impl AsHandle for OwnedHandle {
514 #[inline]
515 fn as_handle(&self) -> BorrowedHandle<'_> {
516 // Safety: `OwnedHandle` and `BorrowedHandle` have the same validity
517 // invariants, and the `BorrowedHandle` is bounded by the lifetime
518 // of `&self`.
519 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
520 }
521}
522
523#[stable(feature = "io_safety", since = "1.63.0")]
524impl AsHandle for fs::File {
525 #[inline]
526 fn as_handle(&self) -> BorrowedHandle<'_> {
527 self.as_inner().as_handle()
528 }
529}
530
531#[stable(feature = "io_safety", since = "1.63.0")]
532impl From<fs::File> for OwnedHandle {
533 /// Takes ownership of a [`File`](fs::File)'s underlying file handle.
534 #[inline]
535 fn from(file: fs::File) -> OwnedHandle {
536 file.into_inner().into_inner().into_inner()
537 }
538}
539
540#[stable(feature = "io_safety", since = "1.63.0")]
541impl From<OwnedHandle> for fs::File {
542 /// Returns a [`File`](fs::File) that takes ownership of the given handle.
543 #[inline]
544 fn from(owned: OwnedHandle) -> Self {
545 Self::from_inner(FromInner::from_inner(FromInner::from_inner(owned)))
546 }
547}
548
549#[stable(feature = "io_safety", since = "1.63.0")]
550impl AsHandle for crate::io::Stdin {
551 #[inline]
552 fn as_handle(&self) -> BorrowedHandle<'_> {
553 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
554 }
555}
556
557#[stable(feature = "io_safety", since = "1.63.0")]
558impl<'a> AsHandle for crate::io::StdinLock<'a> {
559 #[inline]
560 fn as_handle(&self) -> BorrowedHandle<'_> {
561 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
562 }
563}
564
565#[stable(feature = "io_safety", since = "1.63.0")]
566impl AsHandle for crate::io::Stdout {
567 #[inline]
568 fn as_handle(&self) -> BorrowedHandle<'_> {
569 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
570 }
571}
572
573#[stable(feature = "io_safety", since = "1.63.0")]
574impl<'a> AsHandle for crate::io::StdoutLock<'a> {
575 #[inline]
576 fn as_handle(&self) -> BorrowedHandle<'_> {
577 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
578 }
579}
580
581#[stable(feature = "io_safety", since = "1.63.0")]
582impl AsHandle for crate::io::Stderr {
583 #[inline]
584 fn as_handle(&self) -> BorrowedHandle<'_> {
585 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
586 }
587}
588
589#[stable(feature = "io_safety", since = "1.63.0")]
590impl<'a> AsHandle for crate::io::StderrLock<'a> {
591 #[inline]
592 fn as_handle(&self) -> BorrowedHandle<'_> {
593 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
594 }
595}
596
597#[stable(feature = "io_safety", since = "1.63.0")]
598impl AsHandle for crate::process::ChildStdin {
599 #[inline]
600 fn as_handle(&self) -> BorrowedHandle<'_> {
601 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
602 }
603}
604
605#[stable(feature = "io_safety", since = "1.63.0")]
606impl From<crate::process::ChildStdin> for OwnedHandle {
607 /// Takes ownership of a [`ChildStdin`](crate::process::ChildStdin)'s file handle.
608 #[inline]
609 fn from(child_stdin: crate::process::ChildStdin) -> OwnedHandle {
610 unsafe { OwnedHandle::from_raw_handle(child_stdin.into_raw_handle()) }
611 }
612}
613
614#[stable(feature = "io_safety", since = "1.63.0")]
615impl AsHandle for crate::process::ChildStdout {
616 #[inline]
617 fn as_handle(&self) -> BorrowedHandle<'_> {
618 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
619 }
620}
621
622#[stable(feature = "io_safety", since = "1.63.0")]
623impl From<crate::process::ChildStdout> for OwnedHandle {
624 /// Takes ownership of a [`ChildStdout`](crate::process::ChildStdout)'s file handle.
625 #[inline]
626 fn from(child_stdout: crate::process::ChildStdout) -> OwnedHandle {
627 unsafe { OwnedHandle::from_raw_handle(child_stdout.into_raw_handle()) }
628 }
629}
630
631#[stable(feature = "io_safety", since = "1.63.0")]
632impl AsHandle for crate::process::ChildStderr {
633 #[inline]
634 fn as_handle(&self) -> BorrowedHandle<'_> {
635 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
636 }
637}
638
639#[stable(feature = "io_safety", since = "1.63.0")]
640impl From<crate::process::ChildStderr> for OwnedHandle {
641 /// Takes ownership of a [`ChildStderr`](crate::process::ChildStderr)'s file handle.
642 #[inline]
643 fn from(child_stderr: crate::process::ChildStderr) -> OwnedHandle {
644 unsafe { OwnedHandle::from_raw_handle(child_stderr.into_raw_handle()) }
645 }
646}
647
648#[stable(feature = "io_safety", since = "1.63.0")]
649impl<T> AsHandle for crate::thread::JoinHandle<T> {
650 #[inline]
651 fn as_handle(&self) -> BorrowedHandle<'_> {
652 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
653 }
654}
655
656#[stable(feature = "io_safety", since = "1.63.0")]
657impl<T> From<crate::thread::JoinHandle<T>> for OwnedHandle {
658 #[inline]
659 fn from(join_handle: crate::thread::JoinHandle<T>) -> OwnedHandle {
660 join_handle.into_inner().into_handle().into_inner()
661 }
662}