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
106impl ResponseFormat {
107 pub(crate) fn as_label(self) -> &'static str {
109 match self {
110 ResponseFormat::Data => "data",
111 ResponseFormat::Flatten => "flatten",
112 ResponseFormat::Binary => "binary",
113 ResponseFormat::Text => "text",
114 ResponseFormat::Custom => "custom",
115 }
116 }
117}
118
119pub trait ApiResponseTrait: Sized + Send + Sync + 'static {
128 fn data_format() -> ResponseFormat {
130 ResponseFormat::Data
131 }
132
133 fn requires_payload() -> bool {
136 true
137 }
138
139 fn empty_success() -> Option<Self> {
144 None
145 }
146
147 fn from_binary(_file_name: String, _body: Vec<u8>) -> Option<Self> {
149 None
150 }
151
152 fn from_text(_text: String) -> Option<Self> {
154 None
155 }
156
157 fn from_custom(_body: Vec<u8>, _content_type: Option<&str>) -> Option<Self> {
159 None
160 }
161}
162
163#[derive(Debug, Clone, Serialize, Deserialize)]
165pub struct Response<T> {
166 pub data: Option<T>,
168 pub raw_response: RawResponse,
170}
171
172impl<T> Response<T> {
173 pub fn new(data: Option<T>, raw_response: RawResponse) -> Self {
175 Self { data, raw_response }
176 }
177
178 pub fn success(data: T) -> Self {
180 Self {
181 data: Some(data),
182 raw_response: RawResponse::success(),
183 }
184 }
185
186 pub fn success_empty() -> Self {
188 Self {
189 data: None,
190 raw_response: RawResponse::success(),
191 }
192 }
193
194 pub fn error(code: i32, msg: impl Into<String> + Clone) -> Self {
196 Self {
197 data: None,
198 raw_response: RawResponse::error(code, msg),
199 }
200 }
201
202 pub fn is_success(&self) -> bool {
204 self.raw_response.is_success()
205 }
206
207 pub fn code(&self) -> i32 {
209 self.raw_response.code
210 }
211
212 pub fn message(&self) -> &str {
214 &self.raw_response.msg
215 }
216
217 pub fn msg(&self) -> &str {
219 &self.raw_response.msg
220 }
221
222 pub fn data(&self) -> Option<&T> {
224 self.data.as_ref()
225 }
226
227 pub fn raw(&self) -> &RawResponse {
229 &self.raw_response
230 }
231
232 pub fn into_result(self) -> Result<T, crate::error::CoreError> {
234 let is_success = self.is_success();
235 let code = self.raw_response.code;
236 let request_id = self.raw_response.request_id.clone();
237
238 if is_success {
239 match self.data {
240 Some(data) => Ok(data),
241 None => Err(crate::error::api_error(
242 code as u16,
243 "response",
244 "响应数据为空",
245 request_id,
246 )),
247 }
248 } else {
249 Err(crate::error::api_error(
250 code as u16,
251 "response",
252 self.raw_response.msg.clone(),
253 request_id,
254 ))
255 }
256 }
257}
258
259impl ApiResponseTrait for serde_json::Value {}
261impl ApiResponseTrait for String {}
263impl ApiResponseTrait for Vec<u8> {
264 fn data_format() -> ResponseFormat {
265 ResponseFormat::Binary
266 }
267
268 fn from_binary(_file_name: String, body: Vec<u8>) -> Option<Self> {
269 Some(body)
270 }
271}
272impl ApiResponseTrait for () {
273 fn requires_payload() -> bool {
274 false
275 }
276}
277
278pub type BaseResponse<T> = Response<T>;
281
282#[cfg(test)]
283mod tests {
284 use super::*;
285
286 #[test]
287 fn test_raw_response_default() {
288 let response = RawResponse::default();
289 assert_eq!(response.code, 0);
290 assert_eq!(response.msg, "success");
291 assert!(response.request_id.is_none());
292 assert!(response.data.is_none());
293 assert!(response.error.is_none());
294 }
295
296 #[test]
297 fn test_raw_response_success() {
298 let response = RawResponse::success();
299 assert!(response.is_success());
300 }
301
302 #[test]
303 fn test_raw_response_success_with_data() {
304 let data = serde_json::json!({"key": "value"});
305 let response = RawResponse::success_with_data(data.clone());
306 assert!(response.is_success());
307 assert_eq!(response.data, Some(data));
308 }
309
310 #[test]
311 fn test_raw_response_error() {
312 let response = RawResponse::error(400, "Bad Request");
313 assert!(!response.is_success());
314 assert_eq!(response.code, 400);
315 assert!(response.error.is_some());
316 }
317
318 #[test]
319 fn test_raw_response_get_error() {
320 let response = RawResponse::error(404, "Not Found");
321 let error = response.get_error();
322 assert!(error.is_some());
323 assert_eq!(error.unwrap().code, 404);
324 }
325
326 #[test]
327 fn test_raw_response_serialization() {
328 let response = RawResponse::success_with_data(serde_json::json!({"test": 123}));
329 let json = serde_json::to_string(&response).unwrap();
330 let parsed: RawResponse = serde_json::from_str(&json).expect("JSON 反序列化失败");
331 assert!(parsed.is_success());
332 }
333
334 #[test]
335 fn test_error_info_creation() {
336 let error = ErrorInfo {
337 code: 500,
338 message: "Internal Error".to_string(),
339 details: None,
340 };
341 assert_eq!(error.code, 500);
342 assert_eq!(error.message, "Internal Error");
343 }
344
345 #[test]
346 fn test_response_format() {
347 assert_eq!(ResponseFormat::Data, ResponseFormat::Data);
348 assert_ne!(ResponseFormat::Data, ResponseFormat::Flatten);
349 }
350
351 #[test]
352 fn test_response_format_binary() {
353 assert_eq!(<Vec<u8>>::data_format(), ResponseFormat::Binary);
354 }
355
356 #[test]
357 fn test_response_format_default() {
358 assert_eq!(<()>::data_format(), ResponseFormat::Data);
359 }
360
361 #[test]
362 fn test_response_deserialize_requires_raw_response() {
363 let payload = r#"{"code":400,"msg":"Bad Request"}"#;
364 let parsed = serde_json::from_str::<Response<serde_json::Value>>(payload);
365 assert!(parsed.is_err());
366 }
367
368 #[test]
369 fn test_response_deserialize_with_raw_response_error_keeps_code_and_msg() {
370 let payload = r#"{"raw_response":{"code":400,"msg":"Bad Request","request_id":null,"data":null,"error":null},"data":null}"#;
371 let parsed = serde_json::from_str::<Response<serde_json::Value>>(payload)
372 .expect("JSON 反序列化失败");
373 assert_eq!(parsed.raw_response.code, 400);
374 assert_eq!(parsed.raw_response.msg, "Bad Request");
375 assert!(!parsed.is_success());
376 }
377}