1#![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#[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#[repr(transparent)]
65#[stable(feature = "io_safety", since = "1.63.0")]
66pub struct OwnedHandle {
67 handle: RawHandle,
68}
69
70#[repr(transparent)]
88#[stable(feature = "io_safety", since = "1.63.0")]
89#[derive(Debug)]
90pub struct HandleOrNull(RawHandle);
91
92#[repr(transparent)]
107#[stable(feature = "io_safety", since = "1.63.0")]
108#[derive(Debug)]
109pub struct HandleOrInvalid(RawHandle);
110
111#[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 #[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 #[cfg_attr(windows, doc = "```no_run")]
158 #[cfg_attr(not(windows), doc = "```ignore (needs windows)")]
159 #[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 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 #[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 #[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 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 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#[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#[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 #[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 #[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#[stable(feature = "io_safety", since = "1.63.0")]
444pub trait AsHandle {
445 #[cfg_attr(windows, doc = "```no_run")]
450 #[cfg_attr(not(windows), doc = "```ignore (needs windows)")]
451 #[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")]
480impl<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 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 #[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 #[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 #[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 #[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 #[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
704pub(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 fn type_check<T: From<OwnedHandle> + Into<OwnedHandle> + AsHandle>() {}
731
732 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 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}