Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to idiomatically copy a slice?

Tags:

slice

rust

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?

like image 377
Byron Avatar asked Jan 29 '15 16:01

Byron


People also ask

How do you duplicate a slice?

To duplicate a slice in Go, getting a deep copy of its contents, you need to either use the built-in copy() function, or create a new empty slice and add all the elements of the first slice to it using the append() function.

How do I declare a slice in Golang?

A slice can be declare using new keyword followed by capacity in square brackets then type of elements the slice will hold.

What is a slice in Rust?

A slice is a pointer to a block of memory. Slices can be used to access portions of data stored in contiguous memory blocks. It can be used with data structures like arrays, vectors and strings. Slices use index numbers to access portions of data. The size of a slice is determined at runtime.


2 Answers

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.

like image 143
bluss Avatar answered Oct 13 '22 16:10

bluss


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.

like image 33
Byron Avatar answered Oct 13 '22 14:10

Byron