use std::collections::VecDeque;
#[cfg(doc)]
use std::io::BufReader;
use std::io::{BufRead, Read, Result, SeekFrom};
use crate::util::seek_add_offset;
use crate::{
detail::{PeekCursorState, PeekReadImpl},
PeekCursor, PeekRead,
};
#[derive(Debug)]
pub struct BufPeekReader<R> {
buf_storage: VecDeque<u8>,
tmp: Vec<u8>,
min_read_size: usize,
inner: R,
}
impl<R: Read> BufPeekReader<R> {
const MIN_READ_TO_END: usize = 32;
pub fn new(reader: R) -> Self {
Self {
buf_storage: VecDeque::new(),
tmp: Vec::new(),
min_read_size: 0,
inner: reader,
}
}
pub fn unread(&mut self, data: &[u8]) {
self.buf_storage.reserve(data.len());
for byte in data.iter().copied().rev() {
self.buf_storage.push_front(byte);
}
}
pub fn set_min_read_size(&mut self, nbytes: usize) {
self.min_read_size = nbytes;
}
pub fn min_read_size(&self) -> usize {
self.min_read_size
}
pub fn buffer(&self) -> &VecDeque<u8> {
&self.buf_storage
}
pub fn get_ref(&self) -> &R {
&self.inner
}
pub fn get_mut(&mut self) -> &mut R {
&mut self.inner
}
pub fn into_inner(self) -> R {
self.inner
}
fn request_buffer(&mut self, nbytes: usize) -> Result<()> {
let nbytes_needed = nbytes.saturating_sub(self.buf_storage.len());
if nbytes_needed > 0 {
let read_size = nbytes_needed.max(self.min_read_size);
self.inner
.by_ref()
.take(read_size as u64)
.read_to_end(&mut self.tmp)?;
self.buf_storage.reserve(self.tmp.len());
self.buf_storage.extend(self.tmp.drain(..));
}
Ok(())
}
fn peek_slices(&self, peek_pos: usize) -> (&[u8], &[u8]) {
let (a, b) = self.buf_storage.as_slices();
let first = a.get(peek_pos..).unwrap_or_default();
let second = b
.get(peek_pos.saturating_sub(a.len())..)
.unwrap_or_default();
(first, second)
}
}
impl<R: Read> PeekRead for BufPeekReader<R> {
fn peek(&mut self) -> PeekCursor<'_> {
PeekCursor::new(self)
}
}
impl<R: Read> PeekReadImpl for BufPeekReader<R> {
fn peek_read(&mut self, state: &mut PeekCursorState, buf: &mut [u8]) -> Result<usize> {
self.request_buffer(state.peek_pos as usize + buf.len())?;
let (mut first, mut second) = self.peek_slices(state.peek_pos as usize);
let mut written = first.read(buf).unwrap(); written += second.read(&mut buf[written..]).unwrap(); state.peek_pos += written as u64;
Ok(written)
}
fn peek_fill_buf(&mut self, state: &mut PeekCursorState) -> Result<&[u8]> {
self.request_buffer(state.peek_pos as usize + 1)?;
let (first, second) = self.peek_slices(state.peek_pos as usize);
if !first.is_empty() {
Ok(first)
} else {
Ok(second)
}
}
fn peek_consume(&mut self, state: &mut PeekCursorState, amt: usize) {
state.peek_pos += amt as u64;
}
fn peek_read_exact(&mut self, state: &mut PeekCursorState, buf: &mut [u8]) -> Result<()> {
self.request_buffer(state.peek_pos as usize + buf.len())?;
let (mut first, mut second) = self.peek_slices(state.peek_pos as usize);
let written = first.read(buf).unwrap(); second.read_exact(&mut buf[written..])?;
state.peek_pos += buf.len() as u64;
Ok(())
}
fn peek_stream_position(&mut self, state: &mut PeekCursorState) -> Result<u64> {
Ok(state.peek_pos)
}
fn peek_seek(&mut self, state: &mut PeekCursorState, pos: SeekFrom) -> Result<u64> {
match pos {
SeekFrom::Start(offset) => state.peek_pos = offset,
SeekFrom::Current(offset) => {
state.peek_pos = seek_add_offset(state.peek_pos, offset)?;
}
SeekFrom::End(offset) => {
let mut requested_buffer_size = self.buf_storage.len();
while self.buf_storage.len() == requested_buffer_size {
requested_buffer_size = (requested_buffer_size * 2).max(Self::MIN_READ_TO_END);
self.request_buffer(requested_buffer_size)?;
}
state.peek_pos = seek_add_offset(self.buf_storage.len() as u64, offset)?;
}
}
Ok(state.peek_pos)
}
}
impl<R: Read> Read for BufPeekReader<R> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
let (mut first, mut second) = self.buf_storage.as_slices();
let mut written = first.read(buf).unwrap(); written += second.read(&mut buf[written..]).unwrap(); self.inner.read(&mut buf[written..]).map(|inner_written| {
self.consume(written);
written + inner_written
})
}
fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
let (mut first, mut second) = self.buf_storage.as_slices();
let mut written = first.read(buf).unwrap(); written += second.read(&mut buf[written..])?; self.inner
.read_exact(&mut buf[written..])
.map(|_| self.consume(buf.len()))
}
}
impl<R: Read> BufRead for BufPeekReader<R> {
fn fill_buf(&mut self) -> Result<&[u8]> {
self.request_buffer(self.min_read_size)?;
let (first, second) = self.buf_storage.as_slices();
if !first.is_empty() {
Ok(first)
} else {
Ok(second)
}
}
fn consume(&mut self, amt: usize) {
for _ in 0..amt.min(self.buf_storage.len()) {
self.buf_storage.pop_front();
}
}
}