1use std::fmt;
6use thiserror::Error;
7
8pub type TranslationResult<T> = Result<T, TranslationError>;
10
11#[derive(Error, Debug, Clone)]
15pub enum TranslationError {
16 #[error("翻译服务错误: {0}")]
18 ServiceError(String),
19
20 #[error("网络连接错误: {0}")]
22 NetworkError(String),
23
24 #[error("HTML解析错误: {0}")]
26 ParseError(String),
27
28 #[error("配置错误: {0}")]
30 ConfigError(String),
31
32 #[error("缓存操作错误: {0}")]
34 CacheError(String),
35
36 #[error("文件操作错误: {0}")]
38 IoError(String),
39
40 #[error("内部错误: {0}")]
42 InternalError(String),
43
44 #[error("功能特性未启用: {0}")]
46 FeatureNotEnabled(String),
47
48 #[error("不支持的语言: {0}")]
50 UnsupportedLanguage(String),
51
52 #[error("API限制错误: {0}")]
54 ApiLimitError(String),
55
56 #[error("操作超时: {0}")]
58 TimeoutError(String),
59}
60
61impl TranslationError {
62 pub fn service_error(msg: impl Into<String>) -> Self {
64 Self::ServiceError(msg.into())
65 }
66
67 pub fn network_error(msg: impl Into<String>) -> Self {
69 Self::NetworkError(msg.into())
70 }
71
72 pub fn parse_error(msg: impl Into<String>) -> Self {
74 Self::ParseError(msg.into())
75 }
76
77 pub fn config_error(msg: impl Into<String>) -> Self {
79 Self::ConfigError(msg.into())
80 }
81
82 pub fn cache_error(msg: impl Into<String>) -> Self {
84 Self::CacheError(msg.into())
85 }
86
87 pub fn io_error(msg: impl Into<String>) -> Self {
89 Self::IoError(msg.into())
90 }
91
92 pub fn internal_error(msg: impl Into<String>) -> Self {
94 Self::InternalError(msg.into())
95 }
96
97 pub fn is_retryable(&self) -> bool {
99 matches!(
100 self,
101 TranslationError::NetworkError(_)
102 | TranslationError::ServiceError(_)
103 | TranslationError::TimeoutError(_)
104 )
105 }
106
107 pub fn category(&self) -> ErrorCategory {
109 match self {
110 TranslationError::ServiceError(_) => ErrorCategory::Service,
111 TranslationError::NetworkError(_) => ErrorCategory::Network,
112 TranslationError::ParseError(_) => ErrorCategory::Parsing,
113 TranslationError::ConfigError(_) => ErrorCategory::Configuration,
114 TranslationError::CacheError(_) => ErrorCategory::Cache,
115 TranslationError::IoError(_) => ErrorCategory::Io,
116 TranslationError::InternalError(_) => ErrorCategory::Internal,
117 TranslationError::FeatureNotEnabled(_) => ErrorCategory::Feature,
118 TranslationError::UnsupportedLanguage(_) => ErrorCategory::Language,
119 TranslationError::ApiLimitError(_) => ErrorCategory::ApiLimit,
120 TranslationError::TimeoutError(_) => ErrorCategory::Timeout,
121 }
122 }
123
124 pub fn severity(&self) -> ErrorSeverity {
126 match self {
127 TranslationError::NetworkError(_) | TranslationError::TimeoutError(_) => {
128 ErrorSeverity::Warning
129 }
130 TranslationError::ApiLimitError(_) => ErrorSeverity::Warning,
131 TranslationError::ServiceError(_) => ErrorSeverity::Error,
132 TranslationError::ParseError(_) | TranslationError::ConfigError(_) => {
133 ErrorSeverity::Error
134 }
135 TranslationError::InternalError(_) => ErrorSeverity::Critical,
136 TranslationError::FeatureNotEnabled(_) => ErrorSeverity::Error,
137 TranslationError::UnsupportedLanguage(_) => ErrorSeverity::Warning,
138 TranslationError::CacheError(_) | TranslationError::IoError(_) => ErrorSeverity::Warning,
139 }
140 }
141}
142
143#[derive(Debug, Clone, Copy, PartialEq, Eq)]
145pub enum ErrorCategory {
146 Service,
148 Network,
150 Parsing,
152 Configuration,
154 Cache,
156 Io,
158 Internal,
160 Feature,
162 Language,
164 ApiLimit,
166 Timeout,
168}
169
170#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
172pub enum ErrorSeverity {
173 Info,
175 Warning,
177 Error,
179 Critical,
181}
182
183impl fmt::Display for ErrorCategory {
184 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
185 match self {
186 ErrorCategory::Service => write!(f, "服务"),
187 ErrorCategory::Network => write!(f, "网络"),
188 ErrorCategory::Parsing => write!(f, "解析"),
189 ErrorCategory::Configuration => write!(f, "配置"),
190 ErrorCategory::Cache => write!(f, "缓存"),
191 ErrorCategory::Io => write!(f, "IO"),
192 ErrorCategory::Internal => write!(f, "内部"),
193 ErrorCategory::Feature => write!(f, "特性"),
194 ErrorCategory::Language => write!(f, "语言"),
195 ErrorCategory::ApiLimit => write!(f, "API限制"),
196 ErrorCategory::Timeout => write!(f, "超时"),
197 }
198 }
199}
200
201impl fmt::Display for ErrorSeverity {
202 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
203 match self {
204 ErrorSeverity::Info => write!(f, "信息"),
205 ErrorSeverity::Warning => write!(f, "警告"),
206 ErrorSeverity::Error => write!(f, "错误"),
207 ErrorSeverity::Critical => write!(f, "严重"),
208 }
209 }
210}
211
212impl From<std::io::Error> for TranslationError {
214 fn from(err: std::io::Error) -> Self {
215 TranslationError::IoError(err.to_string())
216 }
217}
218
219impl From<serde_json::Error> for TranslationError {
220 fn from(err: serde_json::Error) -> Self {
221 TranslationError::ParseError(format!("JSON解析错误: {err}"))
222 }
223}
224
225impl From<toml::de::Error> for TranslationError {
226 fn from(err: toml::de::Error) -> Self {
227 TranslationError::ConfigError(format!("TOML配置解析错误: {err}"))
228 }
229}
230
231#[cfg(feature = "async")]
232impl From<reqwest::Error> for TranslationError {
233 fn from(err: reqwest::Error) -> Self {
234 if err.is_timeout() {
235 TranslationError::TimeoutError(err.to_string())
236 } else if err.is_connect() || err.is_request() {
237 TranslationError::NetworkError(err.to_string())
238 } else {
239 TranslationError::ServiceError(err.to_string())
240 }
241 }
242}
243
244#[cfg(test)]
245mod tests {
246 use super::*;
247
248 #[test]
249 fn test_error_creation_methods() {
250 let service_error = TranslationError::service_error("Service unavailable");
251 assert!(matches!(service_error, TranslationError::ServiceError(_)));
252 assert_eq!(service_error.to_string(), "翻译服务错误: Service unavailable");
253 }
254}