macro_rules! methods { ($($method:ident,)+) => { $( pub async fn $method serde::Deserialize<'de>>(&self, url: String) -> Result { log::trace!("{} {}", stringify!($method), url); let response = self.send( self.http_client.$method(&url) ).await?; deserialise_response(response).await } )+ }; } macro_rules! route_v1_paged { (($method:ident) $name:ident: $url:expr => $ret:ty) => { doc_comment::doc_comment! { concat!( "Equivalent to `", stringify!($method), " /api/v1/", $url, "`\n", "# Errors\n", "If `access_token` is not set.", ), pub async fn $name<'a>(&'a self) -> Result> { let url = self.route(concat!("/api/v1/", $url)); let response = self.send( self.http_client.$method(&url) ).await?; Page::new(self, response).await } } }; ((get ($($(#[$m:meta])* $param:ident: $typ:ty,)*)) $name:ident: $url:expr => $ret:ty) => { doc_comment::doc_comment! { concat!( "Equivalent to `get /api/v1/", $url, "` with query params\n", "# Errors\n", "If `access_token` is not set.", ), pub async fn $name<'a, 'b>(&'b self, $($param: $typ,)*) -> Result> { use serde_urlencoded; use serde::Serialize; #[derive(Serialize)] struct Data<'a> { $( $( #[$m] )* $param: $typ, )* #[serde(skip)] _marker: ::std::marker::PhantomData<&'a ()>, } let qs_data = Data { $( $param, )* _marker: ::std::marker::PhantomData, }; let qs = serde_urlencoded::to_string(&qs_data)?; let url = format!(concat!("/api/v1/", $url, "?{}"), &qs); let response = self.send( self.http_client.get(&url) ).await?; Page::new(self, response).await } } }; } macro_rules! route_v2 { ((get ($($(#[$m:meta])* $param:ident: $typ:ty,)*)) $name:ident: $url:expr => $ret:ty) => { doc_comment::doc_comment! { concat!( "Equivalent to `get /api/v2/",$url,"`\n", "# Errors\n", "If `access_token` is not set." ), pub async fn $name<'a>(&self, $($param: $typ,)*) -> Result<$ret> { use serde_urlencoded; use serde::Serialize; #[derive(Serialize)] struct Data<'a> { $( $( #[$m] )* $param: $typ, )* #[serde(skip)] _marker: ::std::marker::PhantomData<&'a ()>, } let qs_data = Data { $( $param, )* _marker: ::std::marker::PhantomData, }; let qs = serde_urlencoded::to_string(&qs_data)?; let url = format!(concat!("/api/v2/", $url, "?{}"), &qs); self.get(self.route(&url)).await } } }; } macro_rules! route_v1 { ((get ($($param:ident: $typ:ty,)*)) $name:ident: $url:expr => $ret:ty) => { doc_comment::doc_comment! { concat!( "Equivalent to `get /api/v1/", $url, "`\n", "# Errors\n", "If `access_token` is not set." ), pub async fn $name<'a>(&self, $($param: $typ,)*) -> Result<$ret> { use serde_urlencoded; use serde::Serialize; #[derive(Serialize)] struct Data<'a> { $( $param: $typ, )* #[serde(skip)] _marker: ::std::marker::PhantomData<&'a ()>, } let qs_data = Data { $( $param, )* _marker: ::std::marker::PhantomData, }; let qs = serde_urlencoded::to_string(&qs_data)?; let url = format!(concat!("/api/v1/", $url, "?{}"), &qs); self.get(self.route(&url)).await } } }; (($method:ident ($($param:ident: $typ:ty,)*)) $name:ident: $url:expr => $ret:ty) => { doc_comment::doc_comment! { concat!( "Equivalent to `", stringify!($method), " /api/v1/", $url, "`\n", "# Errors\n", "If `access_token` is not set." ), pub async fn $name(&self, $($param: $typ,)*) -> Result<$ret> { let form_data = serde_json::json!({ $( stringify!($param): $param, )* }); let response = self.send( self.http_client.$method(&self.route(concat!("/api/v1/", $url))) .json(&form_data) ).await?; let status = response.status().clone(); if status.is_client_error() { return Err(Error::Client(status)); } else if status.is_server_error() { return Err(Error::Server(status)); } deserialise_response(response).await } } }; (($method:ident) $name:ident: $url:expr => $ret:ty) => { doc_comment::doc_comment! { concat!( "Equivalent to `", stringify!($method), " /api/v1/", $url, "`\n", "# Errors\n", "If `access_token` is not set." ), pub async fn $name(&self) -> Result<$ret> { self.$method(self.route(concat!("/api/v1/", $url))).await } } }; } macro_rules! route_v1_id { (($method:ident) $name:ident: $url:expr => $ret:ty) => { doc_comment::doc_comment! { concat!( "Equivalent to `", stringify!($method), " /api/v1/", $url, "`\n", "# Errors\n", "If `access_token` is not set." ), pub async fn $name(&self, id: &str) -> Result<$ret> { self.$method(self.route(&format!(concat!("/api/v1/", $url), id))).await } } } } macro_rules! route_v1_paged_id { (($method:ident) $name:ident: $url:expr => $ret:ty) => { doc_comment::doc_comment! { concat!( "Equivalent to `", stringify!($method), " /api/v1/", $url, "` with ID\n", "# Errors\n", "If `access_token` is not set." ), pub async fn $name<'a>(&'a self, id: &str) -> Result> { let url = self.route(&format!(concat!("/api/v1/", $url), id)); let response = self.send( self.http_client.$method(&url) ).await?; Page::new(self, response).await } } }; }