How to idiomatically copy a slice?

49,816

Solution 1

Yes, use the method clone_from_slice(), it is generic over any element type that implements Clone.

fn main() {
    let mut x = vec![0; 8];
    let y = [1, 2, 3];
    x[..3].clone_from_slice(&y);
    println!("{:?}", x);
    // Output:
    // [1, 2, 3, 0, 0, 0, 0, 0]
}

The destination x is either a &mut [T] slice, or anything that derefs to that, like a mutable Vec<T> vector. You need to slice the destination and source so that their lengths match.


As of Rust 1.9, you can also use copy_from_slice(). This works the same way but uses the Copy trait instead of Clone, and is a direct wrapper of memcpy. The compiler can optimize clone_from_slice to be equivalent to copy_from_slice when applicable, but it can still be useful.

Solution 2

This code works, even though I am not sure if it the best way to do it.

fn copy_slice(dst: &mut [u8], src: &[u8]) -> usize {
    let mut c = 0;
    for (d, s) in dst.iter_mut().zip(src.iter()) {
        *d = *s;
        c += 1;
    }
    c 
}

Apparently not specifying access permissions explicitly did the trick. However, I am still confused about this and my mental model doesn't yet cover what's truly going on there. My solutions are mostly trial and error when it comes to these things, and I'd rather like to truly understand instead.

Share:
49,816
Byron
Author by

Byron

A self-taught programmer who likes optimizing things.

Updated on June 27, 2020

Comments

  • Byron
    Byron almost 4 years

    In Go, copying slices is standard-fare and looks like this:

    # It will figure out the details to match slice sizes
    dst = copy(dst[n:], src[:m])
    

    In Rust, I couldn't find a similar method as replacement. Something I came up with looks like this:

    fn copy_slice(dst: &mut [u8], src: &[u8]) -> usize {
        let mut c = 0;
        for (&mut d, &s) in dst.iter_mut().zip(src.iter()) {
            d = s;
            c += 1;
        }
        c
    }
    

    Unfortunately, I get this compile-error that I am unable to solve:

    error[E0384]: re-assignment of immutable variable `d`
     --> src/main.rs:4:9
      |
    3 |     for (&mut d, &s) in dst.iter_mut().zip(src.iter()) {
      |               - first assignment to `d`
    4 |         d = s;
      |         ^^^^^ re-assignment of immutable variable
    

    How can I set d? Is there a better way to copy a slice?