1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
//! Core traits for the configuration system.
//!
//! This module defines the fundamental traits that enable a generic and extensible
//! configuration framework. Types implementing these traits can be used with the
//! generic ConfigManager to provide configuration capabilities.
use async_trait;
use ;
use ConfigValue;
use crateConfigResult;
/// Trait for types that can be configured.
///
/// This trait must be implemented by any type that wants to be managed by the
/// configuration system. It provides methods for validation and merging.
///
/// # Example
///
/// ```
/// use serde::{Serialize, Deserialize};
/// use sublime_standard_tools::config::{Configurable, ConfigResult};
///
/// #[derive(Debug, Clone, Serialize, Deserialize)]
/// struct MyConfig {
/// name: String,
/// timeout: u64,
/// }
///
/// impl Configurable for MyConfig {
/// fn validate(&self) -> ConfigResult<()> {
/// if self.timeout == 0 {
/// return Err("Timeout must be greater than 0".into());
/// }
/// Ok(())
/// }
///
/// fn merge_with(&mut self, other: Self) -> ConfigResult<()> {
/// if !other.name.is_empty() {
/// self.name = other.name;
/// }
/// if other.timeout > 0 {
/// self.timeout = other.timeout;
/// }
/// Ok(())
/// }
/// }
/// ```
/// Trait for configuration providers.
///
/// Configuration providers are sources of configuration data. They can load
/// configuration from files, environment variables, or any other source.
///
/// # Example
///
/// ```
/// use async_trait::async_trait;
/// use sublime_standard_tools::config::{ConfigProvider, ConfigResult, ConfigValue};
/// use std::collections::HashMap;
///
/// struct MemoryProvider {
/// data: HashMap<String, ConfigValue>,
/// }
///
/// #[async_trait]
/// impl ConfigProvider for MemoryProvider {
/// async fn load(&self) -> ConfigResult<ConfigValue> {
/// Ok(ConfigValue::Map(self.data.clone()))
/// }
///
/// async fn save(&self, _value: &ConfigValue) -> ConfigResult<()> {
/// // Memory provider doesn't persist
/// Ok(())
/// }
///
/// fn name(&self) -> &str {
/// "memory"
/// }
/// }
/// ```