message/
queue_name.rs

1#[derive(Debug)]
2pub struct QueueNameComponents<'a> {
3    pub campaign: Option<&'a str>,
4    pub tenant: Option<&'a str>,
5    pub domain: &'a str,
6    pub routing_domain: Option<&'a str>,
7}
8
9fn crack_domain(domain: &str) -> (&str, Option<&str>) {
10    match domain.split_once('!') {
11        Some((domain, routing_domain)) => (domain, Some(routing_domain)),
12        None => (domain, None),
13    }
14}
15
16impl<'a> QueueNameComponents<'a> {
17    pub fn parse(name: &'a str) -> Self {
18        match name.split_once('@') {
19            Some((prefix, domain)) => match prefix.split_once(':') {
20                Some((campaign, tenant)) => {
21                    let (domain, routing_domain) = crack_domain(domain);
22                    Self {
23                        campaign: Some(campaign),
24                        tenant: Some(tenant),
25                        domain,
26                        routing_domain,
27                    }
28                }
29                None => {
30                    let (domain, routing_domain) = crack_domain(domain);
31                    Self {
32                        campaign: None,
33                        tenant: Some(prefix),
34                        domain,
35                        routing_domain,
36                    }
37                }
38            },
39            None => {
40                let (domain, routing_domain) = crack_domain(name);
41                Self {
42                    campaign: None,
43                    tenant: None,
44                    domain,
45                    routing_domain,
46                }
47            }
48        }
49    }
50
51    pub fn to_string(&self) -> String {
52        Self::format(self.campaign, self.tenant, self.domain, self.routing_domain)
53    }
54
55    pub fn format<C: AsRef<str>, T: AsRef<str>, D: AsRef<str>, RD: AsRef<str>>(
56        campaign: Option<C>,
57        tenant: Option<T>,
58        domain: D,
59        routing_domain: Option<RD>,
60    ) -> String {
61        let campaign: Option<&str> = campaign.as_ref().map(|c| c.as_ref());
62        let tenant: Option<&str> = tenant.as_ref().map(|c| c.as_ref());
63        let routing_domain: Option<String> =
64            routing_domain.as_ref().map(|c| format!("!{}", c.as_ref()));
65        let routing_domain = routing_domain.as_deref().unwrap_or("");
66        let domain: &str = domain.as_ref();
67        match (campaign, tenant) {
68            (Some(c), Some(t)) => format!("{c}:{t}@{domain}{routing_domain}"),
69            (Some(c), None) => format!("{c}:@{domain}{routing_domain}"),
70            (None, Some(t)) => format!("{t}@{domain}{routing_domain}"),
71            (None, None) => format!("{domain}{routing_domain}"),
72        }
73    }
74}
75
76#[cfg(test)]
77mod test {
78    use super::*;
79
80    #[test]
81    fn test_routing_domain_syntax() {
82        k9::assert_equal!(crack_domain("foo.com"), ("foo.com", None));
83        k9::assert_equal!(
84            crack_domain("foo.com!bar.com"),
85            ("foo.com", Some("bar.com"))
86        );
87    }
88
89    #[test]
90    fn test_routing_domain_with_port() {
91        k9::snapshot!(
92            QueueNameComponents::parse("foo.com:2025"),
93            r#"
94QueueNameComponents {
95    campaign: None,
96    tenant: None,
97    domain: "foo.com:2025",
98    routing_domain: None,
99}
100"#
101        );
102
103        k9::snapshot!(
104            QueueNameComponents::parse("foo.com!routing.com:2025"),
105            r#"
106QueueNameComponents {
107    campaign: None,
108    tenant: None,
109    domain: "foo.com",
110    routing_domain: Some(
111        "routing.com:2025",
112    ),
113}
114"#
115        );
116
117        k9::snapshot!(
118            QueueNameComponents::parse("tenant@foo.com!routing.com:2025"),
119            r#"
120QueueNameComponents {
121    campaign: None,
122    tenant: Some(
123        "tenant",
124    ),
125    domain: "foo.com",
126    routing_domain: Some(
127        "routing.com:2025",
128    ),
129}
130"#
131        );
132
133        k9::snapshot!(
134            QueueNameComponents::parse("campaign:@foo.com!routing.com:2025"),
135            r#"
136QueueNameComponents {
137    campaign: Some(
138        "campaign",
139    ),
140    tenant: Some(
141        "",
142    ),
143    domain: "foo.com",
144    routing_domain: Some(
145        "routing.com:2025",
146    ),
147}
148"#
149        );
150
151        k9::snapshot!(
152            QueueNameComponents::parse("campaign:tenant@foo.com!routing.com:2025"),
153            r#"
154QueueNameComponents {
155    campaign: Some(
156        "campaign",
157    ),
158    tenant: Some(
159        "tenant",
160    ),
161    domain: "foo.com",
162    routing_domain: Some(
163        "routing.com:2025",
164    ),
165}
166"#
167        );
168    }
169
170    #[test]
171    fn test_queue_name() {
172        k9::snapshot!(
173            QueueNameComponents::parse("foo.com"),
174            r#"
175QueueNameComponents {
176    campaign: None,
177    tenant: None,
178    domain: "foo.com",
179    routing_domain: None,
180}
181"#
182        );
183        k9::snapshot!(
184            QueueNameComponents::parse("tenant@foo.com"),
185            r#"
186QueueNameComponents {
187    campaign: None,
188    tenant: Some(
189        "tenant",
190    ),
191    domain: "foo.com",
192    routing_domain: None,
193}
194"#
195        );
196        k9::snapshot!(
197            QueueNameComponents::parse("campaign:@foo.com"),
198            r#"
199QueueNameComponents {
200    campaign: Some(
201        "campaign",
202    ),
203    tenant: Some(
204        "",
205    ),
206    domain: "foo.com",
207    routing_domain: None,
208}
209"#
210        );
211        k9::snapshot!(
212            QueueNameComponents::parse("campaign:tenant@foo.com"),
213            r#"
214QueueNameComponents {
215    campaign: Some(
216        "campaign",
217    ),
218    tenant: Some(
219        "tenant",
220    ),
221    domain: "foo.com",
222    routing_domain: None,
223}
224"#
225        );
226        k9::snapshot!(
227            QueueNameComponents::parse("campaign:tenant@foo.com!routing.com"),
228            r#"
229QueueNameComponents {
230    campaign: Some(
231        "campaign",
232    ),
233    tenant: Some(
234        "tenant",
235    ),
236    domain: "foo.com",
237    routing_domain: Some(
238        "routing.com",
239    ),
240}
241"#
242        );
243    }
244}