use std::{future::poll_fn, io::IoSliceMut, pin::Pin, task::Poll};
use tokio::io::AsyncRead;
pub trait AsyncReadVectored: AsyncRead + Unpin {
fn poll_read_vectored(
self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
vec: &mut [IoSliceMut<'_>],
) -> Poll<std::io::Result<usize>>;
}
impl<T: ?Sized + AsyncReadVectored> AsyncReadVectored for &mut T {
fn poll_read_vectored(
mut self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
vec: &mut [IoSliceMut<'_>],
) -> Poll<std::io::Result<usize>> {
Pin::new(&mut **self).poll_read_vectored(cx, vec)
}
}
impl<T: ?Sized + AsyncReadVectored> AsyncReadVectored for Box<T> {
fn poll_read_vectored(
mut self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
vec: &mut [IoSliceMut<'_>],
) -> Poll<std::io::Result<usize>> {
Pin::new(&mut **self).poll_read_vectored(cx, vec)
}
}
pub trait AsyncReadVectoredExt {
async fn read_vectored(&mut self, vec: &mut [IoSliceMut<'_>]) -> std::io::Result<usize>;
}
impl<T: AsyncReadVectored> AsyncReadVectoredExt for T {
async fn read_vectored(&mut self, vec: &mut [IoSliceMut<'_>]) -> std::io::Result<usize> {
poll_fn(|cx| Pin::new(&mut *self).poll_read_vectored(cx, vec)).await
}
}
impl AsyncReadVectored for tokio::net::tcp::OwnedReadHalf {
fn poll_read_vectored(
self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
vec: &mut [IoSliceMut<'_>],
) -> Poll<std::io::Result<usize>> {
let this = self.get_mut();
loop {
match this.try_read_vectored(vec) {
Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => {
std::task::ready!(this.as_ref().poll_read_ready(cx)?);
continue;
}
res => return Poll::Ready(res),
}
}
}
}
impl AsyncReadVectored for librqbit_utp::UtpStreamReadHalf {
fn poll_read_vectored(
self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
vec: &mut [IoSliceMut<'_>],
) -> Poll<std::io::Result<usize>> {
librqbit_utp::UtpStreamReadHalf::poll_read_vectored(self, cx, vec)
}
}
pub struct AsyncReadToVectoredCompat<T>(T);
impl<T: AsyncRead + Unpin> AsyncRead for AsyncReadToVectoredCompat<T> {
fn poll_read(
self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
buf: &mut tokio::io::ReadBuf<'_>,
) -> Poll<std::io::Result<()>> {
Pin::new(&mut self.get_mut().0).poll_read(cx, buf)
}
}
impl<T: AsyncRead + Unpin> AsyncReadVectored for AsyncReadToVectoredCompat<T> {
fn poll_read_vectored(
self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
vec: &mut [IoSliceMut<'_>],
) -> Poll<std::io::Result<usize>> {
let first_non_empty = match vec.iter_mut().find(|s| !s.is_empty()) {
Some(s) => &mut **s,
None => return Poll::Ready(Ok(0)),
};
let mut rbuf = tokio::io::ReadBuf::new(first_non_empty);
std::task::ready!(self.poll_read(cx, &mut rbuf)?);
Poll::Ready(Ok(rbuf.filled().len()))
}
}
pub trait AsyncReadVectoredIntoCompat: Sized {
fn into_vectored_compat(self) -> AsyncReadToVectoredCompat<Self>;
}
impl<T: AsyncRead + Unpin + Sized> AsyncReadVectoredIntoCompat for T {
fn into_vectored_compat(self) -> AsyncReadToVectoredCompat<Self> {
AsyncReadToVectoredCompat(self)
}
}