Rust overflowing shift left - rust

I'm trying to combine 4 bytes into a u32, and the compiler telling me that the shift has overflown.
This is my code:
pub fn get_instruction(file: &[u8], counter: usize) {
let ins = u32::from(file[counter] << 24)
| u32::from(file[counter + 1] << 16)
| u32::from(file[counter + 2] << 8)
| u32::from(file[counter + 3]);
println!("{:x}", ins);
}

You got your operator priority and cast wrong:
pub fn get_instruction(file: &[u8], counter: usize) {
let ins = u32::from(file[counter]) << 24
| u32::from(file[counter + 1]) << 16
| u32::from(file[counter + 2]) << 8
| u32::from(file[counter + 3]);
println!("{:x}", ins);
}
You were casting after trying to shift a u8 24 bits, which was your problem.

It's not necessary to twiddle the bits yourself – you can use the function u32::from_be_bytes() instead:
pub fn get_instruction(file: &[u8], counter: usize) {
let ins_bytes = <[u8; 4]>::try_from(&file[counter..counter + 4]).unwrap();
let ins = u32::from_be_bytes(ins_bytes);
println!("{:x}", ins);
}

Related

How do I split a 16-bit value into two 8-bit values?

I have u16 value and want to convert it into two u8 values to put it into u8 array, the same as described here.
0000000000000011 -> 00000000 and 00000011
How would I do that in a convenient way?
Putting the answers provided by #apilat and #Anton into code:
Bit Shifting - verbose style
This can be accomplished in a couple of different ways. I actually think that bit shifting is a little clearer, as no thought needs to be given to whether I need to worry about endianness.
Spelling out each:
fn shift_verbose_split_u16(short_16: u16) -> [u8; 2] {
let high_byte: u8 = (short_16 >> 8) as u8;
let low_byte: u8 = (short_16 & 0xff) as u8;
return [high_byte, low_byte];
}
Bit Shifting - idiomatic style
The above code can be reduced to a one-line function:
fn shift_idiomatic_split_u16(short_16: u16) -> [u8; 2] {
[(short_16 >> 8) as u8, (short_16 & 0xff) as u8]
}
Using to_be_bytes()
Using to_be_bytes() certainly is the simplest solution. Using this solution, you have to realize that you really want to use the big-endian call, regardless of the underlying cpu's architecture:
let [high, low] = short_16.to_be_bytes();
Grouping the code into one file:
fn main() {
let short_16: u16 = 0x3f23;
// verbose bit shifting
let [high, low] = shift_verbose_split_u16(short_16);
assert_eq!(high, 0x3f);
assert_eq!(low, 0x23);
// idiomatic bit shifting
let [high, low] = shift_idiomatic_split_u16(short_16);
assert_eq!(high, 0x3f);
assert_eq!(low, 0x23);
let [high, low] = short_16.to_be_bytes();
assert_eq!(high, 0x3f);
assert_eq!(low, 0x23);
println!("High: {:#0x?}, Low: {:#0x?}", high, low);
}
fn shift_verbose_split_u16(short_16: u16) -> [u8; 2] {
let high_byte: u8 = (short_16 >> 8) as u8;
let low_byte: u8 = (short_16 & 0xff) as u8;
return [high_byte, low_byte];
}
fn shift_idiomatic_split_u16(short_16: u16) -> [u8; 2] {
[(short_16 >> 8) as u8, (short_16 & 0xff) as u8]
}
Output:
High: 0x3f, Low: 0x23

How can I convert the lower/upper 8 bits of a u16 to a u8 in Rust?

I want to convert a u16 to two separate u8s. I tried to use some bit masks:
use std::convert::From;
fn main() {
let n1: u8 = 0x41;
let n2: u16 = 0x4157;
println!("Number:{}", char::from(n1));
let b1: u8 = n2 & 0xFF;
let b2: u8 = n2 >> 8;
println!("b1: {}", b1);
println!("b2: {}", b2);
}
error[E0308]: mismatched types
--> src/main.rs:9:18
|
9 | let b1: u8 = n2 & 0xFF;
| ^^^^^^^^^ expected u8, found u16
error[E0308]: mismatched types
--> src/main.rs:10:18
|
10 | let b2: u8 = n2 >> 8;
| ^^^^^^^ expected u8, found u16
This question is not why does the compiler raise a mismatched type error?, rather, it is How can I convert the lower/upper 8 bits of a u16 to a u8 in Rust?. Potentially, there are other ways to do this and this question does not constrain the answer to the as keyword.
Update: As of Rust 1.32.0 there is u16::to_be_bytes, which can be used in favor a custom function.
fn main() {
let bytes = 28923u16.to_be_bytes();
assert_eq!([0x70, 0xFB], bytes);
}
You can use the as keyword to convert a u16 to u8 in a safe way.
fn convert_u16_to_two_u8s_be(integer: u16) -> [u8; 2] {
[(integer >> 8) as u8, integer as u8]
}
If you need more types or different endianness use the byteorder crate.
extern crate byteorder;
use byteorder::{WriteBytesExt, BigEndian};
fn convert_u16_to_two_u8s_be(integer: u16) -> Vec<u8> {
let mut res = vec![];
res.write_u16::<BigEndian>(integer).unwrap();
res
}
You can cast between integer types with as.
let b1 = n2 as u8;
let b2 = (n2 >> 8) as u8;
Note that the masking is unnecessary, because the cast will truncate the upper bits.

Converting large number stored in array of u32 to bytes and back

I'm doing some computational mathematics in Rust, and I have some large numbers which I store in an array of 24 values. I have functions that convert them to bytes and back, but it doesn't work fine for u32 values, whereas it works fine for u64. The code sample can be found below:
fn main() {
let mut bytes = [0u8; 96]; // since u32 is 4 bytes in my system, 4*24 = 96
let mut j;
let mut k: u32;
let mut num: [u32; 24] = [1335565270, 4203813549, 2020505583, 2839365494, 2315860270, 442833049, 1854500981, 2254414916, 4192631541, 2072826612, 1479410393, 718887683, 1421359821, 733943433, 4073545728, 4141847560, 1761299410, 3068851576, 1582484065, 1882676300, 1565750229, 4185060747, 1883946895, 4146];
println!("original_num: {:?}", num);
for i in 0..96 {
j = i / 4;
k = (i % 4) as u32;
bytes[i as usize] = (num[j as usize] >> (4 * k)) as u8;
}
println!("num_to_ytes: {:?}", &bytes[..]);
num = [0u32; 24];
for i in 0..96 {
j = i / 4;
k = (i % 4) as u32;
num[j as usize] |= (bytes[i as usize] as u32) << (4 * k);
}
println!("recovered_num: {:?}", num);
}
Rust playground
The above code does not retrieve the correct number from the byte array. But, if I change all u32 to u64, all 4s to 8s, and reduce the size of num from 24 values to 12, it works all fine. I assume I have some logical problem for the u32 version. The correctly working u64 version can be found in this Rust playground.
Learning how to create a MCVE is a crucial skill when programming. For example, why do you have an array at all? Why do you reuse variables?
Your original first number is 0x4F9B1BD6, the output first number is 0x000B1BD6.
Comparing the intermediate bytes shows that you have garbage:
let num = 0x4F9B1BD6_u32;
println!("{:08X}", num);
let mut bytes = [0u8; BYTES_PER_U32];
for i in 0..bytes.len() {
let k = (i % BYTES_PER_U32) as u32;
bytes[i] = (num >> (4 * k)) as u8;
}
for b in &bytes {
print!("{:X}", b);
}
println!();
4F9B1BD6
D6BD1BB1
Printing out the values of k:
for i in 0..bytes.len() {
let k = (i % BYTES_PER_U32) as u32;
println!("{} / {}", k, 4 * k);
bytes[i] = (num >> (4 * k)) as u8;
}
Shows that you are trying to shift by multiples of 4 bits:
0 / 0
1 / 4
2 / 8
3 / 12
I'm pretty sure that every common platform today uses 8 bits for a byte, not 4.
This is why magic numbers are bad. If you had used constants for the values, you would have noticed the problem much sooner.
since u32 is 4 bytes in my system
A u32 better be 4 bytes on every system — that's why it's a u32.
Overall, don't reinvent the wheel. Use the byteorder crate or equivalent:
extern crate byteorder;
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
const LENGTH: usize = 24;
const BYTES_PER_U32: usize = 4;
fn main() {
let num: [u32; LENGTH] = [
1335565270, 4203813549, 2020505583, 2839365494, 2315860270, 442833049, 1854500981,
2254414916, 4192631541, 2072826612, 1479410393, 718887683, 1421359821, 733943433,
4073545728, 4141847560, 1761299410, 3068851576, 1582484065, 1882676300, 1565750229,
4185060747, 1883946895, 4146,
];
println!("original_num: {:?}", num);
let mut bytes = [0u8; LENGTH * BYTES_PER_U32];
{
let mut bytes = &mut bytes[..];
for &n in &num {
bytes.write_u32::<BigEndian>(n).unwrap();
}
}
let mut num = [0u32; LENGTH];
{
let mut bytes = &bytes[..];
for n in &mut num {
*n = bytes.read_u32::<BigEndian>().unwrap();
}
}
println!("recovered_num: {:?}", num);
}

Expected reference, found struct [duplicate]

This question already has answers here:
How do I update a variable in a loop to a reference to a value created inside the loop?
(2 answers)
How to abstract over a reference to a value or a value itself?
(1 answer)
Is it possible to return either a borrowed or owned type in Rust?
(1 answer)
Closed 5 years ago.
I'm trying to learn Rust by translating C++ code from the "Elements of Programming" book by Stepanov and McJones. Here's a simple code snippet:
extern crate num_bigint;
use num_bigint::BigInt;
pub fn fibonacci_matrix_multiply(x: (&BigInt, &BigInt), y: (&BigInt, &BigInt)) -> (BigInt, BigInt) {
(x.0 * (y.1 + y.0) + x.1 * y.0, x.0 * y.0 + x.1 * y.1)
}
pub fn power_accumulate_positive(
mut r: (&BigInt, &BigInt),
mut a: (&BigInt, &BigInt),
mut n: i32,
) -> (BigInt, BigInt) {
loop {
if n & 1 == 1 {
r = fibonacci_matrix_multiply(r, a);
if n == 1 {
return r;
}
}
a = fibonacci_matrix_multiply(a, a);
n = n / 2;
}
}
fn main() {}
Here's the error messages:
error[E0308]: mismatched types
--> src/main.rs:16:17
|
16 | r = fibonacci_matrix_multiply(r, a);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found struct `num_bigint::BigInt`
|
= note: expected type `(&num_bigint::BigInt, &num_bigint::BigInt)`
found type `(num_bigint::BigInt, num_bigint::BigInt)`
error[E0308]: mismatched types
--> src/main.rs:18:24
|
18 | return r;
| ^ expected struct `num_bigint::BigInt`, found reference
|
= note: expected type `(num_bigint::BigInt, num_bigint::BigInt)`
found type `(&num_bigint::BigInt, &num_bigint::BigInt)`
error[E0308]: mismatched types
--> src/main.rs:21:13
|
21 | a = fibonacci_matrix_multiply(a, a);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found struct `num_bigint::BigInt`
|
= note: expected type `(&num_bigint::BigInt, &num_bigint::BigInt)`
found type `(num_bigint::BigInt, num_bigint::BigInt)`
I understand that I'm returning a tuple of structs and trying to assign it to a tuple of references, but I don't know how to solve the problem.
Is there a reason you can't take the BigInts by value instead of by reference? This would remove all the borrow checker errors. Unless it's a clear and measured bottleneck to clone the BigInts, passing by reference won't be much faster and it's less ergonomic.
Here's a working solution that doesn't use references (and instead clones the values)
extern crate num_bigint;
use num_bigint::BigInt;
pub fn fibonacci_matrix_multiply(x: (BigInt, BigInt), y: (BigInt, BigInt)) -> (BigInt, BigInt) {
(&x.0 * (&y.1 + &y.0) + &x.1 * &y.0, x.0 * y.0 + x.1 * y.1)
}
pub fn power_accumulate_positive(
mut r: (BigInt, BigInt),
mut a: (BigInt, BigInt),
mut n: i32,
) -> (BigInt, BigInt) {
loop {
if n & 1 == 1 {
r = fibonacci_matrix_multiply(r, a.clone());
if n == 1 {
return r;
}
}
a = fibonacci_matrix_multiply(a.clone(), a);
n = n / 2;
}
}

Crash while trying to do bit shift

I am trying to run this rust code
use std::net::Ipv4Addr;
fn ip_to_int(addr: Ipv4Addr) -> u32 {
let ip = addr.octets();
(ip[0] as u32) << 24 + (ip[1] as u32) << 16 + (ip[2] as u32) << 8 + (ip[3] as u32)
}
fn main() {
let ip = Ipv4Addr::new(74, 125, 227, 0);
println!("{}", ip_to_int(ip));
}
This crashes with
thread '<main>' panicked at 'shift operation overflowed', test.rs:5
I did typecast everything to 32 bit ints and no shift is larger than 32 bits. Why does it crash? Also, isn't the compiler supposed to catch this and prevent compilation?
Abhishek#Abhisheks-MacBook-Pro-2:~$ rustc --version
rustc 1.1.0-nightly (21f278a68 2015-04-23) (built 2015-04-24)
According to the the Rust reference, operator + as a stronger precedence than operator <<, meaning that your expression is actually parsed like this:
(ip[0] as u32) << (24 + (ip[1] as u32)) << (16 + (ip[2] as u32)) << (8 + (ip[3] as u32))
Which can pretty easily overflow.
You need to add the appropriates brackets:
((ip[0] as u32) << 24) + ((ip[1] as u32) << 16) + ((ip[2] as u32) << 8) + (ip[3] as u32)

Resources