zbus_names/
utils.rs

1macro_rules! impl_str_basic {
2    ($type:ty) => {
3        impl zvariant::Basic for $type {
4            const SIGNATURE_CHAR: char = <zvariant::Str<'_>>::SIGNATURE_CHAR;
5            const SIGNATURE_STR: &'static str = <zvariant::Str<'_>>::SIGNATURE_STR;
6        }
7    };
8}
9
10/// Generates all boilerplate code for a D-Bus name type and its owned variant.
11///
12/// This macro generates all the boilerplate code for a D-Bus name type and its owned variant.
13///
14/// # Parameters
15/// - `$name`: The name of the borrowed type (e.g., `InterfaceName`).
16/// - `$owned_name`: The name of the owned type (e.g., `OwnedInterfaceName`).
17/// - `$validate_fn`: The validation function to use.
18macro_rules! define_name_type_impls {
19    (
20        name: $name:ident,
21        owned: $owned_name:ident,
22        validate: $validate_fn:ident $(,)?
23    ) => {
24        // === impl_str_basic for borrowed type ===
25        impl zvariant::Basic for $name<'_> {
26            const SIGNATURE_CHAR: char = <zvariant::Str<'_>>::SIGNATURE_CHAR;
27            const SIGNATURE_STR: &'static str = <zvariant::Str<'_>>::SIGNATURE_STR;
28        }
29
30        impl<'name> $name<'name> {
31            /// This is faster than `Clone::clone` when `self` contains owned data.
32            pub fn as_ref(&self) -> $name<'_> {
33                $name(self.0.as_ref())
34            }
35
36            /// The name as string.
37            pub fn as_str(&self) -> &str {
38                self.0.as_str()
39            }
40
41            /// Create a new name from the given string.
42            ///
43            /// Since the passed string is not checked for correctness, prefer using the
44            /// `TryFrom<&str>` implementation.
45            pub fn from_str_unchecked(name: &'name str) -> Self {
46                Self(zvariant::Str::from(name))
47            }
48
49            /// Same as `try_from`, except it takes a `&'static str`.
50            pub fn from_static_str(name: &'static str) -> crate::Result<Self> {
51                $validate_fn(name)?;
52                Ok(Self(zvariant::Str::from_static(name)))
53            }
54
55            /// Same as `from_str_unchecked`, except it takes a `&'static str`.
56            pub const fn from_static_str_unchecked(name: &'static str) -> Self {
57                Self(zvariant::Str::from_static(name))
58            }
59
60            /// Same as `from_str_unchecked`, except it takes an owned `String`.
61            ///
62            /// Since the passed string is not checked for correctness, prefer using the
63            /// `TryFrom<String>` implementation.
64            pub fn from_string_unchecked(name: String) -> Self {
65                Self(zvariant::Str::from(name))
66            }
67
68            /// Creates an owned clone of `self`.
69            pub fn to_owned(&self) -> $name<'static> {
70                $name(self.0.to_owned())
71            }
72
73            /// Creates an owned clone of `self`.
74            pub fn into_owned(self) -> $name<'static> {
75                $name(self.0.into_owned())
76            }
77        }
78
79        impl std::ops::Deref for $name<'_> {
80            type Target = str;
81
82            fn deref(&self) -> &Self::Target {
83                self.as_str()
84            }
85        }
86
87        impl std::borrow::Borrow<str> for $name<'_> {
88            fn borrow(&self) -> &str {
89                self.as_str()
90            }
91        }
92
93        impl std::fmt::Display for $name<'_> {
94            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
95                std::fmt::Display::fmt(&self.as_str(), f)
96            }
97        }
98
99        impl PartialEq<str> for $name<'_> {
100            fn eq(&self, other: &str) -> bool {
101                self.as_str() == other
102            }
103        }
104
105        impl PartialEq<&str> for $name<'_> {
106            fn eq(&self, other: &&str) -> bool {
107                self.as_str() == *other
108            }
109        }
110
111        impl PartialEq<$owned_name> for $name<'_> {
112            fn eq(&self, other: &$owned_name) -> bool {
113                *self == other.0
114            }
115        }
116
117        impl<'de: 'name, 'name> serde::Deserialize<'de> for $name<'name> {
118            fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
119            where
120                D: serde::Deserializer<'de>,
121            {
122                let name = <std::borrow::Cow<'name, str>>::deserialize(deserializer)?;
123
124                Self::try_from(name).map_err(|e| serde::de::Error::custom(e.to_string()))
125            }
126        }
127
128        /// This never succeeds but is provided so it's easier to pass `Option::None` values for API
129        /// requiring `Option<TryInto<impl BusName>>`, since type inference won't work here.
130        impl TryFrom<()> for $name<'_> {
131            type Error = crate::Error;
132
133            fn try_from(_value: ()) -> crate::Result<Self> {
134                unreachable!("Conversion from `()` is not meant to actually work");
135            }
136        }
137
138        impl<'name> From<&$name<'name>> for $name<'name> {
139            fn from(name: &$name<'name>) -> Self {
140                name.clone()
141            }
142        }
143
144        impl<'name> From<$name<'name>> for zvariant::Str<'name> {
145            fn from(value: $name<'name>) -> Self {
146                value.0
147            }
148        }
149
150        impl<'name> zvariant::NoneValue for $name<'name> {
151            type NoneType = &'name str;
152
153            fn null_value() -> Self::NoneType {
154                <&str>::default()
155            }
156        }
157
158        // === TryFrom impls for borrowed type ===
159        impl<'s> TryFrom<&'s str> for $name<'s> {
160            type Error = crate::Error;
161
162            fn try_from(value: &'s str) -> crate::Result<Self> {
163                let value = zvariant::Str::from(value);
164                $validate_fn(value.as_str())?;
165                Ok(Self(value))
166            }
167        }
168
169        impl<'s> TryFrom<&'s str> for $owned_name {
170            type Error = crate::Error;
171
172            fn try_from(value: &'s str) -> crate::Result<Self> {
173                Ok(Self::from(<$name<'s>>::try_from(value)?))
174            }
175        }
176
177        impl TryFrom<String> for $name<'_> {
178            type Error = crate::Error;
179
180            fn try_from(value: String) -> crate::Result<Self> {
181                let value = zvariant::Str::from(value);
182                $validate_fn(value.as_str())?;
183                Ok(Self(value))
184            }
185        }
186
187        impl TryFrom<String> for $owned_name {
188            type Error = crate::Error;
189
190            fn try_from(value: String) -> crate::Result<Self> {
191                Ok(Self::from(<$name<'_>>::try_from(value)?))
192            }
193        }
194
195        impl TryFrom<std::sync::Arc<str>> for $name<'_> {
196            type Error = crate::Error;
197
198            fn try_from(value: std::sync::Arc<str>) -> crate::Result<Self> {
199                let value = zvariant::Str::from(value);
200                $validate_fn(value.as_str())?;
201                Ok(Self(value))
202            }
203        }
204
205        impl TryFrom<std::sync::Arc<str>> for $owned_name {
206            type Error = crate::Error;
207
208            fn try_from(value: std::sync::Arc<str>) -> crate::Result<Self> {
209                Ok(Self::from(<$name<'_>>::try_from(value)?))
210            }
211        }
212
213        impl<'s> TryFrom<std::borrow::Cow<'s, str>> for $name<'s> {
214            type Error = crate::Error;
215
216            fn try_from(value: std::borrow::Cow<'s, str>) -> crate::Result<Self> {
217                let value = zvariant::Str::from(value);
218                $validate_fn(value.as_str())?;
219                Ok(Self(value))
220            }
221        }
222
223        impl<'s> TryFrom<std::borrow::Cow<'s, str>> for $owned_name {
224            type Error = crate::Error;
225
226            fn try_from(value: std::borrow::Cow<'s, str>) -> crate::Result<Self> {
227                Ok(Self::from(<$name<'s>>::try_from(value)?))
228            }
229        }
230
231        impl<'s> TryFrom<zvariant::Str<'s>> for $name<'s> {
232            type Error = crate::Error;
233
234            fn try_from(value: zvariant::Str<'s>) -> crate::Result<Self> {
235                $validate_fn(value.as_str())?;
236                Ok(Self(value))
237            }
238        }
239
240        impl<'s> TryFrom<zvariant::Str<'s>> for $owned_name {
241            type Error = crate::Error;
242
243            fn try_from(value: zvariant::Str<'s>) -> crate::Result<Self> {
244                Ok(Self::from(<$name<'s>>::try_from(value)?))
245            }
246        }
247
248        // === Owned type impls ===
249
250        // impl_str_basic for owned type
251        impl zvariant::Basic for $owned_name {
252            const SIGNATURE_CHAR: char = <zvariant::Str<'_>>::SIGNATURE_CHAR;
253            const SIGNATURE_STR: &'static str = <zvariant::Str<'_>>::SIGNATURE_STR;
254        }
255
256        impl $owned_name {
257            /// Convert to the inner type, consuming `self`.
258            pub fn into_inner(self) -> $name<'static> {
259                self.0
260            }
261
262            /// Get a reference to the inner type.
263            pub fn inner(&self) -> &$name<'static> {
264                &self.0
265            }
266
267            /// This is faster than `Clone::clone` when `self` contains owned data.
268            pub fn as_ref(&self) -> $name<'_> {
269                self.0.as_ref()
270            }
271        }
272
273        impl std::ops::Deref for $owned_name {
274            type Target = $name<'static>;
275
276            fn deref(&self) -> &Self::Target {
277                &self.0
278            }
279        }
280
281        impl<'a> std::borrow::Borrow<$name<'a>> for $owned_name {
282            fn borrow(&self) -> &$name<'a> {
283                &self.0
284            }
285        }
286
287        impl std::borrow::Borrow<str> for $owned_name {
288            fn borrow(&self) -> &str {
289                self.0.as_str()
290            }
291        }
292
293        impl AsRef<str> for $owned_name {
294            fn as_ref(&self) -> &str {
295                self.0.as_str()
296            }
297        }
298
299        impl std::fmt::Debug for $owned_name {
300            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
301                f.debug_tuple(stringify!($owned_name))
302                    .field(&self.as_str())
303                    .finish()
304            }
305        }
306
307        impl std::fmt::Display for $owned_name {
308            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
309                std::fmt::Display::fmt(&$name::from(self), f)
310            }
311        }
312
313        impl From<$owned_name> for $name<'_> {
314            fn from(name: $owned_name) -> Self {
315                name.into_inner()
316            }
317        }
318
319        impl<'unowned, 'owned: 'unowned> From<&'owned $owned_name> for $name<'unowned> {
320            fn from(name: &'owned $owned_name) -> Self {
321                $name::from_str_unchecked(name.as_str())
322            }
323        }
324
325        impl From<$name<'_>> for $owned_name {
326            fn from(name: $name<'_>) -> Self {
327                $owned_name(name.into_owned())
328            }
329        }
330
331        impl From<$owned_name> for zvariant::Str<'_> {
332            fn from(value: $owned_name) -> Self {
333                value.into_inner().0
334            }
335        }
336
337        impl<'de> serde::Deserialize<'de> for $owned_name {
338            fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
339            where
340                D: serde::de::Deserializer<'de>,
341            {
342                String::deserialize(deserializer)
343                    .and_then(|n| {
344                        $name::try_from(n).map_err(|e| serde::de::Error::custom(e.to_string()))
345                    })
346                    .map(Self)
347            }
348        }
349
350        impl PartialEq<&str> for $owned_name {
351            fn eq(&self, other: &&str) -> bool {
352                self.as_str() == *other
353            }
354        }
355
356        impl PartialEq<$name<'_>> for $owned_name {
357            fn eq(&self, other: &$name<'_>) -> bool {
358                self.0 == *other
359            }
360        }
361
362        impl zvariant::NoneValue for $owned_name {
363            type NoneType = <$name<'static> as zvariant::NoneValue>::NoneType;
364
365            fn null_value() -> Self::NoneType {
366                $name::null_value()
367            }
368        }
369    };
370}
371
372pub(crate) use define_name_type_impls;
373pub(crate) use impl_str_basic;