Reputation: 2170
I'm trying to use a vector as a buffer like this, I'm wondering if there is a way to take a slice from the vector without growing it, so that code like this work:
fn example(r: Read) {
let buffer: Vec<u8> = Vec::with_capacity(1024);
let slice: &mut[u8] = &mut buffer;
r.read(slice); // doesnt work since the slice has length zero
}
Upvotes: 5
Views: 2104
Reputation: 2170
I want to add three details to @Veedrac answer.
1 - This is the relevant code that creates the slices from Vec<T>
, and in both cases the slice goes from the start of the vector up to self.len
:
fn deref_mut(&mut self) -> &mut [T]
2 - There is an optimization in the TcpStream to avoid zeroing the memory, much like @Veedrac's alternative, but it is only used for read_to_end
and not in read
. And the BufReader
that does zeroing starts with small allocations for performance reasons
3 - The slice has no information about the vector size, so the vector the length must be updated anyways, otherwise the buffer will be larger than the data and the zeros will be used.
Upvotes: 0
Reputation: 60137
If one was to just take a slice of the capacity, you would have a slice of uninitialized data. This is unsafe.
You can do this with Vec
's set_len
. However
This is unsafe. Reading the data is memory safe, but a vector of another type, or misuse of set_len
, may not be. Overflow checking and proper cleanup is important.
This could well be a significant security flaw.
If you are using non-primitive types, you need to consider panic safety.
The basic way of doing this is
unsafe {
buffer.set_len(buffer.capacity());
let new_len = try!(r.read(slice));
buffer.set_len(cmp::min(buffer.len(), new_len));
}
The cmp::min
is needed if you don't totally trust read
's implementation, since incorrect output can result in too-large set length.
Upvotes: 6