How to cast a byte array to a primitive type in Rust?
Asked Answered
E

4

5

How would I cast a byte array to a primitive type in Rust?

let barry = [0, 0];
let shorty: u16 = barry;

I have already tried let shorty: u16 = barry as u16; but that didn't work due to a "non scalar cast".

Evenson answered 20/8, 2014 at 21:44 Comment(0)
K
5

You can use bitwise operations. Note that this depends on endianess.

fn main() {
   let barry = [0, 0];
   let shorty: u16 = barry[0] | (barry[1] << 8);
   println!("{0}", shorty);
}
Kaffiyeh answered 20/8, 2014 at 21:58 Comment(3)
Thanks for your answer, and yeah, I'm aware of the endianess. I am using the standard library to get it to the native format.Evenson
Also, it appears that for this to work, barry[0] and barry[1] need to be cast to u16. let shorty: u16 = barry[0] as u16 | (barry[1] as u16 << 8);Evenson
I tried the web runner (rust-lang.org). Yet, to be honest, I am seriously behind on Rust language evolution so I can't tell.Kaffiyeh
C
4

There is an unsafe way to do it with raw pointers too. The benefit being that it works for any type that only exists on the stack. It's completely safe as long as the byte array is correctly formatted, since no pointers are being kept around or modified. Just make sure that no mutable references also exists while this is going on, I would recommend wrapping it into a function that takes a reference to a byte array and a type parameter (with the Clone trait) so that the borrow checker can deal with that case.

let bytes = [0u8, 0u8];
let value = unsafe {
    let byte_ptr = bytes.as_ptr();
    let ptr = byte_ptr as *const u16; // This could be any type
    (*ptr).clone() // We clone it so that no 
                   // matter what type it is, it gets dereferenced. 
};
Cali answered 28/10, 2019 at 13:49 Comment(0)
E
3

The byteorder crate is great for this. You can specify endianness, etc.

Eckard answered 9/4, 2017 at 23:37 Comment(0)
L
2

Depending on the endianness you want, you can use either of the methods from_be_bytes(), from_le_bytes() or from_ne_bytes() of the primitive types, since Rust 1.32.0.

E.g.:

let barry = [0, 0];
let shorty = u16::from_be_bytes(barry);

Playground

Lefthand answered 19/10, 2023 at 17:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.