zbus_names/
property_name.rs

1use 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/// String that identifies a [property][pn] name on the bus.
16///
17/// # Examples
18///
19/// ```
20/// use zbus_names::PropertyName;
21///
22/// // Valid property names.
23/// let name = PropertyName::try_from("Property_for_you").unwrap();
24/// assert_eq!(name, "Property_for_you");
25/// let name = PropertyName::try_from("CamelCase101").unwrap();
26/// assert_eq!(name, "CamelCase101");
27/// let name = PropertyName::try_from("a_very_loooooooooooooooooo_ooooooo_0000o0ngName").unwrap();
28/// assert_eq!(name, "a_very_loooooooooooooooooo_ooooooo_0000o0ngName");
29/// let name = PropertyName::try_from("Property_for_you-1").unwrap();
30/// assert_eq!(name, "Property_for_you-1");
31/// ```
32///
33/// [pn]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-properties
34#[derive(
35    Clone, Debug, Hash, PartialEq, Eq, Serialize, Type, Value, PartialOrd, Ord, OwnedValue,
36)]
37pub struct PropertyName<'name>(Str<'name>);
38
39assert_impl_all!(PropertyName<'_>: Send, Sync, Unpin);
40
41impl_str_basic!(PropertyName<'_>);
42
43impl<'name> PropertyName<'name> {
44    /// This is faster than `Clone::clone` when `self` contains owned data.
45    pub fn as_ref(&self) -> PropertyName<'_> {
46        PropertyName(self.0.as_ref())
47    }
48
49    /// The property name as string.
50    pub fn as_str(&self) -> &str {
51        self.0.as_str()
52    }
53
54    /// Create a new `PropertyName` from the given string.
55    ///
56    /// Since the passed string is not checked for correctness, prefer using the
57    /// `TryFrom<&str>` implementation.
58    pub fn from_str_unchecked(name: &'name str) -> Self {
59        Self(Str::from(name))
60    }
61
62    /// Same as `try_from`, except it takes a `&'static str`.
63    pub fn from_static_str(name: &'static str) -> Result<Self> {
64        ensure_correct_property_name(name)?;
65        Ok(Self(Str::from_static(name)))
66    }
67
68    /// Same as `from_str_unchecked`, except it takes a `&'static str`.
69    pub const fn from_static_str_unchecked(name: &'static str) -> Self {
70        Self(Str::from_static(name))
71    }
72
73    /// Same as `from_str_unchecked`, except it takes an owned `String`.
74    ///
75    /// Since the passed string is not checked for correctness, prefer using the
76    /// `TryFrom<String>` implementation.
77    pub fn from_string_unchecked(name: String) -> Self {
78        Self(Str::from(name))
79    }
80
81    /// Creates an owned clone of `self`.
82    pub fn to_owned(&self) -> PropertyName<'static> {
83        PropertyName(self.0.to_owned())
84    }
85
86    /// Creates an owned clone of `self`.
87    pub fn into_owned(self) -> PropertyName<'static> {
88        PropertyName(self.0.into_owned())
89    }
90}
91
92impl Deref for PropertyName<'_> {
93    type Target = str;
94
95    fn deref(&self) -> &Self::Target {
96        self.as_str()
97    }
98}
99
100impl Borrow<str> for PropertyName<'_> {
101    fn borrow(&self) -> &str {
102        self.as_str()
103    }
104}
105
106impl Display for PropertyName<'_> {
107    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
108        Display::fmt(&self.as_str(), f)
109    }
110}
111
112impl PartialEq<str> for PropertyName<'_> {
113    fn eq(&self, other: &str) -> bool {
114        self.as_str() == other
115    }
116}
117
118impl PartialEq<&str> for PropertyName<'_> {
119    fn eq(&self, other: &&str) -> bool {
120        self.as_str() == *other
121    }
122}
123
124impl PartialEq<OwnedPropertyName> for PropertyName<'_> {
125    fn eq(&self, other: &OwnedPropertyName) -> bool {
126        *self == other.0
127    }
128}
129
130impl<'de: 'name, 'name> Deserialize<'de> for PropertyName<'name> {
131    fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
132    where
133        D: serde::Deserializer<'de>,
134    {
135        let name = <Cow<'name, str>>::deserialize(deserializer)?;
136
137        Self::try_from(name).map_err(|e| de::Error::custom(e.to_string()))
138    }
139}
140
141impl<'name> From<PropertyName<'name>> for Str<'name> {
142    fn from(value: PropertyName<'name>) -> Self {
143        value.0
144    }
145}
146
147impl_try_from! {
148  ty: PropertyName<'s>,
149  owned_ty: OwnedPropertyName,
150  validate_fn: ensure_correct_property_name,
151  try_from: [&'s str, String, Arc<str>, Cow<'s, str>, Str<'s>],
152}
153
154fn ensure_correct_property_name(name: &str) -> Result<()> {
155    if name.is_empty() {
156        return Err(Error::InvalidName(
157            "Invalid property name. It has to be at least 1 character long.",
158        ));
159    } else if name.len() > 255 {
160        return Err(Error::InvalidName(
161            "Invalid property name. It can not be longer than 255 characters.",
162        ));
163    }
164
165    Ok(())
166}
167
168/// This never succeeds but is provided so it's easier to pass `Option::None` values for API
169/// requiring `Option<TryInto<impl BusName>>`, since type inference won't work here.
170impl TryFrom<()> for PropertyName<'_> {
171    type Error = Error;
172
173    fn try_from(_value: ()) -> Result<Self> {
174        unreachable!("Conversion from `()` is not meant to actually work");
175    }
176}
177
178impl<'name> From<&PropertyName<'name>> for PropertyName<'name> {
179    fn from(name: &PropertyName<'name>) -> Self {
180        name.clone()
181    }
182}
183
184impl<'name> NoneValue for PropertyName<'name> {
185    type NoneType = &'name str;
186
187    fn null_value() -> Self::NoneType {
188        <&str>::default()
189    }
190}
191
192/// Owned sibling of [`PropertyName`].
193#[derive(Clone, Hash, PartialEq, Eq, Serialize, Type, Value, PartialOrd, Ord, OwnedValue)]
194pub struct OwnedPropertyName(#[serde(borrow)] PropertyName<'static>);
195
196assert_impl_all!(OwnedPropertyName: Send, Sync, Unpin);
197
198impl_str_basic!(OwnedPropertyName);
199
200impl OwnedPropertyName {
201    /// Convert to the inner `PropertyName`, consuming `self`.
202    pub fn into_inner(self) -> PropertyName<'static> {
203        self.0
204    }
205
206    /// Get a reference to the inner `PropertyName`.
207    pub fn inner(&self) -> &PropertyName<'static> {
208        &self.0
209    }
210}
211
212impl Deref for OwnedPropertyName {
213    type Target = PropertyName<'static>;
214
215    fn deref(&self) -> &Self::Target {
216        &self.0
217    }
218}
219
220impl Borrow<str> for OwnedPropertyName {
221    fn borrow(&self) -> &str {
222        self.0.as_str()
223    }
224}
225
226impl From<OwnedPropertyName> for PropertyName<'_> {
227    fn from(o: OwnedPropertyName) -> Self {
228        o.into_inner()
229    }
230}
231
232impl<'unowned, 'owned: 'unowned> From<&'owned OwnedPropertyName> for PropertyName<'unowned> {
233    fn from(name: &'owned OwnedPropertyName) -> Self {
234        PropertyName::from_str_unchecked(name.as_str())
235    }
236}
237
238impl From<PropertyName<'_>> for OwnedPropertyName {
239    fn from(name: PropertyName<'_>) -> Self {
240        OwnedPropertyName(name.into_owned())
241    }
242}
243
244impl From<OwnedPropertyName> for Str<'_> {
245    fn from(value: OwnedPropertyName) -> Self {
246        value.into_inner().0
247    }
248}
249
250impl<'de> Deserialize<'de> for OwnedPropertyName {
251    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
252    where
253        D: de::Deserializer<'de>,
254    {
255        String::deserialize(deserializer)
256            .and_then(|n| PropertyName::try_from(n).map_err(|e| de::Error::custom(e.to_string())))
257            .map(Self)
258    }
259}
260
261impl PartialEq<&str> for OwnedPropertyName {
262    fn eq(&self, other: &&str) -> bool {
263        self.as_str() == *other
264    }
265}
266
267impl PartialEq<PropertyName<'_>> for OwnedPropertyName {
268    fn eq(&self, other: &PropertyName<'_>) -> bool {
269        self.0 == *other
270    }
271}
272
273impl Debug for OwnedPropertyName {
274    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
275        f.debug_tuple("OwnedPropertyName")
276            .field(&self.as_str())
277            .finish()
278    }
279}
280
281impl Display for OwnedPropertyName {
282    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
283        Display::fmt(&PropertyName::from(self), f)
284    }
285}
286
287impl NoneValue for OwnedPropertyName {
288    type NoneType = <PropertyName<'static> as NoneValue>::NoneType;
289
290    fn null_value() -> Self::NoneType {
291        PropertyName::null_value()
292    }
293}