use tokio::io::{AsyncRead, AsyncReadExt};
pub struct Peekable<const N: usize, R> {
pub(crate) buffer: Vec<u8>,
pub(crate) complete: bool,
pub(crate) reader: R,
}
impl<const N: usize, R: AsyncRead + Unpin> Peekable<N, R> {
pub fn new(reader: R) -> Self {
Self { buffer: Vec::new(), complete: false, reader }
}
pub fn with_buffer(buffer: Vec<u8>, complete: bool, reader: R) -> Self {
Self { buffer, complete, reader }
}
pub async fn peek(&mut self, num: usize) -> &[u8] {
if self.complete {
return self.buffer.as_slice();
}
let to_read = std::cmp::min(N, num);
if self.buffer.len() >= to_read {
return self.buffer.as_slice();
}
if self.buffer.capacity() == 0 {
self.buffer.reserve(N);
}
while self.buffer.len() < to_read {
match self.reader.read_buf::<Vec<u8>>(&mut self.buffer).await {
Ok(0) => {
self.complete = self.buffer.capacity() > self.buffer.len();
break;
},
Ok(_) => { },
Err(e) => {
error!("failed to read into peek buffer: {:?}.", e);
break;
}
}
}
self.buffer.as_slice()
}
}