use crate::commands::*; // use crate::commands::{Configurable, GlobalArgs}; use anyhow::{Context, Result}; use config::{Config, Environment, File}; use serde::Deserialize; #[derive(Debug, Deserialize, Clone)] pub struct AppConfig { #[serde(default)] pub decode: Option, #[serde(default)] pub encode: Option, #[serde(default)] pub import_dict: Option, pub log_level: String, } impl AppConfig { pub fn build(args: &GlobalArgs, handler: &dyn Configurable) -> Result { let mut builder = Config::builder(); // Command-specific defaults via Trait builder = handler.apply_defaults(builder)?; // File Layer let config_path = &args.config; let is_default_path = config_path.to_str() == Some("config.toml"); builder = builder.add_source(File::from(config_path.as_path()).required(!is_default_path)); // Environment Layer (e.g. APP_LISTEN_PORT) builder = builder.add_source(Environment::with_prefix("APP").separator("_")); // Global log level override if let Some(ref level) = args.log_level { builder = builder.set_override("log_level", level.clone())?; } // Command-specific overrides via Trait builder = handler.apply_overrides(builder)?; builder .build() .context("Failed to build configuration layers")? .try_deserialize() .context("Failed to deserialize Config") } } // TODO: move? #[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)] pub enum System { #[serde(rename = "major_en")] MajorEn, #[serde(rename = "major_pl")] MajorPl, } // from: impl From<&str> for System { fn from(s: &str) -> Self { match s { "major_en" => System::MajorEn, "major_pl" => System::MajorPl, _ => panic!("Unknown system: {}", s), } } }