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
use crate::error::Error;
use core::future::Future;
use core::pin::Pin;
use core::task::Context;
use core::task::Poll;
pub use core::time::Duration;

#[cfg(feature = "tokio_asyncs")]
pub mod time_impl {
    use super::{Context, Duration, Future, Pin, Poll};

    pub struct DelayImpl(tokio::time::Delay);
    impl DelayImpl {
        pub fn new(duration: Duration) -> Self {
            Self(tokio::time::delay_for(duration))
        }
        pub fn reset(&mut self, dur: Duration) {
            self.0.reset(tokio::time::Instant::now() + dur)
        }
    }
    impl Future for DelayImpl {
        type Output = ();

        fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
            unsafe { self.map_unchecked_mut(|s| &mut s.0) }.poll(cx)
        }
    }
}

pub fn delay_for(duration: Duration) -> Delay {
    Delay::new(duration)
}

pub struct Delay(time_impl::DelayImpl);
impl Delay {
    fn new(duration: Duration) -> Self {
        Self(time_impl::DelayImpl::new(duration))
    }
    pub fn reset(&mut self, duration: Duration) {
        self.0.reset(duration)
    }
}
impl Future for Delay {
    type Output = ();

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        unsafe { self.map_unchecked_mut(|s| &mut s.0) }.poll(cx)
    }
}

pub fn timeout<T, F: Future<Output = T>>(duration: Duration, future: F) -> TimeoutFuture<F> {
    TimeoutFuture {
        future,
        delay: Delay::new(duration),
    }
}

#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug, Default)]
pub struct TimeoutError(());
impl Error for TimeoutError {}
pub struct TimeoutFuture<F: Future> {
    future: F,
    delay: Delay,
}
impl<F: Future> Future for TimeoutFuture<F> {
    type Output = Result<F::Output, TimeoutError>;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        match unsafe { self.as_mut().map_unchecked_mut(|s| &mut s.future) }.poll(cx) {
            Poll::Ready(v) => Poll::Ready(Ok(v)),
            Poll::Pending => {
                match unsafe { self.as_mut().map_unchecked_mut(|s| &mut s.delay) }.poll(cx) {
                    Poll::Ready(_) => Poll::Ready(Err(TimeoutError(()))),
                    Poll::Pending => Poll::Pending,
                }
            }
        }
    }
}