async_hal/
interrupt.rs

1use core::{
2    pin::Pin,
3    task::{Context, Poll},
4};
5use futures::Stream;
6
7pub trait Interrupt {
8    type Error;
9
10    fn enable(&mut self) -> Result<(), Self::Error>;
11
12    fn disable(&mut self) -> Result<(), Self::Error>;
13
14    fn poll_interrupt(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), Self::Error>>;
15
16    fn poll_interrupt_unpin(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>>
17    where
18        Self: Unpin,
19    {
20        Pin::new(self).poll_interrupt(cx)
21    }
22
23    /// Enable the interrupt and return a [`Stream`] of events.
24    /// This will disable the interrupt on drop.
25    fn interrupts(&mut self) -> Interrupts<Self>
26    where
27        Self: Unpin,
28    {
29        Interrupts {
30            interrupt: self,
31            is_enabled: false,
32        }
33    }
34}
35
36pub struct Interrupts<'a, T: Interrupt + ?Sized> {
37    interrupt: &'a mut T,
38    is_enabled: bool,
39}
40
41impl<T> Stream for Interrupts<'_, T>
42where
43    T: Interrupt + Unpin + ?Sized,
44{
45    type Item = Result<(), T::Error>;
46
47    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
48        if !self.is_enabled {
49            self.interrupt.enable()?;
50            self.is_enabled = true;
51        }
52
53        self.interrupt.poll_interrupt_unpin(cx).map(Some)
54    }
55}
56
57impl<T> Drop for Interrupts<'_, T>
58where
59    T: Interrupt + ?Sized,
60{
61    fn drop(&mut self) {
62        self.interrupt.disable().ok();
63    }
64}