1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
use core::future::Future;
use core::{fmt, task, time};
use core::pin::Pin;
use crate::delay::Delay;
use crate::{Timer, PlatformTimer};
#[must_use = "Timed does nothing unless polled"]
pub struct Timed<F, T=PlatformTimer> {
state: Option<(F, Delay<T>)>,
}
impl<F> Timed<F> {
#[inline]
pub fn platform_new(inner: F, timeout: time::Duration) -> Self {
Timed::<F, PlatformTimer>::new(inner, timeout)
}
}
impl<F, T: Timer> Timed<F, T> {
pub fn new(inner: F, timeout: time::Duration) -> Self {
Self {
state: Some((inner, Delay::<T>::new(timeout))),
}
}
fn state(&mut self) -> &mut (F, Delay<T>) {
match self.state {
Some(ref mut state) => state,
None => unreach!()
}
}
}
impl<F: Future + Unpin, T: Timer> Future for Timed<F, T> {
type Output = Result<F::Output, Expired<F, T>>;
fn poll(mut self: Pin<&mut Self>, ctx: &mut task::Context) -> task::Poll<Self::Output> {
let inner = unsafe { self.as_mut().map_unchecked_mut(|this| &mut this.state().0) };
match Future::poll(inner, ctx) {
task::Poll::Pending => (),
task::Poll::Ready(result) => return task::Poll::Ready(Ok(result)),
}
let delay = unsafe { self.as_mut().map_unchecked_mut(|this| &mut this.state().1) };
match Future::poll(delay, ctx) {
task::Poll::Pending => task::Poll::Pending,
task::Poll::Ready(_) => return task::Poll::Ready(Err(Expired {
state: self.state.take()
}))
}
}
}
pub struct Expired<F, T> {
state: Option<(F, Delay<T>)>,
}
impl<F, T> Expired<F, T> {
pub fn into_inner(self) -> F {
match self.state {
Some((inner, _)) => inner,
None => unreach!()
}
}
}
impl<F: Future + Unpin, T: Timer> Future for Expired<F, T> {
type Output = Timed<F, T>;
fn poll(mut self: Pin<&mut Self>, ctx: &mut task::Context) -> task::Poll<Self::Output> {
match self.state.take() {
Some((inner, mut delay)) => {
delay.restart(ctx);
task::Poll::Ready(Timed::<F, T> {
state: Some((inner, delay)),
})
},
None => unreach!(),
}
}
}
#[cfg(not(feature = "no_std"))]
impl<F, T: Timer> std::error::Error for Expired<F, T> {}
impl<F, T: Timer> fmt::Debug for Expired<F, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self)
}
}
impl<F, T: Timer> fmt::Display for Expired<F, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.state {
Some((_, ref delay)) => match delay.timeout.as_secs() {
0 => write!(f, "Future expired in {}ms", delay.timeout.as_millis()),
secs => write!(f, "Future expired in {} seconds and {} ms", secs, delay.timeout.as_millis()),
},
None => write!(f, "Future expired"),
}
}
}