feat: added readme and documentation

This commit is contained in:
pyrite 2025-08-07 16:28:00 +02:00
parent daeff053f4
commit 8794c076b3
Signed by: pyrite
GPG key ID: 7F1BA9170CD35D15
8 changed files with 279 additions and 26 deletions

View file

@ -1,22 +1,25 @@
use std::future::Future;
use futures::{Stream, StreamExt};
#[cfg(feature = "reqwest")]
use http::{header::AUTHORIZATION, HeaderMap, HeaderValue};
use serde::Deserialize;
#[cfg(feature = "reqwest")]
use crate::request::ApiRequest;
use crate::request::{ApiResponse, IntoRequest};
#[cfg(feature = "scopes")]
use crate::scopes::{
BulkFactionScope, BulkForumScope, BulkMarketScope, BulkRacingScope, BulkTornScope,
BulkUserScope, FactionScope, ForumScope, MarketScope, RacingScope, TornScope, UserScope,
};
use crate::{
request::{ApiRequest, ApiResponse, IntoRequest},
scopes::{BulkKeyScope, KeyScope},
BulkFactionScope, BulkForumScope, BulkKeyScope, BulkMarketScope, BulkRacingScope,
BulkTornScope, BulkUserScope, FactionScope, ForumScope, KeyScope, MarketScope, RacingScope,
TornScope, UserScope,
};
/// Central trait of the crate that is used to execute api requests.
pub trait Executor: Sized {
type Error: From<serde_json::Error> + From<crate::ApiError> + Send;
/// Execute an api request.
fn execute<R>(
self,
request: R,
@ -24,12 +27,13 @@ pub trait Executor: Sized {
where
R: IntoRequest;
/// Execute a request and deserialise the associated response type.
fn fetch<R>(self, request: R) -> impl Future<Output = Result<R::Response, Self::Error>> + Send
where
R: IntoRequest,
{
// HACK: workaround for not using `async` in trait declaration.
// The future is `Send` but `&self` might not be.
// The future is `Send` but `self` might not be.
let fut = self.execute(request);
async {
let resp = fut.await.1?;
@ -59,9 +63,11 @@ pub trait Executor: Sized {
}
}
/// Trait that is used for the execution of bulk requests.
pub trait BulkExecutor: Sized {
type Error: From<serde_json::Error> + From<crate::ApiError> + Send;
/// Generate response stream from a set of api requests.
fn execute<R>(
self,
requests: impl IntoIterator<Item = R>,
@ -69,6 +75,7 @@ pub trait BulkExecutor: Sized {
where
R: IntoRequest;
/// Generate a stream of deserialised responsed based on a set of api requests.
fn fetch_many<R>(
self,
requests: impl IntoIterator<Item = R>,
@ -115,6 +122,7 @@ pub trait BulkExecutor: Sized {
}
}
/// Convenience trait extension to provide easy access to all scopes
#[cfg(feature = "scopes")]
pub trait ExecutorExt: Executor + Sized {
fn user(self) -> UserScope<Self>;
@ -166,6 +174,7 @@ where
}
}
/// Convenience trait extension to provide easy access to all bulk scopes
#[cfg(feature = "scopes")]
pub trait BulkExecutorExt: BulkExecutor + Sized {
fn user_bulk(self) -> BulkUserScope<Self>;
@ -217,9 +226,13 @@ where
}
}
#[cfg(feature = "reqwest")]
/// Default executor based on the reqwest HTTP client.
pub struct ReqwestClient(reqwest::Client);
#[cfg(feature = "reqwest")]
impl ReqwestClient {
/// Instantiate a new client which will use the provided API key.
pub fn new(api_key: &str) -> Self {
let mut headers = HeaderMap::with_capacity(1);
headers.insert(
@ -237,6 +250,7 @@ impl ReqwestClient {
}
}
#[cfg(feature = "reqwest")]
impl ReqwestClient {
async fn execute_api_request(&self, request: ApiRequest) -> Result<ApiResponse, crate::Error> {
let url = request.url();
@ -249,6 +263,7 @@ impl ReqwestClient {
}
}
#[cfg(feature = "reqwest")]
impl Executor for &ReqwestClient {
type Error = crate::Error;
@ -261,6 +276,7 @@ impl Executor for &ReqwestClient {
}
}
#[cfg(feature = "reqwest")]
impl BulkExecutor for &ReqwestClient {
type Error = crate::Error;
@ -277,7 +293,7 @@ impl BulkExecutor for &ReqwestClient {
}
}
#[cfg(test)]
#[cfg(all(test, feature = "reqwest"))]
mod test {
use crate::{scopes::test::test_client, ApiError, Error};