pub struct BufferedReader<'a, R: std::io::BufRead> {
inner: &'a mut R,
buffer: Vec<u8>,
filled: Vec<u8>,
inner_len: usize,
consumed: usize,
}
impl<'a, R: std::io::BufRead> BufferedReader<'a, R> {
pub fn new(inner: &'a mut R) -> Self {
Self {
inner,
buffer: Vec::new(),
filled: Vec::new(),
inner_len: 0,
consumed: 0,
}
}
pub fn buffer_len(&mut self) -> std::io::Result<usize> {
Ok(self.inner.fill_buf()?.len())
}
pub fn len(&mut self) -> std::io::Result<usize> {
Ok(self.inner.fill_buf()?.len() + self.buffer.len())
}
pub fn is_empty(&mut self) -> std::io::Result<bool> {
Ok(self.len()? == 0)
}
pub fn refill(&mut self) -> std::io::Result<()> {
self.buffer = self.inner.fill_buf()?.to_vec();
self.inner.consume(self.buffer.len());
Ok(())
}
pub fn consumed(&self) -> usize {
self.consumed
}
}
impl<R: std::io::BufRead> std::io::Read for BufferedReader<'_, R> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
if buf.is_empty() {
return Ok(0);
}
let mut total_read = 0;
if !self.buffer.is_empty() {
let to_copy = self.buffer.len().min(buf.len());
buf[..to_copy].copy_from_slice(&self.buffer[..to_copy]);
self.buffer.drain(..to_copy);
total_read += to_copy;
}
if total_read < buf.len() {
let from_inner = self.inner.read(&mut buf[total_read..])?;
total_read += from_inner;
}
self.consumed += total_read;
Ok(total_read)
}
}
impl<R: std::io::BufRead> std::io::BufRead for BufferedReader<'_, R> {
fn fill_buf(&mut self) -> std::io::Result<&[u8]> {
if self.buffer.is_empty() {
return self.inner.fill_buf();
}
let inner = self.inner.fill_buf()?;
self.inner_len = inner.len();
self.filled.clear();
self.filled.reserve(inner.len() + self.buffer.len());
self.filled.extend_from_slice(&self.buffer);
self.filled.extend_from_slice(inner);
Ok(&self.filled)
}
fn consume(&mut self, mut amt: usize) {
if self.buffer.is_empty() {
self.inner.consume(amt);
self.consumed += amt;
return;
}
self.filled.clear();
let buf_len = self.buffer.len();
if amt <= buf_len {
self.buffer.drain(..amt);
self.consumed += amt;
return;
}
amt -= buf_len;
self.buffer.clear();
self.consumed += buf_len;
if amt <= self.inner_len {
self.inner.consume(amt);
self.inner_len -= amt;
self.consumed += amt;
} else {
let consumed_from_inner = self.inner_len;
self.inner_len = 0;
self.inner.consume(consumed_from_inner);
self.consumed += consumed_from_inner;
}
}
}
#[cfg(test)]
mod tests {
use super::BufferedReader;
use std::io::{BufRead, Read};
#[test]
fn buffered_reader_refill_read_and_consume() {
let inner = std::io::Cursor::new(vec![1_u8, 2, 3, 4, 5]);
let mut inner = std::io::BufReader::with_capacity(3, inner);
let mut reader = BufferedReader::new(&mut inner);
assert!(!reader.is_empty().expect("is_empty must work"));
assert_eq!(reader.buffer_len().expect("buffer_len must work"), 3);
reader.refill().expect("refill must work");
assert_eq!(reader.buffer_len().expect("inner should be consumed"), 2);
assert_eq!(reader.len().expect("len must work"), 5);
assert_eq!(
reader.fill_buf().expect("fill_buf must work"),
&[1, 2, 3, 4, 5]
);
reader.consume(4);
assert_eq!(reader.fill_buf().expect("fill_buf must work"), &[5]);
let mut out = [0_u8; 1];
let read = reader.read(&mut out).expect("read must work");
assert_eq!(read, 1);
assert_eq!(out, [5]);
assert_eq!(reader.consumed(), 5);
assert!(reader.is_empty().expect("is_empty must work"));
}
#[test]
fn buffered_reader_read_empty_and_overconsume() {
let inner = std::io::Cursor::new(vec![9_u8, 8, 7, 6, 5, 4]);
let mut inner = std::io::BufReader::with_capacity(3, inner);
let mut reader = BufferedReader::new(&mut inner);
reader.refill().expect("refill must work");
let _ = reader.fill_buf().expect("fill_buf must work");
reader.consume(7);
assert_eq!(reader.consumed(), 6);
assert!(reader.is_empty().expect("is_empty must work"));
let mut out = [];
let read = reader
.read(&mut out)
.expect("read with empty buffer must work");
assert_eq!(read, 0);
}
}