mail_parser/view/
content_type.rs1use super::Resolver;
8use crate::store::{ContentTypeEntry, MessageData, ParamEntry};
9use std::fmt;
10
11struct Attributes<'m>(ContentType<'m>);
12
13#[derive(Clone, Copy)]
28pub struct ContentType<'m> {
29 resolver: Resolver<'m>,
30 entry: &'m ContentTypeEntry,
31 params: &'m [ParamEntry],
32}
33
34impl<'m> ContentType<'m> {
35 #[inline]
36 pub(crate) fn new(
37 resolver: Resolver<'m>,
38 data: &'m MessageData,
39 entry: &'m ContentTypeEntry,
40 ) -> Self {
41 ContentType {
42 resolver,
43 entry,
44 params: data.params.get(entry.params.range()).unwrap_or_default(),
45 }
46 }
47
48 #[inline]
50 pub fn ctype(&self) -> &'m str {
51 self.resolver.str(self.entry.ctype)
52 }
53
54 #[inline]
57 pub fn subtype(&self) -> Option<&'m str> {
58 self.resolver.opt(self.entry.subtype)
59 }
60
61 pub fn attribute(&self, name: &str) -> Option<&'m str> {
63 self.attributes()
64 .find(|(param, _)| *param == name)
65 .map(|(_, value)| value)
66 }
67
68 #[inline]
70 pub fn attributes(
71 &self,
72 ) -> impl ExactSizeIterator<Item = (&'m str, &'m str)> + DoubleEndedIterator + use<'m> {
73 let resolver = self.resolver;
74 self.params
75 .iter()
76 .map(move |param| (resolver.str(param.name), resolver.str(param.value)))
77 }
78
79 pub fn has_attribute(&self, name: &str) -> bool {
81 self.attribute(name).is_some()
82 }
83
84 pub fn is_attachment(&self) -> bool {
86 self.ctype().eq_ignore_ascii_case("attachment")
87 }
88
89 pub fn is_inline(&self) -> bool {
91 self.ctype().eq_ignore_ascii_case("inline")
92 }
93}
94
95impl fmt::Debug for Attributes<'_> {
96 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97 f.debug_map().entries(self.0.attributes()).finish()
98 }
99}
100
101impl fmt::Debug for ContentType<'_> {
102 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103 f.debug_struct("ContentType")
104 .field("type", &self.ctype())
105 .field("subtype", &self.subtype())
106 .field("attributes", &Attributes(*self))
107 .finish()
108 }
109}
110
111impl PartialEq for ContentType<'_> {
112 fn eq(&self, other: &Self) -> bool {
113 self.ctype() == other.ctype()
114 && self.subtype() == other.subtype()
115 && self.params.len() == other.params.len()
116 && self.attributes().eq(other.attributes())
117 }
118}
119
120impl Eq for ContentType<'_> {}