#[cfg(any(unix, target_os = "wasi"))]
use std::os::fd::{AsFd, AsRawFd, BorrowedFd, OwnedFd, RawFd};
#[cfg(windows)]
use std::os::windows::io::{AsRawSocket, AsSocket, BorrowedSocket, OwnedSocket, RawSocket};
use std::sync::Arc;
#[derive(Clone, Debug)]
pub struct IoSource(Arc<Owned>);
#[cfg(any(unix, target_os = "wasi"))]
type Owned = OwnedFd;
#[cfg(windows)]
type Owned = OwnedSocket;
impl IoSource {
pub(crate) fn new(owned: Owned) -> Self {
Self(Arc::new(owned))
}
}
#[cfg(any(unix, target_os = "wasi"))]
impl From<OwnedFd> for IoSource {
fn from(owned: OwnedFd) -> Self {
Self::new(owned)
}
}
#[cfg(windows)]
impl From<OwnedSocket> for IoSource {
fn from(owned: OwnedSocket) -> Self {
Self::new(owned)
}
}
#[cfg(any(unix, target_os = "wasi"))]
impl AsFd for IoSource {
fn as_fd(&self) -> BorrowedFd<'_> {
self.0.as_fd()
}
}
#[cfg(any(unix, target_os = "wasi"))]
impl AsRawFd for IoSource {
fn as_raw_fd(&self) -> RawFd {
self.0.as_raw_fd()
}
}
#[cfg(windows)]
impl AsSocket for IoSource {
fn as_socket(&self) -> BorrowedSocket<'_> {
self.0.as_socket()
}
}
#[cfg(windows)]
impl AsRawSocket for IoSource {
fn as_raw_socket(&self) -> RawSocket {
self.0.as_raw_socket()
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum Interest {
Readable,
Writable,
}
#[cfg(test)]
mod tests {
use super::*;
#[cfg(unix)]
fn owned() -> Owned {
std::os::unix::net::UnixStream::pair().unwrap().0.into()
}
#[cfg(windows)]
fn owned() -> Owned {
std::net::TcpListener::bind("127.0.0.1:0").unwrap().into()
}
#[test]
fn clone_keeps_the_descriptor_open() {
let source = IoSource::new(owned());
let clone = source.clone();
drop(source);
#[cfg(unix)]
let _: BorrowedFd<'_> = clone.as_fd();
#[cfg(windows)]
let _: BorrowedSocket<'_> = clone.as_socket();
}
}