use crate::{
buf::{BufResult, IoBuf, IoBufMut, IoVectoredBuf, IoVectoredBufMut},
io::{AsyncBufRead, AsyncRead, AsyncWrite},
};
pub struct BufReader<R> {
reader: R,
buf: Box<[u8]>,
pos: usize,
cap: usize,
}
impl<R: AsyncRead> BufReader<R> {
#[inline]
pub fn new(inner: R) -> Self {
Self::with_capacity(8 * 1024, inner)
}
#[inline]
pub fn with_capacity(capacity: usize, reader: R) -> Self {
Self {
reader,
buf: vec![0; capacity].into_boxed_slice(),
pos: 0,
cap: 0,
}
}
#[inline]
pub const fn get_ref(&self) -> &R {
&self.reader
}
#[inline]
pub fn get_mut(&mut self) -> &mut R {
&mut self.reader
}
#[inline]
pub fn into_inner(self) -> R {
self.reader
}
#[inline]
pub fn buffer(&self) -> &[u8] {
&self.buf[self.pos..self.cap]
}
#[inline]
fn discard_buffer(&mut self) {
self.pos = 0;
self.cap = 0;
}
}
impl<R: AsyncRead> AsyncRead for BufReader<R> {
async fn read<B: IoBufMut>(&mut self, mut buf: B) -> BufResult<usize, B> {
let owned_buf = self.buf.as_ref();
if self.pos == self.cap && buf.as_uninit().len() >= owned_buf.len() {
self.discard_buffer();
return self.reader.read(buf).await;
}
let rem = match self.fill_buf().await {
Ok(slice) => slice,
Err(e) => {
return BufResult(Err(e), buf);
}
};
let amt = rem.len().min(buf.as_uninit().len());
unsafe {
buf.as_uninit()
.as_mut_ptr()
.cast::<u8>()
.copy_from_nonoverlapping(rem.as_ptr(), amt);
buf.set_len(amt);
}
self.consume(amt);
BufResult(Ok(amt), buf)
}
async fn read_vectored<V: IoVectoredBufMut>(&mut self, bufs: V) -> BufResult<usize, V> {
self.discard_buffer();
self.reader.read_vectored(bufs).await
}
}
impl<R: AsyncRead> AsyncBufRead for BufReader<R> {
async fn fill_buf(&mut self) -> std::io::Result<&'_ [u8]> {
if self.pos == self.cap {
let buf = std::mem::take(&mut self.buf);
let (res, buf) = self.reader.read(buf).await.into_parts();
self.buf = buf;
match res {
Ok(bytes_read) => {
self.pos = 0;
self.cap = bytes_read;
return Ok(&self.buf.as_ref()[self.pos..self.cap]);
}
Err(e) => return Err(e),
}
}
Ok(&self.buf)
}
fn consume(&mut self, amount: usize) {
self.pos = self.cap.min(self.pos + amount);
}
fn buffer(&self) -> &[u8] {
&self.buf[self.pos..self.cap]
}
}
impl<R: AsyncRead + AsyncWrite> AsyncWrite for BufReader<R> {
#[inline]
async fn write<T: IoBuf>(&mut self, buf: T) -> BufResult<usize, T> {
self.reader.write(buf).await
}
#[inline]
async fn write_vectored<V: IoVectoredBuf>(&mut self, bufs: V) -> BufResult<usize, V> {
self.reader.write_vectored(bufs).await
}
#[inline]
async fn flush(&mut self) -> std::io::Result<()> {
self.reader.flush().await
}
#[inline]
async fn shutdown(&mut self) -> std::io::Result<()> {
self.reader.shutdown().await
}
}