use compio_buf::{BufResult, IntoInner, IoBuf, IoBufMut, IoVectoredBufMut, buf_try};
use crate::{AsyncRead, IoResult, buffer::Buffer, util::DEFAULT_BUF_SIZE};
pub trait AsyncBufRead: AsyncRead {
async fn fill_buf(&mut self) -> IoResult<&'_ [u8]>;
fn consume(&mut self, amount: usize);
}
impl<A: AsyncBufRead + ?Sized> AsyncBufRead for &mut A {
async fn fill_buf(&mut self) -> IoResult<&'_ [u8]> {
(**self).fill_buf().await
}
fn consume(&mut self, amount: usize) {
(**self).consume(amount)
}
}
#[derive(Debug)]
pub struct BufReader<R> {
reader: R,
buf: Buffer,
}
impl<R> BufReader<R> {
pub fn new(reader: R) -> Self {
Self::with_capacity(DEFAULT_BUF_SIZE, reader)
}
pub fn with_capacity(cap: usize, reader: R) -> Self {
Self {
reader,
buf: Buffer::with_capacity(cap),
}
}
}
impl<R: AsyncRead> AsyncRead for BufReader<R> {
async fn read<B: IoBufMut>(&mut self, buf: B) -> BufResult<usize, B> {
let (mut slice, buf) = buf_try!(self.fill_buf().await, buf);
slice.read(buf).await.map_res(|res| {
self.consume(res);
res
})
}
async fn read_vectored<V: IoVectoredBufMut>(&mut self, buf: V) -> BufResult<usize, V> {
let (mut slice, buf) = buf_try!(self.fill_buf().await, buf);
slice.read_vectored(buf).await.map_res(|res| {
self.consume(res);
res
})
}
}
impl<R: AsyncRead> AsyncBufRead for BufReader<R> {
async fn fill_buf(&mut self) -> IoResult<&'_ [u8]> {
let Self { reader, buf } = self;
if buf.all_done() {
buf.reset()
}
if buf.need_fill() {
buf.with(|b| async move {
let len = b.buf_len();
let b = b.slice(len..);
reader.read(b).await.into_inner()
})
.await?;
}
Ok(buf.buffer())
}
fn consume(&mut self, amount: usize) {
self.buf.advance(amount);
}
}
impl<R> IntoInner for BufReader<R> {
type Inner = R;
fn into_inner(self) -> Self::Inner {
self.reader
}
}