mlb_api/endpoints/meta/kinds/
pitch_codes.rs1use 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}