Skip to main content

mlb_api/request/
mod.rs

1//! Handles the request portion of the code; uses [`::ureq`] or [`::reqwest`] for blocking or non-blocking networking.
2
3use serde::de::DeserializeOwned;
4use crate::MLBError;
5
6#[cfg(feature = "ureq")]
7mod ureq;
8
9#[cfg(feature = "ureq")]
10pub use ureq::*;
11
12#[cfg(feature = "reqwest")]
13mod reqwest;
14#[cfg(feature = "reqwest")]
15pub use reqwest::*;
16
17/// Error variant
18pub type Result<T, E = Error> = std::result::Result<T, E>;
19
20/// Represents the error returned when making an HTTP request for stats
21#[derive(Debug, thiserror::Error)]
22pub enum Error {
23	/// Error from [`::ureq`], likely network error.
24	#[cfg(feature = "ureq")]
25	#[error(transparent)]
26	Network(#[from] ::ureq::Error),
27	/// Error from [`::reqwest`], likely network error.
28	#[cfg(feature = "reqwest")]
29	#[error(transparent)]
30	Network(#[from] ::reqwest::Error),
31	/// Error from [`serde`], likely deserialization error.
32	#[cfg(not(feature = "_debug"))]
33	#[error(transparent)]
34	Serde(#[from] serde_json::Error),
35	/// Error from [`serde`], likely deserialization error.
36	#[cfg(feature = "_debug")]
37	#[error(transparent)]
38	Serde(#[from] serde_path_to_error::Error<serde_json::Error>),
39	/// Error from MLB, likely bad payload.
40	#[error(transparent)]
41	MLB(#[from] MLBError),
42}
43
44#[cfg(all(feature = "reqwest", feature = "ureq"))]
45compile_error!("Only one http backend is allowed!");
46
47/// A type in which you can request the response from its URL
48pub trait RequestURL: ToString {
49	type Response: DeserializeOwned;
50
51	/// Get the response from the URL
52	#[cfg(feature = "ureq")]
53	fn get(&self) -> Result<Self::Response>
54	where
55		Self: Sized,
56	{
57		let url = self.to_string();
58		get::<Self::Response>(url)
59	}
60
61	/// Get the response from the URL
62	#[cfg(feature = "reqwest")]
63	fn get(&self) -> impl Future<Output = Result<Self::Response>>
64	where
65		Self: Sized,
66	{
67		let url = self.to_string();
68		get::<Self::Response>(url)
69	}
70}
71
72/// Extension for request URLs such that `build_and_get` exists.
73pub trait RequestURLBuilderExt where Self: Sized {
74	/// Built type; [`PersonRequest`](crate::person::PersonRequest) for [`PersonRequestBuilder`](crate::person::PersonRequestBuilder)
75	type Built: RequestURL + From<Self>;
76
77	#[cfg(feature = "ureq")]
78	fn build_and_get(self) -> Result<<Self::Built as RequestURL>::Response> {
79		let built = Self::Built::from(self);
80		let url = built.to_string();
81		if cfg!(feature = "_debug") && cfg!(test) {
82			println!("url = {url}");
83		}
84		get::<<Self::Built as RequestURL>::Response>(url)
85	}
86
87	#[cfg(feature = "reqwest")]
88	fn build_and_get(self) -> impl Future<Output = Result<<Self::Built as RequestURL>::Response>> {
89		async {
90			let built = Self::Built::from(self);
91			let url = built.to_string();
92			if cfg!(feature = "_debug") && cfg!(test) {
93				println!("url = {url}");
94			}
95			get::<<Self::Built as RequestURL>::Response>(url).await
96		}
97	}
98}
99