1 // Copyright 2020 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Need non-snake case so the macro can re-use type names for variables.
6 #![allow(non_snake_case)]
7 
8 use std::future::Future;
9 use std::pin::Pin;
10 use std::task::{Context, Poll};
11 
12 use futures::future::{maybe_done, MaybeDone};
13 use pin_utils::unsafe_pinned;
14 
15 // Macro-generate future combinators to allow for running different numbers of top-level futures in
16 // this FutureList. Generates the implementation of `FutureList` for the completion types. For an
17 // explicit example this is modeled after, see `UnitFutures`.
18 macro_rules! generate {
19     ($(
20         $(#[$doc:meta])*
21         ($Complete:ident, <$($Fut:ident),*>),
22     )*) => ($(
23         #[must_use = "Combinations of futures don't do anything unless run in an executor."]
24         pub(crate) struct $Complete<$($Fut: Future),*> {
25             $($Fut: MaybeDone<$Fut>,)*
26         }
27 
28         impl<$($Fut),*> $Complete<$($Fut),*>
29         where $(
30             $Fut: Future,
31         )*
32         {
33             // Safety:
34             // * No Drop impl
35             // * No Unpin impl
36             // * Not #[repr(packed)]
37             $(
38                 unsafe_pinned!($Fut: MaybeDone<$Fut>);
39             )*
40 
41             pub(crate) fn new($($Fut: $Fut),*) -> $Complete<$($Fut),*> {
42                 $(
43                     let $Fut = maybe_done($Fut);
44                 )*
45                 $Complete {
46                     $($Fut),*
47                 }
48             }
49         }
50 
51         impl<$($Fut),*> Future for $Complete<$($Fut),*>
52         where $(
53             $Fut: Future,
54         )*
55         {
56             type Output = ($($Fut::Output),*);
57 
58             fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
59                 let mut complete = true;
60                 $(
61                     complete &= self.as_mut().$Fut().poll(cx).is_ready();
62                 )*
63 
64                 if complete {
65                     $(
66                         let $Fut = self.as_mut().$Fut().take_output().unwrap();
67                     )*
68                     Poll::Ready(($($Fut), *))
69                 } else {
70                     Poll::Pending
71                 }
72             }
73         }
74     )*)
75 }
76 
77 generate! {
78     /// _Future for the [`complete2`] function.
79     (Complete2, <_Fut1, _Fut2>),
80 
81     /// _Future for the [`complete3`] function.
82     (Complete3, <_Fut1, _Fut2, _Fut3>),
83 
84     /// _Future for the [`complete4`] function.
85     (Complete4, <_Fut1, _Fut2, _Fut3, _Fut4>),
86 
87     /// _Future for the [`complete5`] function.
88     (Complete5, <_Fut1, _Fut2, _Fut3, _Fut4, _Fut5>),
89 }
90