Handling results when I just want the loop to exit


#1

Hi All, I’m starting to think I’m not really able to think in a rustical manner :frowning:

Here’s my code:

extern crate bitstream_io;
use bitstream_io::{LE,BitReader,BitQueue};
use std::io::Cursor;
fn main() {
    let data = [128, 124, 198, 123,128, 124, 198, 123,128, 124, 198, 123,128, 124, 198, 123,128, 124, 198, 123,128, 124, 198, 123,128, 124, 198, 123,128, 124, 198, 123,128, 124, 198, 123,128, 124, 198, 123,128, 124, 198, 123,128, 124, 198, 123,128, 124, 198, 123,128, 124, 198, 123,128, 124, 198, 123,128, 124, 198, 123,128, 124, 198, 123,128, 124, 198, 123,128, 124, 198, 123,128, 124, 198, 123 ].to_vec();

    let mut c = Cursor::new(data);
    let mut bits = BitReader::<LE>::new(&mut c);

    loop {
        let mut bit1 = bits.read_bit();
        match bit {
            Ok(v) => v,
            Err(e) => break,
        }
        if bit1.unwrap() {
            print!("1");
        } else {
            print!("0");
        }
    } // end loop
 }

and the compiler errors:

error[E0308]: mismatched types
  --> src/main.rs:16:9
    |
16 | /         match bit1 {
17 | |             Ok(v) => v,
18 | |             Err(e) => break
19 | |         }
    | |_________^ expected (), found bool
    |
   = note: expected type `()`
          found type `bool`

So, the BitReader returns a bit as a bool when read_bit() is called, or an Error if it has reached the end. When it does reach the end I want to break out of the loop to get on with other stuff, not abort, but I can’t for the life of me work out how to do that!

Any pointers on what’s the proper way of handling this?


#2

You can combine looping, value extraction, and error checking by using while let

while let Ok(bit) = bits.read_bit() {
    if bit {
        print!("1");
    } else {
        print!("0");
    }
}

#3

It looks like read_bit is returning a Result that holds a bit as a bool, not a bool directly, which is why you need the match like you have here. Then this part of the match:

Ok(v) => v,

says “If this value matches the Ok variant of a Result, take the v that it’s holding and return that”. However, you’re not returning v to anything, and I think the error message you’re seeing is that Rust is expecting this match to not return any value (which it’s saying by saying it expects the unit type ()), but this match is returning a value.

What I’m guessing you’d rather do is replace the Result in bit1 with just the bool, and we can do that using shadowing instead of making it mutable since we’re changing types. So:

        let bit1 = bits.read_bit();
        let bit1 = match bit1 {
            Ok(v) => v,
            Err(e) => break,
        };

Note the semicolon at the end-- that goes with the let statement. This way, you’re returning v to bit1 rather than main.

Then in the if, you don’t need to unwrap since you’ve extracted the bool from the Result already.

There are lots of ways to write this depending on what you’re doing around this code; @red75prime’s suggestion looks awesome to me, but I wanted to break down what’s going on a bit :slight_smile:


#4

Thank you both, that’s certainly got me squared away! I’d missed the idea that the match section returns, all working as I’d expected now!