1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
use addr::dns::Name;
use addr::parse_dns_name;
use crate::error::RipGenError;
#[derive(Clone)]
/// Contains the byproduct of parsing a domain
pub struct DomainComponents<'domain> {
components: Vec<&'domain str>
}
impl<'domain> DomainComponents<'domain> {
/// Returns an iterator that contains all of the names in the subdomains.
pub fn subdomains_iter(&self) -> impl Iterator<Item = &&'domain str> {
self.all_iter().take(self.count() - 1)
}
/// Returns an iterator that contains all of the names in the original domain.
/// The root is treated as the public suffix and therefore entirely occupies the last slot.
///
/// ```
/// # use ripgen_lib::DomainComponents;
/// # use std::convert::TryFrom;
/// let domain_component = DomainComponents::try_from("www.google.com")
/// .expect("Failed to parse.");
///
/// let mut iter = domain_component
/// .all_iter()
/// .map(|elem| *elem);
///
/// assert_eq!(iter.next(), Some("www"));
/// assert_eq!(iter.next(), Some("google.com"));
/// ```
pub fn all_iter(&self) -> impl Iterator<Item = &&'domain str> {
self.components.iter()
}
/// Returns the number of subdomain names + 1 (for root)
pub fn count(&self) -> usize { self.components.len() }
/// Returns a slice of the inner domain components that represent the subdomain names
pub fn subdomains(&self) -> &[&str] {
&self.components[.. self.count() - 1]
}
/// Returns the root
///
/// ```
/// # use ripgen_lib::DomainComponents;
/// # use std::convert::TryFrom;
/// let domain_component = DomainComponents::try_from("www.google.com")
/// .expect("Failed to parse.");
///
/// assert_eq!(domain_component.root(), "google.com");
/// ```
pub fn root(&self) -> &str {
self.components[self.components.len() - 1]
}
/// Returns a slice with all domain components in it. This includes the root element.
pub fn all(&self) -> &[&str] {
&self.components
}
}
impl<'domain> TryFrom<&'domain str> for DomainComponents<'domain> {
type Error = RipGenError;
fn try_from(domain: &'domain str) -> Result<Self, Self::Error> {
let parsed_domain_name: Name<'domain> = parse_dns_name(domain)
.map_err(|_| RipGenError::ErrorParsingDomain(domain.to_string()))?;
let root: &str = parsed_domain_name
.root()
.unwrap_or(domain);
// we do this so we can appease lifetimes
let root_start = domain.len() - root.len();
let root: &'domain str = &domain[root_start..];
let components: Vec<&'domain str> = domain
.trim_end_matches(root)
.split('.')
.filter(|elem| !elem.is_empty())
.chain(vec![root])
.collect::<Vec<&str>>();
let new_components = Self {
components
};
Ok(new_components)
}
}