diff --git a/src/types/animation.rs b/src/types/animation.rs index 9cf1b0e5..ae0c9de5 100644 --- a/src/types/animation.rs +++ b/src/types/animation.rs @@ -1,6 +1,7 @@ +use mime::Mime; use serde::{Deserialize, Serialize}; -use crate::types::{MimeWrapper, PhotoSize}; +use crate::types::PhotoSize; /// This object represents an animation file (GIF or H.264/MPEG-4 AVC video /// without sound). @@ -33,7 +34,8 @@ pub struct Animation { pub file_name: Option, /// A MIME type of the file as defined by a sender. - pub mime_type: Option, + #[serde(with = "crate::types::non_telegram_types::mime::opt_deser")] + pub mime_type: Option, /// A size of a file. pub file_size: Option, @@ -108,7 +110,7 @@ impl Animation { self } - pub fn mime_type(mut self, val: MimeWrapper) -> Self { + pub fn mime_type(mut self, val: Mime) -> Self { self.mime_type = Some(val); self } @@ -155,7 +157,7 @@ mod tests { file_size: Some(3452), }), file_name: Some("some".to_string()), - mime_type: Some(MimeWrapper("video/gif".parse().unwrap())), + mime_type: Some("video/gif".parse().unwrap()), file_size: Some(6500), }; let actual = serde_json::from_str::(json).unwrap(); diff --git a/src/types/audio.rs b/src/types/audio.rs index b9d6279d..23225eba 100644 --- a/src/types/audio.rs +++ b/src/types/audio.rs @@ -1,6 +1,7 @@ +use mime::Mime; use serde::{Deserialize, Serialize}; -use crate::types::{MimeWrapper, PhotoSize}; +use crate::types::PhotoSize; /// This object represents an audio file to be treated as music by the Telegram /// clients. @@ -27,7 +28,8 @@ pub struct Audio { pub title: Option, /// A MIME type of the file as defined by a sender. - pub mime_type: Option, + #[serde(with = "crate::types::non_telegram_types::mime::opt_deser")] + pub mime_type: Option, /// A size of a file. pub file_size: Option, @@ -91,7 +93,7 @@ impl Audio { self } - pub fn mime_type(mut self, val: MimeWrapper) -> Self { + pub fn mime_type(mut self, val: Mime) -> Self { self.mime_type = Some(val); self } @@ -135,7 +137,7 @@ mod tests { duration: 60, performer: Some("Performer".to_string()), title: Some("Title".to_string()), - mime_type: Some(serde_json::from_str("\"application/zip\"").unwrap()), + mime_type: Some("application/zip".parse().unwrap()), file_size: Some(123_456), thumb: Some(PhotoSize { file_id: "id".to_string(), diff --git a/src/types/document.rs b/src/types/document.rs index aa60c2db..75e28918 100644 --- a/src/types/document.rs +++ b/src/types/document.rs @@ -1,6 +1,7 @@ +use mime::Mime; use serde::{Deserialize, Serialize}; -use crate::types::{MimeWrapper, PhotoSize}; +use crate::types::PhotoSize; /// This object represents a general file (as opposed to [photos], [voice /// messages] and [audio files]). @@ -28,7 +29,8 @@ pub struct Document { pub file_name: Option, /// A MIME type of the file as defined by a sender. - pub mime_type: Option, + #[serde(with = "crate::types::non_telegram_types::mime::opt_deser")] + pub mime_type: Option, /// A size of a file. pub file_size: Option, @@ -79,7 +81,7 @@ impl Document { self } - pub fn mime_type(mut self, val: MimeWrapper) -> Self { + pub fn mime_type(mut self, val: Mime) -> Self { self.mime_type = Some(val); self } diff --git a/src/types/inline_query_result_document.rs b/src/types/inline_query_result_document.rs index 7cf0a5f2..780e2cb7 100644 --- a/src/types/inline_query_result_document.rs +++ b/src/types/inline_query_result_document.rs @@ -1,6 +1,7 @@ +use mime::Mime; use serde::{Deserialize, Serialize}; -use crate::types::{InlineKeyboardMarkup, InputMessageContent, MimeWrapper, ParseMode}; +use crate::types::{InlineKeyboardMarkup, InputMessageContent, ParseMode}; /// Represents a link to a file. /// @@ -35,7 +36,8 @@ pub struct InlineQueryResultDocument { /// Mime type of the content of the file, either `application/pdf` or /// `application/zip`. - pub mime_type: MimeWrapper, + #[serde(with = "crate::types::non_telegram_types::mime::deser")] + pub mime_type: Mime, /// Short description of the result. pub description: Option, @@ -94,7 +96,7 @@ impl InlineQueryResultDocument { self } - pub fn mime_type(mut self, val: MimeWrapper) -> Self { + pub fn mime_type(mut self, val: Mime) -> Self { self.mime_type = val; self } diff --git a/src/types/inline_query_result_video.rs b/src/types/inline_query_result_video.rs index 7d190473..a9d9030f 100644 --- a/src/types/inline_query_result_video.rs +++ b/src/types/inline_query_result_video.rs @@ -1,6 +1,7 @@ +use mime::Mime; use serde::{Deserialize, Serialize}; -use crate::types::{InlineKeyboardMarkup, InputMessageContent, MimeWrapper, ParseMode}; +use crate::types::{InlineKeyboardMarkup, InputMessageContent, ParseMode}; /// Represents a link to a page containing an embedded video player or a video /// file. @@ -20,7 +21,8 @@ pub struct InlineQueryResultVideo { pub video_url: String, /// Mime type of the content of video url, `text/html` or `video/mp4`. - pub mime_type: MimeWrapper, + #[serde(with = "crate::types::non_telegram_types::mime::deser")] + pub mime_type: Mime, /// URL of the thumbnail (jpeg only) for the video. pub thumb_url: String, @@ -69,7 +71,7 @@ impl InlineQueryResultVideo { pub fn new( id: S1, video_url: S2, - mime_type: MimeWrapper, + mime_type: Mime, thumb_url: S3, title: S4, ) -> Self @@ -112,7 +114,7 @@ impl InlineQueryResultVideo { self } - pub fn mime_type(mut self, val: MimeWrapper) -> Self { + pub fn mime_type(mut self, val: Mime) -> Self { self.mime_type = val; self } diff --git a/src/types/non_telegram_types/mime.rs b/src/types/non_telegram_types/mime.rs new file mode 100644 index 00000000..c5655cc7 --- /dev/null +++ b/src/types/non_telegram_types/mime.rs @@ -0,0 +1,100 @@ +use std::fmt; + +use mime::Mime; +use serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer}; + +pub(crate) mod deser { + use mime::Mime; + use serde::{Deserialize, Deserializer, Serialize, Serializer}; + + use super::{MimeDe, MimeSer}; + + pub(crate) fn serialize( + this: &Mime, + serializer: S, + ) -> Result<::Ok, ::Error> + where + S: Serializer, + { + MimeSer(this).serialize(serializer) + } + + pub(crate) fn deserialize<'de, D>( + deserializer: D, + ) -> Result>::Error> + where + D: Deserializer<'de>, + { + MimeDe::deserialize(deserializer).map(|MimeDe(m)| m) + } +} + +pub(crate) mod opt_deser { + use mime::Mime; + use serde::{Deserialize, Deserializer, Serialize, Serializer}; + + use super::{MimeDe, MimeSer}; + + pub(crate) fn serialize( + this: &Option, + serializer: S, + ) -> Result<::Ok, ::Error> + where + S: Serializer, + { + this.as_ref().map(MimeSer).serialize(serializer) + } + + pub(crate) fn deserialize<'de, D>( + deserializer: D, + ) -> Result, >::Error> + where + D: Deserializer<'de>, + { + Option::::deserialize(deserializer).map(|opt| opt.map(|MimeDe(m)| m)) + } +} + +struct MimeSer<'a>(&'a Mime); + +impl Serialize for MimeSer<'_> { + fn serialize(&self, serializer: S) -> Result<::Ok, ::Error> + where + S: Serializer, + { + serializer.serialize_str(self.0.as_ref()) + } +} + +struct MimeVisitor; +impl<'a> Visitor<'a> for MimeVisitor { + type Value = MimeDe; + + fn expecting( + &self, + formatter: &mut fmt::Formatter<'_>, + ) -> Result<(), serde::export::fmt::Error> { + formatter.write_str("mime type") + } + + fn visit_str(self, v: &str) -> Result + where + E: serde::de::Error, + { + match v.parse::() { + Ok(mime_type) => Ok(MimeDe(mime_type)), + Err(e) => Err(E::custom(e)), + } + } +} + +struct MimeDe(Mime); + +impl<'de> Deserialize<'de> for MimeDe { + fn deserialize(deserializer: D) -> Result>::Error> + where + D: Deserializer<'de>, + { + deserializer.deserialize_str(MimeVisitor) + } +} diff --git a/src/types/non_telegram_types/mime_wrapper.rs b/src/types/non_telegram_types/mime_wrapper.rs deleted file mode 100644 index 43326de6..00000000 --- a/src/types/non_telegram_types/mime_wrapper.rs +++ /dev/null @@ -1,44 +0,0 @@ -use derive_more::From; -use mime::Mime; -use serde::{de::Visitor, export::Formatter, Deserialize, Deserializer, Serialize, Serializer}; - -/// Serializable & deserializable `MIME` wrapper. -#[derive(Clone, Debug, Eq, Hash, PartialEq, From)] -pub struct MimeWrapper(pub Mime); - -impl Serialize for MimeWrapper { - fn serialize(&self, serializer: S) -> Result<::Ok, ::Error> - where - S: Serializer, - { - serializer.serialize_str(self.0.as_ref()) - } -} - -struct MimeVisitor; -impl<'a> Visitor<'a> for MimeVisitor { - type Value = MimeWrapper; - - fn expecting(&self, formatter: &mut Formatter<'_>) -> Result<(), serde::export::fmt::Error> { - formatter.write_str("mime type") - } - - fn visit_str(self, v: &str) -> Result - where - E: serde::de::Error, - { - match v.parse::() { - Ok(mime_type) => Ok(MimeWrapper(mime_type)), - Err(e) => Err(E::custom(e)), - } - } -} - -impl<'de> Deserialize<'de> for MimeWrapper { - fn deserialize(deserializer: D) -> Result>::Error> - where - D: Deserializer<'de>, - { - deserializer.deserialize_str(MimeVisitor) - } -} diff --git a/src/types/non_telegram_types/mod.rs b/src/types/non_telegram_types/mod.rs index 6c8e1636..49360c4f 100644 --- a/src/types/non_telegram_types/mod.rs +++ b/src/types/non_telegram_types/mod.rs @@ -1,9 +1,9 @@ pub use country_code::*; pub use currency::*; -pub use mime_wrapper::*; pub use non_strict_vec::*; mod country_code; mod currency; -mod mime_wrapper; mod non_strict_vec; + +pub(crate) mod mime; diff --git a/src/types/video.rs b/src/types/video.rs index 98241c49..1db5737f 100644 --- a/src/types/video.rs +++ b/src/types/video.rs @@ -1,6 +1,7 @@ +use mime::Mime; use serde::{Deserialize, Serialize}; -use crate::types::{MimeWrapper, PhotoSize}; +use crate::types::PhotoSize; /// This object represents a video file. /// @@ -29,7 +30,8 @@ pub struct Video { pub thumb: Option, /// Mime type of a file as defined by sender. - pub mime_type: Option, + #[serde(with = "crate::types::non_telegram_types::mime::opt_deser")] + pub mime_type: Option, /// File size. pub file_size: Option, @@ -95,7 +97,7 @@ impl Video { self } - pub fn mime_type(mut self, val: MimeWrapper) -> Self { + pub fn mime_type(mut self, val: Mime) -> Self { self.mime_type = Some(val); self } diff --git a/src/types/voice.rs b/src/types/voice.rs index f60cc204..2fc7a5b9 100644 --- a/src/types/voice.rs +++ b/src/types/voice.rs @@ -1,4 +1,4 @@ -use crate::types::MimeWrapper; +use mime::Mime; use serde::{Deserialize, Serialize}; /// This object represents a voice note. @@ -19,7 +19,8 @@ pub struct Voice { pub duration: u32, /// MIME type of the file as defined by sender. - pub mime_type: Option, + #[serde(with = "crate::types::non_telegram_types::mime::opt_deser")] + pub mime_type: Option, /// File size. pub file_size: Option, @@ -61,7 +62,7 @@ impl Voice { self } - pub fn mime_type(mut self, val: MimeWrapper) -> Self { + pub fn mime_type(mut self, val: Mime) -> Self { self.mime_type = Some(val); self }