mail_parser/view/
address.rs1use super::Resolver;
8use crate::store::AddressEntry;
9use std::fmt;
10
11#[derive(Clone, Copy)]
26pub struct AddressList<'m> {
27 resolver: Resolver<'m>,
28 items: &'m [AddressEntry],
29}
30
31#[derive(Debug, Clone, Copy, PartialEq, Eq)]
33pub enum Address<'m> {
34 Mailbox(Mailbox<'m>),
36 Group(Group<'m>),
38}
39
40#[derive(Debug, Clone, Copy, PartialEq, Eq)]
43pub struct Mailbox<'m> {
44 name: Option<&'m str>,
45 address: Option<&'m str>,
46}
47
48#[derive(Debug, Clone, Copy, PartialEq, Eq)]
50pub struct Group<'m> {
51 name: Option<&'m str>,
52 members: AddressRun<'m>,
53}
54
55#[derive(Clone, Copy)]
59pub struct AddressRun<'m> {
60 resolver: Resolver<'m>,
61 items: &'m [AddressEntry],
62}
63
64impl fmt::Debug for AddressList<'_> {
65 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66 f.debug_list().entries(self.iter()).finish()
67 }
68}
69
70impl fmt::Debug for AddressRun<'_> {
71 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72 f.debug_list().entries(*self).finish()
73 }
74}
75
76impl PartialEq for AddressList<'_> {
77 fn eq(&self, other: &Self) -> bool {
78 self.items.len() == other.items.len() && self.iter().eq(other.iter())
79 }
80}
81
82impl Eq for AddressList<'_> {}
83
84impl PartialEq for AddressRun<'_> {
85 fn eq(&self, other: &Self) -> bool {
86 self.items.len() == other.items.len() && Iterator::eq(*self, *other)
87 }
88}
89
90impl Eq for AddressRun<'_> {}
91
92impl<'m> Resolver<'m> {
93 fn mailbox(self, entry: &AddressEntry) -> Mailbox<'m> {
94 Mailbox {
95 name: self.opt(entry.name),
96 address: self.opt(entry.address),
97 }
98 }
99}
100
101impl<'m> AddressList<'m> {
102 pub(crate) fn new(resolver: Resolver<'m>, items: &'m [AddressEntry]) -> Self {
103 AddressList { resolver, items }
104 }
105
106 pub fn is_empty(&self) -> bool {
108 self.items.is_empty()
109 }
110
111 pub fn iter(&self) -> impl Iterator<Item = Address<'m>> + use<'m> {
113 let resolver = self.resolver;
114 let mut rest = self.items;
115 std::iter::from_fn(move || {
116 let (first, tail) = rest.split_first()?;
117 if first.is_group() {
118 let (members, tail) = tail.split_at(first.members().min(tail.len()));
119 rest = tail;
120 Some(Address::Group(Group {
121 name: resolver.opt(first.name),
122 members: AddressRun {
123 resolver,
124 items: members,
125 },
126 }))
127 } else {
128 rest = tail;
129 Some(Address::Mailbox(resolver.mailbox(first)))
130 }
131 })
132 }
133
134 pub fn mailboxes(&self) -> impl DoubleEndedIterator<Item = Mailbox<'m>> + use<'m> {
136 let resolver = self.resolver;
137 self.items
138 .iter()
139 .filter(|entry| !entry.is_group())
140 .map(move |entry| resolver.mailbox(entry))
141 }
142
143 pub fn first(&self) -> Option<Mailbox<'m>> {
145 self.mailboxes().next()
146 }
147
148 pub fn last(&self) -> Option<Mailbox<'m>> {
150 self.mailboxes().next_back()
151 }
152
153 pub fn groups(&self) -> impl Iterator<Item = (Option<&'m str>, AddressRun<'m>)> + use<'m> {
156 let resolver = self.resolver;
157 let mut rest = self.items;
158 std::iter::from_fn(move || {
159 let (first, tail) = rest.split_first()?;
160 let (name, run, tail) = if first.is_group() {
161 let (members, tail) = tail.split_at(first.members().min(tail.len()));
162 (resolver.opt(first.name), members, tail)
163 } else {
164 let len = rest.iter().take_while(|entry| !entry.is_group()).count();
165 let (run, tail) = rest.split_at(len);
166 (None, run, tail)
167 };
168 rest = tail;
169 Some((
170 name,
171 AddressRun {
172 resolver,
173 items: run,
174 },
175 ))
176 })
177 }
178
179 pub fn contains(&self, address: &str) -> bool {
181 self.mailboxes().any(|mailbox| {
182 mailbox
183 .address
184 .is_some_and(|a| a.eq_ignore_ascii_case(address))
185 })
186 }
187
188 pub fn has_groups(&self) -> bool {
190 self.items.iter().any(AddressEntry::is_group)
191 }
192}
193
194impl<'m> Mailbox<'m> {
195 pub fn name(&self) -> Option<&'m str> {
197 self.name
198 }
199
200 pub fn address(&self) -> Option<&'m str> {
202 self.address
203 }
204}
205
206impl<'m> Group<'m> {
207 pub fn name(&self) -> Option<&'m str> {
209 self.name
210 }
211
212 pub fn mailboxes(&self) -> AddressRun<'m> {
214 self.members
215 }
216
217 pub fn len(&self) -> usize {
219 self.members.len()
220 }
221
222 pub fn is_empty(&self) -> bool {
224 self.members.len() == 0
225 }
226}
227
228impl<'m> Iterator for AddressRun<'m> {
229 type Item = Mailbox<'m>;
230
231 fn next(&mut self) -> Option<Mailbox<'m>> {
232 let (first, rest) = self.items.split_first()?;
233 self.items = rest;
234 Some(self.resolver.mailbox(first))
235 }
236
237 fn size_hint(&self) -> (usize, Option<usize>) {
238 (self.items.len(), Some(self.items.len()))
239 }
240}
241
242impl DoubleEndedIterator for AddressRun<'_> {
243 fn next_back(&mut self) -> Option<Self::Item> {
244 let (last, rest) = self.items.split_last()?;
245 self.items = rest;
246 Some(self.resolver.mailbox(last))
247 }
248}
249
250impl ExactSizeIterator for AddressRun<'_> {}