HiveBrain v1.2.0
Get Started
← Back to all entries
snippetrustMajor

How can I swap items in a vector, slice, or array in Rust?

Submitted by: @import:stackoverflow-api··
0
Viewed 0 times
arrayhowsliceswapvectorrustcanitems

Problem

My code looks like this:

fn swap(mut collection: Vec, a: usize, b: usize) {
    let temp = collection[a];
    collection[a] = collection[b];
    collection[b] = temp;
}


Rust is pretty sure I'm not allowed to "move out of dereference" or "move out of indexed content", whatever that is. How do I convince Rust that this is possible?

Solution

There is a swap method defined for &mut [T]. Since a Vec can be mutably dereferenced as a &mut [T], this method can be called directly:

fn main() {
    let mut numbers = vec![1, 2, 3];
    println!("before = {:?}", numbers);
    numbers.swap(0, 2);
    println!("after = {:?}", numbers);
}


To implement this yourself, you have to write some unsafe code. Vec::swap is implemented like this:

fn swap(&mut self, a: usize, b: usize) {
    unsafe {
        // Can't take two mutable loans from one vector, so instead just cast
        // them to their raw pointers to do the swap
        let pa: *mut T = &mut self[a];
        let pb: *mut T = &mut self[b];
        ptr::swap(pa, pb);
    }
}


It takes two raw pointers from the vector and uses ptr::swap to swap them safely.

There is also a mem::swap(&mut T, &mut T) when you need to swap two distinct variables. That cannot be used here because Rust won't allow taking two mutable borrows from the same vector.

Code Snippets

fn main() {
    let mut numbers = vec![1, 2, 3];
    println!("before = {:?}", numbers);
    numbers.swap(0, 2);
    println!("after = {:?}", numbers);
}
fn swap(&mut self, a: usize, b: usize) {
    unsafe {
        // Can't take two mutable loans from one vector, so instead just cast
        // them to their raw pointers to do the swap
        let pa: *mut T = &mut self[a];
        let pb: *mut T = &mut self[b];
        ptr::swap(pa, pb);
    }
}

Context

Stack Overflow Q#25531963, score: 88

Revisions (0)

No revisions yet.