Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to iterate over all byte values (overflowing_literals in `0..256`)

Tags:

rust

I'm trying to iterate over all possible byte (u8) values. Unfortunately my range literals in 0..256 are cast to u8 and 256 overflows:

fn foo(byte: u8) {
    println!("{}", byte);
}

fn main() {
    for byte in 0..256 {
        foo(byte);
        println!("Never executed.");
    }
    for byte in 0..1 {
        foo(byte);
        println!("Executed once.");
    }
}

The above compiles with:

warning: literal out of range for u8
 --> src/main.rs:6:20
  |
6 |     for byte in 0..256 {
  |                    ^^^
  |
  = note: #[warn(overflowing_literals)] on by default

The first loop body is never executed at all.

My workaround is very ugly and feels brittle because of the cast:

for short in 0..256 {
    let _explicit_type: u16 = short;
    foo(short as u8);
}

Is there a better way?

like image 214
Perseids Avatar asked Aug 30 '15 12:08

Perseids


2 Answers

As of Rust 1.26, inclusive ranges are stabilized using the syntax ..=, so you can write this as:

for byte in 0..=255 {
    foo(byte);
}
like image 100
porglezomp Avatar answered Oct 08 '22 20:10

porglezomp


This is issue Unable to create a range with max value.

The gist of it is that byte is inferred to be u8, and therefore 0..256 is represented as a Range<u8> but unfortunately 256 overflows as an u8.

The current work-around is to use a larger integral type and cast to u8 later on since 256 is actually never reached.

There is a RFC for inclusive range with ... which has entered final comment period; maybe in the future it'll be possible to have for byte in 0...255 or its alternative (0..255).inclusive().

like image 37
Matthieu M. Avatar answered Oct 08 '22 19:10

Matthieu M.