1#![cfg(target_os = "linux")]
20
21pub use udev::{
22 Attributes, Device, Enumerator, Event, EventType, MonitorBuilder,
23 MonitorSocket, Properties,
24};
25
26use futures_core::stream::Stream;
27use std::{convert::TryFrom, io, pin::Pin, sync::Mutex, task::Poll};
28use tokio::io::unix::AsyncFd;
29
30pub struct AsyncMonitorSocket {
32 inner: Mutex<Inner>,
33}
34
35impl AsyncMonitorSocket {
36 pub fn new(monitor: MonitorSocket) -> io::Result<AsyncMonitorSocket> {
38 Ok(AsyncMonitorSocket {
39 inner: Mutex::new(Inner::new(monitor)?),
40 })
41 }
42}
43
44impl TryFrom<MonitorSocket> for AsyncMonitorSocket {
45 type Error = io::Error;
46
47 fn try_from(
48 monitor: MonitorSocket,
49 ) -> Result<AsyncMonitorSocket, Self::Error> {
50 AsyncMonitorSocket::new(monitor)
51 }
52}
53
54impl Stream for AsyncMonitorSocket {
55 type Item = Result<udev::Event, io::Error>;
56
57 fn poll_next(
58 self: Pin<&mut Self>,
59 ctx: &mut std::task::Context,
60 ) -> Poll<Option<Self::Item>> {
61 self.inner.lock().unwrap().poll_receive(ctx)
62 }
63}
64
65struct Inner {
66 fd: AsyncFd<MonitorSocket>,
67}
68
69impl Inner {
70 fn new(monitor: MonitorSocket) -> io::Result<Inner> {
71 Ok(Inner {
72 fd: AsyncFd::new(monitor)?,
73 })
74 }
75
76 fn poll_receive(
77 &mut self,
78 ctx: &mut std::task::Context,
79 ) -> Poll<Option<Result<Event, io::Error>>> {
80 loop {
81 if let Some(e) = self.fd.get_mut().iter().next() {
82 return Poll::Ready(Some(Ok(e)));
83 }
84 match self.fd.poll_read_ready(ctx) {
85 Poll::Ready(Ok(mut ready_guard)) => {
86 ready_guard.clear_ready();
87 }
88 Poll::Ready(Err(err)) => return Poll::Ready(Some(Err(err))),
89 Poll::Pending => return Poll::Pending,
90 }
91 }
92 }
93}