1use thiserror::Error;
6
7#[derive(Debug, Error)]
16pub enum ZtkError {
17 #[error("网络请求失败: {0}")]
21 Network(#[from] reqwest::Error),
22
23 #[error("API 错误 [{code}]: {message}")]
27 Api {
28 code: i32,
30 message: String,
32 sub_code: Option<String>,
34 sub_msg: Option<String>,
36 },
37
38 #[error("JSON 解析失败: {0}")]
42 Parse(#[from] serde_json::Error),
43
44 #[error("参数验证失败: {0}")]
48 Validation(String),
49
50 #[error("URL 编码失败: {0}")]
54 UrlEncode(String),
55}
56
57pub type ZtkResult<T> = Result<T, ZtkError>;
61
62impl ZtkError {
63 pub fn api(code: i32, message: impl Into<String>) -> Self {
70 ZtkError::Api {
71 code,
72 message: message.into(),
73 sub_code: None,
74 sub_msg: None,
75 }
76 }
77
78 pub fn api_with_sub(
87 code: i32,
88 message: impl Into<String>,
89 sub_code: Option<String>,
90 sub_msg: Option<String>,
91 ) -> Self {
92 ZtkError::Api {
93 code,
94 message: message.into(),
95 sub_code,
96 sub_msg,
97 }
98 }
99
100 pub fn validation(message: impl Into<String>) -> Self {
106 ZtkError::Validation(message.into())
107 }
108
109 pub fn url_encode(message: impl Into<String>) -> Self {
115 ZtkError::UrlEncode(message.into())
116 }
117}
118
119#[cfg(test)]
120mod tests {
121 use super::*;
122
123 #[test]
124 fn test_api_error_display() {
125 let err = ZtkError::api(1001, "测试错误");
126 assert_eq!(format!("{}", err), "API 错误 [1001]: 测试错误");
127 }
128
129 #[test]
130 fn test_validation_error_display() {
131 let err = ZtkError::validation("参数不能为空");
132 assert_eq!(format!("{}", err), "参数验证失败: 参数不能为空");
133 }
134
135 #[test]
136 fn test_url_encode_error_display() {
137 let err = ZtkError::url_encode("无效的 URL 字符");
138 assert_eq!(format!("{}", err), "URL 编码失败: 无效的 URL 字符");
139 }
140
141 #[test]
142 fn test_error_is_std_error() {
143 let err: Box<dyn std::error::Error> = Box::new(ZtkError::validation("test"));
144 assert!(err.source().is_none());
145 }
146
147 #[test]
148 fn test_api_error_with_sub() {
149 let err = ZtkError::api_with_sub(
150 1001,
151 "主错误",
152 Some("SUB_001".to_string()),
153 Some("子错误消息".to_string()),
154 );
155 match err {
156 ZtkError::Api {
157 code,
158 message,
159 sub_code,
160 sub_msg,
161 } => {
162 assert_eq!(code, 1001);
163 assert_eq!(message, "主错误");
164 assert_eq!(sub_code, Some("SUB_001".to_string()));
165 assert_eq!(sub_msg, Some("子错误消息".to_string()));
166 }
167 _ => panic!("Expected Api error"),
168 }
169 }
170}