use super::Resolver;
use crate::store::{ContentTypeEntry, MessageData, ParamEntry};
use std::fmt;
struct Attributes<'m>(ContentType<'m>);
#[derive(Clone, Copy)]
pub struct ContentType<'m> {
resolver: Resolver<'m>,
entry: &'m ContentTypeEntry,
params: &'m [ParamEntry],
}
impl<'m> ContentType<'m> {
#[inline]
pub(crate) fn new(
resolver: Resolver<'m>,
data: &'m MessageData,
entry: &'m ContentTypeEntry,
) -> Self {
ContentType {
resolver,
entry,
params: data.params.get(entry.params.range()).unwrap_or_default(),
}
}
#[inline]
pub fn ctype(&self) -> &'m str {
self.resolver.str(self.entry.ctype)
}
#[inline]
pub fn subtype(&self) -> Option<&'m str> {
self.resolver.opt(self.entry.subtype)
}
pub fn attribute(&self, name: &str) -> Option<&'m str> {
self.attributes()
.find(|(param, _)| *param == name)
.map(|(_, value)| value)
}
#[inline]
pub fn attributes(
&self,
) -> impl ExactSizeIterator<Item = (&'m str, &'m str)> + DoubleEndedIterator + use<'m> {
let resolver = self.resolver;
self.params
.iter()
.map(move |param| (resolver.str(param.name), resolver.str(param.value)))
}
pub fn has_attribute(&self, name: &str) -> bool {
self.attribute(name).is_some()
}
pub fn is_attachment(&self) -> bool {
self.ctype().eq_ignore_ascii_case("attachment")
}
pub fn is_inline(&self) -> bool {
self.ctype().eq_ignore_ascii_case("inline")
}
}
impl fmt::Debug for Attributes<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_map().entries(self.0.attributes()).finish()
}
}
impl fmt::Debug for ContentType<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ContentType")
.field("type", &self.ctype())
.field("subtype", &self.subtype())
.field("attributes", &Attributes(*self))
.finish()
}
}
impl PartialEq for ContentType<'_> {
fn eq(&self, other: &Self) -> bool {
self.ctype() == other.ctype()
&& self.subtype() == other.subtype()
&& self.params.len() == other.params.len()
&& self.attributes().eq(other.attributes())
}
}
impl Eq for ContentType<'_> {}