Skip to content

Commit

Permalink
Add read_all to std:io::Read to parallel write_all in std::io::Write.
Browse files Browse the repository at this point in the history
In the event of EOF, read_all returns a result with the new error
ShortRead(number of bytes successfully read).

Fixes #23174
  • Loading branch information
novalis committed Mar 20, 2015
1 parent f4e0ce6 commit a47d04a
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 0 deletions.
8 changes: 8 additions & 0 deletions src/libstd/io/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,14 @@ pub enum ErrorKind {
/// written.
#[stable(feature = "rust1", since = "1.0.0")]
WriteZero,
/// An error returned when an operation could not be completed because a
/// call to `read` returned `Ok(0)`.
///
/// This typically means that an operation could only succeed if it read a
/// particular number of bytes but only a smaller number of bytes could be
/// read.
#[stable(feature = "rust1", since = "1.0.0")]
ShortRead(usize),
/// This operation was interrupted.
///
/// Interrupted operations can typically be retried.
Expand Down
41 changes: 41 additions & 0 deletions src/libstd/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,32 @@ pub trait Read {
#[stable(feature = "rust1", since = "1.0.0")]
fn read(&mut self, buf: &mut [u8]) -> Result<usize>;

/// Read as many bytes as buf can hold, stopping at EOF or on error
///
/// This method will continuously call `read` while there is more data to
/// read. This method will not return until the entire buffer has been
/// successfully read or an error occurs. The first error generated from
/// this method will be returned.
///
/// # Errors
///
/// This function will return the first error that `read` returns.
#[stable(feature = "rust1", since = "1.0.0")]
fn read_all(&mut self, mut buf: &mut [u8]) -> Result<()> {
let mut total = 0;
while total < buf.len() {
match self.read(&mut buf[total..]) {
Ok(0) => return Err(Error::new(ErrorKind::ShortRead(total),
"failed to read whole buffer",
None)),
Ok(n) => total += n,
Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
}
Ok(())
}

/// Read all bytes until EOF in this source, placing them into `buf`.
///
/// All bytes read from this source will be appended to the specified buffer
Expand Down Expand Up @@ -989,6 +1015,21 @@ mod tests {
assert_eq!(s.next(), None);
}

#[test]
fn read_all() {
let mut c = Cursor::new(b"hello");
let mut v = [0 as u8; 5];
assert_eq!(c.read_all(&mut v), Ok());
assert_eq!(v, b"hello");

let mut c = Cursor::new(b"short");
let mut v = [115 as u8; 6];
assert_eq!(c.read_all(&mut v), Error::new(ErrorKind::ShortRead(5),
"failed to read whole buffer",
None));
assert_eq!(v, b"shorts");
}

#[test]
fn read_to_end() {
let mut c = Cursor::new(&b""[..]);
Expand Down
3 changes: 3 additions & 0 deletions src/libstd/io/stdio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,9 @@ impl Read for Stdin {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.lock().read(buf)
}
fn read_all(&mut self, buf: &mut [u8]) -> io::Result<()> {
self.lock().read_all(buf)
}
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
self.lock().read_to_end(buf)
}
Expand Down

0 comments on commit a47d04a

Please sign in to comment.