Skip to main content

agnostic_lite/embassy/
timeout.rs

1use core::{
2  future::Future,
3  pin::Pin,
4  task::{Context, Poll},
5  time::Duration,
6};
7
8use embassy_time::Timer;
9
10use crate::time::{AsyncLocalTimeout, AsyncTimeout, Elapsed};
11
12use super::{Instant, to_embassy_duration};
13
14pin_project_lite::pin_project! {
15  /// The [`AsyncTimeout`] implementation for the embassy runtime.
16  pub struct EmbassyTimeout<F> {
17    #[pin]
18    future: F,
19    #[pin]
20    delay: Timer,
21  }
22}
23
24impl<F: Future> Future for EmbassyTimeout<F> {
25  type Output = Result<F::Output, Elapsed>;
26
27  fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
28    let this = self.project();
29    match this.future.poll(cx) {
30      Poll::Ready(v) => Poll::Ready(Ok(v)),
31      Poll::Pending => match this.delay.poll(cx) {
32        Poll::Ready(()) => Poll::Ready(Err(Elapsed)),
33        Poll::Pending => Poll::Pending,
34      },
35    }
36  }
37}
38
39impl<F: Future + Send> AsyncTimeout<F> for EmbassyTimeout<F> {
40  type Instant = Instant;
41
42  fn timeout(t: Duration, fut: F) -> Self
43  where
44    Self: Sized,
45  {
46    <Self as AsyncLocalTimeout<F>>::timeout_local(t, fut)
47  }
48
49  fn timeout_at(deadline: Instant, fut: F) -> Self
50  where
51    Self: Sized,
52  {
53    <Self as AsyncLocalTimeout<F>>::timeout_local_at(deadline, fut)
54  }
55}
56
57impl<F: Future> AsyncLocalTimeout<F> for EmbassyTimeout<F> {
58  type Instant = Instant;
59
60  fn timeout_local(timeout: Duration, fut: F) -> Self
61  where
62    Self: Sized,
63  {
64    Self {
65      future: fut,
66      delay: Timer::after(to_embassy_duration(timeout)),
67    }
68  }
69
70  fn timeout_local_at(deadline: Instant, fut: F) -> Self
71  where
72    Self: Sized,
73  {
74    Self {
75      future: fut,
76      delay: Timer::at(deadline.into_embassy()),
77    }
78  }
79}