File::read with a zero-sized buffer closes the stream
abr-egn opened this issue · comments
Abraham Egnor commented
Calling File::read
with a zero-sized buffer results in all subsequent read
s returning 0 even when more data exists.
Minimal repro:
use futures::AsyncReadExt;
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
#[async_std::main]
async fn main() -> Result<()> {
let path = std::path::Path::new("testfile");
async_std::fs::write(path, [0; 8]).await?;
let mut file = async_std::fs::File::open(path).await?;
let mut buf = [0; 2];
assert_eq!(2, file.read(&mut buf).await?);
assert_eq!(0, file.read(&mut []).await?);
assert_eq!(2, file.read(&mut buf).await?); // this fails
Ok(())
}
This is easily encountered when reading a stream into fixed-size chunks, e.g. repeatedly calling
async fn read_exact_or_to_end<T>(buf: &mut [u8], source: &mut T) -> Result<usize>
where
T: AsyncRead + Unpin,
{
let mut total_bytes_read = 0;
loop {
let bytes_read = match dbg!(source.read(&mut buf[total_bytes_read..]).await?) {
0 => break,
n => n,
};
total_bytes_read += bytes_read;
}
Ok(total_bytes_read)
}
This is straightforwardly worked around by checking if the number of bytes read is the size of the buffer, but it's easy to accidentally encounter and a hassle to debug.