Read::read
returns the number of bytes that it actually read, which can be less than the requested buffer. In many cases, it is acceptable to make multiple calls to read
in order to completely fill the buffer.
I have this code, but it seems pretty ungainly:
use std::io::{self, Read};
fn read_complete<R>(mut rdr: R, buf: &mut [u8]) -> io::Result<()>
where R: Read
{
let mut total_read = 0;
loop {
let window = &mut buf[total_read..];
let bytes_read = try!(rdr.read(window));
// Completely filled the buffer
if window.len() == bytes_read {
return Ok(());
}
// Unable to read anything
if bytes_read == 0 {
return Err(io::Error::new(io::ErrorKind::Other, "Unable to read complete buffer"));
}
// Partial read, continue
total_read += bytes_read;
}
}
fn main() {}
Is there a function in the standard library that will abstract this work away for me?
This answer applies to versions of Rust before 1.6.0
Not as far as I know.
Looking at the byteorder
crate's source, there's a read_all
method defined there, too:
fn read_full<R: io::Read + ?Sized>(rdr: &mut R, buf: &mut [u8]) -> Result<()> {
let mut nread = 0usize;
while nread < buf.len() {
match rdr.read(&mut buf[nread..]) {
Ok(0) => return Err(Error::UnexpectedEOF),
Ok(n) => nread += n,
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {},
Err(e) => return Err(From::from(e))
}
}
Ok(())
}
Note that this deals with interrupted IO operations.
There's also a proposed RFC, that was submitted several months ago, went to final comment period, then changed enough that it was taken out of final comment period and is waiting for another go-around.
It turns out that this is unexpectedly complicated. :P
Since the RFC mentioned in the other answer is accepted, implemented, and available in Rust 1.6.0, you can just use the Reader::read_exact()
method:
try!(r.read_exact(&mut buf))
Or, using the ?
operator introduced in Rust 1.13.0:
r.read_exact(&mut buf)?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With