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
//! # `std` and `futures` interoperability //! This crate implements adapters for the two different future types: [`std::future::Future`] and [`futures::Future`]. //! You can seamlessly convert the one into the other. //! The aim is to be able to use new async/await syntax with existing [`futures::Future`] infrastructure, such as tokio. //! //! Keep in mind that many of the used features are still unstable and only available on nightly with feature gates. //! //! A simple example: //! ``` //! #![feature(async_await)] //! #![feature(await_macro)] //! #![feature(futures_api)] //! //! use std::time::{Duration, Instant}; //! use tokio::timer::Delay; //! //! use back_to_the_future::{futures_await, BoxIntoFutures}; //! //! fn main() { //! let f = async { //! // Await an old futures::Future using the futures_await! macro. //! // This macro wraps the future in an adapter behind the scenes. //! futures_await!(Delay::new(Instant::now() + Duration::new(0, 10))).unwrap(); //! Ok(()) //! }; //! //! // Convert the std::future::Future into a futures::Future so that tokio::run can use it. //! tokio::run(f.box_into_futures()); //! } //! ``` #![doc(html_root_url = "https://docs.rs/back_to_the_future/0.1.3")] #![feature(arbitrary_self_types)] #![feature(async_await)] #![feature(await_macro)] #![feature(futures_api)] #![feature(never_type)] #![feature(trait_alias)] #![feature(specialization)] pub mod std_future; pub mod futures_future; use std::pin::Pin; #[macro_export] /// Await a futures::Future by first wrapping it in an std::future::Future adapter. macro_rules! futures_await { ($ex:expr) => { await!($crate::IntoStdFuture::into_std_future($ex)) }; } /// Conversion of non-std futures into `std::future::Future`. pub trait IntoStdFuture { type Output; fn into_std_future(self) -> std_future::FutureAdapter<Self::Output>; } /// Conversion of non-futures future into `futures::Future`. pub trait IntoFutures { type Output; fn into_futures(self) -> futures_future::FutureAdapter<Self::Output>; } /// Conversion of any non-futures future into `futures::Future`. /// /// This is very similar to the `IntoFutures` trait, except that it will first /// box the future to circumvent any movability and lifetime requirements. pub trait BoxIntoFutures { type Output; fn box_into_futures(self) -> futures_future::FutureAdapter<Self::Output>; } impl<T: futures::IntoFuture> IntoStdFuture for T { type Output = futures::executor::Spawn<T::Future>; /// Convert any [`futures::Future`] into a [`std::future::Future`]. fn into_std_future(self) -> std_future::FutureAdapter<Self::Output> { std_future::FutureAdapter(futures::executor::spawn(self.into_future())) } } impl<P, F> IntoFutures for Pin<P> where P: std::ops::Deref<Target = F>, F: std::future::Future, { type Output = Pin<P>; /// Convert a pinned [`std::future::Future`] into a [`futures::Future`]. fn into_futures(self) -> futures_future::FutureAdapter<Self::Output> { futures_future::FutureAdapter(self) } } impl<F> BoxIntoFutures for F where F: std::future::Future, { type Output = Pin<Box<F>>; /// Convert any [`std::future::Future`] into a [`futures::Future`]. /// /// To enable the conversion, it is boxed and pinned. /// If your future is already pinned, prefer using [`IntoFutures`] fn box_into_futures(self) -> futures_future::FutureAdapter<Self::Output> { futures_future::FutureAdapter(Box::pin(self)) } }