use {
problemo::*,
std::{error::Error, path::*},
};
gloss_error!(FileError);
pub struct PathCauseEquality;
impl PathCauseEquality {
pub fn new<ErrorT>() -> CauseEquality
where
ErrorT: 'static + Error + PartialEq,
{
CauseEquality(Box::new(Self::eq_::<ErrorT>))
}
fn eq_<ErrorT>(left: &Cause, right: &Cause) -> bool
where
ErrorT: 'static + Error + PartialEq,
{
if let Some(left_error) = left.error.downcast_ref::<ErrorT>()
&& let Some(right_error) = right.error.downcast_ref::<ErrorT>()
{
if left_error.eq(right_error) {
if let Some(left_path) = left.attachment_of_type::<PathBuf>()
&& let Some(right_path) = right.attachment_of_type::<PathBuf>()
{
left_path.eq(right_path)
} else {
true
}
} else {
false
}
} else {
false
}
}
}
fn read_files<ProblemReceiverT>(
paths: &[&str],
problems: &mut ProblemReceiverT,
) -> Result<Vec<String>, Problem>
where
ProblemReceiverT: ProblemReceiver,
{
let mut strings = Vec::default();
for path in paths {
if let Some(string) = std::fs::read_to_string(path)
.via(FileError::new("read_to_string"))
.with(PathBuf::from(path))
.with(PathCauseEquality::new::<FileError>())
.give_ok(problems)?
{
strings.push(string);
}
}
Ok(strings)
}
fn main() {
let mut problems = Problems::default();
read_files(&["non-existing1.txt", "non-existing2.txt"], &mut problems).unwrap();
read_files(&["non-existing1.txt", "non-existing2.txt"], &mut problems).unwrap();
read_files(&["non-existing3.txt", "non-existing4.txt"], &mut problems).unwrap();
println!("All errors:");
for problem in &problems {
println!("• {}", problem);
if let Some(path) = problem.attachment_of_type::<PathBuf>() {
println!(" {}", path.display());
}
}
println!("\nUnique errors:");
for problem in problems.iter_unique() {
println!("• {}", problem);
if let Some(path) = problem.attachment_of_type::<PathBuf>() {
println!(" {}", path.display());
}
}
}