use super as io;
use super::raw::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle};
use super::win::*;
use core::fmt;
use core::marker::PhantomData;
use core::mem::ManuallyDrop;
use core::ptr;
#[repr(transparent)]
#[derive(Copy, Clone)]
pub struct BorrowedHandle<'handle> {
handle: RawHandle,
_phantom: PhantomData<&'handle OwnedHandle>,
}
#[repr(transparent)]
pub struct OwnedHandle {
handle: RawHandle,
}
#[repr(transparent)]
#[derive(Debug)]
pub struct HandleOrNull(RawHandle);
#[repr(transparent)]
#[derive(Debug)]
pub struct HandleOrInvalid(RawHandle);
unsafe impl Send for OwnedHandle {}
unsafe impl Send for HandleOrNull {}
unsafe impl Send for HandleOrInvalid {}
unsafe impl Send for BorrowedHandle<'_> {}
unsafe impl Sync for OwnedHandle {}
unsafe impl Sync for HandleOrNull {}
unsafe impl Sync for HandleOrInvalid {}
unsafe impl Sync for BorrowedHandle<'_> {}
impl BorrowedHandle<'_> {
#[inline]
pub const unsafe fn borrow_raw(handle: RawHandle) -> Self {
Self {
handle,
_phantom: PhantomData,
}
}
}
impl TryFrom<HandleOrNull> for OwnedHandle {
type Error = NullHandleError;
#[inline]
fn try_from(handle_or_null: HandleOrNull) -> Result<Self, NullHandleError> {
let handle_or_null = ManuallyDrop::new(handle_or_null);
if handle_or_null.is_valid() {
Ok(unsafe { OwnedHandle::from_raw_handle(handle_or_null.0) })
} else {
Err(NullHandleError(()))
}
}
}
impl Drop for HandleOrNull {
#[inline]
fn drop(&mut self) {
if self.is_valid() {
unsafe {
let _ = CloseHandle(self.0.as_windows_handle());
}
}
}
}
impl OwnedHandle {
pub fn try_clone(&self) -> io::Result<Self> {
self.as_handle().try_clone_to_owned()
}
}
impl BorrowedHandle<'_> {
pub fn try_clone_to_owned(&self) -> io::Result<OwnedHandle> {
self.duplicate(0, false, DUPLICATE_SAME_ACCESS.0)
}
pub(crate) fn duplicate(
&self,
access: u32,
inherit: bool,
options: u32,
) -> io::Result<OwnedHandle> {
let handle = self.as_raw_handle();
if handle.is_null() {
return unsafe { Ok(OwnedHandle::from_raw_handle(handle)) };
}
let mut ret = ptr::null_mut();
unsafe {
let cur_proc = GetCurrentProcess();
DuplicateHandle(
cur_proc,
handle.as_windows_handle(),
cur_proc,
&mut ret as *mut _ as *mut _,
access,
inherit,
DUPLICATE_HANDLE_OPTIONS(options),
)?
};
unsafe { Ok(OwnedHandle::from_raw_handle(ret)) }
}
}
impl TryFrom<HandleOrInvalid> for OwnedHandle {
type Error = InvalidHandleError;
#[inline]
fn try_from(handle_or_invalid: HandleOrInvalid) -> Result<Self, InvalidHandleError> {
let handle_or_invalid = ManuallyDrop::new(handle_or_invalid);
if handle_or_invalid.is_valid() {
Ok(unsafe { OwnedHandle::from_raw_handle(handle_or_invalid.0) })
} else {
Err(InvalidHandleError(()))
}
}
}
impl Drop for HandleOrInvalid {
#[inline]
fn drop(&mut self) {
if self.is_valid() {
unsafe {
let _ = CloseHandle(self.0.as_windows_handle());
}
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct NullHandleError(());
impl fmt::Display for NullHandleError {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
"A HandleOrNull could not be converted to a handle because it was null".fmt(fmt)
}
}
impl core::error::Error for NullHandleError {}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct InvalidHandleError(());
impl fmt::Display for InvalidHandleError {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
"A HandleOrInvalid could not be converted to a handle because it was INVALID_HANDLE_VALUE"
.fmt(fmt)
}
}
impl core::error::Error for InvalidHandleError {}
impl AsRawHandle for BorrowedHandle<'_> {
#[inline]
fn as_raw_handle(&self) -> RawHandle {
self.handle
}
}
impl AsRawHandle for OwnedHandle {
#[inline]
fn as_raw_handle(&self) -> RawHandle {
self.handle
}
}
impl IntoRawHandle for OwnedHandle {
#[inline]
fn into_raw_handle(self) -> RawHandle {
ManuallyDrop::new(self).handle
}
}
impl FromRawHandle for OwnedHandle {
#[inline]
unsafe fn from_raw_handle(handle: RawHandle) -> Self {
Self { handle }
}
}
impl HandleOrNull {
#[inline]
pub unsafe fn from_raw_handle(handle: RawHandle) -> Self {
Self(handle)
}
fn is_valid(&self) -> bool {
!self.0.is_null()
}
}
impl HandleOrInvalid {
#[inline]
pub unsafe fn from_raw_handle(handle: RawHandle) -> Self {
Self(handle)
}
fn is_valid(&self) -> bool {
self.0.as_windows_handle() != INVALID_HANDLE_VALUE
}
}
impl Drop for OwnedHandle {
#[inline]
fn drop(&mut self) {
unsafe {
let _ = CloseHandle(self.handle.as_windows_handle());
}
}
}
impl fmt::Debug for BorrowedHandle<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("BorrowedHandle")
.field("handle", &self.handle)
.finish()
}
}
impl fmt::Debug for OwnedHandle {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("OwnedHandle")
.field("handle", &self.handle)
.finish()
}
}
pub trait AsHandle {
fn as_handle(&self) -> BorrowedHandle<'_>;
}
impl<T: AsHandle + ?Sized> AsHandle for &T {
#[inline]
fn as_handle(&self) -> BorrowedHandle<'_> {
T::as_handle(self)
}
}
impl<T: AsHandle + ?Sized> AsHandle for &mut T {
#[inline]
fn as_handle(&self) -> BorrowedHandle<'_> {
T::as_handle(self)
}
}
#[cfg(any(feature = "alloc"))]
impl<T: AsHandle + ?Sized> AsHandle for alloc::sync::Arc<T> {
#[inline]
fn as_handle(&self) -> BorrowedHandle<'_> {
(**self).as_handle()
}
}
#[cfg(feature = "alloc")]
impl<T: AsHandle + ?Sized> AsHandle for alloc::rc::Rc<T> {
#[inline]
fn as_handle(&self) -> BorrowedHandle<'_> {
(**self).as_handle()
}
}
#[cfg(feature = "nightly")]
#[cfg(feature = "alloc")]
impl<T: AsHandle + ?Sized> AsHandle for alloc::rc::UniqueRc<T> {
#[inline]
fn as_handle(&self) -> BorrowedHandle<'_> {
(**self).as_handle()
}
}
impl<T: AsHandle + ?Sized> AsHandle for Box<T> {
#[inline]
fn as_handle(&self) -> BorrowedHandle<'_> {
(**self).as_handle()
}
}
impl AsHandle for BorrowedHandle<'_> {
#[inline]
fn as_handle(&self) -> BorrowedHandle<'_> {
*self
}
}
impl AsHandle for OwnedHandle {
#[inline]
fn as_handle(&self) -> BorrowedHandle<'_> {
unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
}
}