1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
//! REST API client abstraction library.
//!
//! This is a very minimal crate
#![cfg_attr(nightly, feature(doc_auto_cfg))]
#![deny(clippy::all)]
#![forbid(unsafe_code)]
#![deny(clippy::cargo)]
#![warn(missing_docs)]
#![deny(rustdoc::invalid_html_tags)]
#![warn(rustdoc::missing_doc_code_examples)]
#![warn(clippy::pedantic)]
#![warn(clippy::nursery)]
// My project my choice, tabs are literally made for indentation, spaces not.
#![allow(clippy::tabs_in_doc_comments)]
use serde::de::DeserializeOwned;
#[cfg(feature = "reqwest")]
pub mod reqwest;
/// Possible request methods
#[derive(Debug, Clone)]
pub enum RequestMethod {
/// The request should use the `HEAD` method
Head,
/// The request should use the `GET` method
Get,
/// The request should use the `POST` method
Post,
/// The request should use the `PUT` method
Put,
/// The request should use the `PATCH` method
Patch,
/// The request should use the `DELETE` method
Delete,
}
/// Data for a HTTP request & response
pub trait Queryable<RequiredApiState, ResponseType: DeserializeOwned> {
/// The URL of the request
fn url(&self, state: &RequiredApiState) -> String;
/// The method to use for the request
///
/// Defaults to `GET`.
fn method(&self, _state: &RequiredApiState) -> RequestMethod {
RequestMethod::Get
}
/// Creates a JSON body for the request
///
/// Defaults to no body.
fn body(
&self, _state: &RequiredApiState,
) -> Option<serde_json::Result<Vec<u8>>> {
None
}
/// Deserializes the API response into the struct, by default using
/// `serde_json`.
///
/// Required to allow deserializing empty tuples for example,
/// because [`serde_json` considers empty values to not be valid JSON](https://github.com/serde-rs/json/issues/903).
///
/// # Errors
///
/// If deserializing fails
fn deserialize(&self, data: &[u8]) -> serde_json::Result<ResponseType> {
serde_json::from_slice(data)
}
}
/// A trait that should be implemented for API states,
/// to support giving access to the API state to the queryables.
pub trait FromApiState<ApiState> {
/// Gets the wanted state (`Self`) from the current `ApiState`,
/// by borrowing if possible
fn from_state(state: &ApiState) -> &Self;
}