mlb_api/requests/meta/
mod.rs1macro_rules! meta_kind_impl {
14 ($endpoint:literal => $name:ty) => {
15 impl $crate::meta::MetaKind for $name {
16 type Complete = $name;
17
18 const ENDPOINT_NAME: &'static str = $endpoint;
19 }
20 };
21}
22
23macro_rules! test_impl {
24 ($name:ty) => {
25 #[cfg(test)]
26 mod tests {
27 use super::*;
28 use crate::request::RequestURL;
29
30 #[tokio::test]
31 async fn parse_meta() {
32 let _response = $crate::meta::MetaRequest::<$name>::new().get().await.unwrap();
33 }
34 }
35 };
36}
37
38macro_rules! tiered_request_entry_cache_impl {
39 ($complete:ident.$id_field:ident: $id:ident) => {
40 tiered_request_entry_cache_impl!([$complete].$id_field: $id);
41 };
42 ([$complete:ident $(, $($others:ident)*)?].$id_field:ident: $id:ident) => {
43 #[cfg(feature = "cache")]
44 static CACHE: $crate::RwLock<$crate::cache::CacheTable<$complete>> = $crate::rwlock_const_new($crate::cache::CacheTable::new());
45
46 impl $crate::cache::Requestable for $complete {
47 type Identifier = $id;
48 type URL = $crate::meta::MetaRequest<Self>;
49
50 fn id(&self) -> &Self::Identifier {
51 &self.$id_field
52 }
53
54 fn url_for_id(_id: &Self::Identifier) -> Self::URL {
55 $crate::meta::MetaRequest::new()
56 }
57
58 fn get_entries(response: <Self::URL as $crate::request::RequestURL>::Response) -> impl IntoIterator<Item=Self>
59 where
60 Self: Sized
61 {
62 response.entries
63 }
64
65 #[cfg(feature = "cache")]
66 fn get_cache_table() -> &'static $crate::RwLock<$crate::cache::CacheTable<Self>>
67 where
68 Self: Sized
69 {
70 &CACHE
71 }
72 }
73
74 entrypoint!($complete.$id_field => $complete);
75 $($(
76 entrypoint!($others.$id_field => $complete);
77 )*)?
78 entrypoint!($id => $complete);
79 };
80}
81
82macro_rules! static_request_entry_cache_impl {
83 ($name:ident) => {
84 #[cfg(feature = "cache")]
85 static CACHE: $crate::RwLock<$crate::cache::CacheTable<$name>> = $crate::rwlock_const_new($crate::cache::CacheTable::new());
86
87 impl $crate::cache::Requestable for $name {
88 type Identifier = Self;
89 type URL = $crate::meta::MetaRequest<Self>;
90
91 fn id(&self) -> &Self::Identifier {
92 self
93 }
94
95 fn url_for_id(_id: &Self::Identifier) -> Self::URL {
96 $crate::meta::MetaRequest::new()
97 }
98
99 fn get_entries(response: <Self::URL as $crate::request::RequestURL>::Response) -> impl IntoIterator<Item=Self>
100 where
101 Self: Sized
102 {
103 response.entries
104 }
105
106 #[cfg(feature = "cache")]
107 fn get_cache_table() -> &'static $crate::RwLock<$crate::cache::CacheTable<Self>>
108 where
109 Self: Sized
110 {
111 &CACHE
112 }
113 }
114
115 entrypoint!($name => $name);
116 };
117}
118
119mod baseball_stats;
120mod event_types;
121mod game_status;
122mod game_types;
123mod hit_trajectories;
124mod job_types;
125mod languages;
126mod league_leader_types;
127mod logical_events;
128mod metrics;
129mod pitch_codes;
130mod pitch_types;
131mod platforms;
132mod positions;
133mod review_reasons;
134mod roster_types;
135mod schedule_event_types;
136mod situations;
137mod sky;
138mod standings_types;
139mod stat_groups;
140mod stat_types;
141mod wind_direction;
142
143pub use baseball_stats::*;
144pub use event_types::*;
145pub use game_status::*;
146pub use game_types::*;
147pub use hit_trajectories::*;
148pub use job_types::*;
149pub use languages::*;
150pub use league_leader_types::*;
151pub use logical_events::*;
152pub use metrics::*;
153pub use pitch_codes::*;
154pub use pitch_types::*;
155pub use platforms::*;
156pub use positions::*;
157pub use review_reasons::*;
158pub use roster_types::*;
159pub use schedule_event_types::*;
160pub use situations::*;
161pub use sky::*;
162pub use standings_types::*;
163pub use stat_groups::*;
164pub use stat_types::*;
165pub use wind_direction::*;
166
167use crate::request::RequestURL;
168use derive_more::{Deref, DerefMut};
169use serde::de::{DeserializeOwned, Error, MapAccess, SeqAccess};
170use serde::{de, Deserialize, Deserializer};
171use std::fmt::{Debug, Display, Formatter};
172use std::marker::PhantomData;
173
174pub trait MetaKind {
176 type Complete: Debug + DeserializeOwned + PartialEq + Clone;
177
178 const ENDPOINT_NAME: &'static str;
179}
180
181#[derive(Debug, Deref, DerefMut, PartialEq, Clone)]
183pub struct MetaResponse<T: MetaKind> {
184 pub entries: Vec<<T as MetaKind>::Complete>,
185}
186
187impl<'de, T: MetaKind> Deserialize<'de> for MetaResponse<T> {
188 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
189 where
190 D: Deserializer<'de>,
191 {
192 struct Visitor<T: MetaKind>(PhantomData<T>);
193
194 impl<'de, T: MetaKind> de::Visitor<'de> for Visitor<T> {
195 type Value = MetaResponse<T>;
196
197 fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
198 formatter.write_str("either copyright and other entry, or just raw list")
199 }
200
201 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
202 where
203 A: SeqAccess<'de>,
204 {
205 let mut entries = vec![];
206 while let Some(element) = seq.next_element::<<T as MetaKind>::Complete>()? {
207 entries.push(element);
208 }
209 Ok(MetaResponse { entries })
210 }
211
212 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
213 where
214 A: MapAccess<'de>,
215 {
216 while let Some(key) = map.next_key::<String>()? {
217 if key != "copyright" {
218 let entries = map.next_value::<Vec<<T as MetaKind>::Complete>>()?;
219 return Ok(MetaResponse { entries });
220 }
221 }
222 Err(Error::custom("Could not find a field that deserializes to the entries"))
223 }
224 }
225
226 deserializer.deserialize_any(Visitor(PhantomData))
227 }
228}
229
230pub struct MetaRequest<T: MetaKind> {
232 _marker: PhantomData<T>,
233}
234
235impl<T: MetaKind> Default for MetaRequest<T> {
236 fn default() -> Self {
237 Self { _marker: PhantomData }
238 }
239}
240
241impl<T: MetaKind> MetaRequest<T> {
242 #[must_use]
243 pub const fn new() -> Self {
244 Self {
245 _marker: PhantomData
246 }
247 }
248}
249
250impl<T: MetaKind> Display for MetaRequest<T> {
251 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
252 write!(f, "http://statsapi.mlb.com/api/v1/{}", T::ENDPOINT_NAME)
253 }
254}
255
256impl<T: MetaKind> RequestURL for MetaRequest<T> {
257 type Response = MetaResponse<T>;
258}