zbus_names/
well_known_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/// 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<'name, str>>::deserialize(deserializer)?;
138
139        Self::try_from(name).map_err(|e| de::Error::custom(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.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}