I have a struct with a BufStream<T>
where T: Read+Write
.
The BufStream
can be a TcpStream
and I'd like to read n bytes from it.
Not a fixed amount of bytes in a predefined buffer, but I have a string/stream which indicates the number of bytes to read next.
Is there a nice way to do that?
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.
It sounds like you want Read::take
and Read::read_to_end
.
This will allow you to read data into a &mut Vec<u8>
, which is useful when you want to reuse an existing buffer or don't have an appropriately sized slice already. This allows you to avoid initializing the data with dummy values before overwriting them with the newly-read information:
use std::{
io::{prelude::*, BufReader},
str,
};
fn read_n<R>(reader: R, bytes_to_read: u64) -> Vec<u8>
where
R: Read,
{
let mut buf = vec![];
let mut chunk = reader.take(bytes_to_read);
// Do appropriate error handling for your situation
// Maybe it's OK if you didn't read enough bytes?
let n = chunk.read_to_end(&mut buf).expect("Didn't read enough");
assert_eq!(bytes_to_read as usize, n);
buf
}
fn main() {
let input_data = b"hello world";
let mut reader = BufReader::new(&input_data[..]);
let first = read_n(&mut reader, 5);
let _ = read_n(&mut reader, 1);
let second = read_n(&mut reader, 5);
println!(
"{:?}, {:?}",
str::from_utf8(&first),
str::from_utf8(&second)
);
}
If you are worried that Read::take
consumes the reader by reference, note that take
comes from Read
and Read
is implemented for any mutable reference to a type that implements Read
. You can also use Read::by_ref
to create this mutable reference.
See also:
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