1use reqwest::Response;
2use serde::{de::IgnoredAny, de::Visitor, Deserialize};
3
4use crate::AuraxisError;
5
6#[derive(Debug)]
7pub struct CensusResponse {
8 pub items: Vec<serde_json::Value>,
9 pub count: u32,
10}
11
12impl<'de> Deserialize<'de> for CensusResponse {
13 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
14 where
15 D: serde::Deserializer<'de>,
16 {
17 deserializer.deserialize_map(CensusResponseVisitor)
18 }
19}
20
21struct CensusResponseVisitor;
22
23impl<'de> Visitor<'de> for CensusResponseVisitor {
24 type Value = CensusResponse;
25
26 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
27 write!(
28 formatter,
29 "a map with keys '<collection>_list>' and 'returned'"
30 )
31 }
32
33 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
34 where
35 A: serde::de::MapAccess<'de>,
36 {
37 let mut items = None;
38 let mut count = None;
39
40 while let Some(k) = map.next_key::<&str>()? {
41 if k == "returned" {
42 count = Some(map.next_value()?);
43 } else if k.ends_with("_list") {
44 items = Some(map.next_value()?);
45 } else {
46 let _ = map.next_value::<IgnoredAny>()?;
47 }
48 }
49
50 let items =
51 items.ok_or_else(|| serde::de::Error::custom("Missing collection_list or count"))?;
52 let count =
53 count.ok_or_else(|| serde::de::Error::custom("Missing collection_list or count"))?;
54
55 Ok(CensusResponse { items, count })
56 }
57}
58
59impl CensusResponse {
60 pub async fn from_response(response: Response) -> Result<Self, AuraxisError> {
61 Ok(response.json::<CensusResponse>().await?)
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use super::CensusResponse;
68
69 #[test]
70 fn ignores_extra_metadata_keys() {
71 let response = serde_json::from_str::<CensusResponse>(
72 r#"{
73 "character_list": [{"character_id": "1"}],
74 "returned": 1,
75 "timing": {"query": "1.23"},
76 "errorCode": "ok"
77 }"#,
78 )
79 .expect("response should deserialize");
80
81 assert_eq!(response.count, 1);
82 assert_eq!(response.items.len(), 1);
83 }
84}