stream-future 0.5.0

Implement an async iterator with return value.
Documentation
#![feature(async_closure)]
#![feature(coroutines)]
#![feature(iter_from_coroutine)]
#![feature(test)]

extern crate test;
use std::future::Future;
use stream_future::*;
use test::{black_box, Bencher};
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver};
use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt};

fn async_bench<F: Future>(b: &mut Bencher, mut f: impl FnMut() -> F) {
    let runtime = tokio::runtime::Builder::new_current_thread()
        .enable_all()
        .build()
        .unwrap();
    b.iter(|| runtime.block_on(f()))
}

const ITER_MAX: i32 = 10000;

#[bench]
fn this(b: &mut Bencher) {
    #[stream(i32)]
    async fn foo() {
        for i in 0..ITER_MAX {
            yield i;
        }
    }

    async_bench(b, async move || {
        let s = foo();
        tokio::pin!(s);
        while let Some(v) = s.next().await {
            black_box(v);
        }
    })
}

#[bench]
fn async_stream(b: &mut Bencher) {
    fn foo() -> impl Stream<Item = i32> {
        async_stream::stream! {
            for i in 0..ITER_MAX {
                yield i;
            }
        }
    }

    async_bench(b, async move || {
        let s = foo();
        tokio::pin!(s);
        while let Some(v) = s.next().await {
            black_box(v);
        }
    })
}

#[bench]
fn mpsc_channel(b: &mut Bencher) {
    fn foo() -> UnboundedReceiver<i32> {
        let (tx, rx) = unbounded_channel();
        tokio::spawn(async move {
            for i in 0..ITER_MAX {
                tx.send(i).unwrap();
            }
        });
        rx
    }

    async_bench(b, async move || {
        let s = UnboundedReceiverStream::new(foo());
        tokio::pin!(s);
        while let Some(v) = s.next().await {
            black_box(v);
        }
    })
}

#[bench]
fn iter_stream(b: &mut Bencher) {
    async_bench(b, async move || {
        let mut s = tokio_stream::iter(0..ITER_MAX);
        while let Some(v) = s.next().await {
            black_box(v);
        }
    })
}

#[bench]
fn iter(b: &mut Bencher) {
    async_bench(b, async move || {
        for i in 0..ITER_MAX {
            black_box(i);
        }
    })
}

#[bench]
fn coroutine(b: &mut Bencher) {
    async_bench(b, async move || {
        let s = std::iter::from_coroutine(
            #[coroutine]
            || {
                for i in 0..ITER_MAX {
                    yield i;
                }
            },
        );
        for v in s {
            black_box(v);
        }
    })
}