Simplify this code:

Is there a better way to write:

            out[idx + 0] = lhs_bytes[0];
            out[idx + 1] = lhs_bytes[1];
            out[idx + 2] = lhs_bytes[2];
            out[idx + 3] = lhs_bytes[3];

here out: &mut [u8] and lhs_bytes: [u8; 4]




Does this incur a for loop and branching? I'm slightly surprised there isn't a simple way to directly assign a [u8; 4].

optimizing compilers are pretty impressive these days. you should check the assembly output to get a useful answer to that question.


Both versions of the code require branching to check whether the indices are in range. In many contexts this could be optimized, but that would require that you provide a larger context of how this code is used.

@geeklint's version is somewhat better optimized by the compiler than the original code, because the original generates 4 branches in between moving bytes while @geeklint's code generates 2 branches and then moves all 4 bytes in one go:

The compiler could be smarter about the original code, but isn't. There is a ticket for this:

1 Like

You could write this:

pub fn code3(out: &mut [u8], vals: [u8; 4], idx: usize) {
    *<&mut [u8; 4]>::try_from(&mut out[idx..idx+4]).unwrap() = vals;

It compiles down to exactly the same as the copy_from_slice version though.


Exactly what the "get arrays from a slice" methods are going to be is still up in the air. If you're willing to try out nightly things, you could give feedback in the tracking issues for things like and and
Add slice::{split_,}{first,last}_chunk{,_mut} by clarfonthey · Pull Request #95198 · rust-lang/rust · GitHub.

YMMV, but you can also write that as out[idx..][..4], which I tend to prefer since it makes the "it'll end up 4 elements long" blatantly obvious, and means I don't have to think about overflow.


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.