# What is the correct way to extract LSByte from a u32?

Hi,

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);
}
``````

Byte b is 0x78

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.

3 Likes

An alternative to casting to `u8`, as in @H2CO3's answer, are u32::to_le_bytes() and u32::to_be_bytes():

``````fn main() {
let t:u32 = 0x12345678;

let b = t.to_le_bytes(); // First byte in little-endian order
// or
let b = t.to_be_bytes(); // 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(); // 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);
}
``````
1 Like