Skip to main content

mlb_api/requests/
venue.rs

1use crate::season::SeasonId;
2use crate::types::Copyright;
3use crate::request::RequestURL;
4use bon::Builder;
5use derive_more::{Deref, DerefMut};
6use itertools::Itertools;
7use serde::Deserialize;
8use std::fmt::{Display, Formatter};
9use crate::cache::{Requestable};
10use crate::sport::SportId;
11
12#[cfg(feature = "cache")]
13use crate::{rwlock_const_new, RwLock, cache::CacheTable};
14
15#[derive(Debug, Deserialize, PartialEq, Eq, Clone)]
16#[serde(rename_all = "camelCase")]
17pub struct VenuesResponse {
18	pub copyright: Copyright,
19	pub venues: Vec<Venue>,
20}
21
22#[derive(Debug, Deserialize, Clone)]
23#[serde(rename_all = "camelCase")]
24pub struct NamedVenue {
25	pub name: String,
26	#[serde(flatten)]
27	pub id: VenueId,
28}
29
30impl NamedVenue {
31	pub(crate) fn unknown_venue() -> Self {
32		Self {
33			name: "null".to_owned(),
34			id: VenueId::new(0),
35		}
36	}
37
38	#[must_use]
39	pub fn is_unknown(&self) -> bool {
40		*self.id == 0
41	}
42}
43
44#[derive(Debug, Deserialize, Deref, DerefMut, Clone)]
45#[serde(rename_all = "camelCase")]
46pub struct Venue {
47	pub active: bool,
48	pub season: SeasonId,
49
50	#[deref]
51	#[deref_mut]
52	#[serde(flatten)]
53	pub inner: NamedVenue,
54}
55
56id!(VenueId { id: u32 });
57id_only_eq_impl!(NamedVenue, id);
58id_only_eq_impl!(Venue, id);
59
60#[cfg(feature = "cache")]
61static CACHE: RwLock<CacheTable<Venue>> = rwlock_const_new(CacheTable::new());
62
63impl Requestable for Venue {
64	type Identifier = VenueId;
65	type URL = VenuesRequest;
66
67	fn id(&self) -> &Self::Identifier {
68		&self.id
69	}
70
71	#[cfg(feature = "aggressive_cache")]
72	fn url_for_id(_id: &Self::Identifier) -> Self::URL {
73		VenuesRequest::builder().build()
74	}
75
76	#[cfg(not(feature = "aggressive_cache"))]
77	fn url_for_id(id: &Self::Identifier) -> Self::URL {
78		VenuesRequest::builder().venue_ids(vec![*id]).build()
79	}
80
81	fn get_entries(response: <Self::URL as RequestURL>::Response) -> impl IntoIterator<Item=Self>
82	where
83		Self: Sized
84	{
85		response.venues
86	}
87
88	#[cfg(feature = "cache")]
89	fn get_cache_table() -> &'static RwLock<CacheTable<Self>>
90	where
91		Self: Sized
92	{
93		&CACHE
94	}
95}
96
97#[derive(Builder)]
98#[builder(derive(Into))]
99pub struct VenuesRequest {
100	#[builder(into, default)]
101	sport_id: SportId,
102	venue_ids: Option<Vec<VenueId>>,
103	#[builder(into)]
104	season: Option<SeasonId>,
105}
106
107impl<S: venues_request_builder::State + venues_request_builder::IsComplete> crate::request::RequestURLBuilderExt for VenuesRequestBuilder<S> {
108	type Built = VenuesRequest;
109}
110
111impl Display for VenuesRequest {
112	fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
113		write!(f, "http://statsapi.mlb.com/api/v1/venues{}", gen_params! { "season"?: self.season, "sportId": self.sport_id, "venueIds"?: self.venue_ids.as_ref().map(|ids| ids.iter().join(",")) })
114	}
115}
116
117impl RequestURL for VenuesRequest {
118	type Response = VenuesResponse;
119}
120
121#[cfg(test)]
122mod tests {
123	use crate::request::RequestURLBuilderExt;
124	use crate::TEST_YEAR;
125	use crate::venue::VenuesRequest;
126
127	#[tokio::test]
128	#[cfg_attr(not(feature = "_heavy_tests"), ignore)]
129	async fn parse_all_venues_all_seasons() {
130		for season in 1876..=TEST_YEAR {
131			let _response = VenuesRequest::builder().season(season).build_and_get().await.unwrap();
132		}
133	}
134
135	#[tokio::test]
136	async fn parse_all_venues() {
137		let _response = VenuesRequest::builder().build_and_get().await.unwrap();
138	}
139}