Since Rust 1.6, Read::read_exact can be used to do this. If bytes_to_read is the number of bytes you need to read, possibly determined at runtime, and reader is the stream to read from:
let mut buf = vec![0u8; bytes_to_read];
reader.read_exact(&mut buf)?;
The part that wasn’t clear to me from the read_exact documentation was that the target buffer can be a dynamically-allocated Vec.
Thanks to the Rust Gitter community for pointing me to this solution.