Skip to main content

trustformers_core/patterns/
config_unification.rs

1//! Configuration Unification for TrustformeRS Core
2//!
3//! This module provides unified configuration structures and patterns
4//! that standardize configuration management across all modules.
5
6#![allow(unused_variables)] // Config unification
7
8use super::{validators, ConfigSerializable, StandardConfig};
9use crate::errors::Result;
10use serde::{Deserialize, Serialize};
11use std::collections::HashMap;
12use std::path::PathBuf;
13
14/// Unified configuration base that all specific configs should inherit from
15#[derive(Debug, Clone, Serialize, Deserialize, Default)]
16pub struct UnifiedConfig {
17    /// Configuration metadata
18    pub metadata: ConfigMetadata,
19    /// Resource limitations
20    pub resources: ResourceConfig,
21    /// Logging configuration
22    pub logging: LoggingConfig,
23    /// Performance settings
24    pub performance: PerformanceConfig,
25    /// Security settings
26    pub security: SecurityConfig,
27    /// Environment-specific settings
28    pub environment: EnvironmentConfig,
29}
30
31impl StandardConfig for UnifiedConfig {
32    fn validate(&self) -> Result<()> {
33        self.metadata.validate()?;
34        self.resources.validate()?;
35        self.logging.validate()?;
36        self.performance.validate()?;
37        self.security.validate()?;
38        self.environment.validate()?;
39        Ok(())
40    }
41}
42
43/// Configuration metadata
44#[derive(Debug, Clone, Serialize, Deserialize)]
45pub struct ConfigMetadata {
46    /// Configuration name/identifier
47    pub name: String,
48    /// Human-readable description
49    pub description: Option<String>,
50    /// Configuration version
51    pub version: String,
52    /// Tags for categorization
53    pub tags: Vec<String>,
54    /// Whether this configuration is enabled
55    pub enabled: bool,
56    /// Creation timestamp
57    #[serde(default = "chrono::Utc::now")]
58    pub created_at: chrono::DateTime<chrono::Utc>,
59    /// Last modification timestamp
60    #[serde(default = "chrono::Utc::now")]
61    pub modified_at: chrono::DateTime<chrono::Utc>,
62    /// Author/creator information
63    pub author: Option<String>,
64    /// Configuration source (file, environment, default, etc.)
65    pub source: ConfigSource,
66    /// Configuration priority (higher priority configs override lower)
67    pub priority: u32,
68}
69
70impl Default for ConfigMetadata {
71    fn default() -> Self {
72        let now = chrono::Utc::now();
73        Self {
74            name: "default".to_string(),
75            description: None,
76            version: "1.0.0".to_string(),
77            tags: Vec::new(),
78            enabled: true,
79            created_at: now,
80            modified_at: now,
81            author: None,
82            source: ConfigSource::Default,
83            priority: 100,
84        }
85    }
86}
87
88impl StandardConfig for ConfigMetadata {
89    fn validate(&self) -> Result<()> {
90        validators::non_empty_string(&self.name, "name")?;
91        validators::non_empty_string(&self.version, "version")?;
92        Ok(())
93    }
94}
95
96/// Source of configuration
97#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
98pub enum ConfigSource {
99    Default,
100    File,
101    Environment,
102    Database,
103    Remote,
104    CommandLine,
105    Code,
106}
107
108/// Unified resource configuration
109#[derive(Debug, Clone, Serialize, Deserialize, Default)]
110pub struct ResourceConfig {
111    /// Memory limits
112    pub memory: MemoryLimits,
113    /// CPU limits
114    pub cpu: CpuLimits,
115    /// GPU limits
116    pub gpu: GpuLimits,
117    /// Storage limits
118    pub storage: StorageLimits,
119    /// Network limits
120    pub network: NetworkLimits,
121    /// Timeout settings
122    pub timeouts: TimeoutConfig,
123}
124
125impl StandardConfig for ResourceConfig {
126    fn validate(&self) -> Result<()> {
127        self.memory.validate()?;
128        self.cpu.validate()?;
129        self.gpu.validate()?;
130        self.storage.validate()?;
131        self.network.validate()?;
132        self.timeouts.validate()?;
133        Ok(())
134    }
135}
136
137/// Memory configuration limits
138#[derive(Debug, Clone, Serialize, Deserialize)]
139pub struct MemoryLimits {
140    /// Maximum heap memory in bytes
141    pub max_heap_bytes: Option<u64>,
142    /// Maximum GPU memory in bytes
143    pub max_gpu_bytes: Option<u64>,
144    /// Maximum shared memory in bytes
145    pub max_shared_bytes: Option<u64>,
146    /// Memory warning threshold (percentage)
147    pub warning_threshold_percent: f64,
148    /// Enable memory monitoring
149    pub monitoring_enabled: bool,
150    /// Memory pressure detection
151    pub pressure_detection: bool,
152}
153
154impl Default for MemoryLimits {
155    fn default() -> Self {
156        Self {
157            max_heap_bytes: None,
158            max_gpu_bytes: None,
159            max_shared_bytes: None,
160            warning_threshold_percent: 80.0,
161            monitoring_enabled: true,
162            pressure_detection: true,
163        }
164    }
165}
166
167impl StandardConfig for MemoryLimits {
168    fn validate(&self) -> Result<()> {
169        validators::numeric_range(
170            self.warning_threshold_percent,
171            0.0,
172            100.0,
173            "warning_threshold_percent",
174        )?;
175        Ok(())
176    }
177}
178
179/// CPU configuration limits
180#[derive(Debug, Clone, Serialize, Deserialize)]
181pub struct CpuLimits {
182    /// Maximum CPU cores to use
183    pub max_cores: Option<usize>,
184    /// CPU usage limit (percentage)
185    pub max_usage_percent: Option<f64>,
186    /// Thread pool size
187    pub thread_pool_size: Option<usize>,
188    /// CPU affinity settings
189    pub affinity: Vec<usize>,
190    /// NUMA node preferences
191    pub numa_nodes: Vec<usize>,
192}
193
194impl Default for CpuLimits {
195    fn default() -> Self {
196        Self {
197            max_cores: None,
198            max_usage_percent: Some(80.0),
199            thread_pool_size: None,
200            affinity: Vec::new(),
201            numa_nodes: Vec::new(),
202        }
203    }
204}
205
206impl StandardConfig for CpuLimits {
207    fn validate(&self) -> Result<()> {
208        if let Some(usage) = self.max_usage_percent {
209            validators::numeric_range(usage, 0.0, 100.0, "max_usage_percent")?;
210        }
211        if let Some(cores) = self.max_cores {
212            validators::positive(cores, "max_cores")?;
213        }
214        Ok(())
215    }
216}
217
218/// GPU configuration limits
219#[derive(Debug, Clone, Serialize, Deserialize)]
220pub struct GpuLimits {
221    /// Maximum number of GPUs to use
222    pub max_devices: Option<usize>,
223    /// Specific GPU device IDs to use
224    pub device_ids: Vec<usize>,
225    /// GPU memory limit per device in bytes
226    pub memory_per_device_bytes: Option<u64>,
227    /// GPU usage limit per device (percentage)
228    pub max_usage_percent: Option<f64>,
229    /// Enable GPU monitoring
230    pub monitoring_enabled: bool,
231}
232
233impl Default for GpuLimits {
234    fn default() -> Self {
235        Self {
236            max_devices: None,
237            device_ids: Vec::new(),
238            memory_per_device_bytes: None,
239            max_usage_percent: Some(90.0),
240            monitoring_enabled: true,
241        }
242    }
243}
244
245impl StandardConfig for GpuLimits {
246    fn validate(&self) -> Result<()> {
247        if let Some(usage) = self.max_usage_percent {
248            validators::numeric_range(usage, 0.0, 100.0, "max_usage_percent")?;
249        }
250        Ok(())
251    }
252}
253
254/// Storage configuration limits
255#[derive(Debug, Clone, Serialize, Deserialize)]
256pub struct StorageLimits {
257    /// Maximum disk space in bytes
258    pub max_disk_bytes: Option<u64>,
259    /// Temporary directory path
260    pub temp_dir: Option<PathBuf>,
261    /// Cache directory path
262    pub cache_dir: Option<PathBuf>,
263    /// Maximum cache size in bytes
264    pub max_cache_bytes: Option<u64>,
265    /// Disk usage warning threshold (percentage)
266    pub warning_threshold_percent: f64,
267}
268
269impl Default for StorageLimits {
270    fn default() -> Self {
271        Self {
272            max_disk_bytes: None,
273            temp_dir: Some(std::env::temp_dir()),
274            cache_dir: None,
275            max_cache_bytes: Some(1024 * 1024 * 1024), // 1GB
276            warning_threshold_percent: 85.0,
277        }
278    }
279}
280
281impl StandardConfig for StorageLimits {
282    fn validate(&self) -> Result<()> {
283        validators::numeric_range(
284            self.warning_threshold_percent,
285            0.0,
286            100.0,
287            "warning_threshold_percent",
288        )?;
289
290        if let Some(temp_dir) = &self.temp_dir {
291            if !temp_dir.exists() {
292                return Err(anyhow::anyhow!(
293                    "Temp directory does not exist: {}",
294                    temp_dir.display()
295                )
296                .into());
297            }
298        }
299
300        Ok(())
301    }
302}
303
304/// Network configuration limits
305#[derive(Debug, Clone, Serialize, Deserialize)]
306pub struct NetworkLimits {
307    /// Maximum bandwidth in bytes per second
308    pub max_bandwidth_bps: Option<u64>,
309    /// Connection timeout in milliseconds
310    pub connection_timeout_ms: u64,
311    /// Request timeout in milliseconds
312    pub request_timeout_ms: u64,
313    /// Maximum concurrent connections
314    pub max_connections: Option<usize>,
315    /// Retry attempts
316    pub max_retries: u32,
317}
318
319impl Default for NetworkLimits {
320    fn default() -> Self {
321        Self {
322            max_bandwidth_bps: None,
323            connection_timeout_ms: 30_000, // 30 seconds
324            request_timeout_ms: 300_000,   // 5 minutes
325            max_connections: Some(100),
326            max_retries: 3,
327        }
328    }
329}
330
331impl StandardConfig for NetworkLimits {
332    fn validate(&self) -> Result<()> {
333        validators::positive(self.connection_timeout_ms, "connection_timeout_ms")?;
334        validators::positive(self.request_timeout_ms, "request_timeout_ms")?;
335        Ok(())
336    }
337}
338
339/// Timeout configuration
340#[derive(Debug, Clone, Serialize, Deserialize)]
341pub struct TimeoutConfig {
342    /// Default operation timeout in milliseconds
343    pub default_timeout_ms: u64,
344    /// Training timeout in milliseconds
345    pub training_timeout_ms: Option<u64>,
346    /// Inference timeout in milliseconds
347    pub inference_timeout_ms: Option<u64>,
348    /// Export timeout in milliseconds
349    pub export_timeout_ms: Option<u64>,
350    /// Model loading timeout in milliseconds
351    pub loading_timeout_ms: Option<u64>,
352}
353
354impl Default for TimeoutConfig {
355    fn default() -> Self {
356        Self {
357            default_timeout_ms: 300_000, // 5 minutes
358            training_timeout_ms: None,
359            inference_timeout_ms: Some(30_000), // 30 seconds
360            export_timeout_ms: Some(1_800_000), // 30 minutes
361            loading_timeout_ms: Some(600_000),  // 10 minutes
362        }
363    }
364}
365
366impl StandardConfig for TimeoutConfig {
367    fn validate(&self) -> Result<()> {
368        validators::positive(self.default_timeout_ms, "default_timeout_ms")?;
369        Ok(())
370    }
371}
372
373/// Unified logging configuration
374#[derive(Debug, Clone, Serialize, Deserialize)]
375pub struct LoggingConfig {
376    /// Log level
377    pub level: LogLevel,
378    /// Log format
379    pub format: LogFormat,
380    /// Log outputs
381    pub outputs: Vec<LogOutput>,
382    /// Include timestamps
383    pub include_timestamps: bool,
384    /// Include source file information
385    pub include_source: bool,
386    /// Include thread information
387    pub include_thread: bool,
388    /// Maximum log file size in bytes
389    pub max_file_size_bytes: Option<u64>,
390    /// Maximum number of log files to keep
391    pub max_files: Option<usize>,
392    /// Log rotation strategy
393    pub rotation: LogRotation,
394    /// Structured logging fields
395    pub structured_fields: HashMap<String, String>,
396}
397
398impl Default for LoggingConfig {
399    fn default() -> Self {
400        Self {
401            level: LogLevel::Info,
402            format: LogFormat::Text,
403            outputs: vec![LogOutput::Stdout],
404            include_timestamps: true,
405            include_source: false,
406            include_thread: false,
407            max_file_size_bytes: Some(10 * 1024 * 1024), // 10 MB
408            max_files: Some(5),
409            rotation: LogRotation::Size,
410            structured_fields: HashMap::new(),
411        }
412    }
413}
414
415impl StandardConfig for LoggingConfig {}
416
417/// Log levels
418#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
419pub enum LogLevel {
420    Trace,
421    Debug,
422    Info,
423    Warn,
424    Error,
425}
426
427/// Log formats
428#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
429pub enum LogFormat {
430    Text,
431    Json,
432    Pretty,
433    Compact,
434}
435
436/// Log outputs
437#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
438pub enum LogOutput {
439    Stdout,
440    Stderr,
441    File(PathBuf),
442    Syslog,
443    Network(String),
444}
445
446/// Log rotation strategies
447#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
448pub enum LogRotation {
449    None,
450    Size,
451    Time,
452    Daily,
453    Weekly,
454}
455
456/// Performance configuration
457#[derive(Debug, Clone, Serialize, Deserialize)]
458pub struct PerformanceConfig {
459    /// Enable performance monitoring
460    pub monitoring_enabled: bool,
461    /// Profiling level
462    pub profiling_level: ProfilingLevel,
463    /// Benchmark settings
464    pub benchmarking: BenchmarkConfig,
465    /// Optimization settings
466    pub optimization: OptimizationConfig,
467    /// Cache settings
468    pub caching: CacheConfig,
469}
470
471impl Default for PerformanceConfig {
472    fn default() -> Self {
473        Self {
474            monitoring_enabled: true,
475            profiling_level: ProfilingLevel::Basic,
476            benchmarking: BenchmarkConfig::default(),
477            optimization: OptimizationConfig::default(),
478            caching: CacheConfig::default(),
479        }
480    }
481}
482
483impl StandardConfig for PerformanceConfig {}
484
485/// Profiling levels
486#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
487pub enum ProfilingLevel {
488    None,
489    Basic,
490    Detailed,
491    Comprehensive,
492}
493
494/// Benchmark configuration
495#[derive(Debug, Clone, Serialize, Deserialize)]
496pub struct BenchmarkConfig {
497    /// Enable automatic benchmarking
498    pub auto_benchmark: bool,
499    /// Benchmark frequency
500    pub frequency: BenchmarkFrequency,
501    /// Warmup iterations
502    pub warmup_iterations: usize,
503    /// Measurement iterations
504    pub measurement_iterations: usize,
505    /// Statistical confidence level
506    pub confidence_level: f64,
507}
508
509impl Default for BenchmarkConfig {
510    fn default() -> Self {
511        Self {
512            auto_benchmark: false,
513            frequency: BenchmarkFrequency::Never,
514            warmup_iterations: 3,
515            measurement_iterations: 10,
516            confidence_level: 0.95,
517        }
518    }
519}
520
521/// Benchmark frequency
522#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
523pub enum BenchmarkFrequency {
524    Never,
525    OnStartup,
526    Daily,
527    Weekly,
528    OnConfigChange,
529    OnDemand,
530}
531
532/// Optimization configuration
533#[derive(Debug, Clone, Serialize, Deserialize)]
534pub struct OptimizationConfig {
535    /// Optimization level
536    pub level: OptimizationLevel,
537    /// Enable specific optimizations
538    pub optimizations: HashMap<String, bool>,
539    /// Target hardware
540    pub target_hardware: Option<String>,
541    /// Precision settings
542    pub precision: PrecisionConfig,
543}
544
545impl Default for OptimizationConfig {
546    fn default() -> Self {
547        let mut optimizations = HashMap::new();
548        optimizations.insert("simd".to_string(), true);
549        optimizations.insert("vectorization".to_string(), true);
550        optimizations.insert("loop_unrolling".to_string(), true);
551        optimizations.insert("kernel_fusion".to_string(), true);
552
553        Self {
554            level: OptimizationLevel::Balanced,
555            optimizations,
556            target_hardware: None,
557            precision: PrecisionConfig::default(),
558        }
559    }
560}
561
562/// Optimization levels
563#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
564pub enum OptimizationLevel {
565    None,
566    Basic,
567    Balanced,
568    Aggressive,
569    Maximum,
570}
571
572/// Precision configuration
573#[derive(Debug, Clone, Serialize, Deserialize)]
574pub struct PrecisionConfig {
575    /// Default precision
576    pub default_precision: PrecisionType,
577    /// Mixed precision enabled
578    pub mixed_precision: bool,
579    /// Automatic precision selection
580    pub auto_precision: bool,
581    /// Precision loss threshold
582    pub loss_threshold: f64,
583}
584
585impl Default for PrecisionConfig {
586    fn default() -> Self {
587        Self {
588            default_precision: PrecisionType::FP32,
589            mixed_precision: false,
590            auto_precision: false,
591            loss_threshold: 1e-6,
592        }
593    }
594}
595
596/// Precision types
597#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
598pub enum PrecisionType {
599    FP16,
600    BF16,
601    FP32,
602    FP64,
603    INT8,
604    INT16,
605}
606
607/// Cache configuration
608#[derive(Debug, Clone, Serialize, Deserialize)]
609pub struct CacheConfig {
610    /// Enable caching
611    pub enabled: bool,
612    /// Cache size in bytes
613    pub size_bytes: Option<u64>,
614    /// Cache eviction policy
615    pub eviction_policy: CacheEvictionPolicy,
616    /// Cache TTL in seconds
617    pub ttl_seconds: Option<u64>,
618    /// Cache directory
619    pub cache_dir: Option<PathBuf>,
620}
621
622impl Default for CacheConfig {
623    fn default() -> Self {
624        Self {
625            enabled: true,
626            size_bytes: Some(1024 * 1024 * 1024), // 1GB
627            eviction_policy: CacheEvictionPolicy::LRU,
628            ttl_seconds: Some(3600), // 1 hour
629            cache_dir: None,
630        }
631    }
632}
633
634/// Cache eviction policies
635#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
636pub enum CacheEvictionPolicy {
637    LRU,
638    LFU,
639    FIFO,
640    Random,
641    TTL,
642}
643
644/// Security configuration
645#[derive(Debug, Clone, Serialize, Deserialize)]
646pub struct SecurityConfig {
647    /// Enable security features
648    pub enabled: bool,
649    /// Security level
650    pub level: SecurityLevel,
651    /// Encryption settings
652    pub encryption: EncryptionConfig,
653    /// Authentication settings
654    pub authentication: AuthenticationConfig,
655    /// Access control settings
656    pub access_control: AccessControlConfig,
657}
658
659impl Default for SecurityConfig {
660    fn default() -> Self {
661        Self {
662            enabled: true,
663            level: SecurityLevel::Standard,
664            encryption: EncryptionConfig::default(),
665            authentication: AuthenticationConfig::default(),
666            access_control: AccessControlConfig::default(),
667        }
668    }
669}
670
671impl StandardConfig for SecurityConfig {}
672
673/// Security levels
674#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
675pub enum SecurityLevel {
676    Minimal,
677    Standard,
678    High,
679    Maximum,
680}
681
682/// Encryption configuration
683#[derive(Debug, Clone, Serialize, Deserialize)]
684pub struct EncryptionConfig {
685    /// Enable encryption at rest
686    pub at_rest: bool,
687    /// Enable encryption in transit
688    pub in_transit: bool,
689    /// Encryption algorithm
690    pub algorithm: Option<String>,
691    /// Key management
692    pub key_management: KeyManagementConfig,
693}
694
695impl Default for EncryptionConfig {
696    fn default() -> Self {
697        Self {
698            at_rest: false,
699            in_transit: true,
700            algorithm: Some("AES-256-GCM".to_string()),
701            key_management: KeyManagementConfig::default(),
702        }
703    }
704}
705
706/// Key management configuration
707#[derive(Debug, Clone, Serialize, Deserialize)]
708pub struct KeyManagementConfig {
709    /// Key rotation enabled
710    pub rotation_enabled: bool,
711    /// Key rotation interval in days
712    pub rotation_interval_days: Option<u32>,
713    /// Key storage location
714    pub storage_location: KeyStorageLocation,
715}
716
717impl Default for KeyManagementConfig {
718    fn default() -> Self {
719        Self {
720            rotation_enabled: false,
721            rotation_interval_days: Some(90),
722            storage_location: KeyStorageLocation::Local,
723        }
724    }
725}
726
727/// Key storage locations
728#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
729pub enum KeyStorageLocation {
730    Local,
731    Environment,
732    Vault,
733    HSM,
734    Cloud,
735}
736
737/// Authentication configuration
738#[derive(Debug, Clone, Serialize, Deserialize)]
739pub struct AuthenticationConfig {
740    /// Authentication method
741    pub method: AuthenticationMethod,
742    /// Session timeout in seconds
743    pub session_timeout_seconds: Option<u64>,
744    /// Multi-factor authentication
745    pub mfa_enabled: bool,
746}
747
748impl Default for AuthenticationConfig {
749    fn default() -> Self {
750        Self {
751            method: AuthenticationMethod::None,
752            session_timeout_seconds: Some(3600), // 1 hour
753            mfa_enabled: false,
754        }
755    }
756}
757
758/// Authentication methods
759#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
760pub enum AuthenticationMethod {
761    None,
762    ApiKey,
763    JWT,
764    OAuth2,
765    LDAP,
766    SAML,
767}
768
769/// Access control configuration
770#[derive(Debug, Clone, Serialize, Deserialize)]
771pub struct AccessControlConfig {
772    /// Access control model
773    pub model: AccessControlModel,
774    /// Default permissions
775    pub default_permissions: Vec<String>,
776    /// Permission inheritance
777    pub inheritance_enabled: bool,
778}
779
780impl Default for AccessControlConfig {
781    fn default() -> Self {
782        Self {
783            model: AccessControlModel::None,
784            default_permissions: vec!["read".to_string()],
785            inheritance_enabled: true,
786        }
787    }
788}
789
790/// Access control models
791#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
792pub enum AccessControlModel {
793    None,
794    RBAC, // Role-Based Access Control
795    ABAC, // Attribute-Based Access Control
796    DAC,  // Discretionary Access Control
797    MAC,  // Mandatory Access Control
798}
799
800/// Environment configuration
801#[derive(Debug, Clone, Serialize, Deserialize)]
802pub struct EnvironmentConfig {
803    /// Environment type
804    pub environment_type: EnvironmentType,
805    /// Environment variables
806    pub variables: HashMap<String, String>,
807    /// Feature flags
808    pub feature_flags: HashMap<String, bool>,
809    /// Debug settings
810    pub debug: DebugConfig,
811}
812
813impl Default for EnvironmentConfig {
814    fn default() -> Self {
815        Self {
816            environment_type: EnvironmentType::Development,
817            variables: HashMap::new(),
818            feature_flags: HashMap::new(),
819            debug: DebugConfig::default(),
820        }
821    }
822}
823
824impl StandardConfig for EnvironmentConfig {}
825
826/// Environment types
827#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
828pub enum EnvironmentType {
829    Development,
830    Testing,
831    Staging,
832    Production,
833}
834
835/// Debug configuration
836#[derive(Debug, Clone, Serialize, Deserialize)]
837pub struct DebugConfig {
838    /// Enable debug mode
839    pub enabled: bool,
840    /// Debug level
841    pub level: DebugLevel,
842    /// Enable verbose output
843    pub verbose: bool,
844    /// Enable stack traces
845    pub stack_traces: bool,
846    /// Debug output format
847    pub output_format: DebugOutputFormat,
848}
849
850impl Default for DebugConfig {
851    fn default() -> Self {
852        Self {
853            enabled: cfg!(debug_assertions),
854            level: DebugLevel::Info,
855            verbose: false,
856            stack_traces: cfg!(debug_assertions),
857            output_format: DebugOutputFormat::Pretty,
858        }
859    }
860}
861
862/// Debug levels
863#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
864pub enum DebugLevel {
865    None,
866    Basic,
867    Info,
868    Verbose,
869    Trace,
870}
871
872/// Debug output formats
873#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
874pub enum DebugOutputFormat {
875    Plain,
876    Pretty,
877    Json,
878    Structured,
879}
880
881/// Configuration manager for handling unified configurations
882pub struct ConfigManager {
883    configs: HashMap<String, UnifiedConfig>,
884    active_config: Option<String>,
885}
886
887impl ConfigManager {
888    /// Create a new configuration manager
889    pub fn new() -> Self {
890        Self {
891            configs: HashMap::new(),
892            active_config: None,
893        }
894    }
895
896    /// Add a configuration
897    pub fn add_config(&mut self, name: String, config: UnifiedConfig) -> Result<()> {
898        config.validate()?;
899        self.configs.insert(name, config);
900        Ok(())
901    }
902
903    /// Get a configuration by name
904    pub fn get_config(&self, name: &str) -> Option<&UnifiedConfig> {
905        self.configs.get(name)
906    }
907
908    /// Set active configuration
909    pub fn set_active(&mut self, name: String) -> Result<()> {
910        if !self.configs.contains_key(&name) {
911            return Err(anyhow::anyhow!("Configuration '{}' not found", name).into());
912        }
913        self.active_config = Some(name);
914        Ok(())
915    }
916
917    /// Get active configuration
918    pub fn get_active(&self) -> Option<&UnifiedConfig> {
919        self.active_config.as_ref().and_then(|name| self.configs.get(name))
920    }
921
922    /// Merge configurations (later configs override earlier ones)
923    pub fn merge_configs(&self, names: &[String]) -> Result<UnifiedConfig> {
924        if names.is_empty() {
925            return Ok(UnifiedConfig::default());
926        }
927
928        let mut result = self
929            .get_config(&names[0])
930            .ok_or_else(|| anyhow::anyhow!("Configuration '{}' not found", names[0]))?
931            .clone();
932
933        for name in &names[1..] {
934            let config = self
935                .get_config(name)
936                .ok_or_else(|| anyhow::anyhow!("Configuration '{}' not found", name))?;
937            result = merge_unified_configs(result, config.clone())?;
938        }
939
940        Ok(result)
941    }
942
943    /// Load configuration from file
944    pub fn load_from_file(&mut self, name: String, path: &std::path::Path) -> Result<()> {
945        let config = UnifiedConfig::load_from_file(path)?;
946        self.add_config(name, config)
947    }
948
949    /// Save configuration to file
950    pub fn save_to_file(&self, name: &str, path: &std::path::Path) -> Result<()> {
951        let config = self
952            .get_config(name)
953            .ok_or_else(|| anyhow::anyhow!("Configuration '{}' not found", name))?;
954        config.save_to_file(path)
955    }
956}
957
958impl Default for ConfigManager {
959    fn default() -> Self {
960        Self::new()
961    }
962}
963
964/// Merge two unified configurations (second overrides first)
965pub fn merge_unified_configs(
966    base: UnifiedConfig,
967    override_config: UnifiedConfig,
968) -> Result<UnifiedConfig> {
969    // For now, we'll do a simple override merge
970    // In a more sophisticated implementation, we might merge nested structures
971    Ok(override_config)
972}
973
974#[cfg(test)]
975mod tests {
976    use super::*;
977    use tempfile::tempdir;
978
979    #[test]
980    fn test_unified_config_creation() {
981        let config = UnifiedConfig::default();
982        assert!(config.validate().is_ok());
983        assert_eq!(config.metadata.name, "default");
984        assert!(config.metadata.enabled);
985    }
986
987    #[test]
988    fn test_config_serialization() {
989        let config = UnifiedConfig::default();
990        let json = config.to_json().expect("operation failed in test");
991        let deserialized = UnifiedConfig::from_json(&json).expect("operation failed in test");
992
993        assert_eq!(config.metadata.name, deserialized.metadata.name);
994        assert_eq!(config.metadata.enabled, deserialized.metadata.enabled);
995    }
996
997    #[test]
998    fn test_config_manager() {
999        let mut manager = ConfigManager::new();
1000        let config = UnifiedConfig::default();
1001
1002        manager.add_config("test".to_string(), config).expect("add operation failed");
1003        manager.set_active("test".to_string()).expect("operation failed in test");
1004
1005        let active = manager.get_active().expect("operation failed in test");
1006        assert_eq!(active.metadata.name, "default");
1007    }
1008
1009    #[test]
1010    fn test_config_file_operations() {
1011        let temp_dir = tempdir().expect("temp file creation failed");
1012        let config_path = temp_dir.path().join("test_config.json");
1013
1014        let config = UnifiedConfig::default();
1015        config.save_to_file(&config_path).expect("operation failed in test");
1016
1017        let loaded_config =
1018            UnifiedConfig::load_from_file(&config_path).expect("operation failed in test");
1019        assert_eq!(config.metadata.name, loaded_config.metadata.name);
1020    }
1021
1022    #[test]
1023    fn test_validation() {
1024        let mut config = UnifiedConfig::default();
1025        config.metadata.name = "".to_string(); // Invalid empty name
1026
1027        let result = config.validate();
1028        assert!(result.is_err());
1029    }
1030
1031    #[test]
1032    fn test_resource_limits_validation() {
1033        let limits = MemoryLimits {
1034            warning_threshold_percent: 150.0, // Invalid percentage
1035            ..Default::default()
1036        };
1037
1038        let result = limits.validate();
1039        assert!(result.is_err());
1040    }
1041}