Augusto Hack
Augusto Hack

Reputation: 2170

Take a mutable slice from a vector with a different length?

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

Answers (2)

Augusto Hack
Augusto Hack

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(&self) -> &[T]

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

Veedrac
Veedrac

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

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

Related Questions