zbus_names/
unique_name.rs
1use crate::{utils::impl_try_from, Error, Result};
2use serde::{de, Deserialize, Serialize};
3use static_assertions::assert_impl_all;
4use std::{
5 borrow::{Borrow, Cow},
6 convert::TryFrom,
7 fmt::{self, Display, Formatter},
8 ops::Deref,
9 sync::Arc,
10};
11use zvariant::{NoneValue, OwnedValue, Str, Type, Value};
12
13#[derive(
38 Clone, Debug, Hash, PartialEq, Eq, Serialize, Type, Value, PartialOrd, Ord, OwnedValue,
39)]
40pub struct UniqueName<'name>(Str<'name>);
41
42assert_impl_all!(UniqueName<'_>: Send, Sync, Unpin);
43
44impl<'name> UniqueName<'name> {
45 pub fn as_ref(&self) -> UniqueName<'_> {
47 UniqueName(self.0.as_ref())
48 }
49
50 pub fn as_str(&self) -> &str {
52 self.0.as_str()
53 }
54
55 pub fn from_str_unchecked(name: &'name str) -> Self {
60 Self(Str::from(name))
61 }
62
63 pub fn from_static_str(name: &'static str) -> Result<Self> {
65 ensure_correct_unique_name(name)?;
66 Ok(Self(Str::from_static(name)))
67 }
68
69 pub const fn from_static_str_unchecked(name: &'static str) -> Self {
71 Self(Str::from_static(name))
72 }
73
74 pub fn from_string_unchecked(name: String) -> Self {
79 Self(Str::from(name))
80 }
81
82 pub fn to_owned(&self) -> UniqueName<'static> {
84 UniqueName(self.0.to_owned())
85 }
86
87 pub fn into_owned(self) -> UniqueName<'static> {
89 UniqueName(self.0.into_owned())
90 }
91}
92
93impl Deref for UniqueName<'_> {
94 type Target = str;
95
96 fn deref(&self) -> &Self::Target {
97 self.as_str()
98 }
99}
100
101impl Borrow<str> for UniqueName<'_> {
102 fn borrow(&self) -> &str {
103 self.as_str()
104 }
105}
106
107impl Display for UniqueName<'_> {
108 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
109 Display::fmt(&self.as_str(), f)
110 }
111}
112
113impl PartialEq<str> for UniqueName<'_> {
114 fn eq(&self, other: &str) -> bool {
115 self.as_str() == other
116 }
117}
118
119impl PartialEq<&str> for UniqueName<'_> {
120 fn eq(&self, other: &&str) -> bool {
121 self.as_str() == *other
122 }
123}
124
125impl PartialEq<OwnedUniqueName> for UniqueName<'_> {
126 fn eq(&self, other: &OwnedUniqueName) -> bool {
127 *self == other.0
128 }
129}
130
131impl<'de: 'name, 'name> Deserialize<'de> for UniqueName<'name> {
132 fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
133 where
134 D: serde::Deserializer<'de>,
135 {
136 let name = <Cow<'name, str>>::deserialize(deserializer)?;
137
138 Self::try_from(name).map_err(|e| de::Error::custom(e.to_string()))
139 }
140}
141
142fn ensure_correct_unique_name(name: &str) -> Result<()> {
143 if name.is_empty() {
150 return Err(Error::InvalidUniqueName(String::from(
151 "must contain at least 4 characters",
152 )));
153 } else if name.len() > 255 {
154 return Err(Error::InvalidUniqueName(format!(
155 "`{}` is {} characters long, which is longer than maximum allowed (255)",
156 name,
157 name.len(),
158 )));
159 } else if name == "org.freedesktop.DBus" {
160 return Ok(());
162 }
163
164 let mut chars = name.chars();
166 let mut prev = match chars.next().expect("no first char") {
167 first @ ':' => first,
168 _ => {
169 return Err(Error::InvalidUniqueName(String::from(
170 "must start with a `:`",
171 )));
172 }
173 };
174
175 let mut no_dot = true;
176 for c in chars {
177 if c == '.' {
178 if prev == '.' {
179 return Err(Error::InvalidUniqueName(String::from(
180 "must not contain a double `.`",
181 )));
182 }
183
184 if no_dot {
185 no_dot = false;
186 }
187 } else if !c.is_ascii_alphanumeric() && c != '_' && c != '-' {
188 return Err(Error::InvalidUniqueName(format!(
189 "`{c}` character not allowed"
190 )));
191 }
192
193 prev = c;
194 }
195
196 if no_dot {
197 return Err(Error::InvalidUniqueName(String::from(
198 "must contain at least 1 `.`",
199 )));
200 }
201
202 Ok(())
203}
204
205impl TryFrom<()> for UniqueName<'_> {
208 type Error = Error;
209
210 fn try_from(_value: ()) -> Result<Self> {
211 unreachable!("Conversion from `()` is not meant to actually work");
212 }
213}
214
215impl<'name> From<&UniqueName<'name>> for UniqueName<'name> {
216 fn from(name: &UniqueName<'name>) -> Self {
217 name.clone()
218 }
219}
220
221impl<'name> From<UniqueName<'name>> for Str<'name> {
222 fn from(value: UniqueName<'name>) -> Self {
223 value.0
224 }
225}
226
227impl<'name> NoneValue for UniqueName<'name> {
228 type NoneType = &'name str;
229
230 fn null_value() -> Self::NoneType {
231 <&str>::default()
232 }
233}
234
235#[derive(
237 Clone, Debug, Hash, PartialEq, Eq, Serialize, Type, Value, PartialOrd, Ord, OwnedValue,
238)]
239pub struct OwnedUniqueName(#[serde(borrow)] UniqueName<'static>);
240
241assert_impl_all!(OwnedUniqueName: Send, Sync, Unpin);
242
243impl OwnedUniqueName {
244 pub fn into_inner(self) -> UniqueName<'static> {
246 self.0
247 }
248
249 pub fn inner(&self) -> &UniqueName<'static> {
251 &self.0
252 }
253}
254
255impl Deref for OwnedUniqueName {
256 type Target = UniqueName<'static>;
257
258 fn deref(&self) -> &Self::Target {
259 &self.0
260 }
261}
262
263impl Borrow<str> for OwnedUniqueName {
264 fn borrow(&self) -> &str {
265 self.0.as_str()
266 }
267}
268
269impl From<OwnedUniqueName> for UniqueName<'static> {
270 fn from(o: OwnedUniqueName) -> Self {
271 o.into_inner()
272 }
273}
274
275impl<'unowned, 'owned: 'unowned> From<&'owned OwnedUniqueName> for UniqueName<'unowned> {
276 fn from(name: &'owned OwnedUniqueName) -> Self {
277 UniqueName::from_str_unchecked(name.as_str())
278 }
279}
280
281impl From<UniqueName<'_>> for OwnedUniqueName {
282 fn from(name: UniqueName<'_>) -> Self {
283 OwnedUniqueName(name.into_owned())
284 }
285}
286
287impl_try_from! {
288 ty: UniqueName<'s>,
289 owned_ty: OwnedUniqueName,
290 validate_fn: ensure_correct_unique_name,
291 try_from: [&'s str, String, Arc<str>, Cow<'s, str>, Str<'s>],
292}
293
294impl From<OwnedUniqueName> for Str<'static> {
295 fn from(value: OwnedUniqueName) -> Self {
296 value.into_inner().0
297 }
298}
299
300impl<'de> Deserialize<'de> for OwnedUniqueName {
301 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
302 where
303 D: de::Deserializer<'de>,
304 {
305 String::deserialize(deserializer)
306 .and_then(|n| UniqueName::try_from(n).map_err(|e| de::Error::custom(e.to_string())))
307 .map(Self)
308 }
309}
310
311impl PartialEq<&str> for OwnedUniqueName {
312 fn eq(&self, other: &&str) -> bool {
313 self.as_str() == *other
314 }
315}
316
317impl PartialEq<UniqueName<'_>> for OwnedUniqueName {
318 fn eq(&self, other: &UniqueName<'_>) -> bool {
319 self.0 == *other
320 }
321}
322
323impl NoneValue for OwnedUniqueName {
324 type NoneType = <UniqueName<'static> as NoneValue>::NoneType;
325
326 fn null_value() -> Self::NoneType {
327 UniqueName::null_value()
328 }
329}
330
331impl Display for OwnedUniqueName {
332 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
333 UniqueName::from(self).fmt(f)
334 }
335}