Bytemuck Vec<T> -> Vec<u8>

Context: some wgpu stuff needing a Vec<u8> for vertex buffers.

The standard approach is:

Vec<T> -> as_slice() -> &[T] -> bytemuck::cast_slice -> &[u] -> .to_vec -> Vec<u8>

I am wondering if there is a more efficient way to just do Vec<T> -> Vec<u8>

Pre-emptive: why not use Vec :: from_raw_parts / std::transmute / ... ?

T may or may not be 'packed', and I think reading un-init bytes is UB in Rust.

Does try_cast_vec in bytemuck::allocation - Rust work for you?

2 Likes

Type signature looks right :slight_smile:

Note that

  • The start and end content type of the Vec must have the exact same alignment.

so this will fail if the starting type has an alignment not equal to 1, which it probably does unless it's repr(packed).

You are probably best off not converting the Vec and converting to &[u8], as you note is the “standard approach”. This is not less efficient (if you mean in terms of run-time cost).

If you need code to be able to store (not just borrow) a converted type-erased vector from any element type, then you'll need a custom smart pointer type that holds, in addition to the usual (pointer, length, capacity) info from Vec, the Layout of the original T to deallocate it. Or for simplicity and no unsafe, you could write a trait (call it AsBytes) implemented for Vec<T> where T: NoUninit, and use a Box<dyn AsBytes> to erase the T type.

9 Likes