translation_lib/
config.rs

1//! 配置管理模块
2//!
3//! 提供简化的翻译配置管理功能。
4
5use crate::error::{TranslationError, TranslationResult};
6use serde::{Deserialize, Serialize};
7use std::time::Duration;
8
9/// 翻译配置
10///
11/// 简化的配置结构,包含翻译所需的基本参数。
12///
13/// # 示例
14///
15/// ```rust
16/// use translation_lib::TranslationConfig;
17/// use std::time::Duration;
18///
19/// let config = TranslationConfig {
20///     api_url: "YOUR_API_URL".to_string(),
21///     api_key: Some("YOUR_API_KEY".to_string()),
22///     timeout: Duration::from_secs(30),
23///     max_concurrent_requests: 5,
24///     enable_cache: true,
25/// };
26/// ```
27#[derive(Debug, Clone, Serialize, Deserialize)]
28pub struct TranslationConfig {
29    /// 翻译API地址
30    pub api_url: String,
31
32    /// API密钥(可选)
33    pub api_key: Option<String>,
34
35    /// 请求超时时间
36    #[serde(with = "serde_duration")]
37    pub timeout: Duration,
38
39    /// 最大并发请求数
40    pub max_concurrent_requests: usize,
41
42    /// 是否启用缓存
43    pub enable_cache: bool,
44}
45
46impl Default for TranslationConfig {
47    fn default() -> Self {
48        Self {
49            api_url: "https://api.example.com/translate".to_string(),
50            api_key: None,
51            timeout: Duration::from_secs(30),
52            max_concurrent_requests: 10,
53            enable_cache: true,
54        }
55    }
56}
57
58impl TranslationConfig {
59    /// 创建新的配置
60    pub fn new(api_url: String) -> Self {
61        Self {
62            api_url,
63            ..Default::default()
64        }
65    }
66
67    /// 设置API密钥
68    pub fn with_api_key(mut self, api_key: String) -> Self {
69        self.api_key = Some(api_key);
70        self
71    }
72
73    /// 设置超时时间
74    pub fn with_timeout(mut self, timeout: Duration) -> Self {
75        self.timeout = timeout;
76        self
77    }
78
79    /// 设置最大并发数
80    pub fn with_max_concurrent(mut self, max_concurrent: usize) -> Self {
81        self.max_concurrent_requests = max_concurrent;
82        self
83    }
84
85    /// 设置是否启用缓存
86    pub fn with_cache(mut self, enable_cache: bool) -> Self {
87        self.enable_cache = enable_cache;
88        self
89    }
90
91    /// 从环境变量加载配置
92    pub fn from_env() -> TranslationResult<Self> {
93        let api_url = std::env::var("TRANSLATION_API_URL")
94            .unwrap_or_else(|_| "https://api.example.com/translate".to_string());
95
96        let api_key = std::env::var("TRANSLATION_API_KEY").ok();
97
98        let timeout_secs = std::env::var("TRANSLATION_TIMEOUT")
99            .unwrap_or_else(|_| "30".to_string())
100            .parse::<u64>()
101            .map_err(|_| TranslationError::Config("Invalid timeout value".to_string()))?;
102
103        let max_concurrent = std::env::var("TRANSLATION_MAX_CONCURRENT")
104            .unwrap_or_else(|_| "10".to_string())
105            .parse::<usize>()
106            .map_err(|_| TranslationError::Config("Invalid max_concurrent value".to_string()))?;
107
108        let enable_cache = std::env::var("TRANSLATION_ENABLE_CACHE")
109            .unwrap_or_else(|_| "true".to_string())
110            .parse::<bool>()
111            .map_err(|_| TranslationError::Config("Invalid enable_cache value".to_string()))?;
112
113        Ok(Self {
114            api_url,
115            api_key,
116            timeout: Duration::from_secs(timeout_secs),
117            max_concurrent_requests: max_concurrent,
118            enable_cache,
119        })
120    }
121
122    /// 验证配置
123    pub fn validate(&self) -> TranslationResult<()> {
124        if self.api_url.is_empty() {
125            return Err(TranslationError::Config(
126                "API URL cannot be empty".to_string(),
127            ));
128        }
129
130        if !self.api_url.starts_with("http://") && !self.api_url.starts_with("https://") {
131            return Err(TranslationError::Config(
132                "API URL must start with http:// or https://".to_string(),
133            ));
134        }
135
136        if self.max_concurrent_requests == 0 {
137            return Err(TranslationError::Config(
138                "max_concurrent_requests must be greater than 0".to_string(),
139            ));
140        }
141
142        if self.timeout.as_secs() == 0 {
143            return Err(TranslationError::Config(
144                "timeout must be greater than 0".to_string(),
145            ));
146        }
147
148        Ok(())
149    }
150}
151
152// Duration序列化辅助模块
153mod serde_duration {
154    use serde::{Deserialize, Deserializer, Serialize, Serializer};
155    use std::time::Duration;
156
157    pub fn serialize<S>(duration: &Duration, serializer: S) -> Result<S::Ok, S::Error>
158    where
159        S: Serializer,
160    {
161        duration.as_secs().serialize(serializer)
162    }
163
164    pub fn deserialize<'de, D>(deserializer: D) -> Result<Duration, D::Error>
165    where
166        D: Deserializer<'de>,
167    {
168        let secs = u64::deserialize(deserializer)?;
169        Ok(Duration::from_secs(secs))
170    }
171}