use std::{collections::VecDeque, io::Read};
pub struct PeekableReader<R> {
buffer: VecDeque<u8>,
reader: R,
}
impl<R: Read> Read for PeekableReader<R> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
let buffer_drain_length = buf.len().min(self.buffer.len());
for (source_byte, destination_byte) in
self.buffer.drain(..buffer_drain_length).zip(buf.iter_mut())
{
*destination_byte = source_byte;
}
self.reader
.read(&mut buf[buffer_drain_length..])
.map(|read_bytes| read_bytes + buffer_drain_length)
}
}
impl<R> PeekableReader<R> {
pub fn new(reader: R) -> Self {
Self {
buffer: Default::default(),
reader,
}
}
}
impl<R: Read> PeekableReader<R> {
pub fn peek_exact(&mut self, buf: &mut [u8]) -> std::io::Result<()> {
self.ensure_buffer_length(buf.len())?;
for (source_byte, destination_byte) in self.buffer.iter().copied().zip(buf.iter_mut()) {
*destination_byte = source_byte;
}
Ok(())
}
fn ensure_buffer_length(&mut self, length: usize) -> std::io::Result<()> {
if length <= self.buffer.len() {
return Ok(());
}
let extend_offset = self.buffer.len();
self.buffer.resize(length, 0);
let (first_slice, second_slice) = self.buffer.as_mut_slices();
if first_slice.len() > extend_offset {
self.reader.read_exact(&mut first_slice[extend_offset..])?;
self.reader.read_exact(second_slice)?;
} else {
self.reader
.read_exact(&mut second_slice[extend_offset - first_slice.len()..])?;
}
Ok(())
}
}