use std::path::PathBuf;
use clap::Parser;
use serde::{Deserialize, Serialize};
use v_utils_macros::{Settings, SettingsNested};
#[derive(Clone, Debug, Default, Deserialize, Serialize, SettingsNested)]
#[allow(unused)]
pub struct Database {
#[serde(default)]
url: String,
#[serde(default)]
max_connections: u32,
#[settings(flatten)]
#[serde(default)]
pool: Pool,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize, SettingsNested)]
#[settings(prefix = "database_pool")]
#[allow(unused)]
pub struct Pool {
#[serde(default)]
min_size: u32,
#[serde(default)]
max_size: u32,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize, SettingsNested)]
#[allow(unused)]
pub struct RiskTiers {
#[serde(default)]
a: String,
#[serde(default)]
b: String,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize, SettingsNested)]
#[allow(unused)]
pub struct Logging {
#[serde(default)]
level: String,
#[serde(default)]
file: Option<String>,
}
#[derive(Debug, Parser)]
#[allow(unused)]
struct Cli {
#[clap(flatten)]
settings_flags: SettingsFlags,
}
#[test]
fn test() {
let flags = SettingsFlags {
config: None,
yes: false,
host: Some("localhost".to_string()),
port: Some("8080".to_string()),
debug: Some(true),
workers: Some("4".to_string()),
database: __SettingsNestedDatabase {
database_url: Some("postgres://localhost".to_string()),
database_max_connections: Some("10".to_string()),
pool: __SettingsNestedPool {
database_pool_min_size: Some("5".to_string()),
database_pool_max_size: Some("20".to_string()),
},
},
risk_tiers: __SettingsNestedRiskTiers {
risk_tiers_a: Some("0.01".to_string()),
risk_tiers_b: Some("0.02".to_string()),
},
logging: __SettingsNestedLogging {
logging_level: Some("debug".to_string()),
logging_file: Some("/var/log/app.log".to_string()),
},
};
assert_eq!(flags.host, Some("localhost".to_string()));
assert_eq!(flags.port, Some("8080".to_string()));
assert_eq!(flags.debug, Some(true));
assert_eq!(flags.workers, Some("4".to_string()));
assert_eq!(flags.database.database_url, Some("postgres://localhost".to_string()));
assert_eq!(flags.database.database_max_connections, Some("10".to_string()));
assert_eq!(flags.risk_tiers.risk_tiers_a, Some("0.01".to_string()));
assert_eq!(flags.risk_tiers.risk_tiers_b, Some("0.02".to_string()));
let _build_exists: fn(SettingsFlags) -> Result<AppConfig, v_utils::__internal::SettingsError> = AppConfig::try_build;
let _test_skip: fn() = || {
let _flags_without_internal_state = SettingsFlags {
config: None,
yes: false,
host: None,
port: None,
debug: None,
workers: None,
database: __SettingsNestedDatabase {
database_url: None,
database_max_connections: None,
pool: __SettingsNestedPool {
database_pool_min_size: None,
database_pool_max_size: None,
},
},
risk_tiers: __SettingsNestedRiskTiers {
risk_tiers_a: None,
risk_tiers_b: None,
},
logging: __SettingsNestedLogging {
logging_level: None,
logging_file: None,
},
};
};
eprintln!("\n=== Testing unknown field warning ===");
let flags_with_config = SettingsFlags {
config: Some(v_utils::io::ExpandedPath(PathBuf::from("tests/test_unknown_field.toml"))),
yes: false,
host: None,
port: None,
debug: None,
workers: None,
database: __SettingsNestedDatabase {
database_url: None,
database_max_connections: None,
pool: __SettingsNestedPool {
database_pool_min_size: None,
database_pool_max_size: None,
},
},
risk_tiers: __SettingsNestedRiskTiers {
risk_tiers_a: None,
risk_tiers_b: None,
},
logging: __SettingsNestedLogging {
logging_level: None,
logging_file: None,
},
};
match AppConfig::try_build(flags_with_config) {
Ok(_config) => {
eprintln!("Config loaded successfully (unknown fields should have triggered warnings above)");
}
Err(e) => {
eprintln!("Note: Config loading skipped ({e})");
}
}
eprintln!("=== End of unknown field warning test ===\n");
}
#[derive(Clone, Debug, Default, v_utils_macros::MyConfigPrimitives, Settings)]
#[allow(unused)]
struct AppConfig {
#[serde(default)]
host: String,
#[serde(default)]
port: u16,
#[serde(default)]
debug: bool,
#[serde(default)]
workers: Option<usize>,
#[settings(flatten)]
#[serde(default)]
database: Database,
#[settings(flatten)]
#[serde(default)]
risk_tiers: RiskTiers,
#[settings(flatten)]
#[serde(default)]
logging: Option<Logging>,
#[settings(skip(flag))]
#[serde(default)]
internal_state: String,
}