1 //! Definition of the Lazy combinator, deferring execution of a function until
2 //! the future is polled.
3 
4 use core::mem;
5 
6 use {Future, IntoFuture, Poll};
7 
8 /// A future which defers creation of the actual future until a callback is
9 /// scheduled.
10 ///
11 /// This is created by the `lazy` function.
12 #[derive(Debug)]
13 #[must_use = "futures do nothing unless polled"]
14 pub struct Lazy<F, R: IntoFuture> {
15     inner: _Lazy<F, R::Future>,
16 }
17 
18 #[derive(Debug)]
19 enum _Lazy<F, R> {
20     First(F),
21     Second(R),
22     Moved,
23 }
24 
25 /// Creates a new future which will eventually be the same as the one created
26 /// by the closure provided.
27 ///
28 /// The provided closure is only run once the future has a callback scheduled
29 /// on it, otherwise the callback never runs. Once run, however, this future is
30 /// the same as the one the closure creates.
31 ///
32 /// # Examples
33 ///
34 /// ```
35 /// use futures::future::*;
36 ///
37 /// let a = lazy(|| ok::<u32, u32>(1));
38 ///
39 /// let b = lazy(|| -> FutureResult<u32, u32> {
40 ///     panic!("oh no!")
41 /// });
42 /// drop(b); // closure is never run
43 /// ```
lazy<F, R>(f: F) -> Lazy<F, R> where F: FnOnce() -> R, R: IntoFuture44 pub fn lazy<F, R>(f: F) -> Lazy<F, R>
45     where F: FnOnce() -> R,
46           R: IntoFuture
47 {
48     Lazy {
49         inner: _Lazy::First(f),
50     }
51 }
52 
53 impl<F, R> Lazy<F, R>
54     where F: FnOnce() -> R,
55           R: IntoFuture,
56 {
get(&mut self) -> &mut R::Future57     fn get(&mut self) -> &mut R::Future {
58         match self.inner {
59             _Lazy::First(_) => {}
60             _Lazy::Second(ref mut f) => return f,
61             _Lazy::Moved => panic!(), // can only happen if `f()` panics
62         }
63         match mem::replace(&mut self.inner, _Lazy::Moved) {
64             _Lazy::First(f) => self.inner = _Lazy::Second(f().into_future()),
65             _ => panic!(), // we already found First
66         }
67         match self.inner {
68             _Lazy::Second(ref mut f) => f,
69             _ => panic!(), // we just stored Second
70         }
71     }
72 }
73 
74 impl<F, R> Future for Lazy<F, R>
75     where F: FnOnce() -> R,
76           R: IntoFuture,
77 {
78     type Item = R::Item;
79     type Error = R::Error;
80 
poll(&mut self) -> Poll<R::Item, R::Error>81     fn poll(&mut self) -> Poll<R::Item, R::Error> {
82         self.get().poll()
83     }
84 }
85