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