use core::pin::Pin;
use core::task::{Context, Poll};
use std::time::Duration;
use async_io::Timer;
use futures_lite::Future;
use pin_project_lite::pin_project;
pub fn timeout<T, F>(future: F, timeout: &Duration) -> Timeout<F>
where
F: Future<Output = T>,
{
Timeout {
future,
timer: Timer::after(timeout.clone()),
}
}
pin_project! {
#[derive(Debug)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct Timeout<F> {
#[pin]
future: F,
#[pin]
timer: Timer,
}
}
impl<T, F> Future for Timeout<F>
where
F: Future<Output = T>,
{
type Output = Option<T>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project();
if let Poll::Ready(t) = this.future.poll(cx) {
return Poll::Ready(Some(t));
}
if let Poll::Ready(_t) = this.timer.poll(cx) {
return Poll::Ready(None);
}
Poll::Pending
}
}