mod args;
mod config;
use args::{ArgParseError, ArgVals};
use indexmap::{indexset, IndexSet};
use std::{error::Error, path::PathBuf};
use crate::{
constants::CONFIG_FILE_PATH,
convert::{InputConverterType, OutputConverterType},
};
use config::Config;
#[derive(Debug, PartialEq)]
pub struct Opts {
pub input: String,
pub inconvs: IndexSet<InputConverterType>,
pub outconvs: IndexSet<OutputConverterType>,
}
impl Opts {
pub fn build(args: &[String]) -> Result<Self, OptsBuildError> {
let file_path = dirs::home_dir().unwrap().join(CONFIG_FILE_PATH);
let config = Config::from_file(&PathBuf::from(file_path))
.map_err(|err| OptsBuildError::Config(err))?;
let argvals = ArgVals::from_args(args)?;
Ok(opts_build_internal(config, argvals))
}
}
fn opts_build_internal(config: Config, args: ArgVals) -> Opts {
let outconvs = if let Some(outconvs) = args.outconvs {
outconvs
} else {
config.default_outconvs.into_iter().collect()
};
let inconvs = if let Some(inconv) = args.inconv {
indexset![inconv]
} else {
config.default_inconvs.into_iter().collect()
};
Opts {
input: args.input,
inconvs,
outconvs,
}
}
pub enum OptsBuildError<'a> {
Args(ArgParseError<'a>),
Config(Box<dyn Error>),
}
impl<'a> OptsBuildError<'a> {
pub fn graceful_exit(&self) -> bool {
if let Self::Args(ArgParseError::GracefulExit) = self {
true
} else {
false
}
}
}
impl<'a> From<ArgParseError<'a>> for OptsBuildError<'a> {
fn from(value: ArgParseError<'a>) -> Self {
Self::Args(value)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn opts_build_internal_ok() {
let tests = [
(
Config {
default_outconvs: vec![
OutputConverterType::HEX,
OutputConverterType::BIN,
OutputConverterType::DEC,
],
default_inconvs: vec![
InputConverterType::HEX,
InputConverterType::BIN,
InputConverterType::DEC,
],
},
ArgVals {
input: "test123".to_string(),
inconv: None,
outconvs: None,
},
Opts {
input: "test123".to_string(),
inconvs: indexset![
InputConverterType::HEX,
InputConverterType::BIN,
InputConverterType::DEC,
],
outconvs: indexset![
OutputConverterType::HEX,
OutputConverterType::BIN,
OutputConverterType::DEC,
],
},
),
(
Config {
default_outconvs: vec![
OutputConverterType::HEX,
OutputConverterType::BIN,
OutputConverterType::DEC,
],
default_inconvs: vec![
InputConverterType::HEX,
InputConverterType::BIN,
InputConverterType::DEC,
],
},
ArgVals {
input: "test123".to_string(),
inconv: Some(InputConverterType::BIN),
outconvs: Some(indexset![
OutputConverterType::HEX,
OutputConverterType::BIN
]),
},
Opts {
input: "test123".to_string(),
inconvs: indexset![InputConverterType::BIN],
outconvs: indexset![OutputConverterType::HEX, OutputConverterType::BIN],
},
),
];
for (config, args, exp) in tests {
assert_eq!(opts_build_internal(config, args), exp);
}
}
}