typestar

From conversions drive ? in Rust

Implement From for each underlying error and ? converts on its own.

use std::fmt;
use std::num::ParseIntError;

#[derive(Debug)]
enum LoadError {
    BadNumber(ParseIntError),
    Empty,
}

impl From<ParseIntError> for LoadError {
    fn from(e: ParseIntError) -> Self {
        LoadError::BadNumber(e)
    }
}

impl fmt::Display for LoadError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            LoadError::BadNumber(e) => write!(f, "not a number: {e}"),
            LoadError::Empty => write!(f, "nothing to load"),
        }
    }
}

fn total(raw: &str) -> Result<i32, LoadError> {
    if raw.trim().is_empty() {
        return Err(LoadError::Empty);
    }
    let mut sum = 0;
    for part in raw.split(',') {
        sum += part.trim().parse::<i32>()?;
    }
    Ok(sum)
}

fn main() {
    println!("{:?}", total("1, 2, 3"));
    println!("{}", total("1, x").unwrap_err());
    println!("{}", total("  ").unwrap_err());
}

How it works

  1. ? calls From::from on the error it is returning.
  2. One From impl per foreign error type is all it takes.
  3. The function then mixes error sources freely.

Keywords and builtins used here

The run, in numbers

Lines
40
Characters to type
775
Tokens
247
Three-star pace
105 tpm

At the three-star pace of 105 tokens a minute, this run takes about 141 seconds.

Type this snippet

Step 3 of 5 in Your own error types, step 10 of 15 in Error handling.

← Previous Next →