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 {
109 ResponseFormat::Data
110 }
111}
112
113#[derive(Debug, Clone, Serialize, Deserialize)]
115pub struct Response<T> {
116 pub data: Option<T>,
118 pub raw_response: RawResponse,
120}
121
122impl<T> Response<T> {
123 pub fn new(data: Option<T>, raw_response: RawResponse) -> Self {
125 Self { data, raw_response }
126 }
127
128 pub fn success(data: T) -> Self {
130 Self {
131 data: Some(data),
132 raw_response: RawResponse::success(),
133 }
134 }
135
136 pub fn success_empty() -> Self {
138 Self {
139 data: None,
140 raw_response: RawResponse::success(),
141 }
142 }
143
144 pub fn error(code: i32, msg: impl Into<String> + Clone) -> Self {
146 Self {
147 data: None,
148 raw_response: RawResponse::error(code, msg),
149 }
150 }
151
152 pub fn is_success(&self) -> bool {
154 self.raw_response.is_success()
155 }
156
157 pub fn code(&self) -> i32 {
159 self.raw_response.code
160 }
161
162 pub fn message(&self) -> &str {
164 &self.raw_response.msg
165 }
166
167 pub fn msg(&self) -> &str {
169 &self.raw_response.msg
170 }
171
172 pub fn data(&self) -> Option<&T> {
174 self.data.as_ref()
175 }
176
177 pub fn raw(&self) -> &RawResponse {
179 &self.raw_response
180 }
181
182 pub fn into_result(self) -> Result<T, crate::error::CoreError> {
184 let is_success = self.is_success();
185 let code = self.raw_response.code;
186 let request_id = self.raw_response.request_id.clone();
187
188 if is_success {
189 match self.data {
190 Some(data) => Ok(data),
191 None => Err(crate::error::api_error(
192 code as u16,
193 "response",
194 "响应数据为空",
195 request_id,
196 )),
197 }
198 } else {
199 Err(crate::error::api_error(
200 code as u16,
201 "response",
202 self.raw_response.msg.clone(),
203 request_id,
204 ))
205 }
206 }
207}
208
209impl ApiResponseTrait for serde_json::Value {}
211impl ApiResponseTrait for String {}
212impl ApiResponseTrait for Vec<u8> {
213 fn data_format() -> ResponseFormat {
214 ResponseFormat::Binary
215 }
216}
217impl ApiResponseTrait for () {}
218
219pub type BaseResponse<T> = Response<T>;
221
222#[cfg(test)]
223mod tests {
224 use super::*;
225
226 #[test]
227 fn test_raw_response_default() {
228 let response = RawResponse::default();
229 assert_eq!(response.code, 0);
230 assert_eq!(response.msg, "success");
231 assert!(response.request_id.is_none());
232 assert!(response.data.is_none());
233 assert!(response.error.is_none());
234 }
235
236 #[test]
237 fn test_raw_response_success() {
238 let response = RawResponse::success();
239 assert!(response.is_success());
240 }
241
242 #[test]
243 fn test_raw_response_success_with_data() {
244 let data = serde_json::json!({"key": "value"});
245 let response = RawResponse::success_with_data(data.clone());
246 assert!(response.is_success());
247 assert_eq!(response.data, Some(data));
248 }
249
250 #[test]
251 fn test_raw_response_error() {
252 let response = RawResponse::error(400, "Bad Request");
253 assert!(!response.is_success());
254 assert_eq!(response.code, 400);
255 assert!(response.error.is_some());
256 }
257
258 #[test]
259 fn test_raw_response_get_error() {
260 let response = RawResponse::error(404, "Not Found");
261 let error = response.get_error();
262 assert!(error.is_some());
263 assert_eq!(error.unwrap().code, 404);
264 }
265
266 #[test]
267 fn test_raw_response_serialization() {
268 let response = RawResponse::success_with_data(serde_json::json!({"test": 123}));
269 let json = serde_json::to_string(&response).unwrap();
270 let parsed: RawResponse = serde_json::from_str(&json).unwrap();
271 assert!(parsed.is_success());
272 }
273
274 #[test]
275 fn test_error_info_creation() {
276 let error = ErrorInfo {
277 code: 500,
278 message: "Internal Error".to_string(),
279 details: None,
280 };
281 assert_eq!(error.code, 500);
282 assert_eq!(error.message, "Internal Error");
283 }
284
285 #[test]
286 fn test_response_format() {
287 assert_eq!(ResponseFormat::Data, ResponseFormat::Data);
288 assert_ne!(ResponseFormat::Data, ResponseFormat::Flatten);
289 }
290
291 #[test]
292 fn test_response_format_binary() {
293 assert_eq!(<Vec<u8>>::data_format(), ResponseFormat::Binary);
294 }
295
296 #[test]
297 fn test_response_format_default() {
298 assert_eq!(<()>::data_format(), ResponseFormat::Data);
299 }
300
301 #[test]
302 fn test_response_deserialize_requires_raw_response() {
303 let payload = r#"{"code":400,"msg":"Bad Request"}"#;
304 let parsed = serde_json::from_str::<Response<serde_json::Value>>(payload);
305 assert!(parsed.is_err());
306 }
307
308 #[test]
309 fn test_response_deserialize_with_raw_response_error_keeps_code_and_msg() {
310 let payload = r#"{"raw_response":{"code":400,"msg":"Bad Request","request_id":null,"data":null,"error":null},"data":null}"#;
311 let parsed = serde_json::from_str::<Response<serde_json::Value>>(payload).unwrap();
312 assert_eq!(parsed.raw_response.code, 400);
313 assert_eq!(parsed.raw_response.msg, "Bad Request");
314 assert!(!parsed.is_success());
315 }
316}