markdown_translator/
simple_config.rs

1//! 简化的翻译配置管理模块
2//!
3//! 这个模块提供了一个精简的配置管理系统,专注于核心配置功能,
4//! 使用函数式编程风格和建造者模式。
5//!
6//! ## 设计原则
7//!
8//! - **简单优先**: 只保留最核心的配置选项
9//! - **函数式**: 使用不可变配置和建造者模式
10//! - **易于使用**: 提供合理的默认值和链式配置API
11//! - **类型安全**: 编译时检查配置的有效性
12
13use serde::{Deserialize, Serialize};
14use std::time::Duration;
15
16// ============================================================================
17// 核心配置结构
18// ============================================================================
19
20/// 简化的翻译配置
21#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
22pub struct SimpleTranslationConfig {
23    /// 是否启用翻译
24    pub enabled: bool,
25    /// 目标语言
26    pub target_lang: String,
27    /// 源语言(默认"auto"自动检测)
28    pub source_lang: String,
29    /// API地址
30    pub api_url: String,
31    /// 请求频率限制(每秒)
32    pub requests_per_second: f64,
33    /// 最大文本长度
34    pub max_text_length: usize,
35    /// 是否启用缓存
36    pub cache_enabled: bool,
37    /// 缓存TTL(秒)
38    pub cache_ttl_seconds: u64,
39}
40
41impl Default for SimpleTranslationConfig {
42    fn default() -> Self {
43        Self {
44            enabled: true,
45            target_lang: "zh".to_string(),
46            source_lang: "auto".to_string(),
47            api_url: "http://localhost:1188/translate".to_string(),
48            requests_per_second: 1.0,
49            max_text_length: 3000,
50            cache_enabled: true,
51            cache_ttl_seconds: 3600,
52        }
53    }
54}
55
56impl SimpleTranslationConfig {
57    /// 创建配置构建器
58    pub fn builder() -> ConfigBuilder {
59        ConfigBuilder::new()
60    }
61
62    /// 从环境变量创建配置
63    pub fn from_env() -> Self {
64        let mut config = Self::default();
65        
66        if let Ok(enabled) = std::env::var("TRANSLATION_ENABLED") {
67            config.enabled = enabled.parse().unwrap_or(true);
68        }
69        
70        if let Ok(target_lang) = std::env::var("TRANSLATION_TARGET_LANG") {
71            config.target_lang = target_lang;
72        }
73        
74        if let Ok(source_lang) = std::env::var("TRANSLATION_SOURCE_LANG") {
75            config.source_lang = source_lang;
76        }
77        
78        if let Ok(api_url) = std::env::var("TRANSLATION_API_URL") {
79            config.api_url = api_url;
80        }
81        
82        if let Ok(rate) = std::env::var("TRANSLATION_REQUESTS_PER_SECOND") {
83            config.requests_per_second = rate.parse().unwrap_or(1.0);
84        }
85        
86        if let Ok(max_len) = std::env::var("TRANSLATION_MAX_TEXT_LENGTH") {
87            config.max_text_length = max_len.parse().unwrap_or(3000);
88        }
89        
90        if let Ok(cache_enabled) = std::env::var("TRANSLATION_CACHE_ENABLED") {
91            config.cache_enabled = cache_enabled.parse().unwrap_or(true);
92        }
93        
94        if let Ok(cache_ttl) = std::env::var("TRANSLATION_CACHE_TTL_SECONDS") {
95            config.cache_ttl_seconds = cache_ttl.parse().unwrap_or(3600);
96        }
97        
98        config
99    }
100
101    /// 快速创建配置
102    pub fn quick(target_lang: &str, api_url: Option<&str>) -> Self {
103        Self {
104            target_lang: target_lang.to_string(),
105            api_url: api_url.unwrap_or("http://localhost:1188/translate").to_string(),
106            ..Default::default()
107        }
108    }
109
110    /// 验证配置有效性
111    pub fn validate(&self) -> Result<(), String> {
112        if self.target_lang.is_empty() {
113            return Err("Target language cannot be empty".to_string());
114        }
115        
116        if self.api_url.is_empty() {
117            return Err("API URL cannot be empty".to_string());
118        }
119        
120        if self.requests_per_second <= 0.0 {
121            return Err("Requests per second must be positive".to_string());
122        }
123        
124        if self.max_text_length == 0 {
125            return Err("Max text length must be positive".to_string());
126        }
127        
128        Ok(())
129    }
130
131    /// 获取请求间隔时间
132    pub fn request_interval(&self) -> Duration {
133        Duration::from_secs_f64(1.0 / self.requests_per_second)
134    }
135
136    /// 获取缓存TTL时长
137    pub fn cache_ttl(&self) -> Duration {
138        Duration::from_secs(self.cache_ttl_seconds)
139    }
140}
141
142// ============================================================================
143// 配置构建器
144// ============================================================================
145
146/// 配置构建器,提供链式API
147#[derive(Debug)]
148pub struct ConfigBuilder {
149    config: SimpleTranslationConfig,
150}
151
152impl ConfigBuilder {
153    pub fn new() -> Self {
154        Self {
155            config: SimpleTranslationConfig::default(),
156        }
157    }
158
159    /// 设置是否启用翻译
160    pub fn enabled(mut self, enabled: bool) -> Self {
161        self.config.enabled = enabled;
162        self
163    }
164
165    /// 设置目标语言
166    pub fn target_lang<S: Into<String>>(mut self, lang: S) -> Self {
167        self.config.target_lang = lang.into();
168        self
169    }
170
171    /// 设置源语言
172    pub fn source_lang<S: Into<String>>(mut self, lang: S) -> Self {
173        self.config.source_lang = lang.into();
174        self
175    }
176
177    /// 设置API地址
178    pub fn api_url<S: Into<String>>(mut self, url: S) -> Self {
179        self.config.api_url = url.into();
180        self
181    }
182
183    /// 设置请求频率
184    pub fn requests_per_second(mut self, rate: f64) -> Self {
185        self.config.requests_per_second = rate;
186        self
187    }
188
189    /// 设置最大文本长度
190    pub fn max_text_length(mut self, length: usize) -> Self {
191        self.config.max_text_length = length;
192        self
193    }
194
195    /// 设置缓存启用状态
196    pub fn cache_enabled(mut self, enabled: bool) -> Self {
197        self.config.cache_enabled = enabled;
198        self
199    }
200
201    /// 设置缓存TTL
202    pub fn cache_ttl_seconds(mut self, seconds: u64) -> Self {
203        self.config.cache_ttl_seconds = seconds;
204        self
205    }
206
207    /// 构建配置
208    pub fn build(self) -> Result<SimpleTranslationConfig, String> {
209        self.config.validate()?;
210        Ok(self.config)
211    }
212
213    /// 构建配置(不验证)
214    pub fn build_unchecked(self) -> SimpleTranslationConfig {
215        self.config
216    }
217}
218
219impl Default for ConfigBuilder {
220    fn default() -> Self {
221        Self::new()
222    }
223}
224
225// ============================================================================
226// 配置管理器
227// ============================================================================
228
229/// 简化的配置管理器
230pub struct SimpleConfigManager {
231    config: SimpleTranslationConfig,
232}
233
234impl SimpleConfigManager {
235    /// 从默认配置创建
236    pub fn new() -> Self {
237        Self {
238            config: SimpleTranslationConfig::default(),
239        }
240    }
241
242    /// 从配置创建
243    pub fn with_config(config: SimpleTranslationConfig) -> Self {
244        Self { config }
245    }
246
247    /// 从环境变量创建
248    pub fn from_env() -> Self {
249        Self {
250            config: SimpleTranslationConfig::from_env(),
251        }
252    }
253
254    /// 获取配置的引用
255    pub fn config(&self) -> &SimpleTranslationConfig {
256        &self.config
257    }
258
259    /// 获取配置的克隆
260    pub fn config_cloned(&self) -> SimpleTranslationConfig {
261        self.config.clone()
262    }
263
264    /// 更新配置
265    pub fn update_config(&mut self, config: SimpleTranslationConfig) {
266        self.config = config;
267    }
268
269    /// 使用配置构建器更新
270    pub fn update_with_builder<F>(&mut self, f: F) -> Result<(), String>
271    where
272        F: FnOnce(ConfigBuilder) -> ConfigBuilder,
273    {
274        let builder = ConfigBuilder {
275            config: self.config.clone(),
276        };
277        let new_config = f(builder).build()?;
278        self.config = new_config;
279        Ok(())
280    }
281
282    /// 验证当前配置
283    pub fn validate(&self) -> Result<(), String> {
284        self.config.validate()
285    }
286}
287
288impl Default for SimpleConfigManager {
289    fn default() -> Self {
290        Self::new()
291    }
292}
293
294// ============================================================================
295// 便利函数
296// ============================================================================
297
298/// 创建快速配置
299pub fn quick_config(target_lang: &str, api_url: Option<&str>) -> SimpleTranslationConfig {
300    SimpleTranslationConfig::quick(target_lang, api_url)
301}
302
303/// 创建配置构建器
304pub fn config_builder() -> ConfigBuilder {
305    ConfigBuilder::new()
306}
307
308/// 从环境变量加载配置
309pub fn load_config_from_env() -> SimpleTranslationConfig {
310    SimpleTranslationConfig::from_env()
311}
312
313/// 验证配置
314pub fn validate_config(config: &SimpleTranslationConfig) -> Result<(), String> {
315    config.validate()
316}
317
318// ============================================================================
319// 预设配置
320// ============================================================================
321
322/// 预设配置模块
323pub mod presets {
324    use super::*;
325
326    /// 开发环境配置
327    pub fn development() -> SimpleTranslationConfig {
328        SimpleTranslationConfig {
329            enabled: true,
330            target_lang: "zh".to_string(),
331            source_lang: "auto".to_string(),
332            api_url: "http://localhost:1188/translate".to_string(),
333            requests_per_second: 2.0,
334            max_text_length: 1000,
335            cache_enabled: true,
336            cache_ttl_seconds: 1800, // 30分钟
337        }
338    }
339
340    /// 生产环境配置
341    pub fn production() -> SimpleTranslationConfig {
342        SimpleTranslationConfig {
343            enabled: true,
344            target_lang: "zh".to_string(),
345            source_lang: "auto".to_string(),
346            api_url: "http://localhost:1188/translate".to_string(),
347            requests_per_second: 1.0,
348            max_text_length: 3000,
349            cache_enabled: true,
350            cache_ttl_seconds: 3600, // 1小时
351        }
352    }
353
354    /// 测试环境配置
355    pub fn testing() -> SimpleTranslationConfig {
356        SimpleTranslationConfig {
357            enabled: false, // 测试时默认禁用
358            target_lang: "zh".to_string(),
359            source_lang: "auto".to_string(),
360            api_url: "http://localhost:1188/translate".to_string(),
361            requests_per_second: 10.0, // 测试时允许高频率
362            max_text_length: 500,
363            cache_enabled: false, // 测试时禁用缓存
364            cache_ttl_seconds: 300, // 5分钟
365        }
366    }
367
368    /// 高性能配置
369    pub fn high_performance() -> SimpleTranslationConfig {
370        SimpleTranslationConfig {
371            enabled: true,
372            target_lang: "zh".to_string(),
373            source_lang: "auto".to_string(),
374            api_url: "http://localhost:1188/translate".to_string(),
375            requests_per_second: 5.0,
376            max_text_length: 5000,
377            cache_enabled: true,
378            cache_ttl_seconds: 7200, // 2小时
379        }
380    }
381}
382
383// ============================================================================
384// 测试
385// ============================================================================
386
387#[cfg(test)]
388mod tests {
389    use super::*;
390
391    #[test]
392    fn test_default_config() {
393        let config = SimpleTranslationConfig::default();
394        assert!(config.enabled);
395        assert_eq!(config.target_lang, "zh");
396        assert_eq!(config.source_lang, "auto");
397        assert!(config.validate().is_ok());
398    }
399
400    #[test]
401    fn test_config_builder() {
402        let config = ConfigBuilder::new()
403            .target_lang("en")
404            .api_url("http://example.com/translate")
405            .requests_per_second(2.0)
406            .build()
407            .unwrap();
408
409        assert_eq!(config.target_lang, "en");
410        assert_eq!(config.api_url, "http://example.com/translate");
411        assert_eq!(config.requests_per_second, 2.0);
412    }
413
414    #[test]
415    fn test_quick_config() {
416        let config = SimpleTranslationConfig::quick("ja", Some("http://api.example.com"));
417        assert_eq!(config.target_lang, "ja");
418        assert_eq!(config.api_url, "http://api.example.com");
419    }
420
421    #[test]
422    fn test_config_validation() {
423        let mut config = SimpleTranslationConfig::default();
424        assert!(config.validate().is_ok());
425
426        config.target_lang = "".to_string();
427        assert!(config.validate().is_err());
428
429        config.target_lang = "zh".to_string();
430        config.requests_per_second = -1.0;
431        assert!(config.validate().is_err());
432    }
433
434    #[test]
435    fn test_config_manager() {
436        let mut manager = SimpleConfigManager::new();
437        assert!(manager.validate().is_ok());
438
439        let result = manager.update_with_builder(|builder| {
440            builder.target_lang("ko").requests_per_second(3.0)
441        });
442        assert!(result.is_ok());
443        assert_eq!(manager.config().target_lang, "ko");
444        assert_eq!(manager.config().requests_per_second, 3.0);
445    }
446
447    #[test]
448    fn test_presets() {
449        let dev_config = presets::development();
450        assert!(dev_config.enabled);
451        assert_eq!(dev_config.requests_per_second, 2.0);
452
453        let prod_config = presets::production();
454        assert_eq!(prod_config.max_text_length, 3000);
455
456        let test_config = presets::testing();
457        assert!(!test_config.enabled);
458        assert!(!test_config.cache_enabled);
459    }
460
461    #[test]
462    fn test_convenience_functions() {
463        let config = quick_config("fr", Some("http://api.example.com"));
464        assert_eq!(config.target_lang, "fr");
465
466        let builder = config_builder().target_lang("de");
467        let config = builder.build().unwrap();
468        assert_eq!(config.target_lang, "de");
469    }
470
471    #[test]
472    fn test_duration_helpers() {
473        let config = SimpleTranslationConfig::default();
474        let interval = config.request_interval();
475        assert_eq!(interval, Duration::from_secs(1));
476
477        let ttl = config.cache_ttl();
478        assert_eq!(ttl, Duration::from_secs(3600));
479    }
480}