diff --git a/src/hru.rs b/src/hru.rs index 70981a3..236a2aa 100644 --- a/src/hru.rs +++ b/src/hru.rs @@ -19,7 +19,7 @@ use std::{ cmp::Ordering, env::args, - io::{ stdin, stdout, Write }, + io::{ Write, stdin, stdout }, process::{ ExitCode, exit }, }; @@ -47,6 +47,16 @@ const LIST: [(u32, &str); 10] = [ (30, "Q"), /* quetta */ ]; +fn err(argv0: &String, message: String, code: Option) -> ExitCode { + eprintln!("{}: {}", argv0, message); + ExitCode::from(code.unwrap_or(1 /* unknown error */)) +} + +fn usage(argv0: &String) -> ExitCode { + eprintln!("Usage: {}", argv0); + ExitCode::from(EX_USAGE) +} + fn convert(input: u128) -> Result<(f64, (u32, &'static str)), String> { /* preserve decimal places in output by casting to a float */ let mut out = (input as f64, (0_u32, "")); @@ -81,49 +91,44 @@ fn convert(input: u128) -> Result<(f64, (u32, &'static str)), String> { fn main() -> ExitCode { let argv = args().collect::>(); - if let Some(_) = argv.get(1) { - eprintln!("Usage: {}", argv[0]); - return ExitCode::from(EX_USAGE as u8); - } + if let Some(_) = argv.get(1) { return usage(&argv[0]); } #[cfg(target_os="openbsd")] { let promises = Promises::new("stdio"); if let Err(e) = pledge(Some(promises), None) { - eprintln!("{}: {}", argv[0], e.strerror()); - return ExitCode::from(EX_OSERR); + return err(&argv[0], e.strerror(), Some(EX_OSERR)); } } let mut buf = String::new(); - while let Ok(_) = stdin().read_line(&mut buf) { - if buf.is_empty() { return ExitCode::SUCCESS; } + if let Err(e) = stdin().read_line(&mut buf) { + return err(&argv[0], e.strerror(), Some(EX_IOERR)); + } - let n: u128 = match buf.trim().parse() { - Ok(f) => { - buf.clear(); - f - }, - Err(e) => { - eprintln!("{}: {}", argv[0], e); - return ExitCode::from(EX_DATAERR); - }, - }; + if buf.is_empty() { return ExitCode::SUCCESS; } - let (number, prefix) = convert(n).unwrap_or_else(|e| { - eprintln!("{}: {}", argv[0], e); - exit(EX_SOFTWARE.into()); - }); + let n: u128 = match buf.trim().parse() { + Ok(f) => { + buf.clear(); + f + }, + Err(e) => return err(&argv[0], e.to_string(), Some(EX_DATAERR)), + }; - let si_prefix = format!("{}B", prefix.1); + let (number, prefix) = convert(n).unwrap_or_else(|e| { + let _ = err(&argv[0], e.to_string(), None); + exit(EX_SOFTWARE.into()); + }); - /* round output number to one decimal place */ - let out = ((number * 10.0).round() / 10.0).to_string(); + let si_prefix = prefix.1.to_owned() + "B"; - if let Err(e) = stdout().write_all(format!("{} {}\n", out, si_prefix).as_bytes()) { - eprintln!("{}: {}", argv[0], e.strerror()); - return ExitCode::from(EX_IOERR); - } + /* round output number to one decimal place */ + let rounded = (number * 10.0).round() / 10.0; + let out = rounded.to_string() + " " + &si_prefix + &'\n'.to_string(); + + if let Err(e) = stdout().write_all(out.as_bytes()) { + return err(&argv[0], e.strerror(), Some(EX_IOERR)); } ExitCode::SUCCESS