use core::pin::Pin; use futures_core::future::{FusedFuture, Future}; use futures_core::ready; use futures_core::task::{Context, Poll}; use pin_project_lite::pin_project; use crate::fns::FnOnce1; pin_project! { /// Internal Map future #[project = MapProj] #[project_replace = MapProjReplace] #[derive(Debug)] #[must_use = "futures do nothing unless you `.await` or poll them"] pub enum Map { Incomplete { #[pin] future: Fut, f: F, }, Complete, } } impl Map { /// Creates a new Map. pub(crate) fn new(future: Fut, f: F) -> Self { Self::Incomplete { future, f } } } impl FusedFuture for Map where Fut: Future, F: FnOnce1, { fn is_terminated(&self) -> bool { match self { Self::Incomplete { .. } => false, Self::Complete => true, } } } impl Future for Map where Fut: Future, F: FnOnce1, { type Output = T; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { match self.as_mut().project() { MapProj::Incomplete { future, .. } => { let output = ready!(future.poll(cx)); match self.project_replace(Map::Complete) { MapProjReplace::Incomplete { f, .. } => Poll::Ready(f.call_once(output)), MapProjReplace::Complete => unreachable!(), } } MapProj::Complete => { panic!("Map must not be polled after it returned `Poll::Ready`") } } } }