use std::mem; use super::{Future, Pin, Poll, task}; pub(crate) trait Started: Future { fn started(&self) -> bool; } pub(crate) fn lazy(func: F) -> Lazy where F: FnOnce() -> R, R: Future + Unpin, { Lazy { inner: Inner::Init(func), } } // FIXME: allow() required due to `impl Trait` leaking types to this lint #[allow(missing_debug_implementations)] pub(crate) struct Lazy { inner: Inner } enum Inner { Init(F), Fut(R), Empty, } impl Started for Lazy where F: FnOnce() -> R, R: Future + Unpin, { fn started(&self) -> bool { match self.inner { Inner::Init(_) => false, Inner::Fut(_) | Inner::Empty => true, } } } impl Future for Lazy where F: FnOnce() -> R, R: Future + Unpin, { type Output = R::Output; fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll { match self.inner { Inner::Fut(ref mut f) => return Pin::new(f).poll(cx), _ => (), } match mem::replace(&mut self.inner, Inner::Empty) { Inner::Init(func) => { let mut fut = func(); let ret = Pin::new(&mut fut).poll(cx); self.inner = Inner::Fut(fut); ret }, _ => unreachable!("lazy state wrong"), } } } // The closure `F` is never pinned impl Unpin for Lazy {}