use std::io::IsTerminal;
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
#[allow(unused)]
pub enum ResourceHandle {
Fd(ResourceHandleFd),
Socket(ResourceHandleSocket),
}
#[cfg(unix)]
pub type ResourceHandleFd = std::os::fd::RawFd;
#[cfg(unix)]
pub type ResourceHandleSocket = std::os::fd::RawFd;
#[cfg(windows)]
pub type ResourceHandleFd = std::os::windows::io::RawHandle;
#[cfg(windows)]
pub type ResourceHandleSocket = std::os::windows::io::RawSocket;
impl ResourceHandle {
#[cfg(windows)]
pub fn from_fd_like(io: &impl std::os::windows::io::AsRawHandle) -> Self {
Self::Fd(io.as_raw_handle())
}
#[cfg(unix)]
pub fn from_fd_like(io: &impl std::os::unix::io::AsRawFd) -> Self {
Self::Fd(io.as_raw_fd())
}
#[cfg(windows)]
pub fn from_socket_like(io: &impl std::os::windows::io::AsRawSocket) -> Self {
Self::Socket(io.as_raw_socket())
}
#[cfg(unix)]
pub fn from_socket_like(io: &impl std::os::unix::io::AsRawFd) -> Self {
Self::Socket(io.as_raw_fd())
}
pub fn is_valid(&self) -> bool {
#[cfg(windows)]
{
match self {
Self::Fd(handle) => {
!handle.is_null()
&& *handle != -1_isize as std::os::windows::io::RawHandle
}
Self::Socket(socket) => {
*socket != -1_i64 as std::os::windows::io::RawSocket
}
}
}
#[cfg(unix)]
{
match self {
Self::Fd(fd) => *fd >= 0,
Self::Socket(fd) => *fd >= 0,
}
}
}
pub fn as_fd_like(&self) -> Option<ResourceHandleFd> {
match self {
Self::Fd(fd) => Some(*fd),
_ => None,
}
}
pub fn as_socket_like(&self) -> Option<ResourceHandleSocket> {
match self {
Self::Socket(socket) => Some(*socket),
_ => None,
}
}
pub fn is_terminal(&self) -> bool {
match self {
Self::Fd(fd) if self.is_valid() => {
#[cfg(windows)]
{
unsafe {
std::os::windows::io::BorrowedHandle::borrow_raw(*fd).is_terminal()
}
}
#[cfg(unix)]
{
unsafe { std::os::fd::BorrowedFd::borrow_raw(*fd).is_terminal() }
}
}
_ => false,
}
}
}