Rust
Beginner
1 min read
Result<T, E> and Error Handling
Example
use std::num::ParseIntError;
#[derive(Debug)]
enum AppError {
ParseError(ParseIntError),
NegativeNumber(i64),
TooBig(i64),
}
impl From<ParseIntError> for AppError {
fn from(e: ParseIntError) -> Self {
AppError::ParseError(e)
}
}
fn parse_and_validate(s: &str) -> Result<i64, AppError> {
let n: i64 = s.trim().parse()?; // ? converts ParseIntError via From
if n < 0 {
return Err(AppError::NegativeNumber(n));
}
if n > 1_000_000 {
return Err(AppError::TooBig(n));
}
Ok(n)
}
fn double(s: &str) -> Result<i64, AppError> {
let n = parse_and_validate(s)?;
Ok(n * 2)
}
fn main() {
let inputs = vec!["42", " 100 ", "-5", "999999999", "abc"];
for input in inputs {
match double(input) {
Ok(v) => println!("double({input:?}) = {v}"),
Err(AppError::ParseError(e)) => println!("{input:?} parse error: {e}"),
Err(AppError::NegativeNumber(n)) => println!("{input:?} is negative: {n}"),
Err(AppError::TooBig(n)) => println!("{input:?} is too big: {n}"),
}
}
// Combinators
let opt: Option<i64> = double("7").ok();
println!("as option: {:?}", opt);
let mapped = double("3").map(|v| v + 1);
println!("mapped: {:?}", mapped);
}