How to copy one buffer to another buffer with an offset?

Looks like this.

#![allow(unused)]
use std::io;

fn main() -> io::Result<()> {
    let mut reader: &[u8] = b"hello";
    let mut writer: Vec<u8> = vec![];

    io::copy(&mut reader, &mut &writer[1..6])?;

    assert_eq!(&b"hello"[..], &writer[..]);
    Ok(())
}

(Playground)

You’re very close. You just don’t need the extra slicing operations on the Vec.

io::copy(&mut reader, &mut writer)?;

This version of the line will compile just fine.

Alternatively you can use std::vec::Vec - Rust

I want to copy to the writer with an offset.
It doesn't work.
E.g.: write to the offset 1 of writer buffer.

io::copy(&mut reader, &mut &writer[1..6])?;

Any ideas?

In C, like this:

char a[] = "abcd1234";
char *b = malloc(1024);
for (int i = 0; i< 1024; i+= sizeof(a)) {
       memcpy(b + i, a, sizeof(a));
}

How could I do this in Rust?

If your source of data is Vec (or, generally, something that is convertible to slice, i.e. something that is already in memory), you don't need io::copy, you need [T]::copy_from_slice.

Note, however, that this will not work if the memory for target is not initialized. If you want to initialize one Vec with copies of another one (that's what your C code is seemingly intended to do - it's UB as written, but this is another story), it would be better to create id directly, by collecting, like this:

fn main() {
    let src = b"abcd1234";
    let dest: Vec<u8> = src.iter().copied().cycle().take(1024).collect();
    println!("{:?}", dest);
}

Playground

1 Like

As noted above using uninitialised memory is a no-no.

If you happen to already have an initialised vector something like this:

    let mut writer: Vec<u8> = vec![0; reader.len() + 1usize];

(Note: This allocates all the required memory as malloc() would in C)

Then, as noted above, you can copy other arrays into it with 'clone_from_slice' like so:

    let reader: &[u8] = b"hello";

    writer[1..6].clone_from_slice(&reader);

Personally I find that a lot more to the point and readable than all that .iter().copied().cycle().take verbiage.

2 Likes

Amazing.

Excellent!
Your answer is very like C and is more readable.
.iter().copied().cycle() is confused to newbie indeed.

Thanks.

From the code, the implementation of this ( clone_from_slice) looks very inefficient.
It just loops and copies.

#[stable(feature = "clone_from_slice", since = "1.7.0")]
pub fn clone_from_slice(&mut self, src: &[T])
where
    T: Clone,
{
    assert!(self.len() == src.len(), "destination and source slices have different lengths");
    // NOTE: We need to explicitly slice them to the same length
    // for bounds checking to be elided, and the optimizer will
    // generate memcpy for simple cases (for example T = u8).
    let len = self.len();
    let src = &src[..len];
    for i in 0..len {
        self[i].clone_from(&src[i]);
    }
}

Yes but. According to the comment in that code there will be no bounds checking and at least for byte arrays it will compile down to a memcpy(). So it will be as efficient as C. Which likely compiles to vector instructions or something cunning. Which is about the best one can get.

If you want to use memcpy explicitly use .copy_from_slice() instead.

As a side note, this code is unsound because sizeof(a) yields 9 due to the nul byte.

Implementation notes - not guaranteed by docs - but clone_from_slice uses copy_from_slice automatically when possible at the moment.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.