use core::fmt;
use std::{cmp, ops::Range};
use crate::buf_ext_iter::BufExtIter;
pub struct BufExt<'a> {
reader: &'a mut dyn std::io::Read, ext: Vec<u8>, sz_read_ext: usize, eos_reached: bool, }
impl<'a> BufExt<'a> {
pub fn new(
reader: &'a mut dyn std::io::Read,
initiale_capacity: usize,
sz_read_ext: usize,
) -> Self {
Self {
reader,
ext: Vec::with_capacity(initiale_capacity),
sz_read_ext,
eos_reached: false,
}
}
pub fn extend(&mut self) -> std::io::Result<usize> {
if self.ext.capacity() < self.ext.len() + self.sz_read_ext {
self.ext.reserve(self.sz_read_ext);
}
let start = self.ext.len();
self.ext.resize(start + self.sz_read_ext, 0);
let sz_read = self.reader.read(&mut self.ext[start..])?;
if start + sz_read < self.ext.len() {
self.ext.resize(start + sz_read, 0);
}
if sz_read == 0 {
self.eos_reached = true;
}
Ok(sz_read)
}
pub fn pop_buf_into(&mut self, buf: &mut [u8]) -> usize {
let sz = cmp::min(self.ext.len(), buf.len());
buf[..sz].copy_from_slice(&self.ext[..sz]);
self.ext.drain(..sz);
sz
}
pub fn drain(&mut self, range: Range<usize>) {
self.ext.drain(range);
}
pub fn read_direct(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
self.reader.read(buf)
}
pub fn push_at_begin(&mut self, buf: &[u8]) {
self.ext.splice(0..0, buf.iter().copied());
}
pub fn len(&self) -> usize {
self.ext.len()
}
pub fn at(&self, pos: usize) -> u8 {
self.ext[pos]
}
pub fn eos_reached(&self) -> bool {
self.eos_reached
}
pub fn iter_growing<'b>(&'b mut self) -> BufExtIter<'b, 'a> {
BufExtIter::new(self)
}
#[allow(dead_code)]
pub fn cloned_internal_vec(&self) -> Vec<u8> {
self.ext.clone()
}
}
impl<'a> fmt::Debug for BufExt<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"buf_extend={:?} sz_read_ext=[{:?}]",
self.ext, self.sz_read_ext
)
}
}