1 use core::pin::Pin;
2 use futures_core::future::{FusedFuture, Future};
3 use futures_core::task::{Context, Poll};
4 use pin_project_lite::pin_project;
5 
6 pin_project! {
7     /// Future for the [`fuse`](super::FutureExt::fuse) method.
8     #[derive(Debug)]
9     #[must_use = "futures do nothing unless you `.await` or poll them"]
10     pub struct Fuse<Fut> {
11         #[pin]
12         inner: Option<Fut>,
13     }
14 }
15 
16 impl<Fut> Fuse<Fut> {
new(f: Fut) -> Self17     pub(super) fn new(f: Fut) -> Self {
18         Self { inner: Some(f) }
19     }
20 }
21 
22 impl<Fut: Future> Fuse<Fut> {
23     /// Creates a new `Fuse`-wrapped future which is already terminated.
24     ///
25     /// This can be useful in combination with looping and the `select!`
26     /// macro, which bypasses terminated futures.
27     ///
28     /// # Examples
29     ///
30     /// ```
31     /// # futures::executor::block_on(async {
32     /// use futures::channel::mpsc;
33     /// use futures::future::{Fuse, FusedFuture, FutureExt};
34     /// use futures::select;
35     /// use futures::stream::StreamExt;
36     /// use futures::pin_mut;
37     ///
38     /// let (sender, mut stream) = mpsc::unbounded();
39     ///
40     /// // Send a few messages into the stream
41     /// sender.unbounded_send(()).unwrap();
42     /// sender.unbounded_send(()).unwrap();
43     /// drop(sender);
44     ///
45     /// // Use `Fuse::terminated()` to create an already-terminated future
46     /// // which may be instantiated later.
47     /// let foo_printer = Fuse::terminated();
48     /// pin_mut!(foo_printer);
49     ///
50     /// loop {
51     ///     select! {
52     ///         _ = foo_printer => {},
53     ///         () = stream.select_next_some() => {
54     ///             if !foo_printer.is_terminated() {
55     ///                 println!("Foo is already being printed!");
56     ///             } else {
57     ///                 foo_printer.set(async {
58     ///                     // do some other async operations
59     ///                     println!("Printing foo from `foo_printer` future");
60     ///                 }.fuse());
61     ///             }
62     ///         },
63     ///         complete => break, // `foo_printer` is terminated and the stream is done
64     ///     }
65     /// }
66     /// # });
67     /// ```
terminated() -> Self68     pub fn terminated() -> Self {
69         Self { inner: None }
70     }
71 }
72 
73 impl<Fut: Future> FusedFuture for Fuse<Fut> {
is_terminated(&self) -> bool74     fn is_terminated(&self) -> bool {
75         self.inner.is_none()
76     }
77 }
78 
79 impl<Fut: Future> Future for Fuse<Fut> {
80     type Output = Fut::Output;
81 
poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Fut::Output>82     fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Fut::Output> {
83         match self.as_mut().project().inner.as_pin_mut() {
84             Some(fut) => fut.poll(cx).map(|output| {
85                 self.project().inner.set(None);
86                 output
87             }),
88             None => Poll::Pending,
89         }
90     }
91 }
92