1 use core::pin::Pin; 2 use futures_core::future::{FusedFuture, Future}; 3 use futures_core::ready; 4 use futures_core::task::{Context, Poll}; 5 use pin_project_lite::pin_project; 6 7 use crate::fns::FnOnce1; 8 9 pin_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 25 impl<Fut, F> Map<Fut, F> { 26 /// Creates a new Map. new(future: Fut, f: F) -> Self27 pub(crate) fn new(future: Fut, f: F) -> Self { 28 Self::Incomplete { future, f } 29 } 30 } 31 32 impl<Fut, F, T> FusedFuture for Map<Fut, F> 33 where 34 Fut: Future, 35 F: FnOnce1<Fut::Output, Output = T>, 36 { is_terminated(&self) -> bool37 fn is_terminated(&self) -> bool { 38 match self { 39 Self::Incomplete { .. } => false, 40 Self::Complete => true, 41 } 42 } 43 } 44 45 impl<Fut, F, T> Future for Map<Fut, F> 46 where 47 Fut: Future, 48 F: FnOnce1<Fut::Output, Output = T>, 49 { 50 type Output = T; 51 poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T>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(Self::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