futures_macro_await/
lib.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#![no_std]

//! An internal helper crate to workaround limitations in the
//! `use_extern_macros` feature with re-exported Macros 1.0 macros.
//!
//! All macros defined here should be imported via [`futures::prelude`] instead.

/// Await a sub-future inside an `#[async]` function.
///
/// You should pass an object implementing [`Future`] or [`StableFuture`] to
/// this macro, it will implicitly `yield` while that future returns
/// [`Async::Pending`] and evaluate to a [`Result`] containing the result of
/// that future once complete.
///
/// # Examples
///
#[cfg_attr(feature = "nightly", doc = "```")]
#[cfg_attr(not(feature = "nightly"), doc = "```ignore")]
/// #![feature(proc_macro, generators, pin)]
/// extern crate futures;
///
/// use futures::prelude::*;
/// use futures::future;
/// use futures::stable::block_on_stable;
///
/// #[async]
/// fn probably_one() -> Result<u32, u32> {
///     let one = await!(future::ok::<u32, u32>(1))?;
///     Ok(one)
/// }
///
/// assert_eq!(Ok(1), block_on_stable(probably_one()));
/// ```

#[macro_export]
macro_rules! await {
    ($e:expr) => ({
        let mut future = $e;
        let future = &mut future;
        // The above borrow is necessary to force a borrow across a
        // yield point, proving that we're currently in an immovable
        // generator, making the below `PinMut::new_unchecked` call
        // safe.
        loop {
            let poll = ::futures::__rt::in_ctx(|ctx| {
                let pin = unsafe {
                    ::futures::__rt::std::mem::PinMut::new_unchecked(future)
                };
                ::futures::__rt::StableFuture::poll(pin, ctx)
            });
            // Allow for #[feature(never_type)] and Future<Error = !>
            #[allow(unreachable_code, unreachable_patterns)]
            match poll {
                ::futures::__rt::std::result::Result::Ok(::futures::__rt::Async::Ready(e)) => {
                    break ::futures::__rt::std::result::Result::Ok(e)
                }
                ::futures::__rt::std::result::Result::Ok(::futures::__rt::Async::Pending) => {}
                ::futures::__rt::std::result::Result::Err(e) => {
                    break ::futures::__rt::std::result::Result::Err(e)
                }
            }
            yield ::futures::__rt::Async::Pending
        }
    })
}

/// Await an item from a stream inside an `#[async]` function.
///
/// You should pass an object implementing [`Stream`] to this macro, it will
/// implicitly `yield` while that stream returns [`Async::Pending`] and evaluate
/// to a [`Result`] containing the next item or error from that stream.
///
/// If you want to iterate over all items in a `Stream` you should instead see
/// the documentation on `#[async] for` in the main `#[async]` documentation.
///
/// # Examples
///
#[cfg_attr(feature = "nightly", doc = "```")]
#[cfg_attr(not(feature = "nightly"), doc = "```ignore")]
/// #![feature(proc_macro, generators, pin)]
/// extern crate futures;
///
/// use futures::prelude::*;
/// use futures::stream;
/// use futures::stable::block_on_stable;
///
/// #[async]
/// fn eventually_ten() -> Result<u32, u32> {
///     let mut stream = stream::repeat::<u32, u32>(5);
///     if let Some(first) = await_item!(stream)? {
///         if let Some(second) = await_item!(stream)? {
///             return Ok(first + second);
///         }
///     }
///     Err(0)
/// }
///
/// assert_eq!(Ok(10), block_on_stable(eventually_ten()));
/// ```

#[macro_export]
macro_rules! await_item {
    ($e:expr) => ({
        loop {
            let poll = ::futures::__rt::in_ctx(|ctx| ::futures::Stream::poll_next(&mut $e, ctx));
            // Allow for #[feature(never_type)] and Stream<Error = !>
            #[allow(unreachable_code, unreachable_patterns)]
            match poll {
                ::futures::__rt::std::result::Result::Ok(::futures::__rt::Async::Ready(e)) => {
                    break ::futures::__rt::std::result::Result::Ok(e)
                }
                ::futures::__rt::std::result::Result::Ok(::futures::__rt::Async::Pending) => {}
                ::futures::__rt::std::result::Result::Err(e) => {
                    break ::futures::__rt::std::result::Result::Err(e)
                }
            }

            yield ::futures::__rt::Async::Pending
        }
    })
}

/// Yield an item from an `#[async_stream]` function.
///
/// # Examples
///
#[cfg_attr(feature = "nightly", doc = "```")]
#[cfg_attr(not(feature = "nightly"), doc = "```ignore")]
/// #![feature(proc_macro, generators, pin)]
/// extern crate futures;
///
/// use futures::prelude::*;
/// use futures::stream;
/// use futures::executor::block_on;
///
/// #[async_stream(item = u32)]
/// fn one_five() -> Result<(), u32> {
///     stream_yield!(1);
///     stream_yield!(5);
///     Ok(())
/// }
///
/// assert_eq!(Ok(vec![1, 5]), block_on(one_five().pin().collect()));
/// ```

// TODO: This macro needs to use an extra temporary variable because of
// rust-lang/rust#44197, once that's fixed this should just use $e directly
// inside the yield expression
#[macro_export]
macro_rules! stream_yield {
    ($e:expr) => ({
        let e = $e;
        yield ::futures::__rt::Async::Ready(e)
    })
}