Can I take a byte array and deserialize it into a struct?

The issue here is that the y field is 16-bit-aligned. So your memory layout is actually

x
padding
y
y

Note that swapping the order of x and y doesn’t help, because Rust’s memory layout for structs is actually undefined (and thus still 32 bits for no reason but simplicity in the compiler). If you depend on it you will get undefined behavior.

The reasons for alignment are explained in Purpose of memory alignment.

You can prevent alignment from happening by adding the attribute repr(packed) to your struct, but you’ll lose performance and the ability to take references of fields:

#[repr(packed)]
struct Things {
    x: u8,
    y: u16,
}

The best way would be to not use transmute at all, but to extract the values manually and hope the optimizer makes it fast:

let foobar = Things {
    x: array[0],
    y: ((array[1] as u16) << 8) | (array[2] as u16),
};

A crate like byteorder may simplify the process of reading different sizes and endianness from the bytes.

Leave a Comment