#![warn(missing_docs)]
use std::error;
use std::fmt;
use std::io::{self, BufRead, Read};
pub const DEFAULT_BUFFER_SIZE: usize = 8 * 1024;
pub const DEFAULT_ENSURED_BYTES: usize = 128;
pub struct EnsuredBufReader<R, B>
where
R: Read,
B: AsRef<[u8]> + AsMut<[u8]>,
{
inner: R,
buf: B,
pos: usize,
cap: usize,
ensured_size: usize,
}
impl<R: Read> EnsuredBufReader<R, Vec<u8>> {
pub fn new(inner: R) -> EnsuredBufReader<R, Vec<u8>> {
EnsuredBufReader::with_capacity_and_ensured_size(
DEFAULT_BUFFER_SIZE,
DEFAULT_ENSURED_BYTES,
inner,
)
}
pub fn with_capacity_and_ensured_size(
capacity: usize,
ensured_size: usize,
inner: R,
) -> EnsuredBufReader<R, Vec<u8>> {
assert_ne!(ensured_size, 0, "'ensure' must be positive.");
assert!(
capacity >= ensured_size,
"'capacity' ({}) must be larger than or equal to 'ensured_size' ({}).",
capacity,
ensured_size
);
EnsuredBufReader {
inner,
buf: vec![0; capacity],
pos: 0,
cap: 0,
ensured_size,
}
}
}
impl<R: Read> EnsuredBufReader<R, &mut [u8]> {
pub fn from_mut_ref(buf: &mut [u8], inner: R) -> EnsuredBufReader<R, &mut [u8]> {
assert!(
buf.len() >= DEFAULT_ENSURED_BYTES,
"buffer size ({}) must be larger than or equal to default ensured size' ({}).",
buf.len(),
DEFAULT_ENSURED_BYTES
);
EnsuredBufReader::from_mut_ref_and_ensured_size(buf, DEFAULT_ENSURED_BYTES, inner)
}
pub fn from_mut_ref_and_ensured_size(
buf: &mut [u8],
ensured_size: usize,
inner: R,
) -> EnsuredBufReader<R, &mut [u8]> {
assert_ne!(ensured_size, 0, "'ensure' must be positive.");
assert!(
buf.len() >= ensured_size,
"buffer size ({}) must be larger than or equal to 'ensured_size' ({}).",
buf.len(),
ensured_size
);
EnsuredBufReader {
inner,
buf,
pos: 0,
cap: 0,
ensured_size,
}
}
}
impl<R: Read, B: AsRef<[u8]> + AsMut<[u8]>> EnsuredBufReader<R, B> {
pub fn from_buffer(buf: B, inner: R) -> EnsuredBufReader<R, B> {
assert!(
buf.as_ref().len() >= DEFAULT_ENSURED_BYTES,
"buffer size ({}) must be larger than or equal to 'ensured_size' ({}).",
buf.as_ref().len(),
DEFAULT_ENSURED_BYTES
);
EnsuredBufReader::from_buffer_and_ensured_size(buf, DEFAULT_ENSURED_BYTES, inner)
}
pub fn from_buffer_and_ensured_size(
buf: B,
ensured_size: usize,
inner: R,
) -> EnsuredBufReader<R, B> {
assert_ne!(ensured_size, 0, "'ensure' must be positive.");
assert!(
buf.as_ref().len() >= ensured_size,
"buffer size ({}) must be larger than or equal to 'ensured_size' ({}).",
buf.as_ref().len(),
ensured_size
);
EnsuredBufReader {
inner,
buf,
pos: 0,
cap: 0,
ensured_size,
}
}
pub fn buffer(&self) -> &[u8] {
&self.buf.as_ref()[self.pos..self.cap]
}
pub fn fill_buf_to_expected_size(&mut self, expected_size: usize) -> io::Result<&[u8]> {
if self.current_bytes() >= expected_size {
return Ok(self.buffer());
}
if self.buf.as_mut().len() < expected_size {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
ExpectedSizeTooLargeError(),
));
}
if self.buf.as_mut().len() - self.pos < expected_size {
self.move_buf_to_head()
}
while self.current_bytes() < expected_size {
let n = self.inner.read(&mut self.buf.as_mut()[self.cap..])?;
if n == 0 {
break;
}
self.cap += n;
}
Ok(self.buffer())
}
pub fn get_capacity(&self) -> usize {
self.buf.as_ref().len()
}
pub fn get_ensured_size(&self) -> usize {
self.ensured_size
}
pub fn current_bytes(&self) -> usize {
self.cap - self.pos
}
fn move_buf_to_head(&mut self) {
if self.pos == self.cap {
self.pos = 0;
self.cap = 0;
} else {
self.buf.as_mut().copy_within(self.pos..self.cap, 0);
self.cap -= self.pos;
self.pos = 0;
}
}
}
impl<R: Read, B: AsRef<[u8]> + AsMut<[u8]>> Read for EnsuredBufReader<R, B> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let n = self.fill_buf()?.read(buf)?;
self.consume(n);
Ok(n)
}
}
impl<R: Read, B: AsRef<[u8]> + AsMut<[u8]>> BufRead for EnsuredBufReader<R, B> {
fn fill_buf(&mut self) -> io::Result<&[u8]> {
self.fill_buf_to_expected_size(self.ensured_size)
}
fn consume(&mut self, amt: usize) {
assert!(
amt <= self.current_bytes(),
"the amt must be <= the number of bytes in the buffer returned by fill_buf."
);
self.pos += amt;
}
}
impl<R, B> fmt::Debug for EnsuredBufReader<R, B>
where
R: Read + fmt::Debug,
B: AsRef<[u8]> + AsMut<[u8]>,
{
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("EnsuredBufReader")
.field("reader", &self.inner)
.field(
"buffer",
&format_args!("{}/{}", self.cap - self.pos, self.buf.as_ref().len()),
)
.finish()
}
}
#[derive(Debug, Clone, Copy)]
pub struct ExpectedSizeTooLargeError();
impl fmt::Display for ExpectedSizeTooLargeError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "internal buffer is too small.")
}
}
impl error::Error for ExpectedSizeTooLargeError {}