use std::cmp;
use std::fmt;
use std::io::{self, BufRead};
use std::slice;
static DEFAULT_BUF_SIZE: usize = 1024 * 64;
pub struct BufReader<R> {
inner: R,
buf: io::Cursor<Vec<u8>>,
}
impl<R: io::Read> BufReader<R> {
pub fn new(inner: R) -> BufReader<R> {
BufReader::with_capacity(DEFAULT_BUF_SIZE, inner)
}
pub fn with_capacity(cap: usize, inner: R) -> BufReader<R> {
BufReader {
inner: inner,
buf: io::Cursor::new(Vec::with_capacity(cap)),
}
}
#[allow(dead_code)] pub fn get_ref(&self) -> &R { &self.inner }
pub fn get_mut(&mut self) -> &mut R { &mut self.inner }
#[allow(dead_code)] pub fn into_inner(self) -> R { self.inner }
pub fn clear(&mut self) {
self.buf.set_position(0);
self.buf.get_mut().truncate(0);
}
}
impl<R: io::Read> io::Read for BufReader<R> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
if self.buf.get_ref().len() == self.buf.position() as usize &&
buf.len() >= self.buf.get_ref().capacity() {
return self.inner.read(buf);
}
try!(self.fill_buf());
self.buf.read(buf)
}
}
impl<R: io::Read> io::BufRead for BufReader<R> {
fn fill_buf(&mut self) -> io::Result<&[u8]> {
if self.buf.position() as usize == self.buf.get_ref().len() {
self.buf.set_position(0);
let v = self.buf.get_mut();
v.truncate(0);
let inner = &mut self.inner;
try!(with_end_to_cap(v, |b| inner.read(b)));
}
self.buf.fill_buf()
}
fn consume(&mut self, amt: usize) {
self.buf.consume(amt)
}
}
impl<R> fmt::Debug for BufReader<R> where R: fmt::Debug {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "BufReader {{ reader: {:?}, buffer: {}/{} }}",
self.inner, self.buf.position(), self.buf.get_ref().len())
}
}
fn with_end_to_cap<F>(v: &mut Vec<u8>, f: F) -> io::Result<usize>
where F: FnOnce(&mut [u8]) -> io::Result<usize> {
unsafe {
let n = try!(f({
let base = v.as_mut_ptr().offset(v.len() as isize);
slice::from_raw_parts_mut(base, v.capacity() - v.len())
}));
let new_len = cmp::min(v.capacity(), v.len() + n);
v.set_len(new_len);
return Ok(n);
}
}