#future #async-await #async #await

nightly futures-async-combinators

玩具式未来组合器

5 个不稳定版本

0.3.2 2019年10月3日
0.3.1 2019年8月22日
0.3.0 2019年8月2日
0.2.0 2019年2月24日
0.1.0 2019年2月21日

#1918异步

MIT 协议

58KB
860

futures-async-combinators

Build Status Coverage Status Docs

仅用于学习目的

这是一个对Future 组合器FutureExt::mapTryFutureExt::and_then...的极大简化实现。

要求

支持 async_await 的 Rust nightly-2019-08-21。

状态

未来

  • future::and_then
  • future::err_into
  • future::flatten
  • future::flatten_stream
  • future::inspect
  • future::into_stream
  • future::map
  • future::map_err
  • future::map_ok
  • future::or_else
  • future::poll_fn
  • future::ready
  • future::then
  • future::unwrap_or_else

  • stream::chain
  • stream::collect
  • stream::concat
  • stream::filter
  • stream::filter_map
  • stream::flatten
  • stream::fold
  • stream::for_each
  • stream::into_future
  • stream::iter
  • stream::map
  • stream::next
  • stream::poll_fn
  • stream::repeat
  • stream::skip
  • stream::skip_while
  • stream::take
  • stream::take_while
  • stream::then
  • stream::unfold
  • stream::zip

为什么

通过查看干净的源代码来了解组合器的工作原理。与原始代码进行比较

pub async fn then<...>(future, f) -> ...
{
    let new_future = f(future.await);
    new_future.await
}

进行比较

impl Then
{
    fn poll(self, waker) -> Poll<...> {
        self.as_mut().chain().poll(waker, |output, f| f(output))
    }
}

impl Chain
{
    fn poll(self, waker, f) -> Poll<...>
    {
        let mut f = Some(f);

        // Safe to call `get_unchecked_mut` because we won't move the futures.
        let this = unsafe { Pin::get_unchecked_mut(self) };

        loop {
            let (output, data) = match this {
                Chain::First(fut1, data) => {
                    match unsafe { Pin::new_unchecked(fut1) }.poll(waker) {
                        Poll::Pending => return Poll::Pending,
                        Poll::Ready(output) => (output, data.take().unwrap()),
                    }
                }
                Chain::Second(fut2) => {
                    return unsafe { Pin::new_unchecked(fut2) }.poll(waker);
                }
                Chain::Empty => unreachable!()
            };

            *this = Chain::Empty; // Drop fut1
            let fut2 = (f.take().unwrap())(output, data);
            *this = Chain::Second(fut2)
        }
    }
}

依赖项

~54KB