arnak/endpoints/
hot_list_models.rs

1use core::fmt;
2
3use serde::Deserialize;
4
5use crate::deserialize::{XmlSignedValue, XmlStringValue};
6
7/// The returned struct containing a list of hot board games.
8#[derive(Clone, Debug, Deserialize, PartialEq)]
9pub(crate) struct HotList {
10    /// The list of trending board games currently on the hot list.
11    #[serde(default, rename = "item")]
12    pub(crate) games: Vec<HotListGame>,
13}
14
15/// An game on the hot list, has the rank from 1 to 50 on the list,
16/// as well as some basic information about the game like the name
17/// and year published.
18#[derive(Clone, Debug, PartialEq)]
19pub struct HotListGame {
20    /// The ID of the game.
21    pub id: u64,
22    /// The rank within the hot list, should be ordered from 1 to 50.
23    pub rank: u64,
24    /// A link to a jpg thumbnail image for the game.
25    pub thumbnail: Option<String>,
26    /// The name of the game.
27    pub name: String,
28    /// The year the game was first published.
29    pub year_published: i64,
30}
31
32impl<'de> Deserialize<'de> for HotListGame {
33    fn deserialize<D: serde::de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
34        #[derive(Deserialize)]
35        #[serde(field_identifier, rename_all = "lowercase")]
36        enum Field {
37            ID,
38            Rank,
39            Thumbnail,
40            Name,
41            YearPublished,
42        }
43
44        struct HotListGameVisitor;
45
46        impl<'de> serde::de::Visitor<'de> for HotListGameVisitor {
47            type Value = HotListGame;
48
49            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
50                formatter.write_str("a string containing the XML a game off the hot list.")
51            }
52
53            fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
54            where
55                A: serde::de::MapAccess<'de>,
56            {
57                let mut id = None;
58                let mut rank = None;
59                let mut thumbnail = None;
60                let mut name = None;
61                let mut year_published = None;
62                while let Some(key) = map.next_key()? {
63                    match key {
64                        Field::ID => {
65                            if id.is_some() {
66                                return Err(serde::de::Error::duplicate_field("id"));
67                            }
68                            let id_str: String = map.next_value()?;
69                            id = Some(id_str.parse::<u64>().map_err(|e| {
70                                serde::de::Error::custom(format!(
71                                    "failed to parse value a u64: {e}"
72                                ))
73                            })?);
74                        },
75                        Field::Rank => {
76                            if rank.is_some() {
77                                return Err(serde::de::Error::duplicate_field("rank"));
78                            }
79                            let rank_str: String = map.next_value()?;
80                            rank = Some(rank_str.parse::<u64>().map_err(|e| {
81                                serde::de::Error::custom(format!(
82                                    "failed to parse value a u64: {e}"
83                                ))
84                            })?);
85                        },
86                        Field::Thumbnail => {
87                            if thumbnail.is_some() {
88                                return Err(serde::de::Error::duplicate_field("thumbnail"));
89                            }
90                            let thumbnail_xml_tag: XmlStringValue = map.next_value()?;
91                            thumbnail = Some(thumbnail_xml_tag.value);
92                        },
93                        Field::Name => {
94                            if name.is_some() {
95                                return Err(serde::de::Error::duplicate_field("name"));
96                            }
97                            let name_xml_tag: XmlStringValue = map.next_value()?;
98                            name = Some(name_xml_tag.value);
99                        },
100                        Field::YearPublished => {
101                            if year_published.is_some() {
102                                return Err(serde::de::Error::duplicate_field("yearpublished"));
103                            }
104                            let year_published_xml_tag: XmlSignedValue = map.next_value()?;
105                            year_published = Some(year_published_xml_tag.value);
106                        },
107                    }
108                }
109                let id = id.ok_or_else(|| serde::de::Error::missing_field("id"))?;
110                let rank = rank.ok_or_else(|| serde::de::Error::missing_field("rank"))?;
111                let name = name.ok_or_else(|| serde::de::Error::missing_field("name"))?;
112                let year_published = year_published
113                    .ok_or_else(|| serde::de::Error::missing_field("yearpublished"))?;
114                Ok(Self::Value {
115                    id,
116                    rank,
117                    thumbnail,
118                    name,
119                    year_published,
120                })
121            }
122        }
123        deserializer.deserialize_any(HotListGameVisitor)
124    }
125}