1use std::{
22 pin::Pin,
23 task::{Context, Poll},
24};
25
26use either::Either;
27use futures::prelude::*;
28use pin_project::pin_project;
29
30use crate::{
31 muxing::{StreamMuxer, StreamMuxerEvent},
32 transport::{DialOpts, ListenerId, Transport, TransportError, TransportEvent},
33 Multiaddr,
34};
35
36impl<A, B> StreamMuxer for future::Either<A, B>
37where
38 A: StreamMuxer,
39 B: StreamMuxer,
40{
41 type Substream = future::Either<A::Substream, B::Substream>;
42 type Error = Either<A::Error, B::Error>;
43
44 fn poll_inbound(
45 self: Pin<&mut Self>,
46 cx: &mut Context<'_>,
47 ) -> Poll<Result<Self::Substream, Self::Error>> {
48 match self.as_pin_mut() {
49 future::Either::Left(inner) => inner
50 .poll_inbound(cx)
51 .map_ok(future::Either::Left)
52 .map_err(Either::Left),
53 future::Either::Right(inner) => inner
54 .poll_inbound(cx)
55 .map_ok(future::Either::Right)
56 .map_err(Either::Right),
57 }
58 }
59
60 fn poll_outbound(
61 self: Pin<&mut Self>,
62 cx: &mut Context<'_>,
63 ) -> Poll<Result<Self::Substream, Self::Error>> {
64 match self.as_pin_mut() {
65 future::Either::Left(inner) => inner
66 .poll_outbound(cx)
67 .map_ok(future::Either::Left)
68 .map_err(Either::Left),
69 future::Either::Right(inner) => inner
70 .poll_outbound(cx)
71 .map_ok(future::Either::Right)
72 .map_err(Either::Right),
73 }
74 }
75
76 fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
77 match self.as_pin_mut() {
78 future::Either::Left(inner) => inner.poll_close(cx).map_err(Either::Left),
79 future::Either::Right(inner) => inner.poll_close(cx).map_err(Either::Right),
80 }
81 }
82
83 fn poll(
84 self: Pin<&mut Self>,
85 cx: &mut Context<'_>,
86 ) -> Poll<Result<StreamMuxerEvent, Self::Error>> {
87 match self.as_pin_mut() {
88 future::Either::Left(inner) => inner.poll(cx).map_err(Either::Left),
89 future::Either::Right(inner) => inner.poll(cx).map_err(Either::Right),
90 }
91 }
92}
93
94#[pin_project(project = EitherFutureProj)]
96#[derive(Debug, Copy, Clone)]
97#[must_use = "futures do nothing unless polled"]
98pub enum EitherFuture<A, B> {
99 First(#[pin] A),
100 Second(#[pin] B),
101}
102
103impl<AFuture, BFuture, AInner, BInner> Future for EitherFuture<AFuture, BFuture>
104where
105 AFuture: TryFuture<Ok = AInner>,
106 BFuture: TryFuture<Ok = BInner>,
107{
108 type Output = Result<future::Either<AInner, BInner>, Either<AFuture::Error, BFuture::Error>>;
109
110 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
111 match self.project() {
112 EitherFutureProj::First(a) => TryFuture::try_poll(a, cx)
113 .map_ok(future::Either::Left)
114 .map_err(Either::Left),
115 EitherFutureProj::Second(a) => TryFuture::try_poll(a, cx)
116 .map_ok(future::Either::Right)
117 .map_err(Either::Right),
118 }
119 }
120}
121
122impl<A, B> Transport for Either<A, B>
123where
124 B: Transport,
125 A: Transport,
126{
127 type Output = future::Either<A::Output, B::Output>;
128 type Error = Either<A::Error, B::Error>;
129 type ListenerUpgrade = EitherFuture<A::ListenerUpgrade, B::ListenerUpgrade>;
130 type Dial = EitherFuture<A::Dial, B::Dial>;
131
132 fn poll(
133 self: Pin<&mut Self>,
134 cx: &mut Context<'_>,
135 ) -> Poll<TransportEvent<Self::ListenerUpgrade, Self::Error>> {
136 match self.as_pin_mut() {
137 Either::Left(a) => match a.poll(cx) {
138 Poll::Pending => Poll::Pending,
139 Poll::Ready(event) => {
140 Poll::Ready(event.map_upgrade(EitherFuture::First).map_err(Either::Left))
141 }
142 },
143 Either::Right(b) => match b.poll(cx) {
144 Poll::Pending => Poll::Pending,
145 Poll::Ready(event) => Poll::Ready(
146 event
147 .map_upgrade(EitherFuture::Second)
148 .map_err(Either::Right),
149 ),
150 },
151 }
152 }
153
154 fn remove_listener(&mut self, id: ListenerId) -> bool {
155 match self {
156 Either::Left(t) => t.remove_listener(id),
157 Either::Right(t) => t.remove_listener(id),
158 }
159 }
160
161 fn listen_on(
162 &mut self,
163 id: ListenerId,
164 addr: Multiaddr,
165 ) -> Result<(), TransportError<Self::Error>> {
166 use TransportError::*;
167 match self {
168 Either::Left(a) => a.listen_on(id, addr).map_err(|e| match e {
169 MultiaddrNotSupported(addr) => MultiaddrNotSupported(addr),
170 Other(err) => Other(Either::Left(err)),
171 }),
172 Either::Right(b) => b.listen_on(id, addr).map_err(|e| match e {
173 MultiaddrNotSupported(addr) => MultiaddrNotSupported(addr),
174 Other(err) => Other(Either::Right(err)),
175 }),
176 }
177 }
178
179 fn dial(
180 &mut self,
181 addr: Multiaddr,
182 opts: DialOpts,
183 ) -> Result<Self::Dial, TransportError<Self::Error>> {
184 use TransportError::*;
185 match self {
186 Either::Left(a) => match a.dial(addr, opts) {
187 Ok(connec) => Ok(EitherFuture::First(connec)),
188 Err(MultiaddrNotSupported(addr)) => Err(MultiaddrNotSupported(addr)),
189 Err(Other(err)) => Err(Other(Either::Left(err))),
190 },
191 Either::Right(b) => match b.dial(addr, opts) {
192 Ok(connec) => Ok(EitherFuture::Second(connec)),
193 Err(MultiaddrNotSupported(addr)) => Err(MultiaddrNotSupported(addr)),
194 Err(Other(err)) => Err(Other(Either::Right(err))),
195 },
196 }
197 }
198}