1use serde::{Deserialize, Serialize};
6use std::collections::HashMap;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct RawResponse {
11 pub code: i32,
13 pub msg: String,
15 pub request_id: Option<String>,
17 pub data: Option<serde_json::Value>,
19 pub error: Option<ErrorInfo>,
21}
22
23#[derive(Debug, Clone, Serialize, Deserialize)]
25pub struct ErrorInfo {
26 pub code: i32,
28 pub message: String,
30 pub details: Option<HashMap<String, serde_json::Value>>,
32}
33
34impl Default for RawResponse {
35 fn default() -> Self {
36 Self {
37 code: 0,
38 msg: "success".to_string(),
39 request_id: None,
40 data: None,
41 error: None,
42 }
43 }
44}
45
46impl RawResponse {
47 pub fn success() -> Self {
49 Self::default()
50 }
51
52 pub fn success_with_data(data: serde_json::Value) -> Self {
54 Self {
55 data: Some(data),
56 ..Default::default()
57 }
58 }
59
60 pub fn error(code: i32, msg: impl Into<String> + Clone) -> Self {
62 let msg_str = msg.into();
63 Self {
64 code,
65 msg: msg_str.clone(),
66 error: Some(ErrorInfo {
67 code,
68 message: msg_str,
69 details: None,
70 }),
71 ..Default::default()
72 }
73 }
74
75 pub fn is_success(&self) -> bool {
77 self.code == 0
78 }
79
80 pub fn get_error(&self) -> Option<&ErrorInfo> {
82 self.error.as_ref()
83 }
84}
85
86#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
88pub enum ResponseFormat {
89 #[serde(rename = "data")]
91 Data,
92 #[serde(rename = "flatten")]
94 Flatten,
95 #[serde(rename = "binary")]
97 Binary,
98 #[serde(rename = "text")]
100 Text,
101 #[serde(rename = "custom")]
103 Custom,
104}
105
106pub trait ApiResponseTrait: Send + Sync + 'static {
108 fn data_format() -> ResponseFormat {
110 ResponseFormat::Data
111 }
112}
113
114#[derive(Debug, Clone, Serialize, Deserialize)]
116pub struct Response<T> {
117 pub data: Option<T>,
119 pub raw_response: RawResponse,
121}
122
123impl<T> Response<T> {
124 pub fn new(data: Option<T>, raw_response: RawResponse) -> Self {
126 Self { data, raw_response }
127 }
128
129 pub fn success(data: T) -> Self {
131 Self {
132 data: Some(data),
133 raw_response: RawResponse::success(),
134 }
135 }
136
137 pub fn success_empty() -> Self {
139 Self {
140 data: None,
141 raw_response: RawResponse::success(),
142 }
143 }
144
145 pub fn error(code: i32, msg: impl Into<String> + Clone) -> Self {
147 Self {
148 data: None,
149 raw_response: RawResponse::error(code, msg),
150 }
151 }
152
153 pub fn is_success(&self) -> bool {
155 self.raw_response.is_success()
156 }
157
158 pub fn code(&self) -> i32 {
160 self.raw_response.code
161 }
162
163 pub fn message(&self) -> &str {
165 &self.raw_response.msg
166 }
167
168 pub fn msg(&self) -> &str {
170 &self.raw_response.msg
171 }
172
173 pub fn data(&self) -> Option<&T> {
175 self.data.as_ref()
176 }
177
178 pub fn raw(&self) -> &RawResponse {
180 &self.raw_response
181 }
182
183 pub fn into_result(self) -> Result<T, crate::error::CoreError> {
185 let is_success = self.is_success();
186 let code = self.raw_response.code;
187 let request_id = self.raw_response.request_id.clone();
188
189 if is_success {
190 match self.data {
191 Some(data) => Ok(data),
192 None => Err(crate::error::api_error(
193 code as u16,
194 "response",
195 "响应数据为空",
196 request_id,
197 )),
198 }
199 } else {
200 Err(crate::error::api_error(
201 code as u16,
202 "response",
203 self.raw_response.msg.clone(),
204 request_id,
205 ))
206 }
207 }
208}
209
210impl ApiResponseTrait for serde_json::Value {}
212impl ApiResponseTrait for String {}
213impl ApiResponseTrait for Vec<u8> {
214 fn data_format() -> ResponseFormat {
215 ResponseFormat::Binary
216 }
217}
218impl ApiResponseTrait for () {}
219
220pub type BaseResponse<T> = Response<T>;
223
224#[cfg(test)]
225mod tests {
226 use super::*;
227
228 #[test]
229 fn test_raw_response_default() {
230 let response = RawResponse::default();
231 assert_eq!(response.code, 0);
232 assert_eq!(response.msg, "success");
233 assert!(response.request_id.is_none());
234 assert!(response.data.is_none());
235 assert!(response.error.is_none());
236 }
237
238 #[test]
239 fn test_raw_response_success() {
240 let response = RawResponse::success();
241 assert!(response.is_success());
242 }
243
244 #[test]
245 fn test_raw_response_success_with_data() {
246 let data = serde_json::json!({"key": "value"});
247 let response = RawResponse::success_with_data(data.clone());
248 assert!(response.is_success());
249 assert_eq!(response.data, Some(data));
250 }
251
252 #[test]
253 fn test_raw_response_error() {
254 let response = RawResponse::error(400, "Bad Request");
255 assert!(!response.is_success());
256 assert_eq!(response.code, 400);
257 assert!(response.error.is_some());
258 }
259
260 #[test]
261 fn test_raw_response_get_error() {
262 let response = RawResponse::error(404, "Not Found");
263 let error = response.get_error();
264 assert!(error.is_some());
265 assert_eq!(error.unwrap().code, 404);
266 }
267
268 #[test]
269 fn test_raw_response_serialization() {
270 let response = RawResponse::success_with_data(serde_json::json!({"test": 123}));
271 let json = serde_json::to_string(&response).unwrap();
272 let parsed: RawResponse = serde_json::from_str(&json).unwrap();
273 assert!(parsed.is_success());
274 }
275
276 #[test]
277 fn test_error_info_creation() {
278 let error = ErrorInfo {
279 code: 500,
280 message: "Internal Error".to_string(),
281 details: None,
282 };
283 assert_eq!(error.code, 500);
284 assert_eq!(error.message, "Internal Error");
285 }
286
287 #[test]
288 fn test_response_format() {
289 assert_eq!(ResponseFormat::Data, ResponseFormat::Data);
290 assert_ne!(ResponseFormat::Data, ResponseFormat::Flatten);
291 }
292
293 #[test]
294 fn test_response_format_binary() {
295 assert_eq!(<Vec<u8>>::data_format(), ResponseFormat::Binary);
296 }
297
298 #[test]
299 fn test_response_format_default() {
300 assert_eq!(<()>::data_format(), ResponseFormat::Data);
301 }
302
303 #[test]
304 fn test_response_deserialize_requires_raw_response() {
305 let payload = r#"{"code":400,"msg":"Bad Request"}"#;
306 let parsed = serde_json::from_str::<Response<serde_json::Value>>(payload);
307 assert!(parsed.is_err());
308 }
309
310 #[test]
311 fn test_response_deserialize_with_raw_response_error_keeps_code_and_msg() {
312 let payload = r#"{"raw_response":{"code":400,"msg":"Bad Request","request_id":null,"data":null,"error":null},"data":null}"#;
313 let parsed = serde_json::from_str::<Response<serde_json::Value>>(payload).unwrap();
314 assert_eq!(parsed.raw_response.code, 400);
315 assert_eq!(parsed.raw_response.msg, "Bad Request");
316 assert!(!parsed.is_success());
317 }
318}