use std::fs;
use rootcause::prelude::*;
#[derive(Debug, Clone)]
enum ParseError {
InvalidFormat,
MissingField(String),
}
impl core::fmt::Display for ParseError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::InvalidFormat => write!(f, "Invalid format"),
Self::MissingField(field) => write!(f, "Missing required field: {field}"),
}
}
}
impl core::error::Error for ParseError {}
fn parse_value(input: &str) -> Result<u32, Report<ParseError>> {
if input.is_empty() {
Err(ParseError::InvalidFormat)?;
}
if !input.chars().all(|c| c.is_ascii_digit()) {
Err(report!(ParseError::InvalidFormat).attach(format!("Input: {input}")))?;
}
let value: u32 = input
.parse()
.context(ParseError::MissingField("value".to_string()))?;
Ok(value)
}
fn process_file(path: &str) -> Result<u32, Report> {
let contents = fs::read_to_string(path).attach(format!("Path: {path}"))?;
let value = parse_value(&contents)?;
Ok(value)
}
fn main() {
println!("Typed errors - Report<ParseError>:\n");
if let Err(report) = parse_value("") {
eprintln!("{report}\n");
}
if let Err(report) = parse_value("abc") {
eprintln!("{report}\n");
}
println!("Dynamic errors - mixing types:\n");
if let Err(report) = process_file("/nonexistent/config.txt") {
eprintln!("{report}");
}
}