Idiomatic way to add u8 to i8

Consider the following code:

let mut val : u8 = 125; let deltas : [i8; 4] = [5, -5, 5, 5]; let delta = select_current_delta(deltas); val += delta; 

It seems simple. I want to either increase or decrease the byte value based on some criteria (and I have a way to prevent overflow of the u8 value).

This, of course, does not compile:

  > rustc lala.rs lala.rs:7:12: 7:17 error: mismatched types: expected `u8`, found `i8` (expected u8, found i8) [E0308] lala.rs:7 val += delta; ^~~~~ 

Duh! Mixing signed and unsigned types seems to be prohibited in Rust. How about this?

 val = (val as i8 + delta) as u8; 

This compiles, but when I try to run it ...

 > ./lala thread '<main>' panicked at 'arithmetic operation overflowed', lala.rs:7 

Yes, i8 maximum value of 125, adding 5 will overflow, although the value is great for u8 .

I was able to come up with two solutions that work:

 val = (val as i16 + delta as i16) as u8; // or if delta < 0 { val -= (-delta) as u8 } else { val += delta as u8} 

None of them seem elegant to me. Is there an idiomatic way to add u8 to i8?

+4
source share
2 answers

Is there an idiomatic way to add u8 to i8 ?

The problem of adding u8 to i8 (c + ): what type should be the result? Neither u8 or i8 better, and using i16 , although correct, would probably be surprising.

Thus, at the moment, the operands of the mixed integral are not supported. The idiomatic way is to include both operands in a generic type, which will also be the result type. This is what you are doing.

But which of u8 += i8 ?

Unfortunately, at the moment this is sugar for u8 = u8 + i8 and therefore has all the limitations + , although the type of result will not be a problem.

Like all the annoying limitations of Rust, there is an RFC in it! This is PR # 953: Overloaded assignment operations . This RFC is in the final comment period, so a solution is expected soon, and hopefully this means that it will be adopted and Rust will receive support for assignment operations for mixed integrals.


As a personal preference, at the moment, I would go for:

 val = (val as i16 + delta as i16) as u8; 

which avoids branching.

+6
source

You can do this to avoid overflow and wrap the add:

 val = (val as i8).wrapping_add(delta) as u8; 

Look here for all arithmetic operations

+7
source

All Articles