How do you copy between arrays of different sizes in Rust?

Manually one can do

for (dst, src) in array1.iter_mut().zip(&array2) {
    *dst = *src
}

for a typical slice. However, there is a likely faster specialization in clone_from_slice:

dst[..4].clone_from_slice(&src)

A slightly older method is to use std::io::Write, which was implemented for &mut [u8].

use std::io::Write;
let _ = dst.write(&src)

This will write up to the end of dst and return how many values were written in a Result. If you use write_all, this will return an Err if not all bytes could be written.


The most flexible way is to use iterators to handle each element successively:

for (place, data) in array1.iter_mut().zip(array2.iter()) {
    *place = *data
}

.mut_iter creates an Iterator that yields &mut u8, that is, mutable references pointing into the slice/array. iter does the same but with shared references. .zip takes two iterators and steps over them in lock-step, yielding the elements from both as a tuple (and stops as soon as either one stops).

If you need/want to do anything 'fancy' with the data before writing to place this is the approach to use.

However, the plain copying functionality is also provided as single methods,

  • .copy_from, used like array1.copy_from(array2).

  • std::slice::bytes::copy_memory, although you will need to trim the two arrays because copy_memory requires they are the same length:

    use std::cmp;
    use std::slice::bytes;
    
    let len = cmp::min(array1.len(), array2.len());
    bytes::copy_memory(array1.mut_slice_to(len), array2.slice_to(len));
    

    (If you know that array1 is always longer than array2 then bytes::copy_memory(array1.mut_slice_to(array2.len()), array2) should also work.)

At the moment, the bytes version optimises the best, down to a memcpy call, but hopefully rustc/LLVM improvements will eventually take them all to that.


You could simply use copy_from_slice() and use Range & Co:

fn main() {
    let mut dest = [0; 8];
    let src = [1, 2, 3, 4];

    dest[..4].copy_from_slice(&src);

    assert_eq!(dest, [1, 2, 3, 4, 0, 0, 0, 0]);
}

Inverse case:

fn main() {
    let src = [1, 2, 3, 4, 5, 6, 7, 8];
    let mut dest = [0; 4];

    dest.copy_from_slice(&src[2..6]);

    assert_eq!(dest, [3, 4 ,5, 6]);
}

Combined case:

fn main() {
    let src = [1, 2, 3, 4, 5, 6, 7, 8];
    let mut dest = [0; 4];

    dest[1..3].copy_from_slice(&src[3..5]);

    assert_eq!(dest, [0, 4, 5, 0]);
}

Tags:

Arrays

Rust