volans-core 0.2.0

Core trait and struct for Volans networking framework
Documentation
pub(crate) mod boxed;

pub mod and_then;
pub mod apply;
pub mod choice;
pub mod map;
pub mod map_err;
pub mod timeout;
pub mod upgrade;

pub use boxed::{Boxed, BoxedListener};

use futures::TryFuture;

use std::{
    error, fmt,
    pin::Pin,
    task::{Context, Poll},
    time::Duration,
};

use crate::{
    ConnectedPoint, Multiaddr, Negotiated,
    upgrade::{InboundConnectionUpgrade, OutboundConnectionUpgrade},
};

pub trait Listener {
    type Output;
    type Error: std::error::Error;
    type Upgrade: Future<Output = Result<Self::Output, Self::Error>>;

    fn poll_event(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<ListenerEvent<Self::Upgrade, Self::Error>>;

    fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>>;
}
pub trait Transport {
    type Output;
    type Error: std::error::Error;
    type Dial: Future<Output = Result<Self::Output, Self::Error>>;
    type Incoming: Future<Output = Result<Self::Output, Self::Error>>;
    type Listener: Listener<Output = Self::Output, Error = Self::Error, Upgrade = Self::Incoming>;

    fn dial(&self, addr: Multiaddr) -> Result<Self::Dial, TransportError<Self::Error>>;
    fn listen(&self, addr: Multiaddr) -> Result<Self::Listener, TransportError<Self::Error>>;

    fn and_then<D, TMap, TMapFut>(self, map: TMap) -> and_then::AndThen<Self, TMap>
    where
        Self: Sized,
        TMap: FnOnce(Self::Output, ConnectedPoint) -> TMapFut + Clone,
        TMapFut: TryFuture<Ok = D>,
        TMapFut::Error: std::error::Error,
    {
        and_then::AndThen::new(self, map)
    }

    fn map<D, TMap>(self, map: TMap) -> map::Map<Self, TMap>
    where
        Self: Sized,
        TMap: FnOnce(Self::Output, ConnectedPoint) -> D + Clone,
    {
        map::Map::new(self, map)
    }

    fn map_err<TErr, F>(self, map: F) -> map_err::MapErr<Self, F>
    where
        Self: Sized,
        F: FnOnce(Self::Error) -> TErr + Clone,
        TErr: std::error::Error,
    {
        map_err::MapErr::new(self, map)
    }

    fn apply<C, D, E, U>(self, upgrade: U) -> apply::UpgradeApply<Self, U>
    where
        Self: Sized,
        Self: Transport<Output = C>,
        U: InboundConnectionUpgrade<Negotiated<C>, Output = D, Error = E>,
        U: OutboundConnectionUpgrade<Negotiated<C>, Output = D, Error = E>,
        E: std::error::Error,
    {
        apply::UpgradeApply::new(self, upgrade)
    }

    fn choice<B>(self, other: B) -> choice::Choice<Self, B>
    where
        Self: Sized,
        B: Transport,
    {
        choice::Choice::new(self, other)
    }

    fn timeout(self, timeout: Duration) -> timeout::Timeout<Self>
    where
        Self: Sized,
    {
        timeout::Timeout::new(self, timeout)
    }

    fn boxed(self) -> boxed::Boxed<Self::Output>
    where
        Self: Sized + Send + Unpin + 'static,
        Self::Dial: Send + 'static,
        Self::Incoming: Send + 'static,
        Self::Error: Send + Sync,
        Self::Listener: Send + Unpin + 'static,
    {
        boxed::boxed(self)
    }

    fn upgrade(self) -> upgrade::Builder<Self>
    where
        Self: Sized,
        Self::Error: 'static,
    {
        upgrade::Builder::new(self)
    }
}

pub enum ListenerEvent<TUpgr, TErr> {
    NewAddress(Multiaddr),
    AddressExpired(Multiaddr),
    Incoming {
        local_addr: Multiaddr,
        remote_addr: Multiaddr,
        upgrade: TUpgr,
    },
    Closed(Result<(), TErr>),
    Error(TErr),
}

impl<TUpgr, TErr> ListenerEvent<TUpgr, TErr> {
    pub fn map_upgrade<F, TUpgr2>(self, map: F) -> ListenerEvent<TUpgr2, TErr>
    where
        F: FnOnce(TUpgr) -> TUpgr2,
    {
        match self {
            ListenerEvent::NewAddress(addr) => ListenerEvent::NewAddress(addr),
            ListenerEvent::AddressExpired(addr) => ListenerEvent::AddressExpired(addr),
            ListenerEvent::Incoming {
                local_addr,
                remote_addr,
                upgrade,
            } => ListenerEvent::Incoming {
                local_addr,
                remote_addr,
                upgrade: map(upgrade),
            },
            ListenerEvent::Closed(res) => ListenerEvent::Closed(res),
            ListenerEvent::Error(err) => ListenerEvent::Error(err),
        }
    }

    pub fn map_err<F, TErr2>(self, map: F) -> ListenerEvent<TUpgr, TErr2>
    where
        F: FnOnce(TErr) -> TErr2,
    {
        match self {
            ListenerEvent::NewAddress(addr) => ListenerEvent::NewAddress(addr),
            ListenerEvent::AddressExpired(addr) => ListenerEvent::AddressExpired(addr),
            ListenerEvent::Incoming {
                local_addr,
                remote_addr,
                upgrade,
            } => ListenerEvent::Incoming {
                local_addr,
                remote_addr,
                upgrade,
            },
            ListenerEvent::Closed(res) => ListenerEvent::Closed(res.map_err(map)),
            ListenerEvent::Error(err) => ListenerEvent::Error(map(err)),
        }
    }
}

#[derive(Debug, Clone)]
pub enum TransportError<TErr> {
    NotSupported(Multiaddr),
    Other(TErr),
}

impl<TErr> From<TErr> for TransportError<TErr> {
    fn from(err: TErr) -> Self {
        TransportError::Other(err)
    }
}

impl<TErr> TransportError<TErr> {
    pub fn map<E, F>(self, map: F) -> TransportError<E>
    where
        F: FnOnce(TErr) -> E,
        E: std::error::Error,
    {
        match self {
            TransportError::NotSupported(addr) => TransportError::NotSupported(addr),
            TransportError::Other(err) => TransportError::Other(map(err)),
        }
    }
}

impl<TErr> fmt::Display for TransportError<TErr>
where
    TErr: fmt::Display,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            TransportError::NotSupported(addr) => {
                write!(f, "Transport not supported for address: {}", addr)
            }
            TransportError::Other(err) => write!(f, "Transport error: {}", err),
        }
    }
}

impl<TErr> error::Error for TransportError<TErr>
where
    TErr: error::Error + 'static,
{
    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
        match self {
            TransportError::NotSupported(_) => None,
            TransportError::Other(err) => Some(err),
        }
    }
}