mlb_api/endpoints/meta/kinds/
pitch_codes.rs

1use crate::endpoints::meta::{MetaEndpointUrl, MetaKind};
2use derive_more::{Deref, DerefMut, Display, From};
3use serde::Deserialize;
4use std::ops::{Deref, DerefMut};
5use strum::EnumTryAs;
6use crate::cache::{EndpointEntryCache, HydratedCacheTable};
7use crate::{rwlock_const_new, RwLock};
8use crate::endpoints::StatsAPIUrl;
9
10#[derive(Debug, Deserialize, Deref, DerefMut, PartialEq, Eq, Clone)]
11#[serde(rename_all = "camelCase")]
12pub struct HydratedPitchCode {
13	pub description: String,
14	#[serde(rename = "swingStatus")]
15	pub has_swing: bool,
16	#[serde(rename = "swingMissStatus")]
17	pub is_whiff: bool,
18	#[serde(rename = "swingContactStatus")]
19	pub swing_made_contact: bool,
20	#[serde(rename = "strikeStatus")]
21	pub is_strike: bool,
22	#[serde(rename = "ballStatus")]
23	pub is_ball: bool,
24	#[serde(rename = "pitchStatus")]
25	pub is_pitch: bool,
26	pub pitch_result_text: String,
27	#[serde(rename = "buntAttemptStatus")]
28	pub is_bunt_attempt: bool,
29	#[serde(rename = "contactStatus")]
30	pub made_contact: bool,
31
32	#[deref]
33	#[deref_mut]
34	#[serde(flatten)]
35	inner: IdentifiablePitchCode,
36}
37
38#[derive(Debug, Deserialize, PartialEq, Eq, Clone)]
39pub struct IdentifiablePitchCode {
40	#[serde(rename = "code")] pub id: PitchCodeId,
41}
42
43#[repr(transparent)]
44#[derive(Debug, Deserialize, Deref, Display, PartialEq, Eq, Clone, Hash)]
45pub struct PitchCodeId(String);
46
47#[derive(Debug, Deserialize, Eq, Clone, From, EnumTryAs)]
48#[serde(untagged)]
49pub enum PitchCode {
50	Hydrated(HydratedPitchCode),
51	Identifiable(IdentifiablePitchCode),
52}
53
54impl PartialEq for PitchCode {
55	fn eq(&self, other: &Self) -> bool {
56		self.id == other.id
57	}
58}
59
60impl Deref for PitchCode {
61	type Target = IdentifiablePitchCode;
62
63	fn deref(&self) -> &Self::Target {
64		match self {
65			Self::Hydrated(inner) => inner,
66			Self::Identifiable(inner) => inner,
67		}
68	}
69}
70
71impl DerefMut for PitchCode {
72	fn deref_mut(&mut self) -> &mut Self::Target {
73		match self {
74			Self::Hydrated(inner) => inner,
75			Self::Identifiable(inner) => inner,
76		}
77	}
78}
79
80impl MetaKind for PitchCode {
81	const ENDPOINT_NAME: &'static str = "pitchCodes";
82}
83
84static CACHE: RwLock<HydratedCacheTable<PitchCode>> = rwlock_const_new(HydratedCacheTable::new());
85
86impl EndpointEntryCache for PitchCode {
87	type HydratedVariant = HydratedPitchCode;
88	type Identifier = PitchCodeId;
89	type URL = MetaEndpointUrl<Self>;
90
91	fn into_hydrated_variant(self) -> Option<Self::HydratedVariant> {
92		self.try_as_hydrated()
93	}
94
95	fn id(&self) -> &Self::Identifier {
96		&self.id
97	}
98
99	fn url_for_id(_id: &Self::Identifier) -> Self::URL {
100		MetaEndpointUrl::new()
101	}
102
103	fn get_entries(response: <Self::URL as StatsAPIUrl>::Response) -> impl IntoIterator<Item=Self>
104	where
105		Self: Sized
106	{
107		response.entries
108	}
109
110	fn get_hydrated_cache_table() -> &'static RwLock<HydratedCacheTable<Self>>
111	where
112		Self: Sized
113	{
114		&CACHE
115	}
116}
117
118#[cfg(test)]
119mod tests {
120	use crate::endpoints::StatsAPIUrl;
121	use crate::endpoints::meta::MetaEndpointUrl;
122
123	#[tokio::test]
124	async fn parse_meta() {
125		let _response = MetaEndpointUrl::<super::PitchCode>::new().get().await.unwrap();
126	}
127}