#![cfg(any(feature = "tokio", feature = "async-io"))]
use core::task::Poll;
use std::{io, os::unix::prelude::AsRawFd};
use crate::{event::InputEvent, uinput::UinputDevice, util::r#async::AsyncHelper};
#[derive(Debug)]
pub struct AsyncEvents<'a> {
helper: AsyncHelper,
dev: &'a UinputDevice,
}
impl<'a> AsyncEvents<'a> {
pub(crate) fn new(dev: &'a UinputDevice) -> io::Result<Self> {
Ok(Self {
helper: AsyncHelper::new(dev.as_raw_fd())?,
dev,
})
}
pub async fn next_event(&mut self) -> io::Result<InputEvent> {
self.helper
.asyncify(|| match self.dev.events().next() {
Some(res) => Poll::Ready(res),
None => Poll::Pending,
})
.await
}
}
#[cfg(test)]
mod tests {
use crate::{
event::{EventKind, Led, LedEvent},
test::pair,
util::r#async::test::AsyncTest,
};
use super::*;
#[test]
#[cfg_attr(
target_os = "freebsd",
ignore = "FreeBSD does not support non-blocking uinput devices"
)]
fn smoke() -> io::Result<()> {
let (uinput, evdev) = pair(|b| b.with_leds([Led::CAPSL]))?;
AsyncTest::new(
async {
let ev = uinput.async_events()?.next_event().await?;
match ev.kind() {
EventKind::Led(ev) if ev.led() == Led::CAPSL && ev.is_on() => {}
_ => panic!("unexpected event {ev:?}"),
}
Ok(())
},
|| evdev.write(&[LedEvent::new(Led::CAPSL, true).into()]),
)
.run()?;
Ok(())
}
}