use core::marker::PhantomData;
use core::mem::MaybeUninit;
use libredox::error::{Error, Result};
use crate::raw;
pub use crate::raw::EventFlags;
pub struct RawEventQueue {
inner: usize,
}
pub type RawEvent = raw::RawEventV1;
impl RawEventQueue {
pub fn new() -> Result<Self> {
Ok(Self {
inner: Error::demux(unsafe { raw::redox_event_queue_create_v1(0) })?,
})
}
pub fn subscribe(&self, fd: usize, user_data: usize, flags: EventFlags) -> Result<()> {
let _ = Error::demux(unsafe {
raw::redox_event_queue_ctl_v1(self.inner, fd, flags.bits(), user_data)
})?;
Ok(())
}
pub fn unsubscribe(&self, fd: usize) -> Result<()> {
self.subscribe(fd, 0, EventFlags::empty())
}
pub fn next_event(&self) -> Result<RawEvent> {
let mut event = MaybeUninit::uninit();
unsafe {
let res = Error::demux(raw::redox_event_queue_get_events_v1(
self.inner,
event.as_mut_ptr(),
1,
0,
core::ptr::null(),
core::ptr::null(),
))?;
assert_eq!(res, 1, "EOF is not yet well defined for event queues");
Ok(event.assume_init())
}
}
pub fn iter(&self) -> impl Iterator<Item = Result<RawEvent>> + '_ {
core::iter::from_fn(|| Some(self.next_event()))
}
}
impl Drop for RawEventQueue {
fn drop(&mut self) {
unsafe {
let _ = Error::demux(raw::redox_event_queue_destroy_v1(self.inner));
}
}
}
impl Iterator for RawEventQueue {
type Item = Result<RawEvent>;
fn next(&mut self) -> Option<Self::Item> {
Some(self.next_event())
}
}
#[macro_export]
macro_rules! user_data {
{
$vis:vis enum $name:ident {
$($variant:ident),*$(,)?
}
} => {
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[repr(usize)]
$vis enum $name {
$($variant),*
}
impl $crate::UserData for $name {
fn into_user_data(self) -> usize {
self as usize
}
fn from_user_data(raw: usize) -> Self {
assert!(raw < [$(Self::$variant),*].len());
unsafe { ::core::mem::transmute(raw) }
}
}
};
}
pub trait UserData: Clone + Copy {
fn into_user_data(self) -> usize;
fn from_user_data(user_data: usize) -> Self;
}
impl UserData for usize {
fn into_user_data(self) -> usize {
self
}
fn from_user_data(user_data: usize) -> Self {
user_data
}
}
#[non_exhaustive]
pub struct Event<U: UserData> {
pub user_data: U,
pub flags: EventFlags,
pub fd: usize,
}
pub struct EventQueue<U: UserData> {
inner: RawEventQueue,
_marker: PhantomData<*mut U>,
}
impl<U: UserData> EventQueue<U> {
#[inline]
pub fn new() -> Result<Self> {
Ok(EventQueue {
inner: RawEventQueue::new()?,
_marker: PhantomData,
})
}
#[inline]
pub fn subscribe(&self, fd: usize, data: U, flags: EventFlags) -> Result<()> {
self.inner.subscribe(fd, data.into_user_data(), flags)
}
#[inline]
pub fn unsubscribe(&self, fd: usize) -> Result<()> {
self.inner.unsubscribe(fd)
}
#[inline]
pub fn raw(&self) -> &RawEventQueue {
&self.inner
}
pub fn next_event(&self) -> Result<Event<U>> {
self.inner.next_event().map(|raw| Event {
user_data: U::from_user_data(raw.user_data),
fd: raw.fd,
flags: EventFlags::from_bits_retain(raw.flags),
})
}
pub fn iter(&self) -> impl Iterator<Item = Result<Event<U>>> + '_ {
core::iter::from_fn(|| Some(self.next_event()))
}
}
impl<U: UserData> Iterator for EventQueue<U> {
type Item = Result<Event<U>>;
fn next(&mut self) -> Option<Self::Item> {
Some(self.next_event())
}
}