use std::num::NonZeroU32;
use std::str::FromStr;
use anyhow::anyhow;
use clap::builder::PossibleValue;
use clap::{ArgMatches, ValueEnum};
use ordered_float::OrderedFloat;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ErrorHandler {
Panic,
Skip,
Warn,
}
impl FromStr for ErrorHandler {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"panic" => Ok(Self::Panic),
"skip" => Ok(Self::Skip),
"warn" => Ok(Self::Warn),
_ => Err(anyhow!("invalid value for error handler")),
}
}
}
impl ValueEnum for ErrorHandler {
fn value_variants<'a>() -> &'a [Self] {
&[Self::Panic, Self::Skip, Self::Warn]
}
fn to_possible_value(&self) -> Option<PossibleValue> {
Some(match self {
Self::Panic => PossibleValue::new("panic"),
Self::Skip => PossibleValue::new("skip"),
Self::Warn => PossibleValue::new("warn"),
})
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum StandardDeviationMode {
Population,
Sample,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Config {
pub error_handler: ErrorHandler,
pub progress: Option<f64>,
pub bin_width: Option<NonZeroU32>,
pub bin_breaks: Option<Vec<f64>>,
pub sd_mode: StandardDeviationMode,
}
impl Config {
pub fn from_args(args: &ArgMatches) -> Self {
let error_handler = *args.get_one::<ErrorHandler>("handler").unwrap();
let progress = args.get_one::<u32>("progress").copied().map(f64::from);
let bin_width = args.get_one::<NonZeroU32>("bin_width").copied();
let bin_breaks = args.get_many::<f64>("bin_breaks").map(|breaks| {
let mut breaks: Vec<OrderedFloat<f64>> =
breaks.map(|value| OrderedFloat(*value)).collect();
breaks.sort_unstable();
breaks.into_iter().map(|value| value.0).collect()
});
let population = args.get_flag("population");
let sample = args.get_flag("sample");
let sd_mode = match (population, sample) {
(true, false) => StandardDeviationMode::Population,
(false, _) => StandardDeviationMode::Sample,
(true, true) => unreachable!("flags override each other"),
};
Self {
error_handler,
progress,
bin_width,
bin_breaks,
sd_mode,
}
}
}