use serde::{Deserialize, Serialize};
use crate::support::processing::template::OutputFormat;
pub(crate) fn default_true() -> bool {
true
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct GlobalConfig {
#[serde(default = "default_global_level")]
pub level: String,
#[serde(default = "default_global_format")]
pub format: String,
#[serde(default = "default_true")]
pub masking_enabled: bool,
#[serde(default = "default_true")]
pub auto_fallback: bool,
#[serde(default = "default_fallback_initial_delay")]
pub fallback_initial_delay_ms: u64,
#[serde(default = "default_fallback_max_delay")]
pub fallback_max_delay_ms: u64,
#[serde(default = "default_fallback_max_retries")]
pub fallback_max_retries: u32,
#[serde(default)]
pub output_format: OutputFormat,
}
fn default_global_level() -> String {
"info".to_string()
}
fn default_global_format() -> String {
"{timestamp} [{level}] {target} - {message}".to_string()
}
fn default_fallback_initial_delay() -> u64 {
1000
}
fn default_fallback_max_delay() -> u64 {
60000
}
fn default_fallback_max_retries() -> u32 {
10
}
impl Default for GlobalConfig {
fn default() -> Self {
Self {
level: default_global_level(),
format: default_global_format(),
masking_enabled: default_true(),
auto_fallback: default_true(),
fallback_initial_delay_ms: default_fallback_initial_delay(),
fallback_max_delay_ms: default_fallback_max_delay(),
fallback_max_retries: default_fallback_max_retries(),
output_format: OutputFormat::default(),
}
}
}
impl GlobalConfig {
pub fn validate(&mut self) {
if self.fallback_initial_delay_ms > self.fallback_max_delay_ms {
tracing::warn!("{}", crate::i18n::tr("warn-delay_clamp"));
self.fallback_initial_delay_ms = self.fallback_max_delay_ms;
}
if self.fallback_max_retries == 0 {
tracing::warn!("{}", crate::i18n::tr("warn-fallback_retries_zero"));
self.fallback_max_retries = 1;
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_values() {
let cfg = GlobalConfig::default();
assert_eq!(cfg.level, "info");
assert_eq!(cfg.format, "{timestamp} [{level}] {target} - {message}");
assert!(cfg.masking_enabled);
assert!(cfg.auto_fallback);
assert_eq!(cfg.fallback_initial_delay_ms, 1000);
assert_eq!(cfg.fallback_max_delay_ms, 60000);
assert_eq!(cfg.fallback_max_retries, 10);
}
#[test]
fn test_validate_clamps_initial_delay() {
let mut cfg = GlobalConfig::default();
cfg.fallback_initial_delay_ms = 99999;
cfg.fallback_max_delay_ms = 5000;
cfg.validate();
assert_eq!(cfg.fallback_initial_delay_ms, 5000);
}
#[test]
fn test_validate_resets_zero_retries() {
let mut cfg = GlobalConfig::default();
cfg.fallback_max_retries = 0;
cfg.validate();
assert_eq!(cfg.fallback_max_retries, 1);
}
#[test]
fn test_validate_no_change_when_valid() {
let mut cfg = GlobalConfig::default();
cfg.fallback_initial_delay_ms = 1000;
cfg.fallback_max_delay_ms = 60000;
cfg.fallback_max_retries = 3;
cfg.validate();
assert_eq!(cfg.fallback_initial_delay_ms, 1000);
assert_eq!(cfg.fallback_max_retries, 3);
}
}