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)
})
}