mlb_api/endpoints/meta/
mod.rs1use crate::endpoints::{MetaKind, StatsAPIUrl};
2use derive_more::{Deref, DerefMut};
3use serde::de::{Error, MapAccess, SeqAccess};
4use serde::{Deserialize, Deserializer, de};
5use std::fmt::{Debug, Display, Formatter};
6use std::marker::PhantomData;
7
8pub mod kinds;
9
10#[derive(Debug, Deref, DerefMut, PartialEq, Eq, Clone)]
11pub struct MetaResponse<T: MetaKind> {
12 pub entries: Vec<T>,
13}
14
15impl<'de, T: MetaKind> Deserialize<'de> for MetaResponse<T> {
16 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
17 where
18 D: Deserializer<'de>,
19 {
20 struct Visitor<T>(PhantomData<T>);
21
22 impl<'de, T: MetaKind> de::Visitor<'de> for Visitor<T> {
23 type Value = MetaResponse<T>;
24
25 fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
26 formatter.write_str("either copyright and other entry, or just raw list")
27 }
28
29 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
30 where
31 A: SeqAccess<'de>,
32 {
33 let mut entries = vec![];
34 while let Some(element) = seq.next_element::<T>()? {
35 entries.push(element);
36 }
37 Ok(MetaResponse { entries })
38 }
39
40 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
41 where
42 A: MapAccess<'de>,
43 {
44 while let Some(key) = map.next_key::<String>()? {
45 if key != "copyright" {
46 let entries = map.next_value::<Vec<T>>()?;
47 return Ok(MetaResponse { entries });
48 }
49 }
50 Err(Error::custom("Could not find a field that deserializes to the entries"))
51 }
52 }
53
54 deserializer.deserialize_any(Visitor(PhantomData))
55 }
56}
57
58pub struct MetaEndpointUrl<T: MetaKind> {
59 _marker: PhantomData<T>,
60}
61
62impl<T: MetaKind> MetaEndpointUrl<T> {
63 #[must_use]
64 pub const fn new() -> Self {
65 Self { _marker: PhantomData }
66 }
67}
68
69impl<T: MetaKind> Display for MetaEndpointUrl<T> {
70 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
71 write!(f, "http://statsapi.mlb.com/api/v1/{}", T::ENDPOINT_NAME)
72 }
73}
74
75impl<T: MetaKind> StatsAPIUrl for MetaEndpointUrl<T> {
76 type Response = MetaResponse<T>;
77}