mlb_api/endpoints/meta/
mod.rs

1use 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}