futures_micro/
lib.rs

1//! A very small, no-std compatible toolbox of async utilities.
2#![no_std]
3#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)]
4
5pub mod prelude;
6
7#[doc(no_inline)]
8pub use core::future::Future;
9#[doc(no_inline)]
10pub use core::pin::Pin;
11#[doc(no_inline)]
12pub use core::task::{Context, Poll, Waker};
13
14use core::fmt;
15
16use pin_project_lite::pin_project;
17
18// ---------- futures using the poll api -----------
19
20/// Creates a future from a function returning [`Poll`].
21///
22/// # Examples
23///
24/// ```
25/// use futures_lite::future::block_on;
26/// use futures_micro::poll_fn;
27/// use std::task::{Context, Poll};
28///
29/// # block_on(async {
30/// fn f(_ctx: &mut Context<'_>) -> Poll<i32> {
31///     Poll::Ready(7)
32/// }
33///
34/// assert_eq!(poll_fn(f).await, 7);
35/// # })
36/// ```
37#[inline(always)]
38pub fn poll_fn<F, T>(inner: F) -> PollFn<F>
39where
40    F: FnMut(&mut Context<'_>) -> Poll<T>,
41{
42    PollFn { inner }
43}
44
45pin_project! {
46    /// Future for the [`poll_fn()`] function.
47    #[must_use = "futures do nothing unless you `.await` or poll them"]
48    pub struct PollFn<F> {
49        inner: F,
50    }
51}
52
53impl<F> fmt::Debug for PollFn<F> {
54    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55        f.debug_struct("PollFn").finish()
56    }
57}
58
59impl<F, T> Future for PollFn<F>
60where
61    F: FnMut(&mut Context<'_>) -> Poll<T>,
62{
63    type Output = T;
64    fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<T> {
65        let this = self.project();
66        (this.inner)(ctx)
67    }
68}
69
70pin_project! {
71    /// Returns the result of `left` or `right` future, preferring `left` if both are ready.
72    #[derive(Debug)]
73    #[must_use = "futures do nothing unless you `.await` or poll them"]
74    pub struct Or<F1, F2> {
75        #[pin]
76        future1: F1,
77        #[pin]
78        future2: F2,
79    }
80}
81
82impl<F1, F2> Or<F1, F2>
83where
84    F1: Future,
85    F2: Future,
86{
87    /// Returns the result of `left` or `right` future, preferring `left` if both are ready.
88    pub fn new(future1: F1, future2: F2) -> Self {
89        Or { future1, future2 }
90    }
91}
92
93impl<T, F1, F2> Future for Or<F1, F2>
94where
95    F1: Future<Output = T>,
96    F2: Future<Output = T>,
97{
98    type Output = T;
99
100    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
101        let this = self.project();
102
103        if let Poll::Ready(t) = this.future1.poll(cx) {
104            Poll::Ready(t)
105        } else if let Poll::Ready(t) = this.future2.poll(cx) {
106            Poll::Ready(t)
107        } else {
108            Poll::Pending
109        }
110    }
111}
112
113pin_project! {
114    /// Waits for two [`Future`]s to complete, returning both results.
115    #[derive(Debug)]
116    #[must_use = "futures do nothing unless you `.await` or poll them"]
117    pub struct Zip<F1, F2>
118    where
119        F1: Future,
120        F2: Future,
121    {
122        #[pin]
123        future1: F1,
124        output1: Option<F1::Output>,
125        #[pin]
126        future2: F2,
127        output2: Option<F2::Output>,
128    }
129}
130
131impl<F1, F2> Zip<F1, F2>
132where
133    F1: Future,
134    F2: Future,
135{
136    /// Zips two futures, waiting for both to complete.
137    ///
138    /// # Examples
139    ///
140    /// ```
141    /// use futures_micro::Zip;
142    ///
143    /// # futures_lite::future::block_on(async {
144    /// let a = async { 1 };
145    /// let b = async { 2 };
146    ///
147    /// assert_eq!(Zip::new(a, b).await, (1, 2));
148    /// # })
149    /// ```
150    pub fn new(future1: F1, future2: F2) -> Self {
151        Zip {
152            future1,
153            future2,
154            output1: None,
155            output2: None,
156        }
157    }
158}
159
160impl<F1, F2> Future for Zip<F1, F2>
161where
162    F1: Future,
163    F2: Future,
164{
165    type Output = (F1::Output, F2::Output);
166
167    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
168        let this = self.project();
169
170        if this.output1.is_none() {
171            if let Poll::Ready(out) = this.future1.poll(cx) {
172                *this.output1 = Some(out);
173            }
174        }
175
176        if this.output2.is_none() {
177            if let Poll::Ready(out) = this.future2.poll(cx) {
178                *this.output2 = Some(out);
179            }
180        }
181
182        if this.output1.is_some() && this.output2.is_some() {
183            Poll::Ready((this.output1.take().unwrap(), this.output2.take().unwrap()))
184        } else {
185            Poll::Pending
186        }
187    }
188}
189
190/// Get the [`Waker`] inside an async fn where you aren't supposed to
191/// have it.
192///
193/// This is a low level primitive for implementing more complex
194/// patterns while avoiding the [`Poll`] API.
195///
196/// # Examples
197///
198/// ```
199/// use futures_micro::{sleep, waker};
200///
201/// # futures_lite::future::block_on(async {
202/// let waker = waker().await;
203/// assert_eq!(async { waker.wake(); sleep().await; 1 }.await, 1)
204/// # })
205/// ```
206pub fn waker() -> impl Future<Output = Waker> {
207    poll_fn(|ctx| Poll::Ready(ctx.waker().clone()))
208}
209
210/// Goes to sleep until woken by its [`Waker`] being called.
211///
212/// This is a low level primitive for implementing more complex
213/// patterns while avoiding the [`Poll`] API.
214///
215/// # Examples
216///
217/// ```
218/// use futures_micro::{sleep, waker};
219///
220/// # futures_lite::future::block_on(async {
221/// let waker = waker().await;
222/// assert_eq!(async { waker.wake(); sleep().await; 1 }.await, 1)
223/// # })
224/// ```
225pub fn sleep() -> impl Future<Output = ()> {
226    let mut done = false;
227    poll_fn(move |_| {
228        if done {
229            Poll::Ready(())
230        } else {
231            done = true;
232            Poll::Pending
233        }
234    })
235}
236
237
238/// Pushes itself to the back of the executor queue so some other
239/// tasks can do some work.
240pub fn yield_once() -> impl Future<Output = ()> {
241    let mut done = false;
242    poll_fn(move |ctx| {
243        if done {
244            Poll::Ready(())
245        } else {
246            done = true;
247            ctx.waker().wake_by_ref();
248            Poll::Pending        }
249    })
250}
251
252// --------- MACROS ---------
253
254// Helper for `or!`
255#[doc(hidden)]
256#[macro_export]
257macro_rules! __internal_fold_with {
258    ($func:path, $e:expr) => { $e };
259    ($func:path, $e:expr, $($es:expr),+) => {
260        $func($e, $crate::__internal_fold_with!($func, $($es),+))
261    };
262}
263
264/// Polls arbitrarily many futures, returning the first ready value.
265///
266/// All futures must have the same output type. Left biased when more
267/// than one Future is ready at the same time.
268#[macro_export]
269macro_rules! or {
270    ($($es:expr),+$(,)?) => { $crate::__internal_fold_with!($crate::Or::new, $($es),+) };
271}
272
273/// Pins a variable of type `T` on the stack and rebinds it as `Pin<&mut T>`.
274///
275/// ```
276/// use futures_micro::*;
277/// use std::fmt::Debug;
278/// use std::time::Instant;
279///
280/// // Inspects each invocation of `Future::poll()`.
281/// async fn inspect<T: Debug>(f: impl Future<Output = T>) -> T {
282///     pin!(f);
283///     poll_fn(|cx| dbg!(f.as_mut().poll(cx))).await
284/// }
285///
286/// # futures_lite::future::block_on(async {
287/// let f = async { 1 + 2 };
288/// inspect(f).await;
289/// # })
290/// ```
291#[macro_export]
292macro_rules! pin {
293    ($($x:ident),* $(,)?) => {
294        $(
295            let mut $x = $x;
296            #[allow(unused_mut)]
297            let mut $x = unsafe {
298                core::pin::Pin::new_unchecked(&mut $x)
299            };
300        )*
301    }
302}
303
304/// Unwraps `Poll<T>` or returns [`Pending`][`Poll::Pending`].
305///
306/// # Examples
307///
308/// ```
309/// use futures_micro::*;
310///
311/// // Polls two futures and sums their results.
312/// fn poll_sum(
313///     cx: &mut Context<'_>,
314///     mut a: impl Future<Output = i32> + Unpin,
315///     mut b: impl Future<Output = i32> + Unpin,
316/// ) -> Poll<i32> {
317///     let x = ready!(Pin::new(&mut a).poll(cx));
318///     let y = ready!(Pin::new(&mut b).poll(cx));
319///     Poll::Ready(x + y)
320/// }
321/// ```
322#[macro_export]
323macro_rules! ready {
324    ($e:expr $(,)?) => {
325        match $e {
326            core::task::Poll::Ready(t) => t,
327            t @ core::task::Poll::Pending => return t,
328        }
329    };
330}
331
332/// Zips arbitrarily many futures, waiting for all to complete.
333///
334/// # Examples
335///
336/// ```
337/// use futures_micro::zip;
338///
339/// # futures_lite::future::block_on(async {
340/// let a = async { 1 };
341/// let b = async { 2 };
342///
343/// assert_eq!(zip!(a, b).await, (1, 2));
344/// # })
345/// ```
346#[macro_export]
347macro_rules! zip {
348    ($($es:expr),+ $(,)?) => {{
349        let mut zips = $crate::__internal_fold_with!($crate::Zip::new, $($es),+);
350        $crate::poll_fn(move |ctx| {
351            use ::core::pin::Pin;
352            use ::core::task::Poll;
353
354            let zips = unsafe { Pin::new_unchecked(&mut zips) };
355            if let Poll::Ready(val) = ::core::future::Future::poll(zips, ctx) {
356                Poll::Ready($crate::zip!(@flatten; ; val; $($es),+))
357            } else {
358                Poll::Pending
359            }
360        })
361    }};
362
363    (@flatten; $($prev:expr,)*; $tuple:expr; $e:expr) => {
364        ($($prev,)* $tuple)
365    };
366
367    (@flatten; $($prev:expr,)*; $tuple:expr; $e:expr, $($es:expr),+) => {
368        $crate::zip!(@flatten; $($prev,)* $tuple.0,; $tuple.1; $($es),+)
369    };
370}