use std::{
borrow::Cow,
io,
mem::MaybeUninit,
pin::Pin,
task::{Context, Poll, ready},
};
use compio::{
io::{AsyncRead, AsyncWrite, util::Splittable},
tls::{MaybeTlsStream, TlsStream},
};
use send_wrapper::SendWrapper;
#[derive(Debug)]
pub struct HyperStream<S: Splittable>(SendWrapper<MaybeTlsStream<S>>);
impl<S: Splittable> HyperStream<S> {
pub fn new_plain(s: S) -> Self {
Self(SendWrapper::new(MaybeTlsStream::new_plain(s)))
}
pub fn new_tls(s: TlsStream<S>) -> Self {
Self(SendWrapper::new(MaybeTlsStream::new_tls(s)))
}
pub fn is_tls(&self) -> bool {
self.0.is_tls()
}
}
impl<S: Splittable + 'static> HyperStream<S>
where
S::ReadHalf: AsyncRead + Unpin,
S::WriteHalf: AsyncWrite + Unpin,
{
pub fn negotiated_alpn(&self) -> Option<Cow<'_, [u8]>> {
self.0.negotiated_alpn()
}
}
impl<S: Splittable + 'static> hyper::rt::Read for HyperStream<S>
where
S::ReadHalf: AsyncRead + Unpin,
S::WriteHalf: AsyncWrite + Unpin,
{
fn poll_read(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
mut buf: hyper::rt::ReadBufCursor<'_>,
) -> Poll<io::Result<()>> {
let uninit = unsafe { buf.as_mut() };
uninit.fill(MaybeUninit::new(0));
let res = ready!(futures_util::AsyncRead::poll_read(
Pin::new(&mut *self.0),
cx,
unsafe { uninit.assume_init_mut() }
))?;
unsafe { buf.advance(res) };
Poll::Ready(Ok(()))
}
}
impl<S: Splittable + 'static> hyper::rt::Write for HyperStream<S>
where
S::ReadHalf: AsyncRead + Unpin,
S::WriteHalf: AsyncWrite + Unpin,
{
fn poll_write(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<io::Result<usize>> {
futures_util::AsyncWrite::poll_write(Pin::new(&mut *self.0), cx, buf)
}
fn poll_write_vectored(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
bufs: &[io::IoSlice<'_>],
) -> Poll<io::Result<usize>> {
futures_util::AsyncWrite::poll_write_vectored(Pin::new(&mut *self.0), cx, bufs)
}
fn is_write_vectored(&self) -> bool {
true
}
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
futures_util::AsyncWrite::poll_flush(Pin::new(&mut *self.0), cx)
}
fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
futures_util::AsyncWrite::poll_close(Pin::new(&mut *self.0), cx)
}
}