Skip to content

Commit a47d04a

Browse files
committed
Add read_all to std:io::Read to parallel write_all in std::io::Write.
In the event of EOF, read_all returns a result with the new error ShortRead(number of bytes successfully read). Fixes #23174
1 parent f4e0ce6 commit a47d04a

File tree

3 files changed

+52
-0
lines changed

3 files changed

+52
-0
lines changed

Diff for: src/libstd/io/error.rs

+8
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,14 @@ pub enum ErrorKind {
107107
/// written.
108108
#[stable(feature = "rust1", since = "1.0.0")]
109109
WriteZero,
110+
/// An error returned when an operation could not be completed because a
111+
/// call to `read` returned `Ok(0)`.
112+
///
113+
/// This typically means that an operation could only succeed if it read a
114+
/// particular number of bytes but only a smaller number of bytes could be
115+
/// read.
116+
#[stable(feature = "rust1", since = "1.0.0")]
117+
ShortRead(usize),
110118
/// This operation was interrupted.
111119
///
112120
/// Interrupted operations can typically be retried.

Diff for: src/libstd/io/mod.rs

+41
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,32 @@ pub trait Read {
187187
#[stable(feature = "rust1", since = "1.0.0")]
188188
fn read(&mut self, buf: &mut [u8]) -> Result<usize>;
189189

190+
/// Read as many bytes as buf can hold, stopping at EOF or on error
191+
///
192+
/// This method will continuously call `read` while there is more data to
193+
/// read. This method will not return until the entire buffer has been
194+
/// successfully read or an error occurs. The first error generated from
195+
/// this method will be returned.
196+
///
197+
/// # Errors
198+
///
199+
/// This function will return the first error that `read` returns.
200+
#[stable(feature = "rust1", since = "1.0.0")]
201+
fn read_all(&mut self, mut buf: &mut [u8]) -> Result<()> {
202+
let mut total = 0;
203+
while total < buf.len() {
204+
match self.read(&mut buf[total..]) {
205+
Ok(0) => return Err(Error::new(ErrorKind::ShortRead(total),
206+
"failed to read whole buffer",
207+
None)),
208+
Ok(n) => total += n,
209+
Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
210+
Err(e) => return Err(e),
211+
}
212+
}
213+
Ok(())
214+
}
215+
190216
/// Read all bytes until EOF in this source, placing them into `buf`.
191217
///
192218
/// All bytes read from this source will be appended to the specified buffer
@@ -989,6 +1015,21 @@ mod tests {
9891015
assert_eq!(s.next(), None);
9901016
}
9911017

1018+
#[test]
1019+
fn read_all() {
1020+
let mut c = Cursor::new(b"hello");
1021+
let mut v = [0 as u8; 5];
1022+
assert_eq!(c.read_all(&mut v), Ok());
1023+
assert_eq!(v, b"hello");
1024+
1025+
let mut c = Cursor::new(b"short");
1026+
let mut v = [115 as u8; 6];
1027+
assert_eq!(c.read_all(&mut v), Error::new(ErrorKind::ShortRead(5),
1028+
"failed to read whole buffer",
1029+
None));
1030+
assert_eq!(v, b"shorts");
1031+
}
1032+
9921033
#[test]
9931034
fn read_to_end() {
9941035
let mut c = Cursor::new(&b""[..]);

Diff for: src/libstd/io/stdio.rs

+3
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,9 @@ impl Read for Stdin {
164164
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
165165
self.lock().read(buf)
166166
}
167+
fn read_all(&mut self, buf: &mut [u8]) -> io::Result<()> {
168+
self.lock().read_all(buf)
169+
}
167170
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
168171
self.lock().read_to_end(buf)
169172
}

0 commit comments

Comments
 (0)