agnostic_lite/embassy/
interval.rs1use 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
14pub 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}