trustformers_core/patterns/
mod.rs1pub mod builder;
8pub mod config_unification;
9
10pub use builder::{
11 Buildable, Builder, BuilderError, BuilderResult, ConfigBuilder, ConfigBuilderImpl,
12 ConfigSerializable, StandardBuilder, StandardConfig, ValidatedBuilder,
13};
14
15pub use config_unification::{
16 merge_unified_configs, AccessControlConfig, AccessControlModel, AuthenticationConfig,
17 AuthenticationMethod, BenchmarkConfig, BenchmarkFrequency, CacheConfig, CacheEvictionPolicy,
18 ConfigManager, ConfigMetadata, ConfigSource, CpuLimits, DebugConfig, DebugLevel,
19 DebugOutputFormat, EncryptionConfig, EnvironmentConfig, EnvironmentType, GpuLimits,
20 KeyManagementConfig, KeyStorageLocation, LogFormat, LogLevel, LogOutput, LogRotation,
21 LoggingConfig, MemoryLimits, NetworkLimits, OptimizationConfig, OptimizationLevel,
22 PerformanceConfig, PrecisionConfig, PrecisionType, ProfilingLevel, ResourceConfig,
23 SecurityConfig, SecurityLevel, StorageLimits, TimeoutConfig, UnifiedConfig,
24};
25
26pub use crate::{builder_methods, quick_builder};
28
29pub type PatternResult<T> = std::result::Result<T, PatternError>;
31
32#[derive(Debug, thiserror::Error)]
34pub enum PatternError {
35 #[error("Builder error: {0}")]
36 Builder(#[from] BuilderError),
37 #[error("Validation error: {reason}")]
38 Validation { reason: String },
39 #[error("Configuration error: {reason}")]
40 Configuration { reason: String },
41 #[error("Serialization error: {0}")]
42 Serialization(#[from] serde_json::Error),
43 #[error("IO error: {0}")]
44 Io(#[from] std::io::Error),
45}
46
47pub mod validators {
49
50 use crate::errors::Result;
51
52 pub fn non_empty_string(value: &str, field_name: &str) -> Result<()> {
54 if value.trim().is_empty() {
55 return Err(crate::errors::TrustformersError::invalid_config(format!(
56 "Field '{}' cannot be empty",
57 field_name
58 )));
59 }
60 Ok(())
61 }
62
63 pub fn numeric_range<T: PartialOrd + std::fmt::Display>(
65 value: T,
66 min: T,
67 max: T,
68 field_name: &str,
69 ) -> Result<()> {
70 if value < min || value > max {
71 return Err(crate::errors::TrustformersError::invalid_config(format!(
72 "Field '{}' value {} must be between {} and {}",
73 field_name, value, min, max
74 )));
75 }
76 Ok(())
77 }
78
79 pub fn positive<T: PartialOrd + Default + std::fmt::Display>(
81 value: T,
82 field_name: &str,
83 ) -> Result<()> {
84 if value <= T::default() {
85 return Err(crate::errors::TrustformersError::invalid_config(format!(
86 "Field '{}' value {} must be positive",
87 field_name, value
88 )));
89 }
90 Ok(())
91 }
92
93 pub fn non_empty_collection<T>(collection: &[T], field_name: &str) -> Result<()> {
95 if collection.is_empty() {
96 return Err(crate::errors::TrustformersError::invalid_config(format!(
97 "Field '{}' cannot be empty",
98 field_name
99 )));
100 }
101 Ok(())
102 }
103
104 pub fn path_exists(path: &std::path::Path, field_name: &str) -> Result<()> {
106 if !path.exists() {
107 return Err(crate::errors::TrustformersError::invalid_config(format!(
108 "Path '{}' for field '{}' does not exist",
109 path.display(),
110 field_name
111 )));
112 }
113 Ok(())
114 }
115}
116
117pub mod config_patterns {
119 use super::*;
120 use serde::{Deserialize, Serialize};
121
122 #[derive(Debug, Clone, Serialize, Deserialize)]
124 pub struct BaseConfig {
125 pub name: Option<String>,
127 pub description: Option<String>,
129 pub version: String,
131 pub tags: Vec<String>,
133 pub enabled: bool,
135 #[serde(default = "chrono::Utc::now")]
137 pub created_at: chrono::DateTime<chrono::Utc>,
138 #[serde(default = "chrono::Utc::now")]
140 pub modified_at: chrono::DateTime<chrono::Utc>,
141 }
142
143 impl Default for BaseConfig {
144 fn default() -> Self {
145 let now = chrono::Utc::now();
146 Self {
147 name: None,
148 description: None,
149 version: "1.0.0".to_string(),
150 tags: Vec::new(),
151 enabled: true,
152 created_at: now,
153 modified_at: now,
154 }
155 }
156 }
157
158 impl StandardConfig for BaseConfig {
159 fn validate(&self) -> crate::errors::Result<()> {
160 if let Some(name) = &self.name {
161 validators::non_empty_string(name, "name")?;
162 }
163 Ok(())
164 }
165 }
166
167 #[derive(Debug, Clone, Serialize, Deserialize)]
169 pub struct ResourceLimits {
170 pub max_memory_bytes: Option<usize>,
172 pub max_cpu_percent: Option<f64>,
174 pub max_gpu_memory_bytes: Option<usize>,
176 pub timeout_ms: Option<u64>,
178 pub max_concurrent: Option<usize>,
180 }
181
182 impl Default for ResourceLimits {
183 fn default() -> Self {
184 Self {
185 max_memory_bytes: None,
186 max_cpu_percent: Some(80.0),
187 max_gpu_memory_bytes: None,
188 timeout_ms: Some(300_000), max_concurrent: Some(4),
190 }
191 }
192 }
193
194 impl StandardConfig for ResourceLimits {
195 fn validate(&self) -> crate::errors::Result<()> {
196 if let Some(cpu) = self.max_cpu_percent {
197 validators::numeric_range(cpu, 0.0, 100.0, "max_cpu_percent")?;
198 }
199 if let Some(concurrent) = self.max_concurrent {
200 validators::positive(concurrent, "max_concurrent")?;
201 }
202 Ok(())
203 }
204 }
205
206 #[derive(Debug, Clone, Serialize, Deserialize)]
208 pub struct LoggingConfig {
209 pub level: String,
211 pub format: String,
213 pub output: String,
215 pub include_timestamps: bool,
217 pub include_source: bool,
219 pub max_file_size_bytes: Option<usize>,
221 pub max_files: Option<usize>,
223 }
224
225 impl Default for LoggingConfig {
226 fn default() -> Self {
227 Self {
228 level: "info".to_string(),
229 format: "text".to_string(),
230 output: "stdout".to_string(),
231 include_timestamps: true,
232 include_source: false,
233 max_file_size_bytes: Some(10 * 1024 * 1024), max_files: Some(5),
235 }
236 }
237 }
238
239 impl StandardConfig for LoggingConfig {
240 fn validate(&self) -> crate::errors::Result<()> {
241 let valid_levels = ["trace", "debug", "info", "warn", "error"];
242 if !valid_levels.contains(&self.level.as_str()) {
243 return Err(crate::errors::TrustformersError::invalid_config(format!(
244 "Invalid log level '{}'. Must be one of: {}",
245 self.level,
246 valid_levels.join(", ")
247 )));
248 }
249
250 let valid_formats = ["json", "text", "pretty"];
251 if !valid_formats.contains(&self.format.as_str()) {
252 return Err(crate::errors::TrustformersError::invalid_config(format!(
253 "Invalid log format '{}'. Must be one of: {}",
254 self.format,
255 valid_formats.join(", ")
256 )));
257 }
258
259 Ok(())
260 }
261 }
262}
263
264pub mod examples {
266 use super::*;
267 use serde::{Deserialize, Serialize};
268
269 #[derive(Debug, Clone, Default, Serialize, Deserialize)]
270 pub struct ExampleConfig {
271 pub base: config_patterns::BaseConfig,
272 pub resources: config_patterns::ResourceLimits,
273 pub logging: config_patterns::LoggingConfig,
274 pub custom_setting: String,
275 }
276
277 impl StandardConfig for ExampleConfig {
278 fn validate(&self) -> crate::errors::Result<()> {
279 self.base.validate()?;
280 self.resources.validate()?;
281 self.logging.validate()?;
282 validators::non_empty_string(&self.custom_setting, "custom_setting")?;
283 Ok(())
284 }
285 }
286
287 pub fn example_config_builder() -> ConfigBuilderImpl<ExampleConfig, ExampleConfig> {
289 ConfigBuilderImpl::new()
290 }
291
292 #[allow(dead_code)]
294 pub fn example_usage() -> crate::errors::Result<ExampleConfig> {
295 let config = ExampleConfig {
296 custom_setting: "example_value".to_string(),
297 ..Default::default()
298 };
299
300 let builder = example_config_builder()
301 .config(config)
302 .name("example_configuration")
303 .description("An example of using standardized builder patterns")
304 .tag("example")
305 .tag("documentation");
306
307 builder.build()
308 }
309}