diff --git a/src/error.rs b/src/error.rs index 34ca128..7722809 100644 --- a/src/error.rs +++ b/src/error.rs @@ -14,6 +14,8 @@ pub enum Error { ProblemCheckFailed, #[error("formatting: {_0}")] Format(#[from] std::fmt::Error), + #[error("outputting: {_0}")] + Output(#[from] std::io::Error), } impl From>> for Error { diff --git a/src/main.rs b/src/main.rs index 3ce691c..420390f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,7 @@ #![feature(iter_intersperse)] #![feature(doc_notable_trait)] -use std::{collections::HashSet, fmt::Write, fs::read_to_string}; +use std::{collections::HashSet, fmt::Write as WriteFmt, fs::read_to_string, io::Write as WriteIo}; use aba::problems::admissibility::{ EnumerateAdmissibleExtensions, SampleAdmissibleExtension, VerifyAdmissibleExtension, @@ -35,56 +35,77 @@ mod parser; #[cfg(test)] mod tests; +trait IccmaFormattable { + fn fmt_iccma(&self) -> Result; +} + fn __main() -> Result { let args = args::Args::parse(); let content = read_to_string(&args.file).map_err(Error::OpeningAbaFile)?; let aba = parser::aba_file(&content)?; - match args.problem { - args::Problems::VerifyAdmissibility { set } => { - let result = aba::problems::solve( - VerifyAdmissibleExtension { - assumptions: set.into_iter().collect(), - }, - &aba, - )?; - print_bool_result(result); - } + let result = match args.problem { + args::Problems::VerifyAdmissibility { set } => aba::problems::solve( + VerifyAdmissibleExtension { + assumptions: set.into_iter().collect(), + }, + &aba, + )? + .fmt_iccma(), args::Problems::EnumerateAdmissibility => { - let result = - aba::problems::multishot_solve(EnumerateAdmissibleExtensions::default(), &aba)?; - print_witnesses_result(result)?; + aba::problems::multishot_solve(EnumerateAdmissibleExtensions::default(), &aba)? + .fmt_iccma() } args::Problems::SampleAdmissibility => { - let result = aba::problems::solve(SampleAdmissibleExtension, &aba)?; - print_witness_result(result)?; + aba::problems::solve(SampleAdmissibleExtension, &aba)?.fmt_iccma() } + }?; + let mut stdout = std::io::stdout().lock(); + match writeln!(stdout, "{}", result) { + Ok(()) => Ok(()), + Err(why) => match why.kind() { + std::io::ErrorKind::BrokenPipe => Ok(()), + _ => Err(Error::Output(why)), + }, } - Ok(()) } fn main() -> Result { __main().inspect_err(|why| eprintln!("Error: {why}")) } -fn print_bool_result(result: bool) { - match result { - true => println!("YES"), - false => println!("NO"), +impl IccmaFormattable for Vec> { + fn fmt_iccma(&self) -> Result { + let output = self + .iter() + .try_fold(String::new(), |mut output, set| -> Result { + writeln!(output, "{}", set.fmt_iccma()?)?; + Ok(output) + })? + .trim_end() + .to_owned(); + Ok(output) } } -fn print_witnesses_result(result: Vec>) -> Result { - result.into_iter().try_for_each(print_witness_result) +impl IccmaFormattable for HashSet { + fn fmt_iccma(&self) -> Result { + let set = self + .iter() + .try_fold(String::new(), |mut list, num| -> Result<_, Error> { + write!(list, " {num}")?; + Result::Ok(list) + })?; + Ok(format!("w{set}")) + } } -fn print_witness_result(result: HashSet) -> Result { - let set = result - .into_iter() - .try_fold(String::new(), |mut list, num| -> Result<_, Error> { - write!(list, " {num}")?; - Result::Ok(list) - })?; - println!("w{set}"); - Ok(()) +impl IccmaFormattable for bool { + fn fmt_iccma(&self) -> Result { + let output = match self { + true => "YES", + false => "NO", + }; + Ok(String::from(output)) + } }