1use super::parse::*;
2use std::{
3 borrow::Cow,
4 cmp::Ordering,
5 fmt,
6 hash::{Hash, Hasher},
7};
8
9#[derive(Debug, Copy, Clone)]
17pub struct Name<'a>(&'a str);
18
19impl<'a> Name<'a> {
20 #[must_use]
24 pub fn new(s: &'a str) -> Option<Self> {
25 if is_restricted_name(s) {
26 Some(Self(s))
27 } else {
28 None
29 }
30 }
31
32 #[must_use]
34 pub const fn as_str(&self) -> &'a str {
35 self.0
36 }
37
38 pub const MAX_LENGTH: usize = 127;
40
41 pub const fn new_unchecked(s: &'a str) -> Self {
43 Self(s)
44 }
45}
46
47impl fmt::Display for Name<'_> {
48 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49 f.write_str(self.0)
50 }
51}
52
53impl AsRef<str> for Name<'_> {
54 fn as_ref(&self) -> &str {
55 self.0
56 }
57}
58
59impl PartialEq for Name<'_> {
60 fn eq(&self, other: &Self) -> bool {
61 self.0.eq_ignore_ascii_case(other.as_ref())
62 }
63}
64
65impl Eq for Name<'_> {}
66
67impl PartialOrd for Name<'_> {
68 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
69 Some(self.cmp(other))
70 }
71}
72
73impl Ord for Name<'_> {
74 fn cmp(&self, other: &Self) -> Ordering {
75 self.0
76 .chars()
77 .map(|c| c.to_ascii_lowercase())
78 .cmp(other.0.chars().map(|c| c.to_ascii_lowercase()))
79 }
80}
81
82impl Hash for Name<'_> {
83 fn hash<H: Hasher>(&self, state: &mut H) {
84 self.0.to_ascii_lowercase().hash(state);
85 }
86}
87
88impl PartialEq<String> for Name<'_> {
89 fn eq(&self, other: &String) -> bool {
90 self.eq(other.as_str())
91 }
92}
93
94impl PartialOrd<String> for Name<'_> {
95 fn partial_cmp(&self, other: &String) -> Option<Ordering> {
96 self.partial_cmp(other.as_str())
97 }
98}
99
100impl PartialEq<&String> for Name<'_> {
101 fn eq(&self, other: &&String) -> bool {
102 self.eq(other.as_str())
103 }
104}
105
106impl PartialOrd<&String> for Name<'_> {
107 fn partial_cmp(&self, other: &&String) -> Option<Ordering> {
108 self.partial_cmp(other.as_str())
109 }
110}
111
112impl PartialEq<str> for Name<'_> {
113 fn eq(&self, other: &str) -> bool {
114 self.0.eq_ignore_ascii_case(other)
115 }
116}
117
118impl PartialOrd<str> for Name<'_> {
119 fn partial_cmp(&self, other: &str) -> Option<Ordering> {
120 Some(
121 self.0
122 .chars()
123 .map(|c| c.to_ascii_lowercase())
124 .cmp(other.chars().map(|c| c.to_ascii_lowercase())),
125 )
126 }
127}
128
129impl PartialEq<&str> for Name<'_> {
130 fn eq(&self, other: &&str) -> bool {
131 self.eq(*other)
132 }
133}
134
135impl PartialOrd<&str> for Name<'_> {
136 fn partial_cmp(&self, other: &&str) -> Option<Ordering> {
137 self.partial_cmp(*other)
138 }
139}
140
141impl PartialEq<Cow<'_, str>> for Name<'_> {
142 fn eq(&self, other: &Cow<'_, str>) -> bool {
143 self.eq(other.as_ref())
144 }
145}
146
147impl PartialOrd<Cow<'_, str>> for Name<'_> {
148 fn partial_cmp(&self, other: &Cow<'_, str>) -> Option<Ordering> {
149 self.partial_cmp(other.as_ref())
150 }
151}
152
153impl PartialEq<&Cow<'_, str>> for Name<'_> {
154 fn eq(&self, other: &&Cow<'_, str>) -> bool {
155 self.eq(other.as_ref())
156 }
157}
158
159impl PartialOrd<&Cow<'_, str>> for Name<'_> {
160 fn partial_cmp(&self, other: &&Cow<'_, str>) -> Option<Ordering> {
161 self.partial_cmp(other.as_ref())
162 }
163}