std: Add an I/O reader method to fill a buffer

I've found a common use case being to fill a slice (not an owned vector)
completely with bytes. It's posible for short reads to happen, and if you're
trying to get an exact number of bytes then this helper will be useful.
This commit is contained in:
Alex Crichton 2014-03-20 18:52:00 -07:00
parent e233a43f5a
commit 5560383071
3 changed files with 38 additions and 7 deletions

View File

@ -87,7 +87,7 @@ impl<R: Reader> BufferedReader<R> {
}
impl<R: Reader> Buffer for BufferedReader<R> {
fn fill<'a>(&'a mut self) -> IoResult<&'a [u8]> {
fn fill_buf<'a>(&'a mut self) -> IoResult<&'a [u8]> {
if self.pos == self.cap {
self.cap = try!(self.inner.read(self.buf));
self.pos = 0;
@ -104,7 +104,7 @@ impl<R: Reader> Buffer for BufferedReader<R> {
impl<R: Reader> Reader for BufferedReader<R> {
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
let nread = {
let available = try!(self.fill());
let available = try!(self.fill_buf());
let nread = cmp::min(available.len(), buf.len());
slice::bytes::copy_memory(buf, available.slice_to(nread));
nread
@ -336,7 +336,7 @@ impl<S: Stream> BufferedStream<S> {
}
impl<S: Stream> Buffer for BufferedStream<S> {
fn fill<'a>(&'a mut self) -> IoResult<&'a [u8]> { self.inner.fill() }
fn fill_buf<'a>(&'a mut self) -> IoResult<&'a [u8]> { self.inner.fill_buf() }
fn consume(&mut self, amt: uint) { self.inner.consume(amt) }
}

View File

@ -190,7 +190,7 @@ impl Seek for MemReader {
}
impl Buffer for MemReader {
fn fill<'a>(&'a mut self) -> IoResult<&'a [u8]> {
fn fill_buf<'a>(&'a mut self) -> IoResult<&'a [u8]> {
if self.pos < self.buf.len() {
Ok(self.buf.slice_from(self.pos))
} else {
@ -322,7 +322,7 @@ impl<'a> Seek for BufReader<'a> {
}
impl<'a> Buffer for BufReader<'a> {
fn fill<'a>(&'a mut self) -> IoResult<&'a [u8]> {
fn fill_buf<'a>(&'a mut self) -> IoResult<&'a [u8]> {
if self.pos < self.buf.len() {
Ok(self.buf.slice_from(self.pos))
} else {
@ -555,4 +555,18 @@ mod test {
let mut r = BufWriter::new(buf);
assert!(r.seek(-1, SeekSet).is_err());
}
#[test]
fn io_fill() {
let mut r = MemReader::new(~[1, 2, 3, 4, 5, 6, 7, 8]);
let mut buf = [0, ..3];
assert_eq!(r.fill(buf), Ok(()));
assert_eq!(buf.as_slice(), &[1, 2, 3]);
assert_eq!(r.fill(buf.mut_slice_to(0)), Ok(()));
assert_eq!(buf.as_slice(), &[1, 2, 3]);
assert_eq!(r.fill(buf), Ok(()));
assert_eq!(buf.as_slice(), &[4, 5, 6]);
assert!(r.fill(buf).is_err());
assert_eq!(buf.as_slice(), &[7, 8, 6]);
}
}

View File

@ -360,6 +360,23 @@ pub trait Reader {
}
}
/// Fills the provided slice with bytes from this reader
///
/// This will continue to call `read` until the slice has been completely
/// filled with bytes.
///
/// # Error
///
/// If an error occurs at any point, that error is returned, and no further
/// bytes are read.
fn fill(&mut self, buf: &mut [u8]) -> IoResult<()> {
let mut read = 0;
while read < buf.len() {
read += try!(self.read(buf.mut_slice_from(read)));
}
Ok(())
}
/// Reads exactly `len` bytes and appends them to a vector.
///
/// May push fewer than the requested number of bytes on error
@ -1045,7 +1062,7 @@ pub trait Buffer: Reader {
/// This function will return an I/O error if the underlying reader was
/// read, but returned an error. Note that it is not an error to return a
/// 0-length buffer.
fn fill<'a>(&'a mut self) -> IoResult<&'a [u8]>;
fn fill_buf<'a>(&'a mut self) -> IoResult<&'a [u8]>;
/// Tells this buffer that `amt` bytes have been consumed from the buffer,
/// so they should no longer be returned in calls to `fill` or `read`.
@ -1116,7 +1133,7 @@ pub trait Buffer: Reader {
let mut used;
loop {
{
let available = match self.fill() {
let available = match self.fill_buf() {
Ok(n) => n,
Err(ref e) if res.len() > 0 && e.kind == EndOfFile => {
used = 0;