diff options
Diffstat (limited to 'third_party/rust/futures-0.1.31/src/future/lazy.rs')
-rw-r--r-- | third_party/rust/futures-0.1.31/src/future/lazy.rs | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/third_party/rust/futures-0.1.31/src/future/lazy.rs b/third_party/rust/futures-0.1.31/src/future/lazy.rs new file mode 100644 index 0000000000..2f310337b6 --- /dev/null +++ b/third_party/rust/futures-0.1.31/src/future/lazy.rs @@ -0,0 +1,84 @@ +//! 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<F, R: IntoFuture> { + inner: _Lazy<F, R::Future>, +} + +#[derive(Debug)] +enum _Lazy<F, R> { + 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::<u32, u32>(1)); +/// +/// let b = lazy(|| -> FutureResult<u32, u32> { +/// panic!("oh no!") +/// }); +/// drop(b); // closure is never run +/// ``` +pub fn lazy<F, R>(f: F) -> Lazy<F, R> + where F: FnOnce() -> R, + R: IntoFuture +{ + Lazy { + inner: _Lazy::First(f), + } +} + +impl<F, R> Lazy<F, R> + 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<F, R> Future for Lazy<F, R> + where F: FnOnce() -> R, + R: IntoFuture, +{ + type Item = R::Item; + type Error = R::Error; + + fn poll(&mut self) -> Poll<R::Item, R::Error> { + self.get().poll() + } +} |