//! Module containing everything related to media attachements. use serde::Deserialize; /// A struct representing a media attachment. #[derive(Debug, Clone, Deserialize, PartialEq)] pub struct Attachment { /// ID of the attachment. pub id: String, /// The media type of an attachment. #[serde(rename = "type")] pub media_type: MediaType, /// URL of the locally hosted version of the image. pub url: String, /// For remote images, the remote URL of the original image. pub remote_url: Option, /// URL of the preview image. pub preview_url: String, /// Shorter URL for the image, for insertion into text /// (only present on local images) pub text_url: Option, /// Meta information about the attachment. pub meta: Option, /// Noop will be removed. pub description: Option, } /// Information about the attachment itself. #[derive(Debug, Deserialize, Clone, PartialEq)] pub struct Meta { /// Original version. pub original: Option, /// Smaller version. pub small: Option, } /// Dimensions of an attachement. #[derive(Debug, Deserialize, Clone, PartialEq)] pub struct ImageDetails { /// width of attachment. width: u64, /// height of attachment. height: u64, /// A string of `widthxheight`. size: Option, /// The aspect ratio of the attachment. aspect: Option, } /// The type of media attachment. #[derive(Debug, Deserialize, Clone, PartialEq)] // Deserialize "Other" trick from https://github.com/serde-rs/serde/issues/912#issuecomment-803097289 #[serde(remote = "MediaType")] pub enum MediaType { /// An image. #[serde(rename = "image")] Image, /// A video file. #[serde(rename = "video")] Video, /// An audio file. #[serde(rename = "audio")] Audio, /// A gifv format file. #[serde(rename = "gifv")] Gifv, /// Unknown format. #[serde(rename = "unknown")] Unknown, /// Anything else #[serde(skip_deserializing)] Other(String), } use std::str::FromStr; use serde::de::{value, Deserializer, IntoDeserializer}; impl FromStr for MediaType { type Err = value::Error; fn from_str(s: &str) -> Result { Self::deserialize(s.into_deserializer()) } } impl<'de> Deserialize<'de> for MediaType { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { let s = String::deserialize(deserializer)?; let deserialized = Self::from_str(&s).unwrap_or_else(|_| { Self::Other(s) }); Ok(deserialized) } } #[cfg(test)] mod tests { use crate::entities::prelude::MediaType; use serde_json::Value; #[test] fn test_deserialize_media_type() { assert_eq!(MediaType::Image, serde_json::from_value(Value::String("image".to_owned())).unwrap()); assert_eq!(MediaType::Audio, serde_json::from_value(Value::String("audio".to_owned())).unwrap()); assert_eq!(MediaType::Other("pleroma_weird_thing".to_string()), serde_json::from_value(Value::String("pleroma_weird_thing".to_owned())).unwrap()); } }