I know Rust doesn't support variable-length arrays, but that leaves me wondering what to replace them with, given that:
- I don't want to allocate and deallocate a tiny Vec in a loop
- The borrow checker doesn't let me move the code outside the loop
- There are many limitations on fixed-size arrays, so I can't figure out how to use them
The C code I'm converting processes an image by calling a callback on each line, passing a small array of pointers:
float *tmp[img->channels]; // Small, up to 4 elements
for(int y = 0; y < height; y++) {
for(int ch = 0; ch < img->channels; ch++) {
tmp[ch] = &img->channel[ch]->pixels[width * y];
}
callback(tmp, img->channels);
}
My Rust attempt (example in playpen):
for y in 0..height {
let tmp = &img.channel.iter().map(|channel| {
&mut channel.pixels.as_ref().unwrap()[width * y .. width * (y+1)]
}).collect();
callback(tmp);
}
But it's rejected:
a collection of type
[&mut [f32]]
cannot be built from an iterator over elements of type&mut [f32]
Sadly, that sounds exactly like what I was trying to do!
I've tried using a fixed-size array, but Rust doesn't support generics on them, so I can't populate it from an iterator, and I can't populate them in a C-like loop, because references taken in the loop don't outlive it.
the trait
core::iter::FromIterator<&mut [f32]>
is not implemented for the type[&mut [f32]; 4]
Another approach with taking slice of memory from a fixed-size array, also fails:
let mut row_tmp: [&mut [f32]; 4] = unsafe{mem::zeroed()};
for y in 0..height {
row_tmp[0..channels].iter_mut().zip(img.chan.iter_mut()).map(|(t, chan)| {
*t = &mut chan.img.as_ref().unwrap()[(width * y) as usize .. (width * (y+1)) as usize]
});
cb(&row_tmp[0..channels], y, width, image_data);
}
error: cannot borrow
img.chan
as mutable more than once at a time