mlb_api/endpoints/awards/
mod.rs

1use crate::endpoints::StatsAPIUrl;
2use crate::endpoints::league::{League, LeagueId};
3use crate::endpoints::sports::{Sport, SportId};
4use crate::{gen_params, rwlock_const_new, RwLock};
5use crate::types::Copyright;
6use derive_more::{Deref, DerefMut, Display, From};
7use serde::Deserialize;
8use std::fmt::{Display, Formatter};
9use std::ops::Deref;
10use strum::EnumTryAs;
11use crate::cache::{HydratedCacheTable, EndpointEntryCache};
12
13#[derive(Debug, Deserialize, PartialEq, Eq, Clone)]
14pub struct AwardsResponse {
15	pub copyright: Copyright,
16	pub awards: Vec<Award>,
17}
18
19#[derive(Debug, Deserialize, Deref, DerefMut, PartialEq, Eq, Clone)]
20pub struct HydratedAward {
21	pub name: String,
22	pub description: Option<String>,
23	pub sport: Option<Sport>,
24	pub league: Option<League>,
25	pub notes: Option<String>,
26
27	#[deref]
28	#[deref_mut]
29	#[serde(flatten)]
30	inner: IdentifiableAward,
31}
32
33#[derive(Debug, Deserialize, PartialEq, Eq, Clone)]
34pub struct IdentifiableAward {
35	pub id: AwardId,
36}
37
38#[repr(transparent)]
39#[derive(Debug, Deserialize, Deref, Display, PartialEq, Eq, Clone, Hash)]
40pub struct AwardId(String);
41
42#[derive(Debug, Deserialize, Eq, Clone, From, EnumTryAs)]
43#[serde(untagged)]
44pub enum Award {
45	Hydrated(HydratedAward),
46	Identifiable(IdentifiableAward),
47}
48
49impl PartialEq for Award {
50	fn eq(&self, other: &Self) -> bool {
51		self.id == other.id
52	}
53}
54
55impl Deref for Award {
56	type Target = IdentifiableAward;
57
58	fn deref(&self) -> &Self::Target {
59		match self {
60			Self::Hydrated(inner) => inner,
61			Self::Identifiable(inner) => inner,
62		}
63	}
64}
65
66#[derive(Default)]
67pub struct AwardEndpointUrl {
68	pub award_id: Option<AwardId>,
69	pub sport_id: Option<SportId>,
70	pub league_id: Option<LeagueId>,
71	pub season: Option<u16>,
72}
73
74impl Display for AwardEndpointUrl {
75	fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
76		write!(
77			f,
78			"http://statsapi.mlb.com/api/v1/awards{}",
79			gen_params! { "awardId"?: self.award_id.as_ref(), "sportId"?: self.sport_id, "leagueId"?: self.league_id, "season"?: self.season }
80		)
81	}
82}
83
84impl StatsAPIUrl for AwardEndpointUrl {
85	type Response = AwardsResponse;
86}
87
88static CACHE: RwLock<HydratedCacheTable<Award>> = rwlock_const_new(HydratedCacheTable::new());
89
90impl EndpointEntryCache for Award {
91	type HydratedVariant = HydratedAward;
92	type Identifier = AwardId;
93	type URL = AwardEndpointUrl;
94
95	fn into_hydrated_variant(self) -> Option<Self::HydratedVariant> {
96		self.try_as_hydrated()
97	}
98
99	fn id(&self) -> &Self::Identifier {
100		&self.id
101	}
102
103	fn url_for_id(id: &Self::Identifier) -> Self::URL {
104		AwardEndpointUrl {
105			award_id: Some(id.clone()),
106			sport_id: None,
107			league_id: None,
108			season: None,
109		}
110	}
111
112	fn get_entries(response: <Self::URL as StatsAPIUrl>::Response) -> impl IntoIterator<Item=Self>
113	where
114		Self: Sized
115	{
116		response.awards
117	}
118
119	fn get_hydrated_cache_table() -> &'static RwLock<HydratedCacheTable<Self>>
120	where
121		Self: Sized
122	{
123		&CACHE
124	}
125}
126
127#[cfg(test)]
128mod tests {
129	use crate::endpoints::StatsAPIUrl;
130	use crate::endpoints::awards::AwardEndpointUrl;
131
132	#[tokio::test]
133	async fn parse_this_season() {
134		let _response = AwardEndpointUrl::default().get().await.unwrap();
135	}
136}