Let's say we have a structure, all fields of which are of the same sized types:
struct Homogeneous {
a: u64,
b: u64,
c: u64,
d: u64
}
And we have a "safe" way to construct it from array of bytes:
impl From<[u8; 32]> for Homogeneous {
fn from(slice: [u8; 32]) -> Self {
// helper macro to convert slice of u8s into u64
macro_rules! to_u64 {
($slice: expr, $at: expr) => {{
let ss = &$slice[$at..$at + 8];
let mut buf = [0u8; 8];
buf.copy_from_slice(&ss);
u64::from_ne_bytes(buf)
}};
}
Self {
a: to_u64!(bytes, 0),
b: to_u64!(bytes, 8),
c: to_u64!(bytes, 16),
d: to_u64!(bytes, 24),
}
}
}
Which is all good and it works. The question is whether unsafe solution (using transmute) is more efficient (safe?), also whether the reverse conversion will not cause UB due to optimizing compiler reordering struct fields?
impl From<[u8; 32]> for Homogeneous {
fn from(slice: [u8; 32]) -> Self {
unsafe { std::mem::transmute(slice) };
}
}
impl From<Homogeneous> for [u8; 32] {
fn from(h: Homogeneous) -> Self {
unsafe { std::mem::transmute(h) }
}
}
Those conversions work on my x86 processor using rust 1.57 compiler, and I wonder if they will always work, despite the architecture/compiler.