1use core::pin::Pin;
2use futures_core::future::{FusedFuture, Future};
3use futures_core::ready;
4use futures_core::task::{Context, Poll};
5use pin_project_lite::pin_project;
6
7use crate::fns::FnOnce1;
8
9pin_project! {
10 /// Internal Map future
11 #[project = MapProj]
12 #[project_replace = MapProjReplace]
13 #[derive(Debug)]
14 #[must_use = "futures do nothing unless you `.await` or poll them"]
15 pub enum Map<Fut, F> {
16 Incomplete {
17 #[pin]
18 future: Fut,
19 f: F,
20 },
21 Complete,
22 }
23}
24
25impl<Fut, F> Map<Fut, F> {
26 /// Creates a new Map.
27 pub(crate) fn new(future: Fut, f: F) -> Self {
28 Self::Incomplete { future, f }
29 }
30}
31
32impl<Fut, F, T> FusedFuture for Map<Fut, F>
33where
34 Fut: Future,
35 F: FnOnce1<Fut::Output, Output = T>,
36{
37 fn is_terminated(&self) -> bool {
38 match self {
39 Self::Incomplete { .. } => false,
40 Self::Complete => true,
41 }
42 }
43}
44
45impl<Fut, F, T> Future for Map<Fut, F>
46where
47 Fut: Future,
48 F: FnOnce1<Fut::Output, Output = T>,
49{
50 type Output = T;
51
52 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
53 match self.as_mut().project() {
54 MapProj::Incomplete { future, .. } => {
55 let output = ready!(future.poll(cx));
56 match self.project_replace(Map::Complete) {
57 MapProjReplace::Incomplete { f, .. } => Poll::Ready(f.call_once(output)),
58 MapProjReplace::Complete => unreachable!(),
59 }
60 }
61 MapProj::Complete => {
62 panic!("Map must not be polled after it returned `Poll::Ready`")
63 }
64 }
65 }
66}
67