use std::{io, ops::Deref};
#[cfg(unix)]
use std::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, RawFd};
#[cfg(windows)]
use std::os::windows::io::{AsRawHandle, AsRawSocket, FromRawHandle, FromRawSocket, RawHandle, RawSocket};
use super::io_handle::SharedIoHandle;
#[cfg(windows)]
use crate::runtime::local::CURRENT_DRIVER;
pub(crate) struct AttachedHandle<T> {
source: SharedIoHandle<T>,
}
impl<T> std::fmt::Debug for AttachedHandle<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("AttachedHandle").finish_non_exhaustive()
}
}
impl<T> AttachedHandle<T> {
pub unsafe fn new_unchecked(source: T) -> Self {
Self {
source: SharedIoHandle::new(source),
}
}
}
#[cfg(windows)]
impl<T: AsRawHandle> AttachedHandle<T> {
pub fn new(source: T) -> io::Result<Self> {
let source = SharedIoHandle::new(source);
current_driver()?.associate(&source.handle_registration())?;
Ok(Self { source })
}
}
#[cfg(windows)]
impl<T: AsRawSocket> AttachedHandle<T> {
pub fn new_socket(source: T) -> io::Result<Self> {
let source = SharedIoHandle::new(source);
current_driver()?.associate(&source.socket_registration())?;
Ok(Self { source })
}
}
#[cfg(windows)]
fn current_driver() -> io::Result<crate::driver::Handle> {
if !CURRENT_DRIVER.is_set() {
return Err(io::Error::new(
io::ErrorKind::NotConnected,
"handle attachment requires a running karmaio runtime",
));
}
CURRENT_DRIVER.with(|handle| {
if handle.upgrade().is_none() {
return Err(io::Error::new(
io::ErrorKind::BrokenPipe,
"karmaio runtime is no longer available for handle attachment",
));
}
Ok(handle.clone())
})
}
#[cfg(unix)]
impl<T: AsFd> AttachedHandle<T> {
pub fn new(source: T) -> io::Result<Self> {
Ok(unsafe { Self::new_unchecked(source) })
}
}
impl<T> Deref for AttachedHandle<T> {
type Target = SharedIoHandle<T>;
fn deref(&self) -> &Self::Target {
&self.source
}
}
impl<T> AttachedHandle<T> {
pub(crate) fn ptr_eq(&self, other: &Self) -> bool {
self.source.ptr_eq(&other.source)
}
pub(crate) fn strong_count(&self) -> usize {
self.source.strong_count()
}
pub(crate) fn into_inner(self) -> SharedIoHandle<T> {
self.source
}
pub(crate) fn try_unwrap(self) -> Result<T, Self> {
self.source.try_unwrap().map_err(|source| Self { source })
}
}
impl<T> Clone for AttachedHandle<T> {
fn clone(&self) -> Self {
Self {
source: self.source.clone(),
}
}
}
#[cfg(unix)]
impl<T: AsFd> AsFd for AttachedHandle<T> {
fn as_fd(&self) -> BorrowedFd<'_> {
self.source.as_fd()
}
}
#[cfg(unix)]
impl<T: AsRawFd> AsRawFd for AttachedHandle<T> {
fn as_raw_fd(&self) -> RawFd {
self.source.raw_fd()
}
}
#[cfg(windows)]
impl<T: AsRawHandle> AsRawHandle for AttachedHandle<T> {
fn as_raw_handle(&self) -> RawHandle {
self.source.raw_handle()
}
}
#[cfg(windows)]
impl<T: AsRawSocket> AsRawSocket for AttachedHandle<T> {
fn as_raw_socket(&self) -> RawSocket {
self.source.raw_socket()
}
}
#[cfg(windows)]
impl<T: FromRawHandle> FromRawHandle for AttachedHandle<T> {
unsafe fn from_raw_handle(handle: RawHandle) -> Self {
unsafe { Self::new_unchecked(T::from_raw_handle(handle)) }
}
}
#[cfg(windows)]
impl<T: FromRawSocket> FromRawSocket for AttachedHandle<T> {
unsafe fn from_raw_socket(sock: RawSocket) -> Self {
unsafe { Self::new_unchecked(T::from_raw_socket(sock)) }
}
}
#[cfg(unix)]
impl<T: FromRawFd> FromRawFd for AttachedHandle<T> {
unsafe fn from_raw_fd(fd: RawFd) -> Self {
unsafe { Self::new_unchecked(T::from_raw_fd(fd)) }
}
}