Transmuting u8 buffer to struct in Rust
You can use methods on raw pointers and functions in std::ptr
to directly read/write objects in place.
std::ptr::read
std::ptr::read_unaligned
std::ptr::write
std::ptr::write_unaligned
In your case:
fn main() {
let v: Vec<u8> = vec![1, 2, 3];
let s: MyStruct = unsafe { std::ptr::read(v.as_ptr() as *const _) };
println!("here is the struct: {:?}", s);
}
I would encourage you to wrap this in a reusable method and perform a length check on the source buffer before attempting the read.
If you don't want to copy the data to the struct but instead leave it in place, you can use slice::align_to
. This creates a &MyStruct
instead:
#[repr(C, packed)]
#[derive(Debug, Copy, Clone)]
struct MyStruct {
foo: u16,
bar: u8,
}
fn main() {
let v = vec![1u8, 2, 3];
// I copied this code from Stack Overflow
// without understanding why this case is safe.
let (head, body, _tail) = unsafe { v.align_to::<MyStruct>() };
assert!(head.is_empty(), "Data was not aligned");
let my_struct = &body[0];
println!("{:?}", my_struct);
}
Here, it's safe to use align_to
to transmute some bytes to MyStruct
because we've used repr(C, packed)
and all of the types in MyStruct
can be any arbitrary bytes.
See also:
- How to read a struct from a file in Rust?
- Can I take a byte array and deserialize it into a struct?