Fix mapping of upgrade errors. (#656)

The current implementation of `MapUpgradeErr` implements `InboundUpgrade`
and `OutboundUpgrade` and applies the transformation in both cases which
means that mapping is always applied to inbound and outbound upgrade
errors. This commit uses separate `MapInboundUpgradeErr` and
`MapOutboundUpgradeErr` types which implements both traits but only map
errors in one direction.
This commit is contained in:
Toralf Wittner 2018-11-19 16:08:00 +01:00 committed by GitHub
parent e7bffd009f
commit 64af676178
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 68 additions and 22 deletions

View File

@ -770,7 +770,7 @@ where
type InboundProtocol =
upgrade::OrUpgrade<
upgrade::Toggleable<
upgrade::MapUpgradeErr<
upgrade::MapInboundUpgradeErr<
upgrade::MapInboundUpgrade<
TProto1::InboundProtocol,
fn(TProto1Out) -> EitherOutput<TProto1Out, TProto2Out>
@ -783,7 +783,7 @@ where
>
>,
upgrade::Toggleable<
upgrade::MapUpgradeErr<
upgrade::MapInboundUpgradeErr<
upgrade::MapInboundUpgrade<
TProto2::InboundProtocol,
fn(TProto2Out) -> EitherOutput<TProto1Out, TProto2Out>
@ -800,7 +800,7 @@ where
type OutboundProtocol =
upgrade::OrUpgrade<
upgrade::Toggleable<
upgrade::MapUpgradeErr<
upgrade::MapOutboundUpgradeErr<
upgrade::MapOutboundUpgrade<
TProto1::OutboundProtocol,
fn(TProto1Out) -> EitherOutput<TProto1Out, TProto2Out>
@ -813,7 +813,7 @@ where
>
>,
upgrade::Toggleable<
upgrade::MapUpgradeErr<
upgrade::MapOutboundUpgradeErr<
upgrade::MapOutboundUpgrade<
TProto2::OutboundProtocol,
fn(TProto2Out) -> EitherOutput<TProto1Out, TProto2Out>

View File

@ -60,10 +60,9 @@ where
}
}
impl<C, U, F, T> OutboundUpgrade<C> for MapInboundUpgrade<U, F>
impl<C, U, F> OutboundUpgrade<C> for MapInboundUpgrade<U, F>
where
U: OutboundUpgrade<C>,
F: FnOnce(U::Output) -> T
U: OutboundUpgrade<C>
{
type Output = U::Output;
type Error = U::Error;
@ -96,10 +95,9 @@ where
}
}
impl<C, U, F, T> InboundUpgrade<C> for MapOutboundUpgrade<U, F>
impl<C, U, F> InboundUpgrade<C> for MapOutboundUpgrade<U, F>
where
U: InboundUpgrade<C>,
F: FnOnce(U::Output) -> T
U: InboundUpgrade<C>
{
type Output = U::Output;
type Error = U::Error;
@ -129,15 +127,15 @@ where
/// Wraps around an upgrade and applies a closure to the error.
#[derive(Debug, Clone)]
pub struct MapUpgradeErr<U, F> { upgrade: U, fun: F }
pub struct MapInboundUpgradeErr<U, F> { upgrade: U, fun: F }
impl<U, F> MapUpgradeErr<U, F> {
impl<U, F> MapInboundUpgradeErr<U, F> {
pub fn new(upgrade: U, fun: F) -> Self {
MapUpgradeErr { upgrade, fun }
MapInboundUpgradeErr { upgrade, fun }
}
}
impl<U, F> UpgradeInfo for MapUpgradeErr<U, F>
impl<U, F> UpgradeInfo for MapInboundUpgradeErr<U, F>
where
U: UpgradeInfo
{
@ -149,7 +147,7 @@ where
}
}
impl<C, U, F, T> InboundUpgrade<C> for MapUpgradeErr<U, F>
impl<C, U, F, T> InboundUpgrade<C> for MapInboundUpgradeErr<U, F>
where
U: InboundUpgrade<C>,
F: FnOnce(U::Error) -> T
@ -166,10 +164,45 @@ where
}
}
impl<C, U, F, T> OutboundUpgrade<C> for MapUpgradeErr<U, F>
impl<C, U, F> OutboundUpgrade<C> for MapInboundUpgradeErr<U, F>
where
U: OutboundUpgrade<C>
{
type Output = U::Output;
type Error = U::Error;
type Future = U::Future;
fn upgrade_outbound(self, sock: C, id: Self::UpgradeId) -> Self::Future {
self.upgrade.upgrade_outbound(sock, id)
}
}
/// Wraps around an upgrade and applies a closure to the error.
#[derive(Debug, Clone)]
pub struct MapOutboundUpgradeErr<U, F> { upgrade: U, fun: F }
impl<U, F> MapOutboundUpgradeErr<U, F> {
pub fn new(upgrade: U, fun: F) -> Self {
MapOutboundUpgradeErr { upgrade, fun }
}
}
impl<U, F> UpgradeInfo for MapOutboundUpgradeErr<U, F>
where
U: UpgradeInfo
{
type UpgradeId = U::UpgradeId;
type NamesIter = U::NamesIter;
fn protocol_names(&self) -> Self::NamesIter {
self.upgrade.protocol_names()
}
}
impl<C, U, F, T> OutboundUpgrade<C> for MapOutboundUpgradeErr<U, F>
where
U: OutboundUpgrade<C>,
F: FnOnce(U::Error) -> T,
F: FnOnce(U::Error) -> T
{
type Output = U::Output;
type Error = T;
@ -183,6 +216,19 @@ where
}
}
impl<C, U, F> InboundUpgrade<C> for MapOutboundUpgradeErr<U, F>
where
U: InboundUpgrade<C>
{
type Output = U::Output;
type Error = U::Error;
type Future = U::Future;
fn upgrade_inbound(self, sock: C, id: Self::UpgradeId) -> Self::Future {
self.upgrade.upgrade_inbound(sock, id)
}
}
pub struct MapFuture<TInnerFut, TMap> {
inner: TInnerFut,
map: Option<TMap>,

View File

@ -71,7 +71,7 @@ pub use self::{
apply::{apply, apply_inbound, apply_outbound, InboundUpgradeApply, OutboundUpgradeApply},
denied::DeniedUpgrade,
error::UpgradeError,
map::{MapInboundUpgrade, MapOutboundUpgrade, MapUpgradeErr},
map::{MapInboundUpgrade, MapOutboundUpgrade, MapInboundUpgradeErr, MapOutboundUpgradeErr},
or::OrUpgrade,
toggleable::{toggleable, Toggleable}
};
@ -119,12 +119,12 @@ pub trait InboundUpgradeExt<C>: InboundUpgrade<C> {
}
/// Returns a new object that wraps around `Self` and applies a closure to the `Error`.
fn map_inbound_err<F, T>(self, f: F) -> MapUpgradeErr<Self, F>
fn map_inbound_err<F, T>(self, f: F) -> MapInboundUpgradeErr<Self, F>
where
Self: Sized,
F: FnOnce(Self::Error) -> T
{
MapUpgradeErr::new(self, f)
MapInboundUpgradeErr::new(self, f)
}
/// Returns a new object that combines `Self` and another upgrade to support both at the same
@ -169,12 +169,12 @@ pub trait OutboundUpgradeExt<C>: OutboundUpgrade<C> {
}
/// Returns a new object that wraps around `Self` and applies a closure to the `Error`.
fn map_outbound_err<F, T>(self, f: F) -> MapUpgradeErr<Self, F>
fn map_outbound_err<F, T>(self, f: F) -> MapOutboundUpgradeErr<Self, F>
where
Self: Sized,
F: FnOnce(Self::Error) -> T
{
MapUpgradeErr::new(self, f)
MapOutboundUpgradeErr::new(self, f)
}
/// Returns a new object that combines `Self` and another upgrade to support both at the same