#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md"))]
mod client;
mod logging;
pub mod models;
mod routes;
mod services;
use models::HttpError;
use serde::Deserialize;
pub use client::Client;
use models::ErrorCode;
use models::HttpResult;
use models::Wrapped;
macro_rules! response_error {
($code:expr, $err:expr) => {
::std::result::Result::Err($crate::models::HttpError::new($code, $err.to_string()))
};
}
pub(crate) async fn parse_response<T>(result: HttpResult) -> Result<T, HttpError>
where
T: for<'a> Deserialize<'a>,
{
let data = match result {
Ok(r) => r.text().await,
Err(e) => {
logging::error!(format!("HTTP request failed: {}", e.to_string()));
Err(e)
}
};
match data {
Err(e) => response_error!(ErrorCode::Unknown, e),
Ok(text) => {
logging::debug!(format!("INCOMING: {text}"));
match serde_json::from_str::<Wrapped<T>>(&text) {
Err(e) => response_error!(ErrorCode::Unknown, e),
Ok(r) => r.into(),
}
}
}
}
pub(crate) async fn parse_empty_response(result: HttpResult) -> Result<(), HttpError> {
let data = match result {
Ok(r) => r.text().await,
Err(e) => {
logging::error!(format!("HTTP request failed: {}", e.to_string()));
Err(e)
}
};
match data {
Err(e) => response_error!(ErrorCode::Unknown, e),
Ok(text) => {
logging::debug!(format!("INCOMING: {text}"));
match serde_json::from_str::<Wrapped<()>>(&text) {
Ok(r) => r.into(),
Err(e) => {
if text.contains("error") {
response_error!(ErrorCode::Unknown, e)
} else {
Ok(())
}
}
}
}
}
}
macro_rules! fetch {
($http:expr, $route:ident) => {
$http.fetch($route, None::<u8>)
};
($http:expr, $route:ident, $payload:expr) => {
$http.fetch($route, Some($payload))
};
}
pub(crate) use fetch;
#[cfg(test)]
mod test {
use crate::models::ErrorCode;
use crate::models::HttpError;
struct FakeHttp;
impl FakeHttp {
pub fn fetch(&self, route: u8, payload: Option<u8>) -> u8 {
let mut res = route;
if let Some(p) = payload {
res += p;
}
res
}
}
#[test]
fn response_error() {
let res: Result<(), _> = response_error!(ErrorCode::NotFound, "not found!");
assert_eq!(
res,
Err(HttpError::new(
ErrorCode::NotFound,
String::from("not found!")
))
);
}
#[test]
fn fetch_no_payload() {
let route = 69;
let res = fetch!(FakeHttp, route);
assert_eq!(res, 69);
}
#[test]
fn fetch_with_payload() {
let route = 69;
let res = fetch!(FakeHttp, route, 1);
assert_eq!(res, 70);
}
}