Add raw_stream::enumerate() -> Iterator<RawDevice>

This commit is contained in:
Noah 2021-03-22 12:17:26 -05:00 committed by Jeff Hiner
parent be24cc15be
commit 9f63c9a0eb
3 changed files with 42 additions and 18 deletions

View file

@ -86,7 +86,6 @@ pub mod uinput;
#[cfg(feature = "tokio")] #[cfg(feature = "tokio")]
mod tokio_stream; mod tokio_stream;
use std::os::unix::ffi::OsStrExt;
use std::time::{Duration, SystemTime}; use std::time::{Duration, SystemTime};
use std::{fmt, io}; use std::{fmt, io};
@ -241,28 +240,17 @@ impl fmt::Debug for InputEvent {
/// an empty iterator or omits the devices that could not be opened. /// an empty iterator or omits the devices that could not be opened.
pub fn enumerate() -> EnumerateDevices { pub fn enumerate() -> EnumerateDevices {
EnumerateDevices { EnumerateDevices {
readdir: std::fs::read_dir("/dev/input").ok(), inner: raw_stream::enumerate(),
} }
} }
pub struct EnumerateDevices { pub struct EnumerateDevices {
readdir: Option<std::fs::ReadDir>, inner: raw_stream::EnumerateDevices,
} }
impl Iterator for EnumerateDevices { impl Iterator for EnumerateDevices {
type Item = Device; type Item = Device;
fn next(&mut self) -> Option<Device> { fn next(&mut self) -> Option<Device> {
let readdir = self.readdir.as_mut()?; self.inner.next().map(Device::from_raw_device)
loop {
if let Ok(entry) = readdir.next()? {
let path = entry.path();
let fname = path.file_name().unwrap();
if fname.as_bytes().starts_with(b"event") {
if let Ok(dev) = Device::open(&path) {
return Some(dev);
}
}
}
}
} }
} }

View file

@ -518,6 +518,38 @@ fn vec_spare_capacity_mut<T>(v: &mut Vec<T>) -> &mut [mem::MaybeUninit<T>] {
} }
} }
/// Crawls `/dev/input` for evdev devices.
///
/// Will not bubble up any errors in opening devices or traversing the directory. Instead returns
/// an empty iterator or omits the devices that could not be opened.
pub fn enumerate() -> EnumerateDevices {
EnumerateDevices {
readdir: std::fs::read_dir("/dev/input").ok(),
}
}
pub struct EnumerateDevices {
readdir: Option<std::fs::ReadDir>,
}
impl Iterator for EnumerateDevices {
type Item = RawDevice;
fn next(&mut self) -> Option<RawDevice> {
use std::os::unix::ffi::OsStrExt;
let readdir = self.readdir.as_mut()?;
loop {
if let Ok(entry) = readdir.next()? {
let path = entry.path();
let fname = path.file_name().unwrap();
if fname.as_bytes().starts_with(b"event") {
if let Ok(dev) = RawDevice::open(&path) {
return Some(dev);
}
}
}
}
}
}
#[cfg(feature = "tokio")] #[cfg(feature = "tokio")]
mod tokio_stream { mod tokio_stream {
use super::*; use super::*;

View file

@ -35,18 +35,22 @@ impl Device {
Self::_open(path.as_ref()) Self::_open(path.as_ref())
} }
#[inline]
fn _open(path: &Path) -> io::Result<Device> { fn _open(path: &Path) -> io::Result<Device> {
let raw = RawDevice::open(path)?; RawDevice::open(path).map(Self::from_raw_device)
}
// TODO: should this be public?
pub(crate) fn from_raw_device(raw: RawDevice) -> Device {
let state = DeviceState::new(&raw); let state = DeviceState::new(&raw);
let prev_state = state.clone(); let prev_state = state.clone();
Ok(Device { Device {
raw, raw,
prev_state, prev_state,
state, state,
block_dropped: false, block_dropped: false,
}) }
} }
/// Returns the synchronization engine's current understanding (cache) of the device state. /// Returns the synchronization engine's current understanding (cache) of the device state.