mlb_api/endpoints/meta/kinds/
languages.rs1use crate::endpoints::meta::kinds::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::meta::MetaEndpointUrl;
9use crate::endpoints::StatsAPIUrl;
10
11#[derive(Debug, Deserialize, PartialEq, Eq, Clone)]
12#[serde(rename_all = "camelCase")]
13pub struct IdentifiableLanguage {
14 #[serde(rename = "languageId")]
15 id: LanguageId,
16}
17
18#[derive(Debug, Deserialize, Deref, DerefMut, PartialEq, Eq, Clone)]
19#[serde(rename_all = "camelCase")]
20pub struct HydratedLanguage {
21 #[serde(rename = "languageCode")]
22 pub code: String,
23 pub name: String,
24 pub locale: String,
25
26 #[deref]
27 #[deref_mut]
28 #[serde(flatten)]
29 inner: IdentifiableLanguage,
30}
31
32#[repr(transparent)]
33#[derive(Debug, Deserialize, Deref, Display, PartialEq, Eq, Copy, Clone, Hash)]
34pub struct LanguageId(pub(super) u32);
35
36impl LanguageId {
37 #[must_use]
38 pub const fn new(id: u32) -> Self {
39 Self(id)
40 }
41}
42
43#[derive(Debug, Deserialize, Eq, Clone, From, EnumTryAs)]
44#[serde(untagged)]
45pub enum Language {
46 Hydrated(HydratedLanguage),
47 Identifiable(IdentifiableLanguage),
48}
49
50impl Language {
51 #[must_use]
52 pub fn id(&self) -> LanguageId {
53 match self {
54 Self::Hydrated(inner) => inner.id,
55 Self::Identifiable(inner) => inner.id,
56 }
57 }
58}
59
60impl PartialEq for Language {
61 fn eq(&self, other: &Self) -> bool {
62 self.id() == other.id()
63 }
64}
65
66impl Deref for Language {
67 type Target = IdentifiableLanguage;
68
69 fn deref(&self) -> &Self::Target {
70 match self {
71 Self::Hydrated(inner) => inner,
72 Self::Identifiable(inner) => inner,
73 }
74 }
75}
76
77impl DerefMut for Language {
78 fn deref_mut(&mut self) -> &mut Self::Target {
79 match self {
80 Self::Hydrated(inner) => inner,
81 Self::Identifiable(inner) => inner,
82 }
83 }
84}
85
86impl MetaKind for Language {
87 const ENDPOINT_NAME: &'static str = "languages";
88}
89
90static CACHE: RwLock<HydratedCacheTable<Language>> = rwlock_const_new(HydratedCacheTable::new());
91
92impl EndpointEntryCache for Language {
93 type HydratedVariant = HydratedLanguage;
94 type Identifier = LanguageId;
95 type URL = MetaEndpointUrl<Self>;
96
97 fn into_hydrated_variant(self) -> Option<Self::HydratedVariant> {
98 self.try_as_hydrated()
99 }
100
101 fn id(&self) -> &Self::Identifier {
102 &self.id
103 }
104
105 fn url_for_id(_id: &Self::Identifier) -> Self::URL {
106 MetaEndpointUrl::new()
107 }
108
109 fn get_entries(response: <Self::URL as StatsAPIUrl>::Response) -> impl IntoIterator<Item=Self>
110 where
111 Self: Sized
112 {
113 response.entries
114 }
115
116 fn get_hydrated_cache_table() -> &'static RwLock<HydratedCacheTable<Self>>
117 where
118 Self: Sized
119 {
120 &CACHE
121 }
122}
123
124#[cfg(test)]
125mod tests {
126 use crate::endpoints::StatsAPIUrl;
127 use crate::endpoints::meta::MetaEndpointUrl;
128
129 #[tokio::test]
130 async fn parse_meta() {
131 let _response = MetaEndpointUrl::<super::Language>::new().get().await.unwrap();
132 }
133}