1use crate::error::{Kind, Result};
4use crate::matcher;
5use core::fmt;
6use psl_types::{List, Type};
7
8#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
10pub struct Name<'a> {
11 full: &'a str,
12 suffix: psl_types::Suffix<'a>,
13}
14
15impl<'a> Name<'a> {
16 pub(crate) fn parse<T: List + ?Sized>(list: &T, name: &'a str) -> Result<Name<'a>> {
17 let stripped = if name.ends_with('.') {
18 name.get(..name.len() - 1).unwrap_or_default()
19 } else {
20 name
21 };
22 if stripped.contains('.') {
23 matcher::is_domain_name(stripped)?;
24 } else {
25 matcher::is_label(stripped, true)?;
26 }
27 Ok(Self {
28 suffix: list.suffix(name.as_bytes()).ok_or(Kind::InvalidDomain)?,
29 full: name,
30 })
31 }
32
33 pub const fn as_str(&self) -> &'a str {
35 self.full
36 }
37
38 fn without_suffix(&self) -> Option<&'a str> {
39 let domain_len = self.full.len();
40 let suffix_len = self.suffix().len();
41 if domain_len == suffix_len {
42 return None;
43 }
44 self.full.get(..domain_len - suffix_len - 1)
45 }
46
47 pub fn root(&self) -> Option<&'a str> {
49 let offset = self
50 .without_suffix()?
51 .rfind('.')
52 .map(|x| x + 1)
53 .unwrap_or_default();
54 self.full.get(offset..)
55 }
56
57 pub fn prefix(&self) -> Option<&'a str> {
59 let domain_len = self.full.len();
60 let root_len = self.root()?.len();
61 if domain_len == root_len {
62 return None;
63 }
64 self.full.get(..domain_len - root_len - 1)
65 }
66
67 pub fn suffix(&self) -> &'a str {
69 let offset = self.full.len() - self.suffix.as_bytes().len();
70 &self.full[offset..]
71 }
72
73 pub fn has_known_suffix(&self) -> bool {
75 self.suffix.is_known()
76 }
77
78 pub fn is_icann(&self) -> bool {
83 self.suffix.typ() == Some(Type::Icann)
84 }
85
86 pub fn is_private(&self) -> bool {
91 self.suffix.typ() == Some(Type::Private)
92 }
93}
94
95impl fmt::Display for Name<'_> {
96 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
97 write!(f, "{}", self.full)
98 }
99}
100
101impl PartialEq<&str> for Name<'_> {
102 fn eq(&self, other: &&str) -> bool {
103 self.full == *other
104 }
105}