Skip to main content

agnostic_lite/embassy/
interval.rs

1use core::{
2  future::Future,
3  pin::Pin,
4  task::{Context, Poll},
5  time::Duration,
6};
7
8use futures_util::stream::Stream;
9
10use crate::time::{AsyncLocalInterval, AsyncLocalIntervalExt, AsyncLocalSleep, AsyncSleepExt};
11
12use super::{EmbassySleep, Instant};
13
14/// The [`AsyncInterval`](crate::time::AsyncInterval) implementation for the embassy runtime.
15///
16/// **Note:** `EmbassyInterval` is not accurate below the resolution of the configured
17/// [`embassy-time`](https://docs.rs/embassy-time) tick rate.
18pub struct EmbassyInterval {
19  inner: Pin<std::boxed::Box<EmbassySleep>>,
20  first: bool,
21}
22
23impl Stream for EmbassyInterval {
24  type Item = Instant;
25
26  fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
27    self.get_mut().poll_tick(cx).map(Some)
28  }
29}
30
31impl AsyncLocalInterval for EmbassyInterval {
32  type Instant = Instant;
33
34  fn reset(&mut self, interval: Duration) {
35    self.inner.as_mut().reset(Instant::now() + interval);
36  }
37
38  fn reset_at(&mut self, instant: Instant) {
39    self.inner.as_mut().reset(instant);
40  }
41
42  fn poll_tick(&mut self, cx: &mut Context<'_>) -> Poll<Instant> {
43    if self.first {
44      self.first = false;
45      return Poll::Ready(self.inner.ddl - self.inner.duration);
46    }
47
48    match self.inner.as_mut().poll(cx) {
49      Poll::Ready(ins) => {
50        let duration = self.inner.duration;
51        self.inner.as_mut().reset(Instant::now() + duration);
52        Poll::Ready(ins)
53      }
54      Poll::Pending => Poll::Pending,
55    }
56  }
57}
58
59impl AsyncLocalIntervalExt for EmbassyInterval {
60  fn interval_local(period: Duration) -> Self
61  where
62    Self: Sized,
63  {
64    Self {
65      inner: std::boxed::Box::pin(EmbassySleep::sleep(period)),
66      first: true,
67    }
68  }
69
70  fn interval_local_at(start: Instant, period: Duration) -> Self
71  where
72    Self: Sized,
73  {
74    Self {
75      inner: std::boxed::Box::pin(EmbassySleep::sleep_until(start + period)),
76      first: true,
77    }
78  }
79}