mlb_api/requests/
venue.rs1use 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}