open_lark/core/
standard_response.rs

1/// 标准化响应处理特征
2///
3/// 为了解决项目中错误处理方式不统一的问题,提供统一的响应处理接口。
4/// 这个特征允许不同的响应类型以一致的方式处理成功和错误情况。
5use crate::core::{api_resp::BaseResponse, error::LarkAPIError, SDKResult};
6
7/// 标准响应处理特征
8///
9/// 提供统一的响应处理方法,确保所有API调用都有一致的错误处理体验
10pub trait StandardResponse<T> {
11    /// 将响应转换为统一的Result格式
12    ///
13    /// # Returns
14    ///
15    /// * `Ok(T)` - 当响应成功且包含数据时
16    /// * `Err(LarkAPIError)` - 当响应失败或数据处理出错时
17    fn into_result(self) -> SDKResult<T>;
18
19    /// 获取响应数据,失败时返回默认值
20    ///
21    /// 这个方法保持了向后兼容性,对应原来的 `unwrap_or_default()` 行为
22    fn data_or_default(self) -> T
23    where
24        T: Default;
25}
26
27impl<T> StandardResponse<T> for BaseResponse<T> {
28    fn into_result(self) -> SDKResult<T> {
29        if self.success() {
30            match self.data {
31                Some(data) => Ok(data),
32                None => Err(LarkAPIError::DataError(
33                    "Response succeeded but contains no data".to_string(),
34                )),
35            }
36        } else {
37            Err(LarkAPIError::APIError {
38                code: self.code(),
39                msg: self.msg().to_string(),
40                error: self.err().map(|e| format!("{e:?}")),
41            })
42        }
43    }
44
45    fn data_or_default(self) -> T
46    where
47        T: Default,
48    {
49        if self.success() {
50            self.data.unwrap_or_default()
51        } else {
52            T::default()
53        }
54    }
55}
56
57impl<T> StandardResponse<T> for SDKResult<BaseResponse<T>> {
58    fn into_result(self) -> SDKResult<T> {
59        match self {
60            Ok(response) => response.into_result(),
61            Err(error) => Err(error),
62        }
63    }
64
65    fn data_or_default(self) -> T
66    where
67        T: Default,
68    {
69        match self {
70            Ok(response) => response.data_or_default(),
71            Err(_) => T::default(),
72        }
73    }
74}
75
76#[cfg(test)]
77mod tests {
78    use super::*;
79    use crate::core::api_resp::{BaseResponse, RawResponse};
80    use serde::{Deserialize, Serialize};
81
82    #[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
83    struct TestData {
84        value: String,
85    }
86
87    #[test]
88    fn test_successful_response_with_data() {
89        let response = BaseResponse {
90            raw_response: RawResponse {
91                code: 0,
92                msg: "success".to_string(),
93                err: None,
94            },
95            data: Some(TestData {
96                value: "test".to_string(),
97            }),
98        };
99
100        let result = response.into_result();
101        assert!(result.is_ok());
102        assert_eq!(result.unwrap().value, "test");
103    }
104
105    #[test]
106    fn test_successful_response_without_data() {
107        let response: BaseResponse<TestData> = BaseResponse {
108            raw_response: RawResponse {
109                code: 0,
110                msg: "success".to_string(),
111                err: None,
112            },
113            data: None,
114        };
115
116        let result = response.into_result();
117        assert!(result.is_err());
118        if let Err(LarkAPIError::DataError(msg)) = result {
119            assert!(msg.contains("no data"));
120        } else {
121            panic!("Expected DataError");
122        }
123    }
124
125    #[test]
126    fn test_failed_response() {
127        let response: BaseResponse<TestData> = BaseResponse {
128            raw_response: RawResponse {
129                code: -1,
130                msg: "error".to_string(),
131                err: None,
132            },
133            data: None,
134        };
135
136        let result = response.into_result();
137        assert!(result.is_err());
138    }
139
140    #[test]
141    fn test_data_or_default_success() {
142        let response = BaseResponse {
143            raw_response: RawResponse {
144                code: 0,
145                msg: "success".to_string(),
146                err: None,
147            },
148            data: Some(TestData {
149                value: "test".to_string(),
150            }),
151        };
152
153        let data = response.data_or_default();
154        assert_eq!(data.value, "test");
155    }
156
157    #[test]
158    fn test_data_or_default_no_data() {
159        let response: BaseResponse<TestData> = BaseResponse {
160            raw_response: RawResponse {
161                code: 0,
162                msg: "success".to_string(),
163                err: None,
164            },
165            data: None,
166        };
167
168        let data = response.data_or_default();
169        assert_eq!(data, TestData::default());
170    }
171
172    #[test]
173    fn test_data_or_default_failure() {
174        let response: BaseResponse<TestData> = BaseResponse {
175            raw_response: RawResponse {
176                code: -1,
177                msg: "error".to_string(),
178                err: None,
179            },
180            data: None,
181        };
182
183        let data = response.data_or_default();
184        assert_eq!(data, TestData::default());
185    }
186}