Skip to content

Commit 4d1b852

Browse files
ibraheemdevtaiki-e
authored andcommitted
clean up try(join) combinator
1 parent 77d10e9 commit 4d1b852

File tree

2 files changed

+88
-146
lines changed

2 files changed

+88
-146
lines changed

futures-util/src/future/join.rs

Lines changed: 42 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,59 @@
1-
#![allow(non_snake_case)]
2-
3-
use super::assert_future;
4-
use crate::future::{maybe_done, MaybeDone};
1+
use crate::future::{assert_future, maybe_done, MaybeDone};
52
use core::fmt;
63
use core::pin::Pin;
74
use futures_core::future::{FusedFuture, Future};
85
use futures_core::task::{Context, Poll};
96
use pin_project_lite::pin_project;
107

11-
macro_rules! generate {
12-
($(
13-
$(#[$doc:meta])*
14-
($Join:ident, <$($Fut:ident),*>),
15-
)*) => ($(
16-
pin_project! {
17-
$(#[$doc])*
18-
#[must_use = "futures do nothing unless you `.await` or poll them"]
19-
pub struct $Join<$($Fut: Future),*> {
20-
$(#[pin] $Fut: MaybeDone<$Fut>,)*
21-
}
22-
}
8+
pin_project! {
9+
/// Future for the [`join`](super::FutureExt::join) method.
10+
#[must_use = "futures do nothing unless you `.await` or poll them"]
11+
pub struct Join<Fut1, Fut2> where Fut1: Future, Fut2: Future {
12+
#[pin] fut1: MaybeDone<Fut1>,
13+
#[pin] fut2: MaybeDone<Fut2>,
14+
}
15+
}
2316

24-
impl<$($Fut),*> fmt::Debug for $Join<$($Fut),*>
25-
where
26-
$(
27-
$Fut: Future + fmt::Debug,
28-
$Fut::Output: fmt::Debug,
29-
)*
30-
{
31-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32-
f.debug_struct(stringify!($Join))
33-
$(.field(stringify!($Fut), &self.$Fut))*
34-
.finish()
35-
}
36-
}
17+
impl<Fut1: Future, Fut2: Future> Join<Fut1, Fut2> {
18+
pub(crate) fn new(fut1: Fut1, fut2: Fut2) -> Self {
19+
Self { fut1: maybe_done(fut1), fut2: maybe_done(fut2) }
20+
}
21+
}
3722

38-
impl<$($Fut: Future),*> $Join<$($Fut),*> {
39-
fn new($($Fut: $Fut),*) -> Self {
40-
Self {
41-
$($Fut: maybe_done($Fut)),*
42-
}
43-
}
44-
}
23+
impl<Fut1, Fut2> fmt::Debug for Join<Fut1, Fut2>
24+
where
25+
Fut1: Future + fmt::Debug,
26+
Fut1::Output: fmt::Debug,
27+
Fut2: Future + fmt::Debug,
28+
Fut2::Output: fmt::Debug,
29+
{
30+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31+
f.debug_struct("Join").field("fut1", &self.fut1).field("fut2", &self.fut2).finish()
32+
}
33+
}
4534

46-
impl<$($Fut: Future),*> Future for $Join<$($Fut),*> {
47-
type Output = ($($Fut::Output),*);
35+
impl<Fut1: Future, Fut2: Future> Future for Join<Fut1, Fut2> {
36+
type Output = (Fut1::Output, Fut2::Output);
4837

49-
fn poll(
50-
self: Pin<&mut Self>, cx: &mut Context<'_>
51-
) -> Poll<Self::Output> {
52-
let mut all_done = true;
53-
let mut futures = self.project();
54-
$(
55-
all_done &= futures.$Fut.as_mut().poll(cx).is_ready();
56-
)*
38+
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
39+
let mut all_done = true;
40+
let mut futures = self.project();
5741

58-
if all_done {
59-
Poll::Ready(($(futures.$Fut.take_output().unwrap()), *))
60-
} else {
61-
Poll::Pending
62-
}
63-
}
64-
}
42+
all_done &= futures.fut1.as_mut().poll(cx).is_ready();
43+
all_done &= futures.fut2.as_mut().poll(cx).is_ready();
6544

66-
impl<$($Fut: FusedFuture),*> FusedFuture for $Join<$($Fut),*> {
67-
fn is_terminated(&self) -> bool {
68-
$(
69-
self.$Fut.is_terminated()
70-
) && *
71-
}
45+
if all_done {
46+
Poll::Ready((futures.fut1.take_output().unwrap(), futures.fut2.take_output().unwrap()))
47+
} else {
48+
Poll::Pending
7249
}
73-
)*)
50+
}
7451
}
7552

76-
generate! {
77-
/// Future for the [`join`](join()) function.
78-
(Join, <Fut1, Fut2>),
53+
impl<Fut1: FusedFuture, Fut2: FusedFuture> FusedFuture for Join<Fut1, Fut2> {
54+
fn is_terminated(&self) -> bool {
55+
self.fut1.is_terminated() && self.fut2.is_terminated()
56+
}
7957
}
8058

8159
/// Joins the result of two futures, waiting for them both to complete.
@@ -104,6 +82,5 @@ where
10482
Fut1: Future,
10583
Fut2: Future,
10684
{
107-
let f = Join::new(future1, future2);
108-
assert_future::<(Fut1::Output, Fut2::Output), _>(f)
85+
assert_future::<(Fut1::Output, Fut2::Output), _>(Join::new(future1, future2))
10986
}

futures-util/src/future/try_join.rs

Lines changed: 46 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,97 +1,62 @@
1-
#![allow(non_snake_case)]
2-
31
use crate::future::{assert_future, try_maybe_done, TryMaybeDone};
42
use core::fmt;
53
use core::pin::Pin;
64
use futures_core::future::{Future, TryFuture};
75
use futures_core::task::{Context, Poll};
86
use pin_project_lite::pin_project;
97

10-
macro_rules! generate {
11-
($(
12-
$(#[$doc:meta])*
13-
($Join:ident, <Fut1, $($Fut:ident),*>),
14-
)*) => ($(
15-
pin_project! {
16-
$(#[$doc])*
17-
#[must_use = "futures do nothing unless you `.await` or poll them"]
18-
pub struct $Join<Fut1: TryFuture, $($Fut: TryFuture),*> {
19-
#[pin] Fut1: TryMaybeDone<Fut1>,
20-
$(#[pin] $Fut: TryMaybeDone<$Fut>,)*
21-
}
22-
}
8+
pin_project! {
9+
/// Future for the [`try_join`](super::TryFutureExt::try_join) method.
10+
#[must_use = "futures do nothing unless you `.await` or poll them"]
11+
pub struct TryJoin<Fut1: TryFuture, Fut2: TryFuture> {
12+
#[pin] fut1: TryMaybeDone<Fut1>,
13+
#[pin] fut2: TryMaybeDone<Fut2>
14+
}
15+
}
2316

24-
impl<Fut1, $($Fut),*> fmt::Debug for $Join<Fut1, $($Fut),*>
25-
where
26-
Fut1: TryFuture + fmt::Debug,
27-
Fut1::Ok: fmt::Debug,
28-
Fut1::Error: fmt::Debug,
29-
$(
30-
$Fut: TryFuture + fmt::Debug,
31-
$Fut::Ok: fmt::Debug,
32-
$Fut::Error: fmt::Debug,
33-
)*
34-
{
35-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36-
f.debug_struct(stringify!($Join))
37-
.field("Fut1", &self.Fut1)
38-
$(.field(stringify!($Fut), &self.$Fut))*
39-
.finish()
40-
}
41-
}
17+
impl<Fut1: TryFuture, Fut2: TryFuture> TryJoin<Fut1, Fut2> {
18+
pub(crate) fn new(fut1: Fut1, fut2: Fut2) -> Self {
19+
Self { fut1: try_maybe_done(fut1), fut2: try_maybe_done(fut2) }
20+
}
21+
}
4222

43-
impl<Fut1, $($Fut),*> $Join<Fut1, $($Fut),*>
44-
where
45-
Fut1: TryFuture,
46-
$(
47-
$Fut: TryFuture<Error=Fut1::Error>
48-
),*
49-
{
50-
fn new(Fut1: Fut1, $($Fut: $Fut),*) -> Self {
51-
Self {
52-
Fut1: try_maybe_done(Fut1),
53-
$($Fut: try_maybe_done($Fut)),*
54-
}
55-
}
56-
}
23+
impl<Fut1, Fut2> fmt::Debug for TryJoin<Fut1, Fut2>
24+
where
25+
Fut1: TryFuture + fmt::Debug,
26+
Fut1::Ok: fmt::Debug,
27+
Fut1::Error: fmt::Debug,
28+
Fut2: TryFuture + fmt::Debug,
29+
Fut2::Ok: fmt::Debug,
30+
Fut2::Error: fmt::Debug,
31+
{
32+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33+
f.debug_struct("TryJoin").field("fut1", &self.fut1).field("fut2", &self.fut2).finish()
34+
}
35+
}
36+
37+
impl<Fut1, Fut2> Future for TryJoin<Fut1, Fut2>
38+
where
39+
Fut1: TryFuture,
40+
Fut2: TryFuture<Error = Fut1::Error>,
41+
{
42+
type Output = Result<(Fut1::Ok, Fut2::Ok), Fut1::Error>;
5743

58-
impl<Fut1, $($Fut),*> Future for $Join<Fut1, $($Fut),*>
59-
where
60-
Fut1: TryFuture,
61-
$(
62-
$Fut: TryFuture<Error=Fut1::Error>
63-
),*
64-
{
65-
type Output = Result<(Fut1::Ok, $($Fut::Ok),*), Fut1::Error>;
44+
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
45+
let mut all_done = true;
46+
let mut futures = self.project();
6647

67-
fn poll(
68-
self: Pin<&mut Self>, cx: &mut Context<'_>
69-
) -> Poll<Self::Output> {
70-
let mut all_done = true;
71-
let mut futures = self.project();
72-
all_done &= futures.Fut1.as_mut().poll(cx)?.is_ready();
73-
$(
74-
all_done &= futures.$Fut.as_mut().poll(cx)?.is_ready();
75-
)*
48+
all_done &= futures.fut1.as_mut().poll(cx)?.is_ready();
49+
all_done &= futures.fut2.as_mut().poll(cx)?.is_ready();
7650

77-
if all_done {
78-
Poll::Ready(Ok((
79-
futures.Fut1.take_output().unwrap(),
80-
$(
81-
futures.$Fut.take_output().unwrap()
82-
),*
83-
)))
84-
} else {
85-
Poll::Pending
86-
}
87-
}
51+
if all_done {
52+
Poll::Ready(Ok((
53+
futures.fut1.take_output().unwrap(),
54+
futures.fut2.take_output().unwrap(),
55+
)))
56+
} else {
57+
Poll::Pending
8858
}
89-
)*)
90-
}
91-
92-
generate! {
93-
/// Future for the [`try_join`](try_join()) function.
94-
(TryJoin, <Fut1, Fut2>),
59+
}
9560
}
9661

9762
/// Joins the result of two futures, waiting for them both to complete or

0 commit comments

Comments
 (0)