//! # Config settings definitions //! To load config values from TOML file path, it can be provided via command-line arguments
//! It use [serde](https://serde.rs/) via [`load_from_file`] // use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; // ,Deserializer,Serializer}; use std::io::{Error, ErrorKind, Result}; use crate::{defs::CliSettings, CFG_FILE_EXTENSION, DEFAULT_INPUT_PATH, DEFAULT_REG_EXP}; fn default_config_input() -> String { String::from("input.txt") } fn default_config_output() -> String { String::from("") } fn default_config_overwrite() -> bool { true } fn default_config_be_quiet() -> bool { false } fn default_config_reg_exp() -> String { String::from(DEFAULT_REG_EXP) } fn default_config_targets() -> Vec { vec![ConfigTarget::default()] } /// Settings for each target metric defined in **config path** /// **config.toml** content example: /// ```toml /// be_quiet = false /// [[targets]] /// input = "input.txt" /// /// [[targets]] /// input = "input_2.txt" /// ``` #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ConfigTarget { #[serde(default = "default_config_input")] pub input: String, #[serde(default = "default_config_output")] pub output: String, #[serde(default = "default_config_overwrite")] pub out_overwrite: bool, #[serde(default = "default_config_reg_exp")] pub reg_exp: String, } impl Default for ConfigTarget { fn default() -> Self { Self { input: String::from(DEFAULT_INPUT_PATH), output: String::from(""), out_overwrite: true, reg_exp: String::from(DEFAULT_REG_EXP), } } } /// Config Settings with target metric settings [`ConfigTarget`] /// **config.toml** content example: /// ```toml /// be_quiet = false /// [[targets]] /// input = "input.txt" /// /// [[targets]] /// input = "input_2.txt" /// ``` #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Config { #[serde(default = "default_config_be_quiet")] pub be_quiet: bool, #[serde(default = "default_config_targets")] pub targets: Vec, } impl Default for Config { fn default() -> Self { Self { be_quiet: false, targets: vec![ConfigTarget::default()], } } } impl Config { // To override [`Config`] values with [`CliSettings`] provided via command line arguments and loaded via [`parse_args`] pub fn add_cli_settings(&self, cli_settings: CliSettings) -> Self { let be_quiet = if let Some(be_quiet) = cli_settings.be_quiet { be_quiet } else { self.be_quiet }; let targets = if let Some(input) = cli_settings.input { let mut target = ConfigTarget { input, ..Default::default() }; if let Some(output) = cli_settings.output { target.output = output } vec![target] } else { self.targets.to_owned() }; Self { be_quiet, targets } } } /// To load config settings and **Deserialize** content to [`Config`] struct
/// It use **T** as generic, allowing to load from a file to a **T** type /// It use **fs::read_to_string** as it is expecting short files size, no need to buffers. pub fn load_from_file(file_cfg: &str) -> Result { let file_path = if file_cfg.contains(CFG_FILE_EXTENSION) { file_cfg.to_string() } else { format!("{}{}", file_cfg, CFG_FILE_EXTENSION) }; let config_content = match std::fs::read_to_string(&file_path) { Ok(cfgcontent) => cfgcontent, Err(e) => { return Err(Error::new( ErrorKind::InvalidInput, format!("Error read {}: {}", &file_path, e), )) } }; let item_cfg = match toml::from_str::(&config_content) { Ok(cfg) => cfg, Err(e) => { return Err(Error::new( ErrorKind::InvalidInput, format!("Error loading config {}: {}", &file_path, e), )) } }; Ok(item_cfg) }