use hyper::service::Service;
use hyper::Uri;
use hyper_util::client::legacy::connect::{Connected, Connection};
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
use std::error::Error as StdError;
use std::future::Future;
use std::io;
use std::pin::Pin;
use std::sync::Arc;
use std::task::{Context, Poll};
pub mod http;
pub mod hyper_adapter;
pub use self::http::{ConnectError, HttpConnection, HttpConnector};
pub use self::hyper_adapter::HyperConnectorAdapter;
trait NetworkStream: AsyncRead + AsyncWrite + Connection + Unpin + Send + 'static {}
impl<T> NetworkStream for T where T: AsyncRead + AsyncWrite + Connection + Unpin + Send + 'static {}
pub struct NetworkConnection(Box<dyn NetworkStream>);
impl NetworkConnection {
pub fn new<S>(stream: S) -> Self
where
S: AsyncRead + AsyncWrite + Connection + Unpin + Send + 'static,
{
NetworkConnection(Box::new(stream))
}
}
impl Connection for NetworkConnection {
fn connected(&self) -> Connected {
self.0.connected()
}
}
impl AsyncRead for NetworkConnection {
fn poll_read(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut ReadBuf<'_>,
) -> Poll<io::Result<()>> {
Pin::new(&mut self.get_mut().0).poll_read(cx, buf)
}
}
impl AsyncWrite for NetworkConnection {
fn poll_write(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<io::Result<usize>> {
Pin::new(&mut self.get_mut().0).poll_write(cx, buf)
}
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
Pin::new(&mut self.get_mut().0).poll_flush(cx)
}
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
Pin::new(&mut self.get_mut().0).poll_shutdown(cx)
}
}
impl hyper::rt::Read for NetworkConnection {
fn poll_read(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
mut buf: hyper::rt::ReadBufCursor<'_>,
) -> Poll<Result<(), std::io::Error>> {
let mut tmp_buf = unsafe { ReadBuf::uninit(buf.as_mut()) };
let bytes_read = match AsyncRead::poll_read(self, cx, &mut tmp_buf) {
Poll::Ready(Ok(())) => tmp_buf.filled().len(),
other => return other,
};
unsafe { buf.advance(bytes_read) };
Poll::Ready(Ok(()))
}
}
impl hyper::rt::Write for NetworkConnection {
fn poll_write(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<Result<usize, std::io::Error>> {
AsyncWrite::poll_write(self, cx, buf)
}
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), std::io::Error>> {
AsyncWrite::poll_flush(self, cx)
}
fn poll_shutdown(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Result<(), std::io::Error>> {
AsyncWrite::poll_shutdown(self, cx)
}
}
pub trait NetworkConnector: Send + Sync + 'static {
fn connect(
&self,
uri: Uri,
) -> Pin<
Box<dyn Future<Output = Result<NetworkConnection, Box<dyn StdError + Send + Sync>>> + Send>,
>;
}
#[derive(Clone)]
pub(crate) struct ConnectorAdapter(Arc<dyn NetworkConnector>);
impl ConnectorAdapter {
pub fn new<T: NetworkConnector>(connector: T) -> Self {
Self(Arc::new(connector))
}
}
impl Service<Uri> for ConnectorAdapter {
type Response = NetworkConnection;
type Error = Box<dyn StdError + Send + Sync>;
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
fn call(&self, uri: Uri) -> Self::Future {
self.0.connect(uri)
}
}
impl tower_service::Service<Uri> for ConnectorAdapter {
type Response = NetworkConnection;
type Error = Box<dyn StdError + Send + Sync>;
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
fn call(&mut self, uri: Uri) -> Self::Future {
self.0.connect(uri)
}
}