How to efficiently overwrite a part of a Vec?

Hi all.

Is there a better (faster) way to overwrite a part of a Vec with the content of a smaller slice? This is the solution I came up all by myself, leveraging on a previous question I asked here on this forum:

#[derive(Debug)]
struct Stuff {
    buffer: Vec<f32>
}

impl Stuff {

    fn copy_into(&mut self, position: usize, data: &[f32]) {
        
        for (dest, &src) in self.buffer[position..].iter_mut().zip(data.iter()) {
            *dest = src;
        }

    }

}


fn main() {

    let mut s = Stuff { buffer: vec![0.0_f32; 10] };
    let data = vec![5.5_f32; 3];
    s.copy_into(5, &data);

    println!("{s:?}");

}

The sizes of the source and destination vectors are actually going to be a lot bigger that in this example.

In the end, what I need is just a copy of a chunk of memory. Is the compiler able to do it efficiently? If not, what can I do instead?

Thanks.

There is copy_from_slice (edit: and also clone_from_slice if you want to support !Copy types as well):

    fn copy_into(&mut self, position: usize, data: &[f32]) {
        self.buffer[position..position+data.len()].copy_from_slice(data);
    }

(Playground)

3 Likes

Or to preserve your panic cases:

fn copy_into(&mut self, position: usize, data: &[f32]) {
    let buf = &mut self.buffer[position..];
    let len = data.len().min(buf.len());
    buf[..len].copy_from_slice(&data[..len]);
}

Though you may want to consider different behavior for position > self.buffer.len() too.

2 Likes

It panics if I go beyond the end of the destination Vec, but I can deal with it. Thanks!

If you're overwriting something with the same length, then copy_from_slice is absolutely the way to go.

But if you need to replace a sub-range with something that might be longer or shorter, then Vec::splice is the magic wand that can do all kinds of stuff.

Maybe it should be noted that Vec::splice only works on Vecs (because it needs to be able to grow the Vec, for example), while copy_from_slice only requires a &mut[_].

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.