I'd like to copy one Vec
into another, in chunks of [u8; 4]
assigning the first 3 element of each chunk only(leaving the 4th alone). This seems like a practical way to go about it:
let input_pix: Vec<u8> = ...;
let mut output_pix: Vec<u8> = vec![255; input_pix.len()];
for (input_chunk, output_chunk) in input_pix.chunks(4).zip(output_pix.chunks_exact_mut(4)) {
let i: u8 = foo(...);
output_chunk[0..2].clone_from_slice([i,3]);
}
...BUT the compiler doesn't like it. In fact slicing output_chunk
at all throws an error. Most simply:
...
for (input_chunk, output_chunk) in input_pix.chunks(4).zip(output_pix.chunks_exact_mut(4)) {
let s = format!("{:?}", output_chunk[0..2]);
}
Results in...
|
40 | let s = format!("{:?}", output_chunk[0..2]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
From the docs:
The chunks are slices and do not overlap. If chunk_size does not divide the length of the slice, then the last up to chunk_size-1 elements will be omitted and can be retrieved from the remainder function of the iterator.
Due to each chunk having exactly chunk_size elements, the compiler can often optimize the resulting code better than in the case of chunks.
So... it seems it is saying size of the elements of a ChunksExactMut
(returned from chunks_exact_mut
) is exact and in this case 4, so what gives? Knowing the size at compile time feels like it is kind of the point of ChunksExactMut
.
Am I going about this the wrong way? Is there some more idiomatic way to copy into a slice of ChunksExactMut
. I can simply copy element wise with a loop but that seems very smelly. Or perhaps that IS the way to do this and I should let the compiler do the work?
TL;DR: Just change it to
let s = format!("{:?}", &output_chunk[0..2]);
// ^^^ the important bit
When indexing a slice (of type &[T]
) by a range, the return type is [T]
. Being sized is a property of the type rather than a property of the values. So even if we're indexing with a known width (i.e. 0..2
), we still get an unsized type as output.
One downside of being unsized is that values of that type can't be passed to functions. Thus, in order to format elements of such a type as a string, we have to pass a pointer. The easiest way to do this is to simply borrow the slice.
Doesn't work:
fn foo(slice: &[u8]) -> String {
format!("{:?}", slice[0..2])
}
Does work:
fn foo(slice: &[u8]) -> String {
format!("{:?}", &slice[0..2])
}