1include!(concat!(env!("OUT_DIR"), "/known_domains_gen.rs"));
5include!(concat!(env!("OUT_DIR"), "/popular_repos_gen.rs"));
6include!(concat!(env!("OUT_DIR"), "/psl_gen.rs"));
7
8pub fn is_known_domain(domain: &str) -> bool {
10 let lower = domain.to_lowercase();
11 KNOWN_DOMAINS.iter().any(|d| *d == lower)
12}
13
14pub fn is_popular_repo(owner: &str, name: &str) -> bool {
16 let owner_lower = owner.to_lowercase();
17 let name_lower = name.to_lowercase();
18 POPULAR_REPOS
19 .iter()
20 .any(|(o, n)| o.to_lowercase() == owner_lower && n.to_lowercase() == name_lower)
21}
22
23pub fn known_domains() -> &'static [&'static str] {
25 KNOWN_DOMAINS
26}
27
28pub fn is_public_suffix(suffix: &str) -> bool {
30 let lower = suffix.to_lowercase();
31 PUBLIC_SUFFIXES.iter().any(|s| *s == lower)
32}
33
34pub fn registrable_domain(host: &str) -> Option<String> {
37 let lower = host.to_lowercase().trim_end_matches('.').to_string();
38 let labels: Vec<&str> = lower.split('.').collect();
39 if labels.len() < 2 {
40 return None;
41 }
42 for i in 0..labels.len() {
44 let suffix = labels[i..].join(".");
45 if is_public_suffix(&suffix) {
46 if i == 0 {
47 return None;
49 }
50 return Some(labels[i - 1..].join("."));
52 }
53 }
54 if labels.len() >= 2 {
56 Some(labels[labels.len() - 2..].join("."))
57 } else {
58 None
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65
66 #[test]
67 fn test_known_domain() {
68 assert!(is_known_domain("github.com"));
69 assert!(is_known_domain("GitHub.com"));
70 assert!(!is_known_domain("notaknowndomain.com"));
71 }
72
73 #[test]
74 fn test_popular_repo() {
75 assert!(is_popular_repo("torvalds", "linux"));
76 assert!(!is_popular_repo("nobody", "nothing"));
77 }
78}