use {
problemo::{common::*, *},
std::thread,
};
string_attachment!(Path);
fn read_file(path: String) -> Result<String, Problem> {
std::fs::read_to_string(&path)
.into_problem()
.with(Path::new(path))
.via(LowLevelError)
}
fn read_files<ProblemReceiverT>(
paths: Vec<String>,
problems: &mut ProblemReceiverT,
) -> Result<Vec<String>, Problem>
where
ProblemReceiverT: ProblemReceiver,
{
let mut handles = Vec::default();
for path in paths {
handles.push(thread::spawn(move || read_file(path)));
}
let mut strings = Vec::default();
for handle in handles {
match handle.join().expect("join") {
Ok(string) => strings.push(string),
Err(problem) => problems.give(problem)?,
}
}
Ok(strings)
}
fn main() -> Result<(), Problem> {
println!("accumulate:");
let mut problems = Problems::default();
let strings = read_files(
vec![
"non-existing1.txt".into(),
"non-existing2.txt".into(),
"non-existing3.txt".into(),
],
&mut problems,
)?;
println!("{} strings", strings.len());
println!("\nproblems:");
for problem in problems {
print_problem(&problem);
}
println!("\nfail fast:");
match read_files(
vec![
"non-existing4.txt".into(),
"non-existing5.txt".into(),
"non-existing6.txt".into(),
],
&mut FailFast,
) {
Ok(strings) => println!("{} strings", strings.len()),
Err(problem) => print_problem(&problem),
}
Ok(())
}
fn print_problem(problem: &Problem) {
if let Some(path) = problem.attachment_of_type::<Path>() {
println!("• {}\n {}", path, problem);
} else {
println!("• {}", problem);
}
}