Use the ? operator to propagate errors with context or wrap them in a custom error type that implements Display and Error.
use std::fs::File;
use std::io;
fn read_config() -> Result<String, io::Error> {
let mut file = File::open("config.txt")?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
Ok(contents)
}
For custom context, define an error enum and map the underlying error:
use std::fmt;
use std::io;
#[derive(Debug)]
enum AppError {
Io(io::Error),
ConfigNotFound(String),
}
impl fmt::Display for AppError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
AppError::Io(e) => write!(f, "IO error: {}", e),
AppError::ConfigNotFound(path) => write!(f, "Config file not found: {}", path),
}
}
}
impl std::error::Error for AppError {}
fn load_config(path: &str) -> Result<String, AppError> {
std::fs::read_to_string(path)
.map_err(|e| AppError::ConfigNotFound(format!("{}: {}", path, e)))
}