use std::{io, os::unix::io::RawFd};
#[cfg(target_os = "linux")]
mod epoll;
#[cfg(target_os = "linux")]
use epoll::Epoll as Poller;
#[cfg(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
))]
mod kqueue;
#[cfg(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
))]
use kqueue::Kqueue as Poller;
#[derive(Copy, Clone, Debug)]
pub enum Mode {
OneShot,
Level,
Edge,
}
#[derive(Copy, Clone, Debug)]
pub enum Interest {
Readable,
Writable,
Both,
}
#[allow(dead_code)]
impl Interest {
fn contains_read(self) -> bool {
match self {
Interest::Readable => true,
Interest::Writable => false,
Interest::Both => true,
}
}
fn contains_write(self) -> bool {
match self {
Interest::Readable => false,
Interest::Writable => true,
Interest::Both => false,
}
}
}
#[derive(Copy, Clone, Debug)]
pub struct Readiness {
pub readable: bool,
pub writable: bool,
pub error: bool,
}
pub(crate) struct PollEvent {
pub(crate) readiness: Readiness,
pub(crate) token: Token,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Token {
pub(crate) id: u32,
pub sub_id: u32,
}
#[allow(dead_code)]
impl Token {
pub(crate) fn to_u64(self) -> u64 {
((self.id as u64) << 32) + self.sub_id as u64
}
pub(crate) fn from_u64(i: u64) -> Token {
Token {
id: (i >> 32) as u32,
sub_id: (i & std::u32::MAX as u64) as u32,
}
}
pub(crate) fn to_u32(self) -> u32 {
(self.id << 16) + self.sub_id
}
pub(crate) fn from_u32(i: u32) -> Token {
Token {
id: (i >> 16),
sub_id: (i & std::u16::MAX as u32),
}
}
#[cfg(target_pointer_width = "64")]
pub(crate) fn to_usize(self) -> usize {
self.to_u64() as usize
}
#[cfg(target_pointer_width = "32")]
pub(crate) fn to_usize(self) -> usize {
self.to_u32() as usize
}
#[cfg(target_pointer_width = "64")]
pub(crate) fn from_usize(i: usize) -> Token {
Self::from_u64(i as u64)
}
#[cfg(target_pointer_width = "32")]
pub(crate) fn from_usize(i: usize) -> Token {
Self::from_u64(i as u64)
}
}
pub struct Poll {
poller: Poller,
}
impl Poll {
pub(crate) fn new() -> io::Result<Poll> {
Ok(Poll {
poller: Poller::new()?,
})
}
pub(crate) fn poll(
&mut self,
timeout: Option<std::time::Duration>,
) -> io::Result<Vec<PollEvent>> {
self.poller.poll(timeout)
}
pub fn register(
&mut self,
fd: RawFd,
interest: Interest,
mode: Mode,
token: Token,
) -> io::Result<()> {
self.poller.register(fd, interest, mode, token)
}
pub fn reregister(
&mut self,
fd: RawFd,
interest: Interest,
mode: Mode,
token: Token,
) -> io::Result<()> {
self.poller.reregister(fd, interest, mode, token)
}
pub fn unregister(&mut self, fd: RawFd) -> io::Result<()> {
self.poller.unregister(fd)
}
}
#[cfg(test)]
mod tests {
use super::Token;
#[test]
fn token_convert() {
let t = Token {
id: 0x1337,
sub_id: 0x42,
};
assert_eq!(t.to_u64(), 0x0000133700000042);
let t2 = Token::from_u64(0x0000133700000042);
assert_eq!(t, t2);
}
}