use serde::Deserialize;
use serde_json::Error as JsonError;
use serde_urlencoded::ser::Error as UrlEncodeError;
#[derive(Debug, Error)]
pub enum ConversionError {
#[error("failed to convert from/to JSON")]
Json(#[from] JsonError),
#[error("failed to URL-encode data")]
UrlEncode(#[from] UrlEncodeError),
}
use thiserror::Error;
#[derive(Clone, Debug, Deserialize, Error, Eq, PartialEq)]
#[error("{message} ({code})")]
pub struct ApiError {
#[serde(rename = "code")]
pub code: u64,
#[serde(rename = "message")]
pub message: String,
}
macro_rules! EndpointNoParse {
( $(#[$docs:meta])* $pub:vis $name:ident($in:ty),
Ok => $out:ty, [$($(#[$ok_docs:meta])* $ok_status:ident,)*],
Err => $err:ident, [$($(#[$err_docs:meta])* $err_status:ident => $variant:ident,)*]
$($defs:tt)* ) => {
EndpointDef! {
$(#[$docs])* $pub $name($in),
Ok => $out, [$($ok_status,)*],
Err => $err, [
UNAUTHORIZED => AuthenticationFailed,
TOO_MANY_REQUESTS => RateLimitExceeded,
$($(#[$err_docs])* $err_status => $variant,)*
],
ConversionErr => crate::endpoint::ConversionError,
ApiErr => crate::endpoint::ApiError,
$($defs)*
}
};
}
macro_rules! Endpoint {
( $($input:tt)* ) => {
EndpointNoParse! {
$($input)*
fn parse(body: &[u8]) -> Result<Self::Output, Self::ConversionError> {
::serde_json::from_slice::<Self::Output>(body).map_err(Self::ConversionError::from)
}
fn parse_err(body: &[u8]) -> Result<Self::ApiError, Vec<u8>> {
::serde_json::from_slice::<Self::ApiError>(body).map_err(|_| body.to_vec())
}
}
};
}