diff --git a/src/post.rs b/src/post.rs index 15c8301..1f05d27 100644 --- a/src/post.rs +++ b/src/post.rs @@ -8,10 +8,10 @@ use { }, itertools::Itertools, serde::{ - de::{self, MapAccess, Visitor}, + de::{self, Visitor}, Deserialize, Deserializer, }, - std::{borrow::Borrow, pin::Pin}, + std::{borrow::Borrow, pin::Pin, collections::HashMap}, }; /// Chunk size used for iterators performing requests @@ -48,11 +48,21 @@ pub struct PostPreview { pub url: Option, } +#[derive(Debug, PartialEq, Eq, Deserialize)] +pub struct PostSampleAlternates { + #[serde(rename = "type")] + pub stype: String, + pub height: u64, + pub width: u64, + pub urls: Vec>, +} + #[derive(Debug, PartialEq, Eq, Deserialize)] pub struct PostSample { pub width: u64, pub height: u64, pub url: Option, + pub alternates: HashMap, } #[derive(Debug, PartialEq, Eq, Deserialize)] @@ -115,8 +125,7 @@ pub struct Post { pub updated_at: Option>, pub file: PostFile, pub preview: PostPreview, - #[serde(deserialize_with = "PostSample::from_json")] - pub sample: Option, + pub sample: PostSample, pub score: PostScore, pub tags: PostTags, pub locked_tags: Vec, @@ -169,89 +178,6 @@ where de.deserialize_any(NullableBoolVisitor) } -impl PostSample { - fn from_json<'de, D>(de: D) -> Result, D::Error> - where - D: Deserializer<'de>, - { - #[derive(Deserialize)] - #[serde(field_identifier, rename_all = "lowercase")] - enum Field { - Has, - Width, - Height, - Url, - } - - struct PostSampleVisitor; - - impl<'de> Visitor<'de> for PostSampleVisitor { - type Value = Option; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("struct PostSample") - } - - fn visit_map(self, mut map: V) -> Result, V::Error> - where - V: MapAccess<'de>, - { - let mut has = None; - let mut width = None; - let mut height = None; - let mut url = None; - - while let Some(key) = map.next_key()? { - match key { - Field::Has => { - if has.is_some() { - return Err(de::Error::duplicate_field("has")); - } - - has = Some(map.next_value()?); - } - Field::Width => { - if width.is_some() { - return Err(de::Error::duplicate_field("width")); - } - - width = Some(map.next_value()?); - } - Field::Height => { - if height.is_some() { - return Err(de::Error::duplicate_field("height")); - } - - height = Some(map.next_value()?); - } - Field::Url => { - if url.is_some() { - return Err(de::Error::duplicate_field("url")); - } - - url = Some(map.next_value()?); - } - } - } - - let has = has.ok_or_else(|| de::Error::missing_field("has"))?; - let width = width.ok_or_else(|| de::Error::missing_field("width"))?; - let height = height.ok_or_else(|| de::Error::missing_field("height"))?; - let url = url.ok_or_else(|| de::Error::missing_field("url"))?; - - if let Some(true) = has { - Ok(None) - } else { - Ok(Some(PostSample { width, height, url })) - } - } - } - - const FIELDS: &'static [&'static str] = &["has", "width", "height", "url"]; - de.deserialize_struct("PostSample", FIELDS, PostSampleVisitor) - } -} - /// A search query. Contains information about the tags used and an URL encoded version of the tags. #[derive(Debug, PartialEq, Clone)] pub struct Query {