#[macro_export]
macro_rules! endpoint {
(@method GET) => { ::reqwest::Method::GET };
(@method POST) => { ::reqwest::Method::POST };
(@method PUT) => { ::reqwest::Method::PUT };
(@method PATCH) => { ::reqwest::Method::PATCH };
(@method DELETE) => { ::reqwest::Method::DELETE };
(@body $body:expr) => { Some(&$body) };
(@body) => { None::<&()> };
(@decode $resp:ident, $ret:ty, json) => { $resp.json::<$ret>().await };
(@decode $resp:ident, $ret:ty, bytes) => { $resp.bytes().await };
(@decode $resp:ident, $ret:ty, void) => { Ok(()) };
(@decode $resp:ident, $ret:ty, [map $r:ident : $wrap:ty => $proj:expr]) => {
$resp.json::<$wrap>().await.map(|$r| $proj)
};
(@types_entry Request<$lt:lifetime> { $($field:ident $( ( $rename:literal ) )? : $ftype:ty),* $(,)? } $($rest:tt)*) => {
#[derive(Serialize)]
struct Request<$lt> {
$(
$(#[serde(rename = $rename)])?
pub $field: $ftype,
)*
}
endpoint!(@types_entry $($rest)*)
};
(@types_entry Request { $($field:ident $( ( $rename:literal ) )? : $ftype:ty),* $(,)? } $($rest:tt)*) => {
#[derive(Serialize)]
struct Request {
$(
$(#[serde(rename = $rename)])?
pub $field: $ftype,
)*
}
endpoint!(@types_entry $($rest)*)
};
(@types_entry Response<$lt:lifetime> { $($field:ident $( ( $rename:literal ) )? : $ftype:ty),* $(,)? } $($rest:tt)*) => {
#[derive(Deserialize)]
struct Response<$lt> {
$(
$(#[serde(rename = $rename)])?
pub $field: $ftype,
)*
}
endpoint!(@types_entry $($rest)*)
};
(@types_entry Response { $($field:ident $( ( $rename:literal ) )? : $ftype:ty),* $(,)? } $($rest:tt)*) => {
#[derive(Deserialize)]
struct Response {
$(
$(#[serde(rename = $rename)])?
pub $field: $ftype,
)*
}
endpoint!(@types_entry $($rest)*)
};
(@types_entry $name:ident<$lt:lifetime> { $($field:ident $( ( $rename:literal ) )? : $ftype:ty),* $(,)? } $($rest:tt)*) => {
#[derive(Serialize, Deserialize)]
struct $name<$lt> {
$(
$(#[serde(rename = $rename)])?
pub $field: $ftype,
)*
}
endpoint!(@types_entry $($rest)*)
};
(@types_entry $name:ident { $($field:ident $( ( $rename:literal ) )? : $ftype:ty),* $(,)? } $($rest:tt)*) => {
#[derive(Serialize, Deserialize)]
struct $name {
$(
$(#[serde(rename = $rename)])?
pub $field: $ftype,
)*
}
endpoint!(@types_entry $($rest)*)
};
(@types_entry Request $($rest:tt)*) => {
#[derive(Serialize)] struct Request;
endpoint!(@types_entry $($rest)*)
};
(@types_entry Response $($rest:tt)*) => {
#[derive(Deserialize)] struct Response;
endpoint!(@types_entry $($rest)*)
};
(@types_entry $name:ident $($rest:tt)*) => {
#[derive(Serialize, Deserialize)] struct $name;
endpoint!(@types_entry $($rest)*)
};
(@types_entry) => {};
(@fn
attrs = [$(#[$attr:meta])*],
client = $client:ident,
name = $name:ident,
params = [$($param:ident : $param_ty:ty),*],
ret = $ret:ty,
method = $method:ident,
url = $url:expr,
paging = [$($p_var:ident, $p_limit:literal)?],
types = [$($types:tt)*],
pre = [$($pre:tt)*],
query = [$($qk:literal => $qv:expr),*],
body = [$($body_expr:expr)?],
decode = $decode:tt,
) => {
$(#[$attr])*
#[allow(unused_variables)]
pub async fn $name(
$client: &mut $crate::client::Client,
$($param: $param_ty,)*
) -> Result<$ret, $crate::Error> {
endpoint!(@types_entry $($types)*);
$($pre)*
let mut __query_pairs: ::std::vec::Vec<(&str, &str)> = ::std::vec::Vec::new();
$(
let __pq_limit = $p_var.limit.unwrap_or($p_limit).to_string();
let __pq_order = $p_var.order.unwrap_or_default().to_string();
let __pq_cursor = match $p_var.cursor {
Some(cursor) => cursor.to_string(),
None => ::std::string::String::new(),
};
__query_pairs.push(("limit", &__pq_limit));
__query_pairs.push(("sortOrder", &__pq_order));
__query_pairs.push(("cursor", &__pq_cursor));
)?
let url: ::std::string::String = ::std::format!($url);
$( __query_pairs.push(($qk, $qv)); )*
let query = if __query_pairs.is_empty() { None } else { Some(__query_pairs.as_slice()) };
let __response = $client
.requestor
.request(
endpoint!(@method $method),
&url,
endpoint!(@body $($body_expr)?),
query,
None,
)
.await?;
endpoint!(@decode __response, $ret, $decode)
}
};
(@body_inner
attrs = [$(#[$attr:meta])*],
client = $client:ident,
name = $name:ident,
params = [$($param:ident : $param_ty:ty),*],
ret = $ret:ty,
body = [
$method:ident $url:expr;
$(paging_query { $p_var:ident, limit = $p_limit:literal })?
$(types { $($types:tt)* })?
$(prelude { $($pre:tt)* })?
$(query { $($qk:literal => $qv:expr),* $(,)? })?
$(body_serialize { $body_expr:expr })?
map |$r:ident : $wrap:ty| $proj:expr
],
) => {
endpoint!(@fn
attrs = [$(#[$attr])*],
client = $client,
name = $name,
params = [$($param : $param_ty),*],
ret = $ret,
method = $method,
url = $url,
paging = [$($p_var, $p_limit)?],
types = [$($($types)*)?],
pre = [$($($pre)*)?],
query = [$($($qk => $qv),*)?],
body = [$($body_expr)?],
decode = [map $r : $wrap => $proj],
);
};
(@body_inner
attrs = [$(#[$attr:meta])*],
client = $client:ident,
name = $name:ident,
params = [$($param:ident : $param_ty:ty),*],
ret = $ret:ty,
body = [
$method:ident $url:expr;
$(paging_query { $p_var:ident, limit = $p_limit:literal })?
$(types { $($types:tt)* })?
$(prelude { $($pre:tt)* })?
$(query { $($qk:literal => $qv:expr),* $(,)? })?
$(body_serialize { $body_expr:expr })?
raw_bytes
],
) => {
endpoint!(@fn
attrs = [$(#[$attr])*],
client = $client,
name = $name,
params = [$($param : $param_ty),*],
ret = $ret,
method = $method,
url = $url,
paging = [$($p_var, $p_limit)?],
types = [$($($types)*)?],
pre = [$($($pre)*)?],
query = [$($($qk => $qv),*)?],
body = [$($body_expr)?],
decode = bytes,
);
};
(@body_inner
attrs = [$(#[$attr:meta])*],
client = $client:ident,
name = $name:ident,
params = [$($param:ident : $param_ty:ty),*],
ret = $ret:ty,
body = [
$method:ident $url:expr;
$(paging_query { $p_var:ident, limit = $p_limit:literal })?
$(types { $($types:tt)* })?
$(prelude { $($pre:tt)* })?
$(query { $($qk:literal => $qv:expr),* $(,)? })?
$(body_serialize { $body_expr:expr })?
void
],
) => {
endpoint!(@fn
attrs = [$(#[$attr])*],
client = $client,
name = $name,
params = [$($param : $param_ty),*],
ret = (),
method = $method,
url = $url,
paging = [$($p_var, $p_limit)?],
types = [$($($types)*)?],
pre = [$($($pre)*)?],
query = [$($($qk => $qv),*)?],
body = [$($body_expr)?],
decode = void,
);
};
(@body_inner
attrs = [$(#[$attr:meta])*],
client = $client:ident,
name = $name:ident,
params = [$($param:ident : $param_ty:ty),*],
ret = $ret:ty,
body = [
$method:ident $url:expr;
$(paging_query { $p_var:ident, limit = $p_limit:literal })?
$(types { $($types:tt)* })?
$(prelude { $($pre:tt)* })?
$(query { $($qk:literal => $qv:expr),* $(,)? })?
$(body_serialize { $body_expr:expr })?
],
) => {
endpoint!(@fn
attrs = [$(#[$attr])*],
client = $client,
name = $name,
params = [$($param : $param_ty),*],
ret = $ret,
method = $method,
url = $url,
paging = [$($p_var, $p_limit)?],
types = [$($($types)*)?],
pre = [$($($pre)*)?],
query = [$($($qk => $qv),*)?],
body = [$($body_expr)?],
decode = json,
);
};
(
types { $($types:tt)* }
$($rest:tt)*
) => {
endpoint!(@types_entry $($types)*);
endpoint!($($rest)*);
};
(
$(#[$attr:meta])*
$name:ident($cli:ident $(, $param:ident : $param_ty:ty)*) -> $ret:ty {
$($body:tt)*
}
$($rest:tt)*
) => {
endpoint!(@body_inner
attrs = [$(#[$attr])*],
client = $cli,
name = $name,
params = [$($param : $param_ty),*],
ret = $ret,
body = [$($body)*],
);
endpoint!($($rest)*);
};
(
$(#[$attr:meta])*
$name:ident($($param:ident : $param_ty:ty),*) -> $ret:ty {
$($body:tt)*
}
$($rest:tt)*
) => {
endpoint!(@body_inner
attrs = [$(#[$attr])*],
client = client,
name = $name,
params = [$($param : $param_ty),*],
ret = $ret,
body = [$($body)*],
);
endpoint!($($rest)*);
};
() => {};
}