Skip to content

Commit

Permalink
std: Add an I/O reader method to fill a buffer
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
alexcrichton committed Mar 22, 2014
1 parent e233a43 commit 5560383
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 7 deletions.
6 changes: 3 additions & 3 deletions src/libstd/io/buffered.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -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) }
}

Expand Down
18 changes: 16 additions & 2 deletions src/libstd/io/mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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]);
}
}
21 changes: 19 additions & 2 deletions src/libstd/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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`.
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 5560383

Please sign in to comment.