mail_parser/core/
address.rs

1/*
2 * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <hello@stalw.art>
3 *
4 * SPDX-License-Identifier: Apache-2.0 OR MIT
5 */
6
7use crate::{Addr, Address, Group};
8
9impl<'x> Address<'x> {
10    /// Returns the first address in the list, or the first address in the first group.
11    pub fn first(&self) -> Option<&Addr<'x>> {
12        match self {
13            Address::List(list) => list.first(),
14            Address::Group(group) => group.iter().flat_map(|group| group.addresses.iter()).next(),
15        }
16    }
17
18    /// Returns the last address in the list, or the last address in the last group.
19    pub fn last(&self) -> Option<&Addr<'x>> {
20        match self {
21            Address::List(list) => list.last(),
22            Address::Group(group) => group
23                .iter()
24                .flat_map(|group| group.addresses.iter())
25                .next_back(),
26        }
27    }
28
29    /// Converts the address into a list of `Addr`.
30    pub fn into_list(self) -> Vec<Addr<'x>> {
31        match self {
32            Address::List(list) => list,
33            Address::Group(group) => group
34                .into_iter()
35                .flat_map(|group| group.addresses)
36                .collect(),
37        }
38    }
39
40    /// Converts the address into a group of `Addr`.
41    pub fn into_group(self) -> Vec<Group<'x>> {
42        match self {
43            Address::List(list) => list
44                .into_iter()
45                .map(|addr| Group {
46                    name: None,
47                    addresses: vec![addr],
48                })
49                .collect(),
50            Address::Group(group) => group,
51        }
52    }
53
54    /// Returns the list of addresses, or `None` if the address is a group.
55    pub fn as_list(&self) -> Option<&[Addr<'x>]> {
56        match self {
57            Address::List(list) => Some(list),
58            Address::Group(_) => None,
59        }
60    }
61
62    /// Returns the group of addresses, or `None` if the address is a list.
63    pub fn as_group(&self) -> Option<&[Group<'x>]> {
64        match self {
65            Address::List(_) => None,
66            Address::Group(group) => Some(group),
67        }
68    }
69
70    /// Returns an iterator over the addresses in the list, or the addresses in the groups.
71    pub fn iter(&self) -> Box<dyn DoubleEndedIterator<Item = &Addr<'x>> + '_ + Sync + Send> {
72        match self {
73            Address::List(list) => Box::new(list.iter()),
74            Address::Group(group) => {
75                Box::new(group.iter().flat_map(|group| group.addresses.iter()))
76            }
77        }
78    }
79
80    /// Returns whether the list contains the given address.
81    pub fn contains(&self, addr: &str) -> bool {
82        match self {
83            Address::List(list) => list.iter().any(|a| {
84                a.address
85                    .as_ref()
86                    .is_some_and(|a| a.eq_ignore_ascii_case(addr))
87            }),
88            Address::Group(group) => group.iter().any(|group| {
89                group.addresses.iter().any(|a| {
90                    a.address
91                        .as_ref()
92                        .is_some_and(|a| a.eq_ignore_ascii_case(addr))
93                })
94            }),
95        }
96    }
97
98    pub fn into_owned(self) -> Address<'static> {
99        match self {
100            Address::List(list) => {
101                Address::List(list.into_iter().map(|addr| addr.into_owned()).collect())
102            }
103            Address::Group(list) => {
104                Address::Group(list.into_iter().map(|group| group.into_owned()).collect())
105            }
106        }
107    }
108}
109
110impl<'x> Group<'x> {
111    pub fn new(name: &'x str, addresses: Vec<Addr<'x>>) -> Self {
112        Self {
113            name: Some(name.into()),
114            addresses,
115        }
116    }
117
118    pub fn into_owned(self) -> Group<'static> {
119        Group {
120            name: self.name.map(|s| s.into_owned().into()),
121            addresses: self.addresses.into_iter().map(|a| a.into_owned()).collect(),
122        }
123    }
124}
125
126impl<'x> Addr<'x> {
127    pub fn new(name: Option<&'x str>, address: &'x str) -> Self {
128        Self {
129            name: name.map(|name| name.into()),
130            address: Some(address.into()),
131        }
132    }
133
134    pub fn into_owned(self) -> Addr<'static> {
135        Addr {
136            name: self.name.map(|s| s.into_owned().into()),
137            address: self.address.map(|s| s.into_owned().into()),
138        }
139    }
140
141    pub fn name(&self) -> Option<&str> {
142        self.name.as_deref()
143    }
144
145    pub fn address(&self) -> Option<&str> {
146        self.address.as_deref()
147    }
148}