Testing for failure

However, in most cases, we would like to attempt to recover from the error and let the program continue. We have already seen the basic techniques used in Rust to do just this in the Result and Option section in Chapter 4, Structuring Data and Matching Patterns, and in the section Generic data structures and functions in this chapter.

Both the Option and Result types are generic types:

It is used when a computation should return a result, but it can also return an error if something went wrong. The Result type is defined with two generic types T and E as:

enum Result<T, E> { 
    Ok(T), 
    Err(E) 
} 

It again shows Rust's commitment to being on the safe side: if it's OK, give back a value of type T, if there is a problem, then give back the error which is a value of type E (usually an error message string). So, we could read them also as: OK(what) and Err(why), where what has type T and why has type E.

In the following example, we use the Result type to safely read in a value from the keyboard:

let input_num: Result<u32, _> = buf.trim().parse(); 

In other languages, like Java or C#, parsing the input to a number could result in an exception (when the input contains non-numeric characters or when it is nothing or null), and you would have to use a resource heavy try or catch construct to deal with it.

In Rust, the result of the parse() function is a Result type, and we simply test the return value of Result with a match as in line (1) in the following code, which is a much simpler mechanism.

Here is the complete code:

// see code in Chapter 5/code/input_number.rs 
use std::io; 
 
fn main() { 
  println!("Give an integer number bigger than 0:"); 
  let mut buf = String::new(); 
  io::stdin().read_line(&mut buf) 
      .ok() 
      .expect("Failed to read line"); 
  let input_num: Result<u32, _>  = buf.trim().parse(); 
  let res = match input_num {                             // (1)
        Ok(num) => num, 
        Err(_) => 0 
    }; 
    if res != 0 { 
        println!("{}, that's a beautiful number", res); 
    } 
    else { 
 println!("The input was not correct: {:?} ",  input_num); 
    } 
} 

We captured the result variable num in a new variable, using a let binding on the match:

let res = match input_num { 
      Ok(num) => num, 
      Err(_) => 0 
}; 

This prints out the input number or an error message if the input is incorrect.