// Copyright 2018 Parity Technologies (UK) Ltd. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. use futures::prelude::*; use crate::upgrade::{InboundUpgrade, OutboundUpgrade, UpgradeInfo}; /// Wraps around an upgrade and applies a closure to the output. #[derive(Debug, Clone)] pub struct MapUpgrade { upgrade: U, fun: F } impl MapUpgrade { pub fn new(upgrade: U, fun: F) -> Self { MapUpgrade { upgrade, fun } } } impl UpgradeInfo for MapUpgrade where U: UpgradeInfo { type UpgradeId = U::UpgradeId; type NamesIter = U::NamesIter; fn protocol_names(&self) -> Self::NamesIter { self.upgrade.protocol_names() } } impl InboundUpgrade for MapUpgrade where U: InboundUpgrade, F: FnOnce(U::Output) -> T { type Output = T; type Error = U::Error; type Future = MapFuture; fn upgrade_inbound(self, sock: C, id: Self::UpgradeId) -> Self::Future { MapFuture { inner: self.upgrade.upgrade_inbound(sock, id), map: Some(self.fun) } } } impl OutboundUpgrade for MapUpgrade where U: OutboundUpgrade, F: FnOnce(U::Output) -> T { type Output = T; type Error = U::Error; type Future = MapFuture; fn upgrade_outbound(self, sock: C, id: Self::UpgradeId) -> Self::Future { MapFuture { inner: self.upgrade.upgrade_outbound(sock, id), map: Some(self.fun) } } } /// Wraps around an upgrade and applies a closure to the error. #[derive(Debug, Clone)] pub struct MapUpgradeErr { upgrade: U, fun: F } impl MapUpgradeErr { pub fn new(upgrade: U, fun: F) -> Self { MapUpgradeErr { upgrade, fun } } } impl UpgradeInfo for MapUpgradeErr where U: UpgradeInfo { type UpgradeId = U::UpgradeId; type NamesIter = U::NamesIter; fn protocol_names(&self) -> Self::NamesIter { self.upgrade.protocol_names() } } impl InboundUpgrade for MapUpgradeErr where U: InboundUpgrade, F: FnOnce(U::Error) -> T { type Output = U::Output; type Error = T; type Future = MapErrFuture; fn upgrade_inbound(self, sock: C, id: Self::UpgradeId) -> Self::Future { MapErrFuture { fut: self.upgrade.upgrade_inbound(sock, id), fun: Some(self.fun) } } } impl OutboundUpgrade for MapUpgradeErr where U: OutboundUpgrade, F: FnOnce(U::Error) -> T, { type Output = U::Output; type Error = T; type Future = MapErrFuture; fn upgrade_outbound(self, sock: C, id: Self::UpgradeId) -> Self::Future { MapErrFuture { fut: self.upgrade.upgrade_outbound(sock, id), fun: Some(self.fun) } } } pub struct MapFuture { inner: TInnerFut, map: Option, } impl Future for MapFuture where TInnerFut: Future, TMap: FnOnce(TIn) -> TOut, { type Item = TOut; type Error = TInnerFut::Error; fn poll(&mut self) -> Poll { let item = try_ready!(self.inner.poll()); let map = self.map.take().expect("Future has already finished"); Ok(Async::Ready(map(item))) } } pub struct MapErrFuture { fut: T, fun: Option, } impl Future for MapErrFuture where T: Future, F: FnOnce(E) -> A, { type Item = T::Item; type Error = A; fn poll(&mut self) -> Poll { match self.fut.poll() { Ok(Async::NotReady) => Ok(Async::NotReady), Ok(Async::Ready(x)) => Ok(Async::Ready(x)), Err(e) => { let f = self.fun.take().expect("Future has not resolved yet"); Err(f(e)) } } } }