Skip to content

Commit 80340b3

Browse files
Make ChainedConnector use tuples instead of nesting
1 parent bac2bd4 commit 80340b3

File tree

2 files changed

+115
-39
lines changed

2 files changed

+115
-39
lines changed

src/unversioned/transport/chain.rs

+113-37
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,127 @@
1-
use std::fmt;
21
use std::marker::PhantomData;
32

43
use super::{Connector, Transport};
54

6-
/// Two chained connectors called one after another.
5+
/// Chain of up to 8 connectors
76
///
8-
/// Created by calling [`Connector::chain`] on the first connector.
9-
pub struct ChainedConnector<In, First, Second>(First, Second, PhantomData<In>);
10-
11-
impl<In, First, Second> Connector<In> for ChainedConnector<In, First, Second>
12-
where
13-
In: Transport,
14-
First: Connector<In>,
15-
Second: Connector<First::Out>,
16-
{
17-
type Out = Second::Out;
18-
19-
fn connect(
20-
&self,
21-
details: &super::ConnectionDetails,
22-
chained: Option<In>,
23-
) -> Result<Option<Self::Out>, crate::Error> {
24-
let f_out = self.0.connect(details, chained)?;
25-
self.1.connect(details, f_out)
7+
/// Can be created manually from a tuple of connectors through `ChainedConnector::new`
8+
#[derive(Debug)]
9+
pub struct ChainedConnector<In, Connectors>(Connectors, PhantomData<In>);
10+
11+
impl<In, Connectors> ChainedConnector<In, Connectors> {
12+
/// Create a new chained connector that chains a tuple of connectors
13+
///
14+
/// ```rust
15+
/// # use ureq::unversioned::transport::{ChainedConnector, SocsConnector, TcpConnector, RustlsConnector, ConnectProxyConnector};
16+
/// let connector: ChainedConnector<(), (SocsConnector, TcpConnector, RustlsConnector, ConnectProxyConnector)> = ChainedConnector::new(SocsConnector::default(), TcpConnector::default(), RustlsConnector::default(), ConnectProxyConnector::default());
17+
/// ```
18+
pub fn new(connectors: Connectors) -> Self {
19+
Self(connectors, PhantomData)
2620
}
2721
}
2822

29-
impl<In, First, Second> ChainedConnector<In, First, Second> {
30-
pub(crate) fn new(first: First, second: Second) -> Self {
31-
ChainedConnector(first, second, PhantomData)
32-
}
33-
}
23+
macro_rules! impl_chained_connectors {
24+
(($first_ty:ident, $first_name: ident) ; $(($ty:ident, $name:ident, $prev_ty:ident)),* ; ($final_ty:ident, $final_name: ident, $pre_final_ty:ident)) => {
25+
impl<In, $first_ty, $($ty,)* $final_ty> Connector<In> for ChainedConnector<In, ($first_ty, $($ty,)* $final_ty)>
26+
where
27+
In: Transport,
28+
$first_ty: Connector<In>,
29+
$($ty: Connector<$prev_ty::Out>,)*
30+
$final_ty: Connector<$pre_final_ty::Out>,
31+
{
32+
type Out = $final_ty::Out;
33+
fn connect(
34+
&self,
35+
details: &super::ConnectionDetails,
36+
chained: Option<In>,
37+
) -> Result<Option<Self::Out>, crate::Error> {
38+
let ChainedConnector((
39+
ref $first_name,
40+
$(ref $name,)*
41+
ref $final_name,
42+
), _) = self;
43+
44+
let out = $first_name.connect(details, chained)?;
45+
$(
46+
let out = $name.connect(details, out)?;
47+
)*
48+
$final_name.connect(details,out)
49+
}
50+
}
3451

35-
impl<In, First, Second> fmt::Debug for ChainedConnector<In, First, Second>
36-
where
37-
In: Transport,
38-
First: Connector<In>,
39-
Second: Connector<First::Out>,
40-
{
41-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42-
f.debug_tuple("ChainedConnector")
43-
.field(&self.0)
44-
.field(&self.1)
45-
.finish()
46-
}
52+
};
4753
}
4854

55+
impl_chained_connectors!(
56+
(A, a) ;
57+
(B, b, A),
58+
(C, c, B),
59+
(D, d, C),
60+
(E, e, D),
61+
(F, f, E),
62+
(G, g, F);
63+
(H, h, G)
64+
);
65+
66+
impl_chained_connectors!(
67+
(A, a) ;
68+
(B, b, A),
69+
(C, c, B),
70+
(D, d, C),
71+
(E, e, D),
72+
(F, f, E);
73+
(G, g, F)
74+
);
75+
76+
impl_chained_connectors!(
77+
(A, a) ;
78+
(B, b, A),
79+
(C, c, B),
80+
(D, d, C),
81+
(E, e, D);
82+
(F, f, E)
83+
);
84+
85+
impl_chained_connectors!(
86+
(A, a) ;
87+
(B, b, A),
88+
(C, c, B),
89+
(D, d, C);
90+
(E, e, D)
91+
);
92+
impl_chained_connectors!(
93+
(A, a) ;
94+
(B, b, A),
95+
(C, c, B);
96+
(D, d, C)
97+
);
98+
impl_chained_connectors!(
99+
(A, a) ;
100+
(B, b, A);
101+
(C, c, B)
102+
);
103+
impl_chained_connectors!(
104+
(A, a) ;;
105+
(B, b, A)
106+
);
107+
// impl<In, First, Second> Connector<In> for ChainedConnector<In, First, Second>
108+
// where
109+
// In: Transport,
110+
// First: Connector<In>,
111+
// Second: Connector<First::Out>,
112+
// {
113+
// type Out = Second::Out;
114+
115+
// fn connect(
116+
// &self,
117+
// details: &super::ConnectionDetails,
118+
// chained: Option<In>,
119+
// ) -> Result<Option<Self::Out>, crate::Error> {
120+
// let f_out = self.0.connect(details, chained)?;
121+
// self.1.connect(details, f_out)
122+
// }
123+
// }
124+
49125
/// A selection between two transports.
50126
#[derive(Debug)]
51127
pub enum Either<A, B> {

src/unversioned/transport/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,11 @@ pub trait Connector<In: Transport = ()>: Debug + Send + Sync + 'static {
132132
/// Chain this connector to another connector.
133133
///
134134
/// This connector will be called first, and the output goes into the next connector.
135-
fn chain<Next: Connector<Self::Out>>(self, next: Next) -> ChainedConnector<In, Self, Next>
135+
fn chain<Next: Connector<Self::Out>>(self, next: Next) -> ChainedConnector<In, (Self, Next)>
136136
where
137137
Self: Sized,
138138
{
139-
ChainedConnector::new(self, next)
139+
ChainedConnector::new((self, next))
140140
}
141141
}
142142

0 commit comments

Comments
 (0)