1#[macro_export]
2macro_rules! endpoint {
3 (@method GET) => { ::reqwest::Method::GET };
7 (@method POST) => { ::reqwest::Method::POST };
8 (@method PUT) => { ::reqwest::Method::PUT };
9 (@method PATCH) => { ::reqwest::Method::PATCH };
10 (@method DELETE) => { ::reqwest::Method::DELETE };
11
12 (@body $body:expr) => { Some(&$body) };
16 (@body) => { None::<&()> };
17
18 (@decode $resp:ident, $ret:ty, json) => { $resp.json::<$ret>().await };
22 (@decode $resp:ident, $ret:ty, bytes) => { $resp.bytes().await };
23 (@decode $resp:ident, $ret:ty, void) => { Ok(()) };
24 (@decode $resp:ident, $ret:ty, [map $r:ident : $wrap:ty => $proj:expr]) => {
25 $resp.json::<$wrap>().await.map(|$r| $proj)
26 };
27
28 (@types_entry Request<$lt:lifetime> { $($field:ident $( ( $rename:literal ) )? : $ftype:ty),* $(,)? } $($rest:tt)*) => {
42 #[derive(Serialize)]
43 struct Request<$lt> {
44 $(
45 $(#[serde(rename = $rename)])?
46 pub $field: $ftype,
47 )*
48 }
49 endpoint!(@types_entry $($rest)*)
50 };
51 (@types_entry Request { $($field:ident $( ( $rename:literal ) )? : $ftype:ty),* $(,)? } $($rest:tt)*) => {
53 #[derive(Serialize)]
54 struct Request {
55 $(
56 $(#[serde(rename = $rename)])?
57 pub $field: $ftype,
58 )*
59 }
60 endpoint!(@types_entry $($rest)*)
61 };
62
63 (@types_entry Response<$lt:lifetime> { $($field:ident $( ( $rename:literal ) )? : $ftype:ty),* $(,)? } $($rest:tt)*) => {
65 #[derive(Deserialize)]
66 struct Response<$lt> {
67 $(
68 $(#[serde(rename = $rename)])?
69 pub $field: $ftype,
70 )*
71 }
72 endpoint!(@types_entry $($rest)*)
73 };
74 (@types_entry Response { $($field:ident $( ( $rename:literal ) )? : $ftype:ty),* $(,)? } $($rest:tt)*) => {
76 #[derive(Deserialize)]
77 struct Response {
78 $(
79 $(#[serde(rename = $rename)])?
80 pub $field: $ftype,
81 )*
82 }
83 endpoint!(@types_entry $($rest)*)
84 };
85
86 (@types_entry $name:ident<$lt:lifetime> { $($field:ident $( ( $rename:literal ) )? : $ftype:ty),* $(,)? } $($rest:tt)*) => {
88 #[derive(Serialize, Deserialize)]
89 struct $name<$lt> {
90 $(
91 $(#[serde(rename = $rename)])?
92 pub $field: $ftype,
93 )*
94 }
95 endpoint!(@types_entry $($rest)*)
96 };
97 (@types_entry $name:ident { $($field:ident $( ( $rename:literal ) )? : $ftype:ty),* $(,)? } $($rest:tt)*) => {
99 #[derive(Serialize, Deserialize)]
100 struct $name {
101 $(
102 $(#[serde(rename = $rename)])?
103 pub $field: $ftype,
104 )*
105 }
106 endpoint!(@types_entry $($rest)*)
107 };
108
109 (@types_entry Request $($rest:tt)*) => {
111 #[derive(Serialize)] struct Request;
112 endpoint!(@types_entry $($rest)*)
113 };
114 (@types_entry Response $($rest:tt)*) => {
115 #[derive(Deserialize)] struct Response;
116 endpoint!(@types_entry $($rest)*)
117 };
118 (@types_entry $name:ident $($rest:tt)*) => {
119 #[derive(Serialize, Deserialize)] struct $name;
120 endpoint!(@types_entry $($rest)*)
121 };
122
123 (@types_entry) => {};
125
126 (@fn
130 attrs = [$(#[$attr:meta])*],
131 client = $client:ident,
132 name = $name:ident,
133 params = [$($param:ident : $param_ty:ty),*],
134 ret = $ret:ty,
135 method = $method:ident,
136 url = $url:expr,
137 paging = [$($p_var:ident, $p_limit:literal)?],
138 types = [$($types:tt)*],
139 pre = [$($pre:tt)*],
140 query = [$($qk:literal => $qv:expr),*],
141 body = [$($body_expr:expr)?],
142 decode = $decode:tt,
143 ) => {
144 $(#[$attr])*
145 #[allow(unused_variables)]
146 pub async fn $name(
147 $client: &mut $crate::client::Client,
148 $($param: $param_ty,)*
149 ) -> Result<$ret, $crate::Error> {
150 endpoint!(@types_entry $($types)*);
151 $($pre)*
152
153 let mut __query_pairs: ::std::vec::Vec<(&str, &str)> = ::std::vec::Vec::new();
155 $(
156 let __pq_limit = $p_var.limit.unwrap_or($p_limit).to_string();
157 let __pq_order = $p_var.order.unwrap_or_default().to_string();
158 let __pq_cursor = match $p_var.cursor {
159 Some(cursor) => cursor.to_string(),
160 None => ::std::string::String::new(),
161 };
162 __query_pairs.push(("limit", &__pq_limit));
163 __query_pairs.push(("sortOrder", &__pq_order));
164 __query_pairs.push(("cursor", &__pq_cursor));
165 )?
166
167 let url: ::std::string::String = ::std::format!($url);
168
169 $( __query_pairs.push(($qk, $qv)); )*
170 let query = if __query_pairs.is_empty() { None } else { Some(__query_pairs.as_slice()) };
171
172 let __response = $client
173 .requestor
174 .request(
175 endpoint!(@method $method),
176 &url,
177 endpoint!(@body $($body_expr)?),
178 query,
179 None,
180 )
181 .await?;
182 endpoint!(@decode __response, $ret, $decode)
183 }
184 };
185
186 (@body_inner
190 attrs = [$(#[$attr:meta])*],
191 client = $client:ident,
192 name = $name:ident,
193 params = [$($param:ident : $param_ty:ty),*],
194 ret = $ret:ty,
195 body = [
196 $method:ident $url:expr;
197 $(paging_query { $p_var:ident, limit = $p_limit:literal })?
198 $(types { $($types:tt)* })?
199 $(prelude { $($pre:tt)* })?
200 $(query { $($qk:literal => $qv:expr),* $(,)? })?
201 $(body_serialize { $body_expr:expr })?
202 map |$r:ident : $wrap:ty| $proj:expr
203 ],
204 ) => {
205 endpoint!(@fn
206 attrs = [$(#[$attr])*],
207 client = $client,
208 name = $name,
209 params = [$($param : $param_ty),*],
210 ret = $ret,
211 method = $method,
212 url = $url,
213 paging = [$($p_var, $p_limit)?],
214 types = [$($($types)*)?],
215 pre = [$($($pre)*)?],
216 query = [$($($qk => $qv),*)?],
217 body = [$($body_expr)?],
218 decode = [map $r : $wrap => $proj],
219 );
220 };
221
222 (@body_inner
226 attrs = [$(#[$attr:meta])*],
227 client = $client:ident,
228 name = $name:ident,
229 params = [$($param:ident : $param_ty:ty),*],
230 ret = $ret:ty,
231 body = [
232 $method:ident $url:expr;
233 $(paging_query { $p_var:ident, limit = $p_limit:literal })?
234 $(types { $($types:tt)* })?
235 $(prelude { $($pre:tt)* })?
236 $(query { $($qk:literal => $qv:expr),* $(,)? })?
237 $(body_serialize { $body_expr:expr })?
238 raw_bytes
239 ],
240 ) => {
241 endpoint!(@fn
242 attrs = [$(#[$attr])*],
243 client = $client,
244 name = $name,
245 params = [$($param : $param_ty),*],
246 ret = $ret,
247 method = $method,
248 url = $url,
249 paging = [$($p_var, $p_limit)?],
250 types = [$($($types)*)?],
251 pre = [$($($pre)*)?],
252 query = [$($($qk => $qv),*)?],
253 body = [$($body_expr)?],
254 decode = bytes,
255 );
256 };
257
258 (@body_inner
262 attrs = [$(#[$attr:meta])*],
263 client = $client:ident,
264 name = $name:ident,
265 params = [$($param:ident : $param_ty:ty),*],
266 ret = $ret:ty,
267 body = [
268 $method:ident $url:expr;
269 $(paging_query { $p_var:ident, limit = $p_limit:literal })?
270 $(types { $($types:tt)* })?
271 $(prelude { $($pre:tt)* })?
272 $(query { $($qk:literal => $qv:expr),* $(,)? })?
273 $(body_serialize { $body_expr:expr })?
274 void
275 ],
276 ) => {
277 endpoint!(@fn
278 attrs = [$(#[$attr])*],
279 client = $client,
280 name = $name,
281 params = [$($param : $param_ty),*],
282 ret = (),
283 method = $method,
284 url = $url,
285 paging = [$($p_var, $p_limit)?],
286 types = [$($($types)*)?],
287 pre = [$($($pre)*)?],
288 query = [$($($qk => $qv),*)?],
289 body = [$($body_expr)?],
290 decode = void,
291 );
292 };
293
294 (@body_inner
298 attrs = [$(#[$attr:meta])*],
299 client = $client:ident,
300 name = $name:ident,
301 params = [$($param:ident : $param_ty:ty),*],
302 ret = $ret:ty,
303 body = [
304 $method:ident $url:expr;
305 $(paging_query { $p_var:ident, limit = $p_limit:literal })?
306 $(types { $($types:tt)* })?
307 $(prelude { $($pre:tt)* })?
308 $(query { $($qk:literal => $qv:expr),* $(,)? })?
309 $(body_serialize { $body_expr:expr })?
310 ],
311 ) => {
312 endpoint!(@fn
313 attrs = [$(#[$attr])*],
314 client = $client,
315 name = $name,
316 params = [$($param : $param_ty),*],
317 ret = $ret,
318 method = $method,
319 url = $url,
320 paging = [$($p_var, $p_limit)?],
321 types = [$($($types)*)?],
322 pre = [$($($pre)*)?],
323 query = [$($($qk => $qv),*)?],
324 body = [$($body_expr)?],
325 decode = json,
326 );
327 };
328
329 (
333 types { $($types:tt)* }
334 $($rest:tt)*
335 ) => {
336 endpoint!(@types_entry $($types)*);
337 endpoint!($($rest)*);
338 };
339
340 (
344 $(#[$attr:meta])*
345 $name:ident($cli:ident $(, $param:ident : $param_ty:ty)*) -> $ret:ty {
346 $($body:tt)*
347 }
348 $($rest:tt)*
349 ) => {
350 endpoint!(@body_inner
351 attrs = [$(#[$attr])*],
352 client = $cli,
353 name = $name,
354 params = [$($param : $param_ty),*],
355 ret = $ret,
356 body = [$($body)*],
357 );
358 endpoint!($($rest)*);
359 };
360
361 (
365 $(#[$attr:meta])*
366 $name:ident($($param:ident : $param_ty:ty),*) -> $ret:ty {
367 $($body:tt)*
368 }
369 $($rest:tt)*
370 ) => {
371 endpoint!(@body_inner
372 attrs = [$(#[$attr])*],
373 client = client,
374 name = $name,
375 params = [$($param : $param_ty),*],
376 ret = $ret,
377 body = [$($body)*],
378 );
379 endpoint!($($rest)*);
380 };
381
382 () => {};
386}