Read::read_exact does not fill buffer

Viewed 661

I have the following code:

use std::io::{Cursor, BufReader, Read};

fn main() {
    let string = String::from("Cello");
    let bytes = string.as_bytes();
    let cursor = Cursor::new(bytes);
    let mut reader = BufReader::new(cursor);
    let mut buf: Vec<u8> = Vec::with_capacity(4);
    assert_eq!(4, buf.capacity());
    reader.read_exact(&mut buf);
    assert_eq!(4, buf.len()); //thread 'main' panicked at 'assertion failed: `(left == right)`
                              //left: `4`, right: `0`'
}

According to std::io::read_exact's documentation, it will "read the exact number of bytes required to fill buf". But in this case, despite having the capacity for 4 bytes, no bytes are read into the vec. What's going on?

1 Answers

The read_exact() method expects a &mut [u8] slice - i.e. it needs to know the buffer length. But you are passing a slice with length of 0 (the capacity of the buffer is distinct from its length):

// capacity = 4
// length = 0
let mut buf: Vec<u8> = Vec::with_capacity(4);

// the &mut [u8] slice has a length of 0
reader.read_exact(&mut buf);

As a result, the method tries to read 0 bytes. In order to fix the issue you have to pass a non-zero length buffer:

// capacity = 4
// length = 4
let mut buf: Vec<u8> = vec![0; 4];

// the &mut [u8] slice has a length of 4
reader.read_exact(&mut buf).expect("read failed");

and last but not least - .read_exact() can fail. If you do not check the returned Result you may end up with a buffer with invalid content.

Related