ciph 0.1.0

Symmetric cipher layer for async read/write connections.
Documentation
//! Wrap the SalsaStream and SalsaListener to make them compatible with `warp`.
use std::{
    future::Future,
    task::{Context, Poll},
    pin::Pin,
};

use futures::ready;
use tokio::net::TcpStream;
use tower_service::Service;
use hyper::{
    Uri,
    client::{
        connect::{Connection, Connected},
        HttpConnector,
    },
};

use super::{SalsaStream, Connector};

/// Convenience type if `SalsaStream` is to be used to secure the client side of a HTTP
/// connection in lieu of OpenSSL/TLS with [hyper](https://github.com/hyperium/hyper).
#[derive(Clone)]
pub struct HyperSalsaConnector {
    http: HttpConnector,
    connector: Connector,
}

impl HyperSalsaConnector {
    pub fn new(http: HttpConnector, connector: Connector) -> Self {        
        Self { http, connector }
    }

    pub fn new_http(connector: Connector) -> Self {
        Self::new(HttpConnector::new(), connector)
    }    
}

type BoxErr = Box<dyn std::error::Error + Send + Sync>;

impl Service<Uri> for HyperSalsaConnector {
    type Response = SalsaStream<TcpStream>;
    type Error = BoxErr;
    type Future = HyperSalsaConnecting;

    fn poll_ready(&mut self, ctx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        match ready!(self.http.poll_ready(ctx)) {
            Ok(()) => Poll::Ready(Ok(())),
            Err(e) => Poll::Ready(Err(e.into()))
        }
    }

    fn call(&mut self, dst: Uri) -> Self::Future {
        let tcp_connecting = self.http.call(dst);
        let connector = self.connector.clone();

        let fut = async move {
            let socket = tcp_connecting
                .await?;
            
            let wrapped = connector
                .connect(socket)
                .await?;
            
            Ok(wrapped)
        };
        
        HyperSalsaConnecting(Box::pin(fut))
    }
}

type BoxFut = Pin<Box<dyn Future<Output = Result<SalsaStream<TcpStream>, BoxErr>> + Send>>;

pub struct HyperSalsaConnecting(BoxFut);

impl Future for HyperSalsaConnecting {
    type Output = Result<SalsaStream<TcpStream>, BoxErr>;

    fn poll(mut self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> {
        Pin::new(&mut self.0).poll(ctx)
    }
}

impl<T> Connection for SalsaStream<T> {
    fn connected(&self) -> Connected {
        Connected::new()
    }
}