Vec layout / transmute

Hi,

I have some struct, let's call it T, which only holds primitive Copy types.
I have a Vec of groups of those, typed Vec<[T;4]>.
I need to convert this into a Vec<T>.

If I'm understanding this correctly, the layout of the data should be exactly the same in
both vecs, except that len/capacity differs by a factor of 4.

At first I thought of:

unsafe {
   let mut vec2 = std::mem::transmute(vec1);
   vec2.set_len(vec2.len()*4);
}

However, capacity is an issue. And I'm not even completely sure that's how transmute is supposed to work.

I could of course loop through everything and rebuild a new vector from scratch, but that sounds very wasteful since the data is already there and laid out in memory.

Would there be a better way to go around this ?

Thanks,
Jonathan

transmute is always wrong on repr(Rust) types like Vec.

You can do this with Vec::from_raw_parts, however. (Assuming that libs-api agrees that Docs: make Vec::from_raw_parts documentation less strict by janpaul123 · Pull Request #95016 · rust-lang/rust · GitHub is correct.)

I also checked v.into_iter().flatten().collect(), but it looks like that doesn't have a magic allocation re-use the way that v.into_iter().collect() does.

2 Likes

Thanks for your response.
After looking at the doc for Vec::from_raw_parts and reading your linked PR, it seems
like it would be simpler and safer to use std::slice::from_raw_parts(), since at
the end of the day I only need a reference to the data, so I'll try with that.

Thanks again!
Jonathan

1 Like

Have you considered using the bytemuck crate?

1 Like

I have never heard of it before.
However, I was able to fix my issue using Vec::from_raw_parts.

Thanks!
Jonathan

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.