use std::cmp;
use std::io;
use std::ptr;
const DEFAULT_BUFFER_CAPACITY: usize = 8 * (1 << 10);
#[derive(Debug)]
pub struct Buffer {
buf: Vec<u8>,
min: usize,
end: usize,
}
impl Buffer {
pub fn new(min_buffer_len: usize) -> Buffer {
let min = cmp::max(1, min_buffer_len);
let capacity = cmp::max(min * 8, DEFAULT_BUFFER_CAPACITY);
Buffer { buf: vec![0; capacity], min, end: 0 }
}
#[inline]
pub fn buffer(&self) -> &[u8] {
&self.buf[..self.end]
}
#[inline]
pub fn min_buffer_len(&self) -> usize {
self.min
}
#[inline]
pub fn len(&self) -> usize {
self.end
}
fn free_buffer(&mut self) -> &mut [u8] {
&mut self.buf[self.end..]
}
pub fn fill<R: io::Read>(&mut self, mut rdr: R) -> io::Result<bool> {
let mut readany = false;
loop {
let readlen = rdr.read(self.free_buffer())?;
if readlen == 0 {
return Ok(readany);
}
readany = true;
self.end += readlen;
if self.len() >= self.min {
return Ok(true);
}
}
}
pub fn roll(&mut self) {
let roll_start = self
.end
.checked_sub(self.min)
.expect("buffer capacity should be bigger than minimum amount");
let roll_len = self.min;
assert!(roll_start + roll_len <= self.end);
unsafe {
ptr::copy(
self.buf[roll_start..].as_ptr(),
self.buf.as_mut_ptr(),
roll_len,
);
}
self.end = roll_len;
}
}