libp2p_core/transport/
map_err.rs

1// Copyright 2018 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::transport::{ListenerId, Transport, TransportError, TransportEvent};
22use futures::prelude::*;
23use multiaddr::Multiaddr;
24use std::{error, pin::Pin, task::Context, task::Poll};
25
26/// See `Transport::map_err`.
27#[derive(Debug, Copy, Clone)]
28#[pin_project::pin_project]
29pub struct MapErr<T, F> {
30    #[pin]
31    transport: T,
32    map: F,
33}
34
35impl<T, F> MapErr<T, F> {
36    /// Internal function that builds a `MapErr`.
37    pub(crate) fn new(transport: T, map: F) -> MapErr<T, F> {
38        MapErr { transport, map }
39    }
40}
41
42impl<T, F, TErr> Transport for MapErr<T, F>
43where
44    T: Transport,
45    F: FnOnce(T::Error) -> TErr + Clone,
46    TErr: error::Error,
47{
48    type Output = T::Output;
49    type Error = TErr;
50    type ListenerUpgrade = MapErrListenerUpgrade<T, F>;
51    type Dial = MapErrDial<T, F>;
52
53    fn listen_on(
54        &mut self,
55        id: ListenerId,
56        addr: Multiaddr,
57    ) -> Result<(), TransportError<Self::Error>> {
58        let map = self.map.clone();
59        self.transport
60            .listen_on(id, addr)
61            .map_err(|err| err.map(map))
62    }
63
64    fn remove_listener(&mut self, id: ListenerId) -> bool {
65        self.transport.remove_listener(id)
66    }
67
68    fn dial(&mut self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>> {
69        let map = self.map.clone();
70        match self.transport.dial(addr) {
71            Ok(future) => Ok(MapErrDial {
72                inner: future,
73                map: Some(map),
74            }),
75            Err(err) => Err(err.map(map)),
76        }
77    }
78
79    fn dial_as_listener(
80        &mut self,
81        addr: Multiaddr,
82    ) -> Result<Self::Dial, TransportError<Self::Error>> {
83        let map = self.map.clone();
84        match self.transport.dial_as_listener(addr) {
85            Ok(future) => Ok(MapErrDial {
86                inner: future,
87                map: Some(map),
88            }),
89            Err(err) => Err(err.map(map)),
90        }
91    }
92
93    fn address_translation(&self, server: &Multiaddr, observed: &Multiaddr) -> Option<Multiaddr> {
94        self.transport.address_translation(server, observed)
95    }
96
97    fn poll(
98        self: Pin<&mut Self>,
99        cx: &mut Context<'_>,
100    ) -> Poll<TransportEvent<Self::ListenerUpgrade, Self::Error>> {
101        let this = self.project();
102        let map = &*this.map;
103        this.transport.poll(cx).map(|ev| {
104            ev.map_upgrade(move |value| MapErrListenerUpgrade {
105                inner: value,
106                map: Some(map.clone()),
107            })
108            .map_err(map.clone())
109        })
110    }
111}
112
113/// Listening upgrade future for `MapErr`.
114#[pin_project::pin_project]
115pub struct MapErrListenerUpgrade<T: Transport, F> {
116    #[pin]
117    inner: T::ListenerUpgrade,
118    map: Option<F>,
119}
120
121impl<T, F, TErr> Future for MapErrListenerUpgrade<T, F>
122where
123    T: Transport,
124    F: FnOnce(T::Error) -> TErr,
125{
126    type Output = Result<T::Output, TErr>;
127
128    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
129        let this = self.project();
130        match Future::poll(this.inner, cx) {
131            Poll::Ready(Ok(value)) => Poll::Ready(Ok(value)),
132            Poll::Pending => Poll::Pending,
133            Poll::Ready(Err(err)) => {
134                let map = this.map.take().expect("poll() called again after error");
135                Poll::Ready(Err(map(err)))
136            }
137        }
138    }
139}
140
141/// Dialing future for `MapErr`.
142#[pin_project::pin_project]
143pub struct MapErrDial<T: Transport, F> {
144    #[pin]
145    inner: T::Dial,
146    map: Option<F>,
147}
148
149impl<T, F, TErr> Future for MapErrDial<T, F>
150where
151    T: Transport,
152    F: FnOnce(T::Error) -> TErr,
153{
154    type Output = Result<T::Output, TErr>;
155
156    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
157        let this = self.project();
158        match Future::poll(this.inner, cx) {
159            Poll::Ready(Ok(value)) => Poll::Ready(Ok(value)),
160            Poll::Pending => Poll::Pending,
161            Poll::Ready(Err(err)) => {
162                let map = this.map.take().expect("poll() called again after error");
163                Poll::Ready(Err(map(err)))
164            }
165        }
166    }
167}