mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-09-08 00:00:13 +02:00
async-await: track nightly changes (#661)
The `tokio-async-await` crate is no longer a facade. Instead, the `tokio` crate provides a feature flag to enable async/await support.
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
use futures::{Future, Poll};
|
||||
|
||||
use std::pin::Pin;
|
||||
use std::future::{
|
||||
Future as StdFuture,
|
||||
};
|
||||
use std::ptr::NonNull;
|
||||
use std::task::{
|
||||
LocalWaker,
|
||||
Poll as StdPoll,
|
||||
UnsafeWake,
|
||||
Waker,
|
||||
};
|
||||
|
||||
/// Convert an 0.3 `Future` to an 0.1 `Future`.
|
||||
#[derive(Debug)]
|
||||
pub struct Compat<T>(Pin<Box<T>>);
|
||||
|
||||
impl<T> Compat<T> {
|
||||
/// Create a new `Compat` backed by `future`.
|
||||
pub fn new(future: T) -> Compat<T> {
|
||||
Compat(Box::pinned(future))
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a value into one that can be used with `await!`.
|
||||
pub trait IntoAwaitable {
|
||||
type Awaitable;
|
||||
|
||||
fn into_awaitable(self) -> Self::Awaitable;
|
||||
}
|
||||
|
||||
impl<T> IntoAwaitable for T
|
||||
where T: StdFuture,
|
||||
{
|
||||
type Awaitable = Self;
|
||||
|
||||
fn into_awaitable(self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Item, Error> Future for Compat<T>
|
||||
where T: StdFuture<Output = Result<Item, Error>>,
|
||||
{
|
||||
type Item = Item;
|
||||
type Error = Error;
|
||||
|
||||
fn poll(&mut self) -> Poll<Item, Error> {
|
||||
use futures::Async::*;
|
||||
|
||||
let local_waker = noop_local_waker();
|
||||
|
||||
let res = self.0.as_mut().poll(&local_waker);
|
||||
|
||||
match res {
|
||||
StdPoll::Ready(Ok(val)) => Ok(Ready(val)),
|
||||
StdPoll::Ready(Err(err)) => Err(err),
|
||||
StdPoll::Pending => Ok(NotReady),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ===== NoopWaker =====
|
||||
|
||||
struct NoopWaker;
|
||||
|
||||
fn noop_local_waker() -> LocalWaker {
|
||||
let w: NonNull<NoopWaker> = NonNull::dangling();
|
||||
unsafe { LocalWaker::new(w) }
|
||||
}
|
||||
|
||||
fn noop_waker() -> Waker {
|
||||
let w: NonNull<NoopWaker> = NonNull::dangling();
|
||||
unsafe { Waker::new(w) }
|
||||
}
|
||||
|
||||
unsafe impl UnsafeWake for NoopWaker {
|
||||
unsafe fn clone_raw(&self) -> Waker {
|
||||
noop_waker()
|
||||
}
|
||||
|
||||
unsafe fn drop_raw(&self) {
|
||||
}
|
||||
|
||||
unsafe fn wake(&self) {
|
||||
panic!("NoopWake cannot wake");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
|
||||
use futures::{Future, Async};
|
||||
|
||||
use std::marker::Unpin;
|
||||
use std::future::Future as StdFuture;
|
||||
use std::pin::Pin;
|
||||
use std::task::{LocalWaker, Poll as StdPoll};
|
||||
|
||||
/// Converts an 0.1 `Future` into an 0.3 `Future`.
|
||||
#[derive(Debug)]
|
||||
pub struct Compat<T>(T);
|
||||
|
||||
pub(crate) fn convert_poll<T, E>(poll: Result<Async<T>, E>) -> StdPoll<Result<T, E>> {
|
||||
use futures::Async::{Ready, NotReady};
|
||||
|
||||
match poll {
|
||||
Ok(Ready(val)) => StdPoll::Ready(Ok(val)),
|
||||
Ok(NotReady) => StdPoll::Pending,
|
||||
Err(err) => StdPoll::Ready(Err(err)),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn convert_poll_stream<T, E>(
|
||||
poll: Result<Async<Option<T>>, E>) -> StdPoll<Option<Result<T, E>>>
|
||||
{
|
||||
use futures::Async::{Ready, NotReady};
|
||||
|
||||
match poll {
|
||||
Ok(Ready(Some(val))) => StdPoll::Ready(Some(Ok(val))),
|
||||
Ok(Ready(None)) => StdPoll::Ready(None),
|
||||
Ok(NotReady) => StdPoll::Pending,
|
||||
Err(err) => StdPoll::Ready(Some(Err(err))),
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a value into one that can be used with `await!`.
|
||||
pub trait IntoAwaitable {
|
||||
type Awaitable;
|
||||
|
||||
/// Convert `self` into a value that can be used with `await!`.
|
||||
fn into_awaitable(self) -> Self::Awaitable;
|
||||
}
|
||||
|
||||
impl<T: Future + Unpin> IntoAwaitable for T {
|
||||
type Awaitable = Compat<T>;
|
||||
|
||||
fn into_awaitable(self) -> Self::Awaitable {
|
||||
Compat(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> StdFuture for Compat<T>
|
||||
where T: Future + Unpin
|
||||
{
|
||||
type Output = Result<T::Item, T::Error>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, _lw: &LocalWaker) -> StdPoll<Self::Output> {
|
||||
use futures::Async::{Ready, NotReady};
|
||||
|
||||
// TODO: wire in cx
|
||||
|
||||
match self.0.poll() {
|
||||
Ok(Ready(val)) => StdPoll::Ready(Ok(val)),
|
||||
Ok(NotReady) => StdPoll::Pending,
|
||||
Err(e) => StdPoll::Ready(Err(e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
#![doc(hidden)]
|
||||
|
||||
pub mod forward;
|
||||
pub mod backward;
|
||||
Reference in New Issue
Block a user