|
#![feature(conservative_impl_trait, generators, generator_trait)] |
|
|
|
/*! |
|
|
|
A tiny crate that provides async and await macros to create `futures::Future`s and `futures::Stream`s. |
|
|
|
Code that uses these macros requires `#![feature(conservative_impl_trait, generators)]` |
|
|
|
- Returning a `futures::Future` |
|
|
|
```rust |
|
#![feature(conservative_impl_trait, generators)] |
|
|
|
#[macro_use] |
|
extern crate tiny_async_await as futures; // This crate re-exports the contents of the futures crate. |
|
|
|
fn sum() -> impl ::futures::Future<Item = i32, Error = ()> { |
|
async!({ |
|
// await!(future) returns a `Result` |
|
let a = await!(futures::future::ok(5))?; |
|
|
|
let b = await!(futures::future::ok(6))?; |
|
|
|
// Return a `Result` that contains the result of the future |
|
Ok(a + b) |
|
}) |
|
} |
|
|
|
fn main() { |
|
use futures::{ Async, Future }; |
|
|
|
let mut f = sum(); |
|
assert_eq!(f.poll(), Ok(Async::Ready(11))); |
|
} |
|
``` |
|
|
|
- Returning a `futures::Stream` |
|
|
|
```rust |
|
#![feature(conservative_impl_trait, generators)] |
|
|
|
#[macro_use] |
|
extern crate tiny_async_await as futures; |
|
|
|
fn numbers() -> impl ::futures::Stream<Item = i32, Error = ()> { |
|
async!({ |
|
let a = await!(futures::future::ok(5))?; |
|
// Use `syield!` with a `Result` to yield a `futures::Poll` representing the next item... |
|
syield!(Ok(a)); |
|
|
|
// ... or error. |
|
syield!(Err(())); |
|
|
|
let b = await!(futures::future::ok(6))?; |
|
syield!(Ok(b)); |
|
|
|
// Return `Ok(())` to indicate the end of the stream |
|
Ok(()) |
|
}) |
|
} |
|
|
|
fn main() { |
|
use futures::{ Async, Stream }; |
|
|
|
let mut f = numbers(); |
|
assert_eq!(f.poll(), Ok(Async::Ready(Some(5)))); |
|
assert_eq!(f.poll(), Err(())); |
|
assert_eq!(f.poll(), Ok(Async::Ready(Some(6)))); |
|
assert_eq!(f.poll(), Ok(Async::Ready(None))); |
|
} |
|
``` |
|
!*/ |
|
|
|
extern crate futures; |
|
pub use futures::*; |
|
|
|
#[macro_export] |
|
macro_rules! async { |
|
($e:expr) => { |
|
$crate::__internal::Wrapper(move || $e) |
|
}; |
|
} |
|
|
|
#[macro_export] |
|
macro_rules! await { |
|
($e:expr) => {{ |
|
let mut f = $e; |
|
loop { |
|
let poll = $crate::Future::poll(&mut f); |
|
match poll { |
|
Ok($crate::Async::Ready(value)) => break Ok(value), |
|
Ok($crate::Async::NotReady) => yield Ok($crate::Async::NotReady), |
|
Err(err) => break Err(err), |
|
} |
|
} |
|
}}; |
|
} |
|
|
|
#[macro_export] |
|
macro_rules! syield { |
|
($e:expr) => { |
|
yield ::std::result::Result::map($e, |value| $crate::Async::Ready(value)) |
|
}; |
|
} |
|
|
|
pub mod __internal { |
|
use ::futures::{ Async, Future, Poll, Stream }; |
|
use ::std::ops::{ Generator, GeneratorState }; |
|
|
|
pub struct Wrapper<G>(pub G); |
|
|
|
impl<G, T, E> Future for Wrapper<G> where G: Generator<Yield = Poll<T, E>, Return = Result<T, E>> { |
|
type Item = T; |
|
type Error = E; |
|
|
|
fn poll(&mut self) -> Poll<Self::Item, Self::Error> { |
|
match self.0.resume() { |
|
GeneratorState::Yielded(Ok(Async::NotReady)) => Ok(Async::NotReady), |
|
GeneratorState::Yielded(_) => panic!("Can only yield Async::NotReady from a Future generator"), |
|
GeneratorState::Complete(Ok(value)) => Ok(Async::Ready(value)), |
|
GeneratorState::Complete(Err(err)) => Err(err), |
|
} |
|
} |
|
} |
|
|
|
impl<G, T, E> Stream for Wrapper<G> where G: ::std::ops::Generator<Yield = Poll<T, E>, Return = Result<(), E>> { |
|
type Item = T; |
|
type Error = E; |
|
|
|
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> { |
|
match self.0.resume() { |
|
GeneratorState::Yielded(Ok(Async::Ready(value))) => Ok(Async::Ready(Some(value))), |
|
GeneratorState::Yielded(Ok(Async::NotReady)) => Ok(Async::NotReady), |
|
GeneratorState::Yielded(Err(err)) => Err(err), |
|
GeneratorState::Complete(Ok(())) => Ok(Async::Ready(None)), |
|
GeneratorState::Complete(Err(err)) => Err(err), |
|
} |
|
} |
|
} |
|
} |