1#![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#[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#[repr(transparent)]
66#[stable(feature = "io_safety", since = "1.63.0")]
67pub struct OwnedHandle {
68 handle: RawHandle,
69}
70
71#[repr(transparent)]
89#[stable(feature = "io_safety", since = "1.63.0")]
90#[derive(Debug)]
91pub struct HandleOrNull(RawHandle);
92
93#[repr(transparent)]
108#[stable(feature = "io_safety", since = "1.63.0")]
109#[derive(Debug)]
110pub struct HandleOrInvalid(RawHandle);
111
112#[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 #[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 #[cfg_attr(windows, doc = "```no_run")]
159 #[cfg_attr(not(windows), doc = "```ignore (needs windows)")]
160 #[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 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 #[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 #[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 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 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#[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#[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 #[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 #[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#[stable(feature = "io_safety", since = "1.63.0")]
449pub trait AsHandle {
450 #[cfg_attr(windows, doc = "```no_run")]
455 #[cfg_attr(not(windows), doc = "```ignore (needs windows)")]
456 #[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")]
485impl<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 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 #[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 #[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 #[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 #[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 #[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
720pub(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 fn type_check<T: From<OwnedHandle> + Into<OwnedHandle> + AsHandle>() {}
747
748 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 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}