libp2p_core/
either.rs

1// Copyright 2017 Parity Technologies (UK) Ltd.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and associated documentation files (the "Software"),
5// to deal in the Software without restriction, including without limitation
6// the rights to use, copy, modify, merge, publish, distribute, sublicense,
7// and/or sell copies of the Software, and to permit persons to whom the
8// Software is furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19// DEALINGS IN THE SOFTWARE.
20
21use crate::muxing::StreamMuxerEvent;
22use crate::{
23    muxing::StreamMuxer,
24    transport::{ListenerId, Transport, TransportError, TransportEvent},
25    Multiaddr,
26};
27use either::Either;
28use futures::prelude::*;
29use pin_project::pin_project;
30use std::{pin::Pin, task::Context, task::Poll};
31
32impl<A, B> StreamMuxer for future::Either<A, B>
33where
34    A: StreamMuxer,
35    B: StreamMuxer,
36{
37    type Substream = future::Either<A::Substream, B::Substream>;
38    type Error = Either<A::Error, B::Error>;
39
40    fn poll_inbound(
41        self: Pin<&mut Self>,
42        cx: &mut Context<'_>,
43    ) -> Poll<Result<Self::Substream, Self::Error>> {
44        match self.as_pin_mut() {
45            future::Either::Left(inner) => inner
46                .poll_inbound(cx)
47                .map_ok(future::Either::Left)
48                .map_err(Either::Left),
49            future::Either::Right(inner) => inner
50                .poll_inbound(cx)
51                .map_ok(future::Either::Right)
52                .map_err(Either::Right),
53        }
54    }
55
56    fn poll_outbound(
57        self: Pin<&mut Self>,
58        cx: &mut Context<'_>,
59    ) -> Poll<Result<Self::Substream, Self::Error>> {
60        match self.as_pin_mut() {
61            future::Either::Left(inner) => inner
62                .poll_outbound(cx)
63                .map_ok(future::Either::Left)
64                .map_err(Either::Left),
65            future::Either::Right(inner) => inner
66                .poll_outbound(cx)
67                .map_ok(future::Either::Right)
68                .map_err(Either::Right),
69        }
70    }
71
72    fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
73        match self.as_pin_mut() {
74            future::Either::Left(inner) => inner.poll_close(cx).map_err(Either::Left),
75            future::Either::Right(inner) => inner.poll_close(cx).map_err(Either::Right),
76        }
77    }
78
79    fn poll(
80        self: Pin<&mut Self>,
81        cx: &mut Context<'_>,
82    ) -> Poll<Result<StreamMuxerEvent, Self::Error>> {
83        match self.as_pin_mut() {
84            future::Either::Left(inner) => inner.poll(cx).map_err(Either::Left),
85            future::Either::Right(inner) => inner.poll(cx).map_err(Either::Right),
86        }
87    }
88}
89
90/// Implements `Future` and dispatches all method calls to either `First` or `Second`.
91#[pin_project(project = EitherFutureProj)]
92#[derive(Debug, Copy, Clone)]
93#[must_use = "futures do nothing unless polled"]
94pub enum EitherFuture<A, B> {
95    First(#[pin] A),
96    Second(#[pin] B),
97}
98
99impl<AFuture, BFuture, AInner, BInner> Future for EitherFuture<AFuture, BFuture>
100where
101    AFuture: TryFuture<Ok = AInner>,
102    BFuture: TryFuture<Ok = BInner>,
103{
104    type Output = Result<future::Either<AInner, BInner>, Either<AFuture::Error, BFuture::Error>>;
105
106    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
107        match self.project() {
108            EitherFutureProj::First(a) => TryFuture::try_poll(a, cx)
109                .map_ok(future::Either::Left)
110                .map_err(Either::Left),
111            EitherFutureProj::Second(a) => TryFuture::try_poll(a, cx)
112                .map_ok(future::Either::Right)
113                .map_err(Either::Right),
114        }
115    }
116}
117
118impl<A, B> Transport for Either<A, B>
119where
120    B: Transport,
121    A: Transport,
122{
123    type Output = future::Either<A::Output, B::Output>;
124    type Error = Either<A::Error, B::Error>;
125    type ListenerUpgrade = EitherFuture<A::ListenerUpgrade, B::ListenerUpgrade>;
126    type Dial = EitherFuture<A::Dial, B::Dial>;
127
128    fn poll(
129        self: Pin<&mut Self>,
130        cx: &mut Context<'_>,
131    ) -> Poll<TransportEvent<Self::ListenerUpgrade, Self::Error>> {
132        match self.as_pin_mut() {
133            Either::Left(a) => match a.poll(cx) {
134                Poll::Pending => Poll::Pending,
135                Poll::Ready(event) => {
136                    Poll::Ready(event.map_upgrade(EitherFuture::First).map_err(Either::Left))
137                }
138            },
139            Either::Right(b) => match b.poll(cx) {
140                Poll::Pending => Poll::Pending,
141                Poll::Ready(event) => Poll::Ready(
142                    event
143                        .map_upgrade(EitherFuture::Second)
144                        .map_err(Either::Right),
145                ),
146            },
147        }
148    }
149
150    fn remove_listener(&mut self, id: ListenerId) -> bool {
151        match self {
152            Either::Left(t) => t.remove_listener(id),
153            Either::Right(t) => t.remove_listener(id),
154        }
155    }
156
157    fn listen_on(
158        &mut self,
159        id: ListenerId,
160        addr: Multiaddr,
161    ) -> Result<(), TransportError<Self::Error>> {
162        use TransportError::*;
163        match self {
164            Either::Left(a) => a.listen_on(id, addr).map_err(|e| match e {
165                MultiaddrNotSupported(addr) => MultiaddrNotSupported(addr),
166                Other(err) => Other(Either::Left(err)),
167            }),
168            Either::Right(b) => b.listen_on(id, addr).map_err(|e| match e {
169                MultiaddrNotSupported(addr) => MultiaddrNotSupported(addr),
170                Other(err) => Other(Either::Right(err)),
171            }),
172        }
173    }
174
175    fn dial(&mut self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
176        use TransportError::*;
177        match self {
178            Either::Left(a) => match a.dial(addr) {
179                Ok(connec) => Ok(EitherFuture::First(connec)),
180                Err(MultiaddrNotSupported(addr)) => Err(MultiaddrNotSupported(addr)),
181                Err(Other(err)) => Err(Other(Either::Left(err))),
182            },
183            Either::Right(b) => match b.dial(addr) {
184                Ok(connec) => Ok(EitherFuture::Second(connec)),
185                Err(MultiaddrNotSupported(addr)) => Err(MultiaddrNotSupported(addr)),
186                Err(Other(err)) => Err(Other(Either::Right(err))),
187            },
188        }
189    }
190
191    fn dial_as_listener(
192        &mut self,
193        addr: Multiaddr,
194    ) -> Result<Self::Dial, TransportError<Self::Error>>
195    where
196        Self: Sized,
197    {
198        use TransportError::*;
199        match self {
200            Either::Left(a) => match a.dial_as_listener(addr) {
201                Ok(connec) => Ok(EitherFuture::First(connec)),
202                Err(MultiaddrNotSupported(addr)) => Err(MultiaddrNotSupported(addr)),
203                Err(Other(err)) => Err(Other(Either::Left(err))),
204            },
205            Either::Right(b) => match b.dial_as_listener(addr) {
206                Ok(connec) => Ok(EitherFuture::Second(connec)),
207                Err(MultiaddrNotSupported(addr)) => Err(MultiaddrNotSupported(addr)),
208                Err(Other(err)) => Err(Other(Either::Right(err))),
209            },
210        }
211    }
212
213    fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
214        match self {
215            Either::Left(a) => a.address_translation(server, observed),
216            Either::Right(b) => b.address_translation(server, observed),
217        }
218    }
219}