use std::{
error::Error,
fmt::{self, Display},
future::Future,
pin::pin,
task::Poll,
time::{Duration, Instant},
};
use super::sleep::{sleep, sleep_until};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Elapsed(());
impl Display for Elapsed {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("deadline has elapsed")
}
}
impl Error for Elapsed {}
pub async fn timeout<F: Future>(duration: Duration, future: F) -> Result<F::Output, Elapsed> {
let mut future = pin!(future);
let mut delay = pin!(sleep(duration));
std::future::poll_fn(|cx| {
if let Poll::Ready(output) = future.as_mut().poll(cx) {
return Poll::Ready(Ok(output));
}
if delay.as_mut().poll(cx).is_ready() {
return Poll::Ready(Err(Elapsed(())));
}
Poll::Pending
})
.await
}
pub async fn timeout_at<F: Future>(deadline: Instant, future: F) -> Result<F::Output, Elapsed> {
let mut future = pin!(future);
let mut delay = pin!(sleep_until(deadline));
std::future::poll_fn(|cx| {
if let Poll::Ready(output) = future.as_mut().poll(cx) {
return Poll::Ready(Ok(output));
}
if delay.as_mut().poll(cx).is_ready() {
return Poll::Ready(Err(Elapsed(())));
}
Poll::Pending
})
.await
}