2

I have a Vec<T> where T: Copy + Clone and I would like to efficiently copy a slice of the vector to another slice of the same vector, where slices have the same length and do not overlap. In C++ I would use std::memcpy for the same purpose.

I would like to:

What I have tried:

#[test]
fn copy_within_a_vector() {
    let mut data = vec![1, 2, 0, 0];
    let src = &data[0..2];
    let mut dst = &mut data[3..4];
    dst.copy_from_slice(src);
}

This code does not even get compiled because the borrow checker complains about borrowing data both mutable and immutable at the same time (and it is right).

Is it possible to rewrite the code to compile on stable Rust?

Related questions:

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Viktor Chvátal
  • 463
  • 9
  • 19
  • I think that the referred question is about cloning parts of the slice into new owned vectors, I wish not to allocate any new memory, just copy contents of a vector in place as it is – Viktor Chvátal Jul 13 '17 at 13:29
  • @ViktorChvátal: The solution is the same: create two, non-overlapping slices. You can read from a mutable slice just fine. – DK. Jul 13 '17 at 13:48
  • Check out the [*second* answer](https://stackoverflow.com/a/30278246/155423) (yes, sometimes reading past the first answer or first search result is the right thing to do). – Shepmaster Jul 13 '17 at 13:49
  • Thank you, I missed that, using split_at_mut was exactly what I was looking for – Viktor Chvátal Jul 13 '17 at 13:55

1 Answers1

2

As said in comment, use split_at_mut. Then you can use clone_from_slice.

Example of implementation:

// split the slice in two mutable slices
// then copy one subslice to other
fn copy_within_a_slice<T: Clone>(v: &mut [T], from: usize, to: usize, len: usize) {
    if from > to {
        let (dst, src) = v.split_at_mut(from);
        dst[to..to + len].clone_from_slice(&src[..len]);
    } else {
        let (src, dst) = v.split_at_mut(to);
        dst[..len].clone_from_slice(&src[from..from + len]);
    }
}

fn main() {
    let mut v = (0..10).collect::<Vec<_>>();
    println!("{:?}", v);
    copy_within_a_slice(&mut v, 6, 1, 3);
    println!("{:?}", v);
}

Ouput:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 6, 7, 8, 4, 5, 6, 7, 8, 9]

Do not forget to pay attention to the values because the code will panic if you are out of bounds.

Boiethios
  • 38,438
  • 19
  • 134
  • 183
  • If you agree with the duplicate, don't answer the question. That just clutters up SO. – Shepmaster Jul 13 '17 at 13:50
  • 1
    @Shepmaster I considered that the question is distant enough to possible duplicate. That's not an "exact duplicate". – Boiethios Jul 13 '17 at 13:52
  • @Boiethios It is enough for an answer in a duplicate to cover the solution to this question. – E_net4 Jul 13 '17 at 13:58
  • Thank you, @Boiethios, your answer shows a nice implementation of what I was willing to do, however, answers in duplicates already contain solutions to my question. Should I also accept this answer or leave it as it is? – Viktor Chvátal Jul 13 '17 at 14:11
  • 1
    @ViktorChvátal I do not know, I am looking for some source in meta. – Boiethios Jul 13 '17 at 14:15
  • 1
    @Boiethios Ok, on [meta](https://meta.stackexchange.com/questions/10841/how-should-duplicate-questions-be-handled/) I have found an advice "If you don't think the answers on the duplicate question are good enough, write an answer there." I consider your answer better suiting my needs, so I'm accepting it – Viktor Chvátal Jul 13 '17 at 14:35
  • 1
    @ViktorChvátal Got same answer there: https://meta.stackoverflow.com/a/352195/4498831 – Boiethios Jul 13 '17 at 14:37
  • @ViktorChvátal "If you don't think the answers on the duplicate question are good enough, write an answer there." — "there" means *on the duplicate **target***, not on the question that is being marked as the duplicate. – Shepmaster Jul 13 '17 at 14:50
  • @Shepmaster Thank you for pointing that out, I'm going to know next time – Viktor Chvátal Jul 13 '17 at 14:57