restson
This commit is contained in:
commit
a0d3c6cf9c
8 changed files with 2415 additions and 0 deletions
111
cli/src/request/get.rs
Normal file
111
cli/src/request/get.rs
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
/// GET macro
|
||||
#[macro_export]
|
||||
macro_rules! get {
|
||||
// Case 1: no query
|
||||
(
|
||||
$name:ident,
|
||||
( $( $arg:ident : $arg_ty:ty ),* ) => $path:literal -> $out:ty $(,)?
|
||||
) => {
|
||||
get!($name(), ( $( $arg : $arg_ty ),* ) => $path -> $out);
|
||||
};
|
||||
|
||||
// Case 2: empty query ()
|
||||
(
|
||||
$name:ident (),
|
||||
( $( $arg:ident : $arg_ty:ty ),* ) => $path:literal -> $out:ty $(,)?
|
||||
) => {
|
||||
#[bon::builder]
|
||||
pub fn $name(
|
||||
#[builder(finish_fn)] client: &restson::RestClient,
|
||||
$( #[builder(finish_fn)] $arg: $arg_ty ),*
|
||||
) -> impl std::future::Future<Output = Result<$out, restson::Error>> + '_ {
|
||||
#[derive(serde::Deserialize)]
|
||||
struct RP($out);
|
||||
|
||||
impl restson::RestPath<( $( $arg_ty ),* )> for RP {
|
||||
fn get_path(args: ( $( $arg_ty ),* )) -> Result<String, restson::Error> {
|
||||
let ( $( $arg ),* ) = args;
|
||||
Ok(format!($path, $( $arg = $arg ),* ))
|
||||
}
|
||||
}
|
||||
|
||||
async move {
|
||||
let result = client.get_with::<_, RP>(( $( $arg ),* ), &[]).await?;
|
||||
Ok(result.into_inner().0)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Case 3: query with flags / mixed types
|
||||
(
|
||||
$name:ident ( $( $query:tt ),* $(,)? ),
|
||||
( $( $arg:ident : $arg_ty:ty ),* ) => $path:literal -> $out:ty $(,)?
|
||||
) => {
|
||||
#[bon::builder]
|
||||
pub fn $name(
|
||||
#[builder(finish_fn)] client: &restson::RestClient,
|
||||
$( #[builder(finish_fn)] $arg: $arg_ty, )*
|
||||
$(
|
||||
get!(@query_field $query)
|
||||
)*
|
||||
) -> impl std::future::Future<Output = Result<$out, restson::Error>> + '_ {
|
||||
#[derive(serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct Query<'a> {
|
||||
$(
|
||||
get!(@query_field_struct $query)
|
||||
)*
|
||||
}
|
||||
|
||||
impl Query<'_> {
|
||||
fn as_pairs(&self) -> Vec<(&str, String)> {
|
||||
let mut out = Vec::new();
|
||||
$(
|
||||
get!(@push_pair out, self, $query)
|
||||
)*
|
||||
out
|
||||
}
|
||||
}
|
||||
|
||||
let query = Query {
|
||||
$(
|
||||
get!(@query_field_init $query)
|
||||
)*
|
||||
};
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
struct RP($out);
|
||||
|
||||
impl restson::RestPath<( $( $arg_ty ),* )> for RP {
|
||||
fn get_path(args: ( $( $arg_ty ),* )) -> Result<String, restson::Error> {
|
||||
let ( $( $arg ),* ) = args;
|
||||
Ok(format!($path, $( $arg = $arg ),* ))
|
||||
}
|
||||
}
|
||||
|
||||
async move {
|
||||
let result = client.get_with::<_, RP>(&query.as_pairs(), ( $( $arg ),* )).await?;
|
||||
Ok(result.0)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Query helpers
|
||||
(@query_field $field:ident) => { $field: Option<bool>, };
|
||||
(@query_field $field:ident = $ty:ty) => { $field: $ty, };
|
||||
|
||||
(@query_field_struct $field:ident) => { $field: Option<bool>, };
|
||||
(@query_field_struct $field:ident = $ty:ty) => { $field: $ty, };
|
||||
|
||||
(@query_field_init $field:ident) => { $field, };
|
||||
(@query_field_init $field:ident = $ty:ty) => { $field, };
|
||||
|
||||
(@push_pair $vec:ident, $self:ident, $field:ident = $ty:ty) => {
|
||||
$vec.push((stringify!($field), $self.$field.to_string()));
|
||||
};
|
||||
(@push_pair $vec:ident, $self:ident, $field:ident) => {
|
||||
if let Some(v) = &$self.$field {
|
||||
$vec.push((stringify!($field), v.to_string()));
|
||||
}
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue