diff --git a/src/message/header/content_type.rs b/src/message/header/content_type.rs index a3335f7..e556f5d 100644 --- a/src/message/header/content_type.rs +++ b/src/message/header/content_type.rs @@ -12,7 +12,7 @@ use crate::BoxError; /// `Content-Type` of the body /// /// Defined in [RFC2045](https://tools.ietf.org/html/rfc2045#section-5) -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct ContentType(Mime); impl ContentType { @@ -78,6 +78,62 @@ impl Display for ContentTypeErr { } } +// -------------------------------------- +// Serialization and Deserialization +// -------------------------------------- +#[cfg(feature = "serde")] +mod serde { + use serde::de::{self, Deserialize, Deserializer, Visitor}; + use serde::ser::{Serialize, Serializer}; + + use std::fmt; + + use super::ContentType; + + impl Serialize for ContentType { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_newtype_struct("ContentType", &format!("{}", &self.0)) + } + } + + impl<'de> Deserialize<'de> for ContentType { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct ContentTypeVisitor; + + impl<'de> Visitor<'de> for ContentTypeVisitor { + type Value = ContentType; + + // The error message which states what the Visitor expects to + // receive + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a ContentType string like `text/plain`") + } + + fn visit_str(self, mime: &str) -> Result + where + E: de::Error, + { + match ContentType::parse(mime) { + Ok(content_type) => Ok(content_type), + Err(_) => Err(E::custom(format!( + "Couldn't parse the following MIME-Type: {}", + mime + ))), + } + } + } + + deserializer.deserialize_str(ContentTypeVisitor) + } + } +} + #[cfg(test)] mod test { use super::ContentType;