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_queue_name() {
91        k9::snapshot!(
92            QueueNameComponents::parse("foo.com"),
93            r#"
94QueueNameComponents {
95    campaign: None,
96    tenant: None,
97    domain: "foo.com",
98    routing_domain: None,
99}
100"#
101        );
102        k9::snapshot!(
103            QueueNameComponents::parse("tenant@foo.com"),
104            r#"
105QueueNameComponents {
106    campaign: None,
107    tenant: Some(
108        "tenant",
109    ),
110    domain: "foo.com",
111    routing_domain: None,
112}
113"#
114        );
115        k9::snapshot!(
116            QueueNameComponents::parse("campaign:@foo.com"),
117            r#"
118QueueNameComponents {
119    campaign: Some(
120        "campaign",
121    ),
122    tenant: Some(
123        "",
124    ),
125    domain: "foo.com",
126    routing_domain: None,
127}
128"#
129        );
130        k9::snapshot!(
131            QueueNameComponents::parse("campaign:tenant@foo.com"),
132            r#"
133QueueNameComponents {
134    campaign: Some(
135        "campaign",
136    ),
137    tenant: Some(
138        "tenant",
139    ),
140    domain: "foo.com",
141    routing_domain: None,
142}
143"#
144        );
145        k9::snapshot!(
146            QueueNameComponents::parse("campaign:tenant@foo.com!routing.com"),
147            r#"
148QueueNameComponents {
149    campaign: Some(
150        "campaign",
151    ),
152    tenant: Some(
153        "tenant",
154    ),
155    domain: "foo.com",
156    routing_domain: Some(
157        "routing.com",
158    ),
159}
160"#
161        );
162    }
163}