Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I reference a variable used in an unsafe block?

Tags:

rust

I'm trying to read 4 bytes from a socket and then transmute those bytes into a single u32.

let mut length: u32 = 0;

// Transmute 4 byte array into u32
unsafe {
    let length = mem::transmute::<[u8; 4], u32>(buf); // buf is the 4 item array of u8 that the socket was read into
    println!("1: {:}", length);
}

println!("Length: {:}", length);

However, length has the original value of 0 once outside of the unsafe block. How can I get around this?

like image 226
Fluffy Avatar asked Mar 16 '16 15:03

Fluffy


2 Answers

In the inner block, you're not assigning a new value to the outer length binding, you are shadowing it by defining a new length binding.

I believe that in a simple code snippet such as this (where the outer mutable variable isn't reassigned) normally there should be a compiler warning along the lines of:

warning: variable does not need to be mutable

In any case, since you have declared an outer mutable binding, all you have to do to re-assign the original variable is drop the keyword let in the unsafe block.

Additionally, as pointed out in the comments:

  • There's no need to initialize this particular binding with a value, because that value is always going to be replaced before it is ever used.
  • If you aren't really re-assigning that variable later on (in code not shown in your question), then it doesn't even need to be mutable. Mutability doesn't force you to initialize the variable at the point of its declaration in the source code.

So this should suffice:

let length: u32; // or mut  
unsafe {
    length = mem::transmute::<[u8; 4], u32>(buf);
    println!("1: {:}", length);
}

println!("Length: {:}", length);
like image 96
Theodoros Chatzigiannakis Avatar answered Sep 29 '22 17:09

Theodoros Chatzigiannakis


Note (in addition to Theodoros' answer) that unsafe block is an expression, so you can do this:

let buf = [1u8, 2, 3, 4];

// Transmute 4 byte array into u32
let length = unsafe {
    let length = std::mem::transmute::<[u8; 4], u32>(buf); // buf is the 4 item array of u8 that the socket was read into
    println!("1: {:}", length);
    length
};

println!("Length: {:}", length);

Or in short:

let length = unsafe {std::mem::transmute::<[u8; 4], u32>(buf)};
like image 41
ArtemGr Avatar answered Sep 29 '22 17:09

ArtemGr