diff --git a/src/future/future.rs b/src/future/future.rs index 8c9c12a23..fe685176a 100644 --- a/src/future/future.rs +++ b/src/future/future.rs @@ -1,3 +1,11 @@ +cfg_unstable! { + mod delay; + + use std::time::Duration; + + use delay::DelayFuture; +} + extension_trait! { use std::pin::Pin; use std::ops::{Deref, DerefMut}; @@ -99,6 +107,28 @@ extension_trait! { } pub trait FutureExt: std::future::Future { + /// Returns a Future that delays execution for a specified time. + /// + /// # Examples + /// + /// ``` + /// # async_std::task::block_on(async { + /// use async_std::prelude::*; + /// use async_std::future; + /// use std::time::Duration; + /// + /// let a = future::ready(1).delay(Duration::from_millis(2000)); + /// dbg!(a.await); + /// # }) + /// ``` + #[cfg_attr(feature = "docs", doc(cfg(unstable)))] + #[cfg(any(feature = "unstable", feature = "docs"))] + fn delay(self, dur: Duration) -> impl Future [DelayFuture] + where + Self: Future + Sized + { + DelayFuture::new(self, dur) + } } impl Future for Box { diff --git a/src/future/future/delay.rs b/src/future/future/delay.rs new file mode 100644 index 000000000..d672541ee --- /dev/null +++ b/src/future/future/delay.rs @@ -0,0 +1,43 @@ +use std::pin::Pin; +use std::time::Duration; + +use futures_timer::Delay; +use pin_project_lite::pin_project; + +use crate::future::Future; +use crate::task::{Context, Poll}; + +pin_project! { + #[doc(hidden)] + #[derive(Debug)] + pub struct DelayFuture { + #[pin] + future: F, + #[pin] + delay: Delay, + } +} + +impl DelayFuture { + pub fn new(future: F, dur: Duration) -> DelayFuture { + let delay = Delay::new(dur); + + DelayFuture { future, delay } + } +} + +impl Future for DelayFuture { + type Output = F::Output; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let this = self.project(); + + match this.delay.poll(cx) { + Poll::Pending => Poll::Pending, + Poll::Ready(_) => match this.future.poll(cx) { + Poll::Ready(v) => Poll::Ready(v), + Poll::Pending => Poll::Pending, + }, + } + } +}