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/// String that identifies a [well-known bus name][wbn].
14///
15/// # Examples
16///
17/// ```
18/// use core::convert::TryFrom;
19/// use zbus_names::WellKnownName;
20///
21/// // Valid well-known names.
22/// let name = WellKnownName::try_from("org.gnome.Service-for_you").unwrap();
23/// assert_eq!(name, "org.gnome.Service-for_you");
24/// let name = WellKnownName::try_from("a.very.loooooooooooooooooo-ooooooo_0000o0ng.Name").unwrap();
25/// assert_eq!(name, "a.very.loooooooooooooooooo-ooooooo_0000o0ng.Name");
26///
27/// // Invalid well-known names
28/// WellKnownName::try_from("").unwrap_err();
29/// WellKnownName::try_from("double..dots").unwrap_err();
30/// WellKnownName::try_from(".").unwrap_err();
31/// WellKnownName::try_from(".start.with.dot").unwrap_err();
32/// WellKnownName::try_from("1st.element.starts.with.digit").unwrap_err();
33/// WellKnownName::try_from("the.2nd.element.starts.with.digit").unwrap_err();
34/// WellKnownName::try_from("no-dots").unwrap_err();
35/// ```
36///
37/// [wbn]: https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names-bus
38#[derive(
39 Clone, Debug, Hash, PartialEq, Eq, Serialize, Type, Value, PartialOrd, Ord, OwnedValue,
40)]
41pub struct WellKnownName<'name>(Str<'name>);
42
43assert_impl_all!(WellKnownName<'_>: Send, Sync, Unpin);
44
45impl<'name> WellKnownName<'name> {
46 /// A borrowed clone (never allocates, unlike clone).
47 pub fn as_ref(&self) -> WellKnownName<'_> {
48 WellKnownName(self.0.as_ref())
49 }
50
51 /// The well-known-name as string.
52 pub fn as_str(&self) -> &str {
53 self.0.as_str()
54 }
55
56 /// Create a new `WellKnownName` from the given string.
57 ///
58 /// Since the passed string is not checked for correctness, prefer using the
59 /// `TryFrom<&str>` implementation.
60 pub fn from_str_unchecked(name: &'name str) -> Self {
61 Self(Str::from(name))
62 }
63
64 /// Same as `try_from`, except it takes a `&'static str`.
65 pub fn from_static_str(name: &'static str) -> Result<Self> {
66 ensure_correct_well_known_name(name)?;
67 Ok(Self(Str::from_static(name)))
68 }
69
70 /// Same as `from_str_unchecked`, except it takes a `&'static str`.
71 pub const fn from_static_str_unchecked(name: &'static str) -> Self {
72 Self(Str::from_static(name))
73 }
74
75 /// Same as `from_str_unchecked`, except it takes an owned `String`.
76 ///
77 /// Since the passed string is not checked for correctness, prefer using the
78 /// `TryFrom<String>` implementation.
79 pub fn from_string_unchecked(name: String) -> Self {
80 Self(Str::from(name))
81 }
82
83 /// Creates an owned clone of `self`.
84 pub fn to_owned(&self) -> WellKnownName<'static> {
85 WellKnownName(self.0.to_owned())
86 }
87
88 /// Creates an owned clone of `self`.
89 pub fn into_owned(self) -> WellKnownName<'static> {
90 WellKnownName(self.0.into_owned())
91 }
92}
93
94impl Deref for WellKnownName<'_> {
95 type Target = str;
96
97 fn deref(&self) -> &Self::Target {
98 self.as_str()
99 }
100}
101
102impl Borrow<str> for WellKnownName<'_> {
103 fn borrow(&self) -> &str {
104 self.as_str()
105 }
106}
107
108impl Display for WellKnownName<'_> {
109 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
110 Display::fmt(&self.as_str(), f)
111 }
112}
113
114impl<'a> PartialEq<str> for WellKnownName<'a> {
115 fn eq(&self, other: &str) -> bool {
116 self.as_str() == other
117 }
118}
119
120impl<'a> PartialEq<&str> for WellKnownName<'a> {
121 fn eq(&self, other: &&str) -> bool {
122 self.as_str() == *other
123 }
124}
125
126impl PartialEq<OwnedWellKnownName> for WellKnownName<'_> {
127 fn eq(&self, other: &OwnedWellKnownName) -> bool {
128 *self == other.0
129 }
130}
131
132impl<'de: 'name, 'name> Deserialize<'de> for WellKnownName<'name> {
133 fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
134 where
135 D: serde::Deserializer<'de>,
136 {
137 let name: Cow<'_, str> = <Cow<'name, str>>::deserialize(deserializer)?;
138
139 Self::try_from(name).map_err(|e: Error| de::Error::custom(msg:e.to_string()))
140 }
141}
142
143fn ensure_correct_well_known_name(name: &str) -> Result<()> {
144 // Rules
145 //
146 // * Only ASCII alphanumeric, `_` or '-'.
147 // * Must not begin with a `.`.
148 // * Must contain at least one `.`.
149 // * Each element must:
150 // * not begin with a digit.
151 // * be 1 character (so name must be minimum 3 characters long).
152 // * <= 255 characters.
153 if name.is_empty() {
154 return Err(Error::InvalidWellKnownName(String::from(
155 "must contain at least 3 characters",
156 )));
157 } else if name.len() < 3 {
158 return Err(Error::InvalidWellKnownName(format!(
159 "`{}` is {} characters long, which is smaller than minimum allowed (3)",
160 name,
161 name.len(),
162 )));
163 } else if name.len() > 255 {
164 return Err(Error::InvalidWellKnownName(format!(
165 "`{}` is {} characters long, which is longer than maximum allowed (255)",
166 name,
167 name.len(),
168 )));
169 }
170
171 let mut prev = None;
172 let mut no_dot = true;
173 for c in name.chars() {
174 if c == '.' {
175 if prev.is_none() || prev == Some('.') {
176 return Err(Error::InvalidWellKnownName(String::from(
177 "must not contain a double `.`",
178 )));
179 }
180
181 if no_dot {
182 no_dot = false;
183 }
184 } else if c.is_ascii_digit() && (prev.is_none() || prev == Some('.')) {
185 return Err(Error::InvalidWellKnownName(String::from(
186 "each element must not start with a digit",
187 )));
188 } else if !c.is_ascii_alphanumeric() && c != '_' && c != '-' {
189 return Err(Error::InvalidWellKnownName(format!(
190 "`{c}` character not allowed"
191 )));
192 }
193
194 prev = Some(c);
195 }
196
197 if no_dot {
198 return Err(Error::InvalidWellKnownName(String::from(
199 "must contain at least 1 `.`",
200 )));
201 }
202
203 Ok(())
204}
205
206/// This never succeeds but is provided so it's easier to pass `Option::None` values for API
207/// requiring `Option<TryInto<impl BusName>>`, since type inference won't work here.
208impl TryFrom<()> for WellKnownName<'_> {
209 type Error = Error;
210
211 fn try_from(_value: ()) -> Result<Self> {
212 unreachable!("Conversion from `()` is not meant to actually work");
213 }
214}
215
216impl<'name> From<&WellKnownName<'name>> for WellKnownName<'name> {
217 fn from(name: &WellKnownName<'name>) -> Self {
218 name.clone()
219 }
220}
221
222impl<'name> From<WellKnownName<'name>> for Str<'name> {
223 fn from(value: WellKnownName<'name>) -> Self {
224 value.0
225 }
226}
227
228impl<'name> NoneValue for WellKnownName<'name> {
229 type NoneType = &'name str;
230
231 fn null_value() -> Self::NoneType {
232 <&str>::default()
233 }
234}
235
236/// Owned sibling of [`WellKnownName`].
237#[derive(
238 Clone, Debug, Hash, PartialEq, Eq, Serialize, Type, Value, PartialOrd, Ord, OwnedValue,
239)]
240pub struct OwnedWellKnownName(#[serde(borrow)] WellKnownName<'static>);
241
242assert_impl_all!(OwnedWellKnownName: Send, Sync, Unpin);
243
244impl OwnedWellKnownName {
245 /// Convert to the inner `WellKnownName`, consuming `self`.
246 pub fn into_inner(self) -> WellKnownName<'static> {
247 self.0
248 }
249
250 /// Get a reference to the inner `WellKnownName`.
251 pub fn inner(&self) -> &WellKnownName<'static> {
252 &self.0
253 }
254}
255
256impl Deref for OwnedWellKnownName {
257 type Target = WellKnownName<'static>;
258
259 fn deref(&self) -> &Self::Target {
260 &self.0
261 }
262}
263
264impl Borrow<str> for OwnedWellKnownName {
265 fn borrow(&self) -> &str {
266 self.0.as_str()
267 }
268}
269
270impl AsRef<str> for OwnedWellKnownName {
271 fn as_ref(&self) -> &str {
272 self.0.as_str()
273 }
274}
275
276impl Display for OwnedWellKnownName {
277 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
278 WellKnownName::from(self).fmt(f)
279 }
280}
281
282impl From<OwnedWellKnownName> for WellKnownName<'static> {
283 fn from(name: OwnedWellKnownName) -> Self {
284 name.into_inner()
285 }
286}
287
288impl<'unowned, 'owned: 'unowned> From<&'owned OwnedWellKnownName> for WellKnownName<'unowned> {
289 fn from(name: &'owned OwnedWellKnownName) -> Self {
290 WellKnownName::from_str_unchecked(name:name.as_str())
291 }
292}
293
294impl From<WellKnownName<'_>> for OwnedWellKnownName {
295 fn from(name: WellKnownName<'_>) -> Self {
296 OwnedWellKnownName(name.into_owned())
297 }
298}
299
300impl_try_from! {
301 ty: WellKnownName<'s>,
302 owned_ty: OwnedWellKnownName,
303 validate_fn: ensure_correct_well_known_name,
304 try_from: [&'s str, String, Arc<str>, Cow<'s, str>, Str<'s>],
305}
306
307impl From<OwnedWellKnownName> for Str<'static> {
308 fn from(value: OwnedWellKnownName) -> Self {
309 value.into_inner().0
310 }
311}
312
313impl<'de> Deserialize<'de> for OwnedWellKnownName {
314 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
315 where
316 D: de::Deserializer<'de>,
317 {
318 String::deserialize(deserializer)
319 .and_then(|n| WellKnownName::try_from(n).map_err(|e| de::Error::custom(e.to_string())))
320 .map(Self)
321 }
322}
323
324impl PartialEq<&str> for OwnedWellKnownName {
325 fn eq(&self, other: &&str) -> bool {
326 self.as_str() == *other
327 }
328}
329
330impl PartialEq<WellKnownName<'_>> for OwnedWellKnownName {
331 fn eq(&self, other: &WellKnownName<'_>) -> bool {
332 self.0 == *other
333 }
334}
335
336impl NoneValue for OwnedWellKnownName {
337 type NoneType = <WellKnownName<'static> as NoneValue>::NoneType;
338
339 fn null_value() -> Self::NoneType {
340 WellKnownName::null_value()
341 }
342}
343