rust / intermediate
Snippet
Custom Error Types with the ? Operator
Custom error types enable precise error handling with the ? operator through the From trait. By implementing From<ParseIntError> for our DataError enum, the ? operator automatically converts parse errors. Each enum variant represents a distinct error category, allowing callers to handle specific failures or use the Display trait for user-friendly messages. This pattern composes naturally with other functions returning Result.
snippet.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
use std::fmt;use std::num::ParseIntError;#[derive(Debug)]enum DataError {ParseError(ParseIntError),OutOfRange(i32),EmptyInput,}impl fmt::Display for DataError {fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {match self {DataError::ParseError(e) => write!(f, "Parse error: {}", e),DataError::OutOfRange(n) => write!(f, "Value {} out of range (0-100)", n),DataError::EmptyInput => write!(f, "Input cannot be empty"),}}}impl From<ParseIntError> for DataError {fn from(err: ParseIntError) -> Self {DataError::ParseError(err)}}fn parse_and_validate(s: &str) -> Result<u32, DataError> {if s.is_empty() {return Err(DataError::EmptyInput);}let num: i32 = s.parse()?;if !(0..=100).contains(&num) {return Err(DataError::OutOfRange(num));}Ok(num as u32)}fn main() {match parse_and_validate("42") {Ok(n) => println!("Valid number: {}", n),Err(e) => println!("Error: {}", e),}}
Breakdown
1
impl From<ParseIntError> for DataError
Implementing From enables automatic ? conversion between error types
2
let num: i32 = s.parse()?;
? operator calls Into::into() to convert ParseIntError to DataError
3
if !(0..=100).contains(&num)
Range check ensures value is within valid bounds
4
Ok(num as u32)
Cast to target type after validation; safe because range is checked