I'm trying to extract a list of 3D vectors out of a a float buffer. Ideally, I'd like to write something like this:
use nalgebra_glm as glm;
// buf: Vec<f32>
let verts = buf.chunks_exact(3)
.map(|&[x, y, z]| glm::vec3(x, y, z))
.collect::<Vec<_>>()
I understand that the compiler cannot ensure the size of the slice returned by the ChunksExact iterator:
.map(|&[x, y, z]| glm::vec3(x, y, z))
^^^^^^^^^^ patterns `&[]`, `&[_]`, `&[_, _]` and 1 more not covered
I can get away by doing so:
let verts = buf.chunks_exact(3)
.map(|chunk| {
let x = unsafe { *chunk.get_unchecked(0) };
let y = unsafe { *chunk.get_unchecked(1) };
let z = unsafe { *chunk.get_unchecked(2) };
glm::vec3(x, y, z)
})
.collect::<Vec<_>>()
but it feels a bit overwhelming to write and will be even worse when I'll do the same for a 4x4 matrix.
Is there a (unsafe) way to "cast" a &[T] to a &[T; 3] ?
No please don't use any unsafe. It seems totally safe Rust can produce even less opcodes than your unsafe version, though the output asm is not trivial so I can't sure anything before benchmark.
Yes but using unsafe for something like this is not warranted. If you still need the manual conversion, you could perform it even more simply, as [T: Copy; N] implements TryFrom<&[T]>:
let verts = buf.chunks_exact(3)
.map(|slice| {
let [x, y, z] = <[_; 3]>::try_from(slice).expect("3 items");
glm::vec3(x, y, z)
})
.collect::<Vec<_>>();
I thought the panic possibility would add much more code, I'm gonna stick to the glm::make_vec3 for this particular case.
I'm gonna go for try_from / try_into whenever I need it.