Initialize array from array

I've got an array of 5 integers [x; 5] and I need an array [x; 4] with a copy of the first 4 integers.

Does Rust have a language construct for it, or do I need to do it "the hard way" with multiple assignments/a loop?

I've tried:

let a5 = [0u8; 5];

let a4:[u8; 4] = a5; 
let a4:[u8; 4] = a5.into(); 
let a4:[u8; 4] = a5[0..4]; 
let a4:[u8; 4] = a5[0..4].iter().cloned().collect(); 

The closest I know of is copy_from_slice. You'll still need to initialize them as some default, and then copy the correct values over them.

I think the reason why you have to initialize them to something else is that they shouldn't be in an invalid state in case something panics. I seem to remember that this is also the reason for why you can't move out of an array. It's hard to tell the compiler that it shouldn't drop some of the elements.

1 Like

The difficulty here, and I guess why there doesn't seem to be an easy method for it, is that such a method could only work for an array of T that is Copy. Anything else has to be cloned, else you run into use after free and a whole lot of other nasty monsters just waiting to catch you.

If you are sure that the members of the array are Copy, you can use unsafe code to do the trick with mem::uninitiaized and ptr::copy_nonoverlapping, but then you really are on your own when it comes to memory safety.

I'd consider using slices (&[T] instead of plain [T]) to see if that solves your issues:

fn main() {
    let foo: &[u8] = &[0, 1, 2, 3, 4];
    let bar: &[u8] = &foo[0 .. 4];

    println!("{:?}", foo);
    println!("{:?}", bar);
}

Prints out:

[0, 1, 2, 3, 4]
[0, 1, 2, 3]

I deliberately avoid slices in this case, because they can't be returned from functions, and I don't want to use heap allocation for data that is smaller than a pointer to it.

copy_from_slice() is close enough :slight_smile: