Skip to content

Commit a32ea8e

Browse files
darconeouscramertj
authored andcommitted
futures-util: Added FutureExt::now_or_never() (#1747)
`now_or_never()` is a convenience method for `FutureExt` that evaluates and consumes the future, returning the resulting output if the future is ready after the first call to `Future::poll`. If `poll` instead returns `Poll::Pending`, `None` is returned. This method is useful in cases where immediacy is more important than waiting for a result. It is also convenient for quickly obtaining the value of a future that is known to always resolve immediately. It is named after the english phrase "It's *now or never*", which the Macmillan Dictionary defines[¹] as such: > used for saying that if something is not done immediately, there > will not be another chance to do it in the future [¹]: https://www.macmillandictionary.com/us/dictionary/american/it-s-now-or-never
1 parent 7136a1e commit a32ea8e

File tree

1 file changed

+48
-0
lines changed

1 file changed

+48
-0
lines changed

futures-util/src/future/mod.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,54 @@ pub trait FutureExt: Future {
531531
{
532532
Pin::new(self).poll(cx)
533533
}
534+
535+
/// Evaluates and consumes the future, returning the resulting output if
536+
/// the future is ready after the first call to `Future::poll`.
537+
///
538+
/// If `poll` instead returns `Poll::Pending`, `None` is returned.
539+
///
540+
/// This method is useful in cases where immediacy is more important than
541+
/// waiting for a result. It is also convenient for quickly obtaining
542+
/// the value of a future that is known to always resolve immediately.
543+
///
544+
/// # Examples
545+
///
546+
/// ```
547+
/// # use futures::prelude::*;
548+
/// use futures::{future::ready, future::pending};
549+
/// let future_ready = ready("foobar");
550+
/// let future_pending = pending::<&'static str>();
551+
///
552+
/// assert_eq!(future_ready.now_or_never(), Some("foobar"));
553+
/// assert_eq!(future_pending.now_or_never(), None);
554+
/// ```
555+
///
556+
/// In cases where it is absolutely known that a future should always
557+
/// resolve immediately and never return `Poll::Pending`, this method can
558+
/// be combined with `expect()`:
559+
///
560+
/// ```
561+
/// # use futures::{prelude::*, future::ready};
562+
/// let future_ready = ready("foobar");
563+
///
564+
/// assert_eq!(future_ready.now_or_never().expect("Future not ready"), "foobar");
565+
/// ```
566+
fn now_or_never(mut self) -> Option<Self::Output>
567+
where Self: Sized
568+
{
569+
let noop_waker = crate::task::noop_waker();
570+
let mut cx = Context::from_waker(&noop_waker);
571+
572+
// SAFETY: This is safe because this method consumes the future, so `poll` is
573+
// only going to be called once. Thus it doesn't matter to us if the
574+
// future is `Unpin` or not.
575+
let pinned = unsafe { Pin::new_unchecked(&mut self) };
576+
577+
match pinned.poll(&mut cx) {
578+
Poll::Ready(x) => Some(x),
579+
_ => None,
580+
}
581+
}
534582
}
535583

536584
// Just a helper function to ensure the futures we're returning all have the

0 commit comments

Comments
 (0)