//! An improved `BufRead` interface.
use std;
use std::str;
use std::io;
use std::io::{Error,ErrorKind};
use std::cmp;
use std::fmt;
// The default buffer size.
const DEFAULT_BUF_SIZE: usize = 8 * 1024;
/// A `BufferedReader` is a type of `Read`er that has an internal
/// buffer, and allows working directly from that buffer. Like a
/// `BufRead`er, the internal buffer amortizes system calls. And,
/// like a `BufRead`, a `BufferedReader` exposes the internal buffer
/// so that a user can work with the data in place rather than having
/// to first copy it to a local buffer. However, unlike `BufRead`,
/// `BufferedReader` allows the caller to ensure that the internal
/// buffer has a certain amount of data.
pub trait BufferedReader : io::Read + fmt::Debug {
/// Return the data in the internal buffer. Normally, the
/// returned buffer will contain *at least* `amount` bytes worth
/// of data. Less data may be returned if the end of the file is
/// reached or an error occurs. In these cases, any remaining
/// data is returned. Note: the error is not discarded, but will
/// be returned when data is called and the internal buffer is
/// empty.
///
/// This function does not advance the cursor. Thus, multiple
/// calls will return the same data. To advance the cursor, use
/// `consume`.
fn data(&mut self, amount: usize) -> Result<&[u8], io::Error>;
/// Like `data`, but returns an error if there is not at least
/// `amount` bytes available.
fn data_hard(&mut self, amount: usize) -> Result<&[u8], io::Error> {
let result = self.data(amount);
if let Ok(buffer) = result {
if buffer.len() < amount {
return Err(Error::new(ErrorKind::UnexpectedEof, "unepxected EOF"));
}
}
return result;
}
/// Return all of the data until EOF. Like `data`, this does not
/// actually consume the data that is read.
///
/// In general, you shouldn't use this function as it can cause an
/// enormous amount of buffering. But, if you know that the
/// amount of data is limited, this is acceptable.
fn data_eof(&mut self) -> Result<&[u8], io::Error> {
// Don't just read std::usize::MAX bytes at once. The
// implementation might try to actually allocate a buffer that
// large! Instead, try with increasingly larger buffers until
// the read is (strictly) shorter than the specified size.
let mut s = DEFAULT_BUF_SIZE;
while s < std::usize::MAX {
match self.data(s) {
Ok(ref buffer) =>
if buffer.len() < s {
// We really want to do
//
// return Ok(buffer);
//
// But, the borrower checker won't let us:
//
// error[E0499]: cannot borrow `*self` as
// mutable more than once at a time.
//
// Instead, we break out of the loop, and then
// call self.data(s) again. This extra call
// shouldn't have any significant cost,
// because the buffer should already be
// prepared.
break;
} else {
s *= 2;
},
Err(err) =>
return Err(err),
}
}
return self.data(s);
}
/// Mark the first `amount` bytes of the internal buffer as
/// consumed. It is an error to call this function without having
/// first successfully called `data` (or a related function) to
/// buffer `amount` bytes.
///
/// This function returns the data that has been consumed.
fn consume(&mut self, amount: usize) -> &[u8];
/// This is a convenient function that effectively combines data()
/// and consume().
fn data_consume(&mut self, amount: usize)
-> Result<&[u8], std::io::Error>;
// This is a convenient function that effectively combines
// data_hard() and consume().
fn data_consume_hard(&mut self, amount: usize) -> Result<&[u8], io::Error>;
//