#[allow(unused_imports)]
use std::os::fd::RawFd;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct Interest {
pub readable: bool,
pub writable: bool,
pub priority: bool,
pub oneshot: bool,
pub edge: bool,
}
impl Interest {
#[must_use]
pub const fn new() -> Self {
Self {
readable: false,
writable: false,
priority: false,
oneshot: false,
edge: false,
}
}
#[must_use]
pub const fn readable() -> Self {
Self {
readable: true,
writable: false,
priority: false,
oneshot: false,
edge: false,
}
}
#[must_use]
pub const fn writable() -> Self {
Self {
readable: false,
writable: true,
priority: false,
oneshot: false,
edge: false,
}
}
#[must_use]
pub const fn both() -> Self {
Self {
readable: true,
writable: true,
priority: false,
oneshot: false,
edge: false,
}
}
#[must_use]
pub const fn with_readable(mut self) -> Self {
self.readable = true;
self
}
#[must_use]
pub const fn with_writable(mut self) -> Self {
self.writable = true;
self
}
#[must_use]
pub const fn with_priority(mut self) -> Self {
self.priority = true;
self
}
#[must_use]
pub const fn with_oneshot(mut self) -> Self {
self.oneshot = true;
self
}
#[must_use]
pub const fn with_edge(mut self) -> Self {
self.edge = true;
self
}
#[cfg(target_os = "linux")]
pub const fn to_epoll_flags(self) -> u32 {
let mut flags = 0u32;
if self.readable {
flags |= libc::EPOLLIN as u32;
}
if self.writable {
flags |= libc::EPOLLOUT as u32;
}
if self.priority {
flags |= libc::EPOLLPRI as u32;
}
if self.oneshot {
flags |= libc::EPOLLONESHOT as u32;
}
if self.edge {
flags |= libc::EPOLLET as u32;
}
flags
}
#[cfg(target_os = "linux")]
pub fn from_epoll_flags(flags: u32) -> Self {
Self {
readable: (flags & libc::EPOLLIN as u32) != 0,
writable: (flags & libc::EPOLLOUT as u32) != 0,
priority: (flags & libc::EPOLLPRI as u32) != 0,
oneshot: (flags & libc::EPOLLONESHOT as u32) != 0,
edge: (flags & libc::EPOLLET as u32) != 0,
}
}
#[cfg(any(
target_os = "macos",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
target_os = "dragonfly"
))]
#[allow(dead_code)]
pub fn to_kqueue_filters(&self, fd: RawFd) -> (Vec<libc::kevent>, Vec<libc::kevent>) {
use std::mem::zeroed;
let mut add_events = Vec::with_capacity(2);
let remove_events = Vec::new();
if self.readable {
let mut event = unsafe { zeroed::<libc::kevent>() };
event.ident = fd as libc::uintptr_t;
event.filter = libc::EVFILT_READ;
event.flags = libc::EV_ADD | libc::EV_RECEIPT;
if self.edge {
event.flags |= libc::EV_CLEAR;
}
if self.oneshot {
event.flags |= libc::EV_ONESHOT;
}
add_events.push(event);
}
if self.writable {
let mut event = unsafe { zeroed::<libc::kevent>() };
event.ident = fd as libc::uintptr_t;
event.filter = libc::EVFILT_WRITE;
event.flags = libc::EV_ADD | libc::EV_RECEIPT;
if self.edge {
event.flags |= libc::EV_CLEAR;
}
if self.oneshot {
event.flags |= libc::EV_ONESHOT;
}
add_events.push(event);
}
(add_events, remove_events)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_interest_builder() {
let interest = Interest::readable().with_writable().with_edge();
assert!(interest.readable);
assert!(interest.writable);
assert!(interest.edge);
assert!(!interest.priority);
}
#[test]
fn test_interest_both() {
let interest = Interest::both();
assert!(interest.readable);
assert!(interest.writable);
}
}