//! Definition of the Lazy combinator, deferring execution of a function until //! the future is polled. use core::mem; use {Future, IntoFuture, Poll}; /// A future which defers creation of the actual future until a callback is /// scheduled. /// /// This is created by the `lazy` function. #[derive(Debug)] #[must_use = "futures do nothing unless polled"] pub struct Lazy { inner: _Lazy, } #[derive(Debug)] enum _Lazy { First(F), Second(R), Moved, } /// Creates a new future which will eventually be the same as the one created /// by the closure provided. /// /// The provided closure is only run once the future has a callback scheduled /// on it, otherwise the callback never runs. Once run, however, this future is /// the same as the one the closure creates. /// /// # Examples /// /// ``` /// use futures::future::*; /// /// let a = lazy(|| ok::(1)); /// /// let b = lazy(|| -> FutureResult { /// panic!("oh no!") /// }); /// drop(b); // closure is never run /// ``` pub fn lazy(f: F) -> Lazy where F: FnOnce() -> R, R: IntoFuture { Lazy { inner: _Lazy::First(f), } } impl Lazy where F: FnOnce() -> R, R: IntoFuture, { fn get(&mut self) -> &mut R::Future { match self.inner { _Lazy::First(_) => {} _Lazy::Second(ref mut f) => return f, _Lazy::Moved => panic!(), // can only happen if `f()` panics } match mem::replace(&mut self.inner, _Lazy::Moved) { _Lazy::First(f) => self.inner = _Lazy::Second(f().into_future()), _ => panic!(), // we already found First } match self.inner { _Lazy::Second(ref mut f) => f, _ => panic!(), // we just stored Second } } } impl Future for Lazy where F: FnOnce() -> R, R: IntoFuture, { type Item = R::Item; type Error = R::Error; fn poll(&mut self) -> Poll { self.get().poll() } }