In Rust, I want to read (using BufReader) into a buffer array to fill it. I want to read the exact number of bytes, except in case of EOF, where reading less is fine. I have implemented a helper method myself, as follows, and that works. However I wonder if there is no convenience method that already does exactly that.
pub fn read_fully<R: Read>(read: &mut R, buffer: &mut [u8]) -> Result<usize, Error> {
let mut count: usize = 0;
loop {
let r = read.read(&mut buffer[count..])?;
if r == 0 {
return Ok(count);
}
count += r;
}
}
With each existing method I found there seems to be a problem:
Here's how you can do it shorter and cleaner, but using an experimental API:
#![feature(read_buf, core_io_borrowed_buf)]
use std::io::{BorrowedBuf, Error, ErrorKind, Read};
pub fn read_fully<R: Read>(read: &mut R, buffer: &mut [u8]) -> Result<usize, Error> {
let mut buffer = BorrowedBuf::from(buffer);
match read.read_buf_exact(buffer.unfilled()) {
Ok(()) => {}
Err(err) if err.kind() == ErrorKind::UnexpectedEof => {}
Err(err) => return Err(err),
}
Ok(buffer.len())
}
At this point, you may want to just have a BorrowedCursor
as a parameter:
#![feature(read_buf, core_io_borrowed_buf)]
use std::io::{BorrowedCursor, Error, ErrorKind, Read};
pub fn read_fully<R: Read>(read: &mut R, buffer: BorrowedCursor<'_>) -> Result<(), Error> {
match read.read_buf_exact(buffer) {
Err(err) if err.kind() == ErrorKind::UnexpectedEof => Ok(()),
v => v,
}
}
This allows neat things like using an uninitialized buffer.