My code needs to extract LSByte from a u32 (u32 data is from a volatile read of a memory mapped register).
What is the right way to extract the LSByte from a u32 in rust?
What happens internally in rust when a u32 is cast as u8?
will it take the LSByte or MSByte ?
Is it arch dependent?
I did a quick test as below, it extracts the LSByte, but I am not sure this is the correct way and would it work on all hardware independent of endianness, toolchain etc..
fn main() {
let t:u32 = 0x12345678;
let b = (t & 0x000000FF) as u8;
println!("Byte b is {:#x}", b);
}
If you mean the byte that mathematically has the least place value, then casting to u8 (or casting preceded by masking with 0xff) are guaranteed to be correct.
fn main() {
let t:u32 = 0x12345678;
let b = t.to_le_bytes()[0]; // First byte in little-endian order
// or
let b = t.to_be_bytes()[3]; // Fourth byte in big-endian order
println!("Byte b is {:#x}", b);
}
This might make the intent of the code clearer if that memory-mapped register is logically more of a byte-array than an 32-bit integer. In optimized builds both variants in my example generate the same machine code as t as u8 and (t & 0xFF) as u8.
If you want one byte from an u32 in native order instead, you need u32::to_ne_bytes():
fn main() {
let t:u32 = 0x12345678;
let b = t.to_ne_bytes()[0]; // First byte in native byte order, that is
// LSByte 0x78 on little-endian platforms and
// MSByte 0x12 on big-endian platforms
println!("Byte b is {:#x}", b);
}