use crate::futures::Sleep;
use core::{
pin::{Pin, pin},
task::{Context, Poll},
time::Duration,
};
pin_project_lite::pin_project! {
#[derive(Debug)]
pub struct Timeout<F> {
#[pin]
future: F,
#[pin]
sleep: Sleep,
}
}
impl<F> Timeout<F> {
#[inline]
pub fn new(future: F, duration: Duration) -> crate::Result<Self> {
Ok(Self { future, sleep: Sleep::new(duration)? })
}
}
impl<F> Future for Timeout<F>
where
F: Future,
{
type Output = crate::Result<Option<F::Output>>;
#[allow(unused_mut, reason = "depends on feature")]
#[inline]
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project();
if let Poll::Ready(output) = pin!(this.future).as_mut().poll(cx) {
return Poll::Ready(Ok(Some(output)));
}
let poll = this.sleep.poll(cx);
match poll {
Poll::Ready(Ok(_)) => Poll::Ready(Ok(None)),
Poll::Ready(Err(err)) => Poll::Ready(Err(err)),
Poll::Pending => Poll::Pending,
}
}
}
#[cfg(all(not(feature = "tokio"), test))]
mod tests {
use crate::futures::{Sleep, Timeout};
use core::{pin::pin, time::Duration};
#[wtx::test]
async fn timeout() {
assert_eq!(
Timeout::new(pin!(async { 1 }), Duration::from_millis(10)).unwrap().await.unwrap(),
Some(1)
);
assert_eq!(
Timeout::new(
pin!(async {
Sleep::new(Duration::from_millis(20)).unwrap().await.unwrap();
1
}),
Duration::from_millis(10)
)
.unwrap()
.await
.unwrap(),
None
);
}
}