Skip to main content

mlb_api/request/
mod.rs

1//! Handles the request portion of the code
2
3use serde::de::DeserializeOwned;
4use crate::MLBError;
5
6/// # Errors
7/// See variants of [`Error`]
8#[cfg(not(feature = "_debug"))]
9pub async fn get<T: DeserializeOwned>(url: String) -> Result<T> {
10	let bytes = reqwest::Client::builder().build()?.get(url).send().await?.bytes().await?;
11	let e = match serde_json::from_slice::<'_, T>(&bytes) {
12		Ok(t) => return Ok(t),
13		Err(e) => Error::Serde(e),
14	};
15	Err(Error::MLB(serde_json::from_slice::<'_, MLBError>(&bytes).map_err(|_| e)?))
16}
17
18/// # Errors
19/// See variants of [`Error`]
20#[cfg(feature = "_debug")]
21pub async fn get<T: DeserializeOwned>(url: String) -> Result<T> {
22	let bytes = reqwest::Client::builder().build()?.get(url).send().await?.bytes().await?;
23	let mut de = serde_json::Deserializer::from_slice(&bytes);
24	let result: std::result::Result<T, serde_path_to_error::Error<_>> = serde_path_to_error::deserialize(&mut de);
25	let e = match result {
26		Ok(t) => return Ok(t),
27		Err(e) => Error::Serde(e),
28	};
29	Err(Error::MLB(serde_json::from_slice::<'_, MLBError>(&bytes).map_err(|_| e)?))
30}
31
32/// Error variant
33pub type Result<T, E = Error> = std::result::Result<T, E>;
34
35/// Represents the error returned when making an HTTP request for stats
36#[derive(Debug, thiserror::Error)]
37pub enum Error {
38	#[error(transparent)]
39	Network(#[from] ::reqwest::Error),
40	/// Error from [`serde`], likely deserialization error.
41	#[cfg(not(feature = "_debug"))]
42	#[error(transparent)]
43	Serde(#[from] serde_json::Error),
44	/// Error from [`serde`], likely deserialization error.
45	#[cfg(feature = "_debug")]
46	#[error(transparent)]
47	Serde(#[from] serde_path_to_error::Error<serde_json::Error>),
48	/// Error from MLB, likely bad payload.
49	#[error(transparent)]
50	MLB(#[from] MLBError),
51}
52
53/// A type in which you can request the response from its URL
54pub trait RequestURL: ToString {
55	type Response: DeserializeOwned;
56
57	/// Get the response from the URL
58	fn get(&self) -> impl Future<Output = Result<Self::Response>>
59	where
60		Self: Sized,
61	{
62		let url = self.to_string();
63		get::<Self::Response>(url)
64	}
65}
66
67/// Extension for request URLs such that `build_and_get` exists.
68pub trait RequestURLBuilderExt where Self: Sized {
69	/// Built type; [`PersonRequest`](crate::person::PersonRequest) for [`PersonRequestBuilder`](crate::person::PersonRequestBuilder)
70	type Built: RequestURL + From<Self>;
71
72	fn build_and_get(self) -> impl Future<Output = Result<<Self::Built as RequestURL>::Response>> {
73		async {
74			let built = Self::Built::from(self);
75			let url = built.to_string();
76			if cfg!(feature = "_debug") && cfg!(test) {
77				println!("url = {url}");
78			}
79			get::<<Self::Built as RequestURL>::Response>(url).await
80		}
81	}
82}
83