diff --git a/futures-util/src/future/always_ready.rs b/futures-util/src/future/always_ready.rs new file mode 100644 index 000000000..28625e727 --- /dev/null +++ b/futures-util/src/future/always_ready.rs @@ -0,0 +1,62 @@ +use super::assert_future; +use core::pin::Pin; +use futures_core::future::{FusedFuture, Future}; +use futures_core::task::{Context, Poll}; + +/// Future for the [`always_ready`](always_ready()) function. +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct AlwaysReady T>(F); + +impl T> core::fmt::Debug for AlwaysReady { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.debug_tuple("AlwaysReady").finish() + } +} + +impl T + Clone> Clone for AlwaysReady { + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} + +impl T + Copy> Copy for AlwaysReady {} + +impl T> Unpin for AlwaysReady {} + +impl T> FusedFuture for AlwaysReady { + fn is_terminated(&self) -> bool { + false + } +} + +impl T> Future for AlwaysReady { + type Output = T; + + #[inline] + fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { + Poll::Ready(self.0()) + } +} + +/// Creates a future that is always immediately ready with a value. +/// +/// This is particularly useful in avoiding a heap allocation when an API needs [`Box>`], +/// as [`AlwaysReady`] does not have to store a boolean for `is_finished`. +/// +/// # Examples +/// +/// ``` +/// # futures::executor::block_on(async { +/// use std::mem::size_of_val; +/// +/// use futures::future; +/// +/// let a = future::always_ready(|| 1); +/// assert_eq!(size_of_val(&a), 0); +/// assert_eq!(a.await, 1); +/// assert_eq!(a.await, 1); +/// # }); +/// ``` +pub fn always_ready T>(prod: F) -> AlwaysReady { + assert_future::(AlwaysReady(prod)) +} diff --git a/futures-util/src/future/mod.rs b/futures-util/src/future/mod.rs index 21b1a4eb5..1280ce986 100644 --- a/futures-util/src/future/mod.rs +++ b/futures-util/src/future/mod.rs @@ -74,6 +74,9 @@ pub use self::poll_immediate::{poll_immediate, PollImmediate}; mod ready; pub use self::ready::{err, ok, ready, Ready}; +mod always_ready; +pub use self::always_ready::{always_ready, AlwaysReady}; + mod join; pub use self::join::{join, Join};