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