diff --git a/src/bin/histo.rs b/src/bin/histo.rs index 81257ec..2619342 100644 --- a/src/bin/histo.rs +++ b/src/bin/histo.rs @@ -14,8 +14,101 @@ fn main() { } } +fn io_error(error: impl Into>) -> io::Error { + io::Error::new(io::ErrorKind::Other, error) +} + +const HELP_TEXT: &'static str = "\ +Reads data from `stdin` and prints a histogram of the data to `stdout`. + +The input data format must be one unsigned 64-bit integer per line. + +USAGE: + histo [OPTIONS] [FLAGS] + +OPTIONS: + -n, --buckets BUCKETS + Configure the number of buckets in the histogram + +FLAGS: + -h, --help + Prints help information + + -V, --version + Prints version information + +EXAMPLE: + + $ head data.txt + 3 + 1 + 50 + 38 + 1 + 38 + 1 + 38 + 39 + 4 + $ histo < data.txt + # Number of samples = 154653 + # Min = 1 + # Max = 58 + # + # Mean = 4.407945529669717 + # Standard deviation = 5.8241339617399985 + # Variance = 33.92053640429325 + # + # Each ∎ is a count of 2484 + # + 1 .. 7 [ 124222 ]: ∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎ + 7 .. 13 [ 18556 ]: ∎∎∎∎∎∎∎ + 13 .. 19 [ 7117 ]: ∎∎ + 19 .. 25 [ 2059 ]: + 25 .. 31 [ 1245 ]: + 31 .. 37 [ 284 ]: + 37 .. 43 [ 882 ]: + 43 .. 49 [ 122 ]: + 49 .. 55 [ 135 ]: + 55 .. 61 [ 31 ]: +"; + +fn help_text() { + eprintln!("histo {}\n\n{}", env!("CARGO_PKG_VERSION"), HELP_TEXT); +} + +fn fail_with_help_text(msg: impl AsRef) -> ! { + eprintln!("{}", msg.as_ref()); + eprintln!(); + help_text(); + process::exit(1) +} + fn try_main() -> io::Result<()> { - let mut hist = histo::Histogram::with_buckets(10); + let mut buckets = 10; + + let mut args = std::env::args().skip(1); + while let Some(arg) = args.next() { + match arg.as_str() { + "-n" | "--buckets" => { + let arg = args.next().unwrap_or_else(|| { + fail_with_help_text(format!("missing number of buckets for `{arg}`")) + }); + buckets = arg.parse().map_err(|e| io_error(e))?; + } + "-h" | "--help" => { + help_text(); + process::exit(0); + } + "-V" | "--version" => { + println!("histo {}", env!("CARGO_PKG_VERSION")); + process::exit(0); + } + _ => fail_with_help_text(format!("unknown CLI argument: `{arg}`")), + } + } + + let mut hist = histo::Histogram::with_buckets(buckets); let stdin = io::stdin(); let mut stdin = stdin.lock(); @@ -27,9 +120,7 @@ fn try_main() -> io::Result<()> { if line.is_empty() { continue; } - let sample: u64 = line.trim() - .parse() - .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; + let sample: u64 = line.trim().parse().map_err(|e| io_error(e))?; hist.add(sample); }