Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I duplicate a &[u8] slice?

Tags:

rust

borrowing

How do I copy the contents of a &[u8] slice?

I'm trying to write a function that takes a buffer as input and XOR's each byte with the given key and returns the final result.

I don't want it to mangle the input buffer.

pub fn xor_buffer(buffer_in: &[u8], key: char) -> &[u8] {

    let mut buffer_out = buffer_in.clone();

    for byte in &mut buffer_out[..] {
        *byte ^= key as u8;
    }

    buffer_out
}

This code generates the following compile time error:

src/test.rs:29:22: 29:32 error: cannot borrow immutable borrowed content `*buffer_out` as mutable
src/test.rs:29     for byte in &mut buffer_out[..] {
                                               ^~~~~~~~~~

I know I have to be doing something wrong.

Any help would be apprecieated.

like image 205
sambh Avatar asked Feb 27 '16 01:02

sambh


People also ask

How do I easily duplicate a page in Word?

Select Tools > Organize Pages. Select the page you want to duplicate. Hold down the Ctrl key and drag the page with your mouse to a new position to create a duplicate.

How do I duplicate a Word?

Press Ctrl + C on your keyboard. Tip: Another way to copy your highlighted text is to click Home > Copy.

How do you easily duplicate a document?

Right-click the original file and choose Copy (Ctrl+C). Put the mouse cursor on wherever you want a copy to appear, right-click this area and choose Paste (Ctrl+V). Done! Your new Word document is saved and marked as a copy.


1 Answers

First of all, you can't clone a [T] (irrespective of T). Line 3 is not cloning the buffer, it's cloning the pointer to it. If you change the binding to

let mut buffer_out: &[u8] = buffer_in.clone();

you get the same error. If you want an independent copy of a slice, you need to turn it into a Vec or some other owned container type; that can be done by using buffer_in.to_owned() (which generically goes from a borrowed kind of thing to the owned equivalent).

Secondly, you cannot return a borrow to something you created in a function. You can't. No, really. No, not even doing that. Or that. You can only return a borrow (like &[u8]) if the return value is directly borrowed from one of your arguments. That is not true here, so the return type must be Vec<u8> or something else that's owned.

Thirdly, making a copy of the array and then mutating it is probably going to be inefficient. Ideally, you want to do your modifications in as few passes as possible (whilst avoiding even slower things like unnecessary allocations). You can do this using iterators.

Fourth, there's no guarantee key's value actually fits in a u8. You should probably change it to take key: u8 to make it clear to the caller what the valid range of values is.

So, all together:

pub fn xor_buffer(buffer_in: &[u8], key: u8) -> Vec<u8> {
    // Get an iterator of `&u8`s from `buffer_in`.
    buffer_in.iter()
        // Replace each element with the xor'ed value.
        .map(|byte| *byte ^ key)
        // Collect the iterator into an owned collection.
        .collect()
}
like image 125
DK. Avatar answered Sep 30 '22 05:09

DK.