ntex_util/future/
mod.rs

1//! Utilities for futures
2use std::{future::poll_fn, future::Future, mem, pin::Pin, task::Context, task::Poll};
3
4pub use futures_core::{Stream, TryFuture};
5
6mod either;
7mod join;
8mod lazy;
9mod on_drop;
10mod ready;
11mod select;
12
13pub use self::either::Either;
14pub use self::join::{join, join_all};
15pub use self::lazy::{lazy, Lazy};
16pub use self::on_drop::{OnDropFn, OnDropFuture, OnDropFutureExt};
17pub use self::ready::Ready;
18pub use self::select::select;
19
20/// An owned dynamically typed Future for use in cases where
21/// you can't statically type your result or need to add some indirection.
22pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + 'a>>;
23
24/// Creates a future that resolves to the next item in the stream.
25pub async fn stream_recv<S>(stream: &mut S) -> Option<S::Item>
26where
27    S: Stream + Unpin,
28{
29    poll_fn(|cx| Pin::new(&mut *stream).poll_next(cx)).await
30}
31
32enum MaybeDone<F>
33where
34    F: Future,
35{
36    Pending(F),
37    Done(F::Output),
38    Gone,
39}
40
41impl<F: Future> MaybeDone<F> {
42    fn take_output(self: Pin<&mut Self>) -> Option<F::Output> {
43        match &*self {
44            Self::Done(_) => {}
45            Self::Pending(_) | Self::Gone => return None,
46        }
47        unsafe {
48            match mem::replace(self.get_unchecked_mut(), Self::Gone) {
49                MaybeDone::Done(output) => Some(output),
50                _ => unreachable!(),
51            }
52        }
53    }
54}
55
56impl<F: Future> Future for MaybeDone<F> {
57    type Output = ();
58
59    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
60        unsafe {
61            match self.as_mut().get_unchecked_mut() {
62                MaybeDone::Pending(f) => {
63                    let res = futures_core::ready!(Pin::new_unchecked(f).poll(cx));
64                    self.set(Self::Done(res));
65                }
66                MaybeDone::Done(_) => {}
67                MaybeDone::Gone => panic!("MaybeDone polled after value taken"),
68            }
69        }
70        Poll::Ready(())
71    }
72}