Load configuration with mapped errors
Rust
use std::collections::HashMap;
use std::fs;
#[derive(Debug)]
enum ConfigError {
Read(std::io::Error),
Invalid { line: usize, message: String },
}
/// Load "key=123" pairs from a file, reporting the line number on bad input.
fn load_config(path: &str) -> Result<HashMap<String, u16>, ConfigError> {
let text = fs::read_to_string(path).map_err(ConfigError::Read)?;
let mut config = HashMap::new();
for (index, raw) in text.lines().enumerate() {
let line = raw.trim();
if line.is_empty() || line.starts_with('#') {
continue;
}
let Some((key, value)) = line.split_once('=') else {
return Err(ConfigError::Invalid {
line: index + 1,
message: "expected key=value".to_string(),
});
};
let port = value.trim().parse::<u16>().map_err(|_| ConfigError::Invalid {
line: index + 1,
message: format!("{key} is not a valid port"),
})?;
config.insert(key.trim().to_string(), port);
}
Ok(config)
}
fn main() {
match load_config("app.conf") {
Ok(config) => println!("{:?}", config),
Err(ConfigError::Read(error)) => eprintln!("cannot read config: {error}"),
Err(ConfigError::Invalid { line, message }) => eprintln!("line {line}: {message}"),
}
}