openlark_docs/common/
builders.rs1#[macro_export]
23macro_rules! impl_api_builder {
24 (
25 $builder_name:ident,
26 $request_name:ident,
27 $( $field:ident: $field_type:ty ),* $(,)?
28 ) => {
29 #[derive(Default)]
30 pub struct $builder_name {
31 request: $request_name,
32 }
33
34 impl $builder_name {
35 pub fn new() -> Self {
37 Self::default()
38 }
39
40 $(
41 pub fn $field(mut self, $field: impl Into<$field_type>) -> Self {
43 self.request.$field = $field.into();
44 self
45 }
46 )*
47
48 pub fn build(self) -> $request_name {
50 self.request
51 }
52 }
53
54 impl $request_name {
55 pub fn builder() -> $builder_name {
57 $builder_name::new()
58 }
59 }
60 };
61}
62
63#[macro_export]
66macro_rules! impl_base_api_fields {
67 ($request_name:ident) => {
68 impl $request_name {
69 pub fn app_token(mut self, app_token: impl Into<String>) -> Self {
71 self.app_token = app_token.into();
72 self
73 }
74
75 #[cfg(feature = "bitable")]
77 pub fn table_id(mut self, table_id: impl Into<String>) -> Self {
78 self.table_id = table_id.into();
79 self
80 }
81 }
82 };
83}
84
85#[macro_export]
88macro_rules! validate_required {
89 ($field:expr, $error_msg:expr) => {
90 if $field.is_empty() {
91 return Err(openlark_core::error::CoreError::validation_msg($error_msg));
92 }
93 };
94
95 ($field:expr, $error_msg:expr, $($fields:expr, $error_msgs:expr),+ $(,)?) => {
96 if $field.is_empty() {
97 return Err(openlark_core::error::CoreError::validation_msg($error_msg));
98 }
99 $(
100 if $fields.is_empty() {
101 return Err(openlark_core::error::CoreError::validation_msg($error_msgs));
102 }
103 )*
104 };
105}
106
107#[macro_export]
110macro_rules! build_api_path {
111 ($base:expr, $($segment:expr),+ $(,)?) => {
112 format!("/{}/{}", $base.trim_matches('/'), [$($segment),+].join("/"))
113 };
114}
115
116#[macro_export]
119macro_rules! impl_response_data {
120 (
121 $response_name:ident,
122 $data_name:ident {
123 $( $field:ident: $field_type:ty ),* $(,)?
124 }
125 ) => {
126 pub struct $data_name {
127 $( pub $field: $field_type, )*
128 }
129
130 pub struct $response_name {
131 pub data: $data_name,
132 }
133
134 impl openlark_core::api::ApiResponseTrait for $response_name {
135 fn data_format() -> openlark_core::api::ResponseFormat {
136 openlark_core::api::ResponseFormat::Data
137 }
138 }
139 };
140}
141
142#[cfg(test)]
143mod tests {
144 use openlark_core::config::Config;
145
146 #[derive(Default)]
148 pub struct TestRequest {
149 app_token: String,
150 table_id: String,
151 name: Option<String>,
152 }
153
154 impl_api_builder!(
156 TestRequestBuilder,
157 TestRequest,
158 app_token: String,
159 table_id: String,
160 name: Option<String>,
161 );
162
163 #[test]
164 fn test_builder_macro() {
165 let _config = Config::builder().app_id("test").app_secret("test").build();
166
167 let request = TestRequest::builder()
168 .app_token("test_token")
169 .table_id("test_table")
170 .name("test_name".to_string())
171 .build();
172
173 assert_eq!(request.app_token, "test_token");
174 assert_eq!(request.table_id, "test_table");
175 assert_eq!(request.name, Some("test_name".to_string()));
176 }
177
178 #[test]
179 fn test_validate_macro() {
180 fn test_function() -> Result<(), openlark_core::error::CoreError> {
182 validate_required!("valid_field", "字段不能为空");
184
185 validate_required!("", "字段不能为空");
187
188 Ok(())
189 }
190
191 let result = test_function();
193 assert!(result.is_err());
194 }
195
196 #[test]
197 fn test_path_building_macro() {
198 let path = build_api_path!("open-apis", "v1", "apps", "123", "tables", "456");
199 assert_eq!(path, "/open-apis/v1/apps/123/tables/456");
200 }
201
202 #[test]
203 fn test_response_data_macro() {
204 impl_response_data!(
205 TestResponse,
206 TestData {
207 id: String,
208 name: String,
209 created_time: String,
210 }
211 );
212
213 let data = TestData {
215 id: "123".to_string(),
216 name: "测试".to_string(),
217 created_time: "2023-01-01".to_string(),
218 };
219 let response = TestResponse { data };
220
221 assert_eq!(response.data.id, "123");
222 assert_eq!(response.data.name, "测试");
223 assert_eq!(response.data.created_time, "2023-01-01");
224 }
225}