Skip to main content

mlb_api/requests/team/
uniforms.rs

1use crate::cache::{Requestable, RequestableEntrypoint};
2use crate::season::SeasonId;
3use crate::team::TeamId;
4use crate::types::Copyright;
5use crate::request::RequestURL;
6use bon::Builder;
7use itertools::Itertools;
8use serde::Deserialize;
9use std::fmt::{Display, Formatter};
10
11#[cfg(feature = "cache")]
12use crate::{rwlock_const_new, RwLock, cache::CacheTable};
13
14#[derive(Debug, Deserialize, PartialEq, Eq, Clone)]
15pub struct UniformsResponse {
16    pub copyright: Copyright,
17    #[serde(rename = "uniforms")] pub teams: Vec<TeamUniformAssets>,
18}
19
20id!(UniformAssetId { uniformAssetId: u32 });
21id!(UniformAssetCategoryId { uniformAssetTypeId: u32 });
22
23#[derive(Debug, Deserialize, PartialEq, Eq, Clone)]
24#[serde(rename_all = "camelCase")]
25pub struct TeamUniformAssets {
26    pub team_id: TeamId,
27    pub uniform_assets: Vec<UniformAsset>,
28}
29
30#[derive(Debug, Deserialize, Clone)]
31pub struct UniformAsset {
32    #[serde(rename = "uniformAssetText")] pub name: String,
33    #[serde(rename = "uniformAssetType")] pub category: UniformAssetCategory,
34    #[serde(rename = "uniformAssetCode")] pub code: String,
35    #[serde(flatten)]
36    pub id: UniformAssetId,
37}
38
39#[derive(Debug, Deserialize, Clone)]
40pub struct UniformAssetCategory {
41    #[serde(rename = "uniformAssetTypeText")] pub name: String,
42    #[serde(rename = "uniformAssetTypeCode")] pub code: String,
43    #[serde(rename = "uniformAssetTypeDesc")] pub description: String,
44    #[serde(rename = "uniformAssetTypeId")] pub id: UniformAssetCategoryId,
45}
46
47id_only_eq_impl!(UniformAsset, id);
48id_only_eq_impl!(UniformAssetCategory, id);
49
50#[derive(Builder)]
51#[builder(derive(Into))]
52pub struct UniformsRequest {
53    teams: Vec<TeamId>,
54    #[builder(into)]
55    season: Option<SeasonId>,
56}
57
58impl<S: uniforms_request_builder::State + uniforms_request_builder::IsComplete> crate::request::RequestURLBuilderExt for UniformsRequestBuilder<S> {
59    type Built = UniformsRequest;
60}
61
62impl Display for UniformsRequest {
63    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
64        write!(f, "http://statsapi.mlb.com/api/v1/uniforms/team{}", gen_params! { "teamIds": self.teams.iter().copied().join(","), "season"?: self.season })
65    }
66}
67
68impl RequestURL for UniformsRequest {
69    type Response = UniformsResponse;
70}
71
72#[cfg(feature = "cache")]
73static CACHE: RwLock<CacheTable<UniformAsset>> = rwlock_const_new(CacheTable::new());
74
75impl Requestable for UniformAsset {
76    type Identifier = String;
77    type URL = UniformsRequest;
78
79    fn id(&self) -> &Self::Identifier {
80        &self.code
81    }
82
83    fn url_for_id(id: &Self::Identifier) -> Self::URL {
84        UniformsRequest::builder()
85            .teams(vec![TeamId::new(id.split_once('_').and_then(|(num, _)| num.parse().ok()).unwrap_or(0))])
86            .build()
87    }
88
89    fn get_entries(response: <Self::URL as RequestURL>::Response) -> impl IntoIterator<Item=Self>
90    where
91        Self: Sized
92    {
93        response.teams.into_iter().flat_map(|team| team.uniform_assets)
94    }
95
96    #[cfg(feature = "cache")]
97    fn get_cache_table() -> &'static RwLock<CacheTable<Self>>
98    where
99        Self: Sized
100    {
101        &CACHE
102    }
103}
104
105impl RequestableEntrypoint for UniformAsset {
106    type Complete = Self;
107
108    fn id(&self) -> &<<Self as RequestableEntrypoint>::Complete as Requestable>::Identifier {
109        &self.code
110    }
111}
112
113#[cfg(test)]
114mod tests {
115    use crate::team::uniforms::UniformsRequest;
116    use crate::team::teams::TeamsRequest;
117    use crate::request::RequestURLBuilderExt;
118
119    #[tokio::test]
120    async fn parse_all_mlb_teams_this_season() {
121        let mlb_teams = TeamsRequest::mlb_teams().build_and_get().await.unwrap();
122        let team_ids = mlb_teams.teams.into_iter().map(|team| team.id).collect::<Vec<_>>();
123        let _ = UniformsRequest::builder().teams(team_ids).build_and_get().await.unwrap();
124    }
125}