zbus_names/
member_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(
40 Clone, Debug, Hash, PartialEq, Eq, Serialize, Type, Value, PartialOrd, Ord, OwnedValue,
41)]
42pub struct MemberName<'name>(Str<'name>);
43
44assert_impl_all!(MemberName<'_>: Send, Sync, Unpin);
45
46impl_str_basic!(MemberName<'_>);
47
48impl<'name> MemberName<'name> {
49 pub fn as_ref(&self) -> MemberName<'_> {
51 MemberName(self.0.as_ref())
52 }
53
54 pub fn as_str(&self) -> &str {
56 self.0.as_str()
57 }
58
59 pub fn from_str_unchecked(name: &'name str) -> Self {
64 Self(Str::from(name))
65 }
66
67 pub fn from_static_str(name: &'static str) -> Result<Self> {
69 ensure_correct_member_name(name)?;
70 Ok(Self(Str::from_static(name)))
71 }
72
73 pub const fn from_static_str_unchecked(name: &'static str) -> Self {
75 Self(Str::from_static(name))
76 }
77
78 pub fn from_string_unchecked(name: String) -> Self {
83 Self(Str::from(name))
84 }
85
86 pub fn to_owned(&self) -> MemberName<'static> {
88 MemberName(self.0.to_owned())
89 }
90
91 pub fn into_owned(self) -> MemberName<'static> {
93 MemberName(self.0.into_owned())
94 }
95}
96
97impl Deref for MemberName<'_> {
98 type Target = str;
99
100 fn deref(&self) -> &Self::Target {
101 self.as_str()
102 }
103}
104
105impl Borrow<str> for MemberName<'_> {
106 fn borrow(&self) -> &str {
107 self.as_str()
108 }
109}
110
111impl Display for MemberName<'_> {
112 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
113 Display::fmt(&self.as_str(), f)
114 }
115}
116
117impl PartialEq<str> for MemberName<'_> {
118 fn eq(&self, other: &str) -> bool {
119 self.as_str() == other
120 }
121}
122
123impl PartialEq<&str> for MemberName<'_> {
124 fn eq(&self, other: &&str) -> bool {
125 self.as_str() == *other
126 }
127}
128
129impl PartialEq<OwnedMemberName> for MemberName<'_> {
130 fn eq(&self, other: &OwnedMemberName) -> bool {
131 *self == other.0
132 }
133}
134
135impl<'de: 'name, 'name> Deserialize<'de> for MemberName<'name> {
136 fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
137 where
138 D: serde::Deserializer<'de>,
139 {
140 let name = <Cow<'name, str>>::deserialize(deserializer)?;
141
142 Self::try_from(name).map_err(|e| de::Error::custom(e.to_string()))
143 }
144}
145
146impl<'name> From<MemberName<'name>> for Str<'name> {
147 fn from(value: MemberName<'name>) -> Self {
148 value.0
149 }
150}
151
152impl_try_from! {
153 ty: MemberName<'s>,
154 owned_ty: OwnedMemberName,
155 validate_fn: ensure_correct_member_name,
156 try_from: [&'s str, String, Arc<str>, Cow<'s, str>, Str<'s>],
157}
158
159fn ensure_correct_member_name(name: &str) -> Result<()> {
160 if name.is_empty() {
167 return Err(Error::InvalidMemberName(format!(
168 "`{}` is {} characters long, which is smaller than minimum allowed (1)",
169 name,
170 name.len(),
171 )));
172 } else if name.len() > 255 {
173 return Err(Error::InvalidMemberName(format!(
174 "`{}` is {} characters long, which is longer than maximum allowed (255)",
175 name,
176 name.len(),
177 )));
178 }
179
180 if name.chars().next().unwrap().is_ascii_digit() {
182 return Err(Error::InvalidMemberName(String::from(
183 "must not start with a digit",
184 )));
185 }
186
187 for c in name.chars() {
188 if !c.is_ascii_alphanumeric() && c != '_' {
189 return Err(Error::InvalidMemberName(format!(
190 "`{c}` character not allowed"
191 )));
192 }
193 }
194
195 Ok(())
196}
197
198impl TryFrom<()> for MemberName<'_> {
201 type Error = Error;
202
203 fn try_from(_value: ()) -> Result<Self> {
204 unreachable!("Conversion from `()` is not meant to actually work");
205 }
206}
207
208impl<'name> From<&MemberName<'name>> for MemberName<'name> {
209 fn from(name: &MemberName<'name>) -> Self {
210 name.clone()
211 }
212}
213
214impl<'name> NoneValue for MemberName<'name> {
215 type NoneType = &'name str;
216
217 fn null_value() -> Self::NoneType {
218 <&str>::default()
219 }
220}
221
222#[derive(Clone, Hash, PartialEq, Eq, Serialize, Type, Value, PartialOrd, Ord, OwnedValue)]
224pub struct OwnedMemberName(#[serde(borrow)] MemberName<'static>);
225
226assert_impl_all!(OwnedMemberName: Send, Sync, Unpin);
227
228impl_str_basic!(OwnedMemberName);
229
230impl OwnedMemberName {
231 pub fn into_inner(self) -> MemberName<'static> {
233 self.0
234 }
235
236 pub fn inner(&self) -> &MemberName<'static> {
238 &self.0
239 }
240}
241
242impl Deref for OwnedMemberName {
243 type Target = MemberName<'static>;
244
245 fn deref(&self) -> &Self::Target {
246 &self.0
247 }
248}
249
250impl Borrow<str> for OwnedMemberName {
251 fn borrow(&self) -> &str {
252 self.0.as_str()
253 }
254}
255
256impl From<OwnedMemberName> for MemberName<'_> {
257 fn from(o: OwnedMemberName) -> Self {
258 o.into_inner()
259 }
260}
261
262impl<'unowned, 'owned: 'unowned> From<&'owned OwnedMemberName> for MemberName<'unowned> {
263 fn from(name: &'owned OwnedMemberName) -> Self {
264 MemberName::from_str_unchecked(name.as_str())
265 }
266}
267
268impl From<MemberName<'_>> for OwnedMemberName {
269 fn from(name: MemberName<'_>) -> Self {
270 OwnedMemberName(name.into_owned())
271 }
272}
273
274impl From<OwnedMemberName> for Str<'_> {
275 fn from(value: OwnedMemberName) -> Self {
276 value.into_inner().0
277 }
278}
279
280impl<'de> Deserialize<'de> for OwnedMemberName {
281 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
282 where
283 D: de::Deserializer<'de>,
284 {
285 String::deserialize(deserializer)
286 .and_then(|n| MemberName::try_from(n).map_err(|e| de::Error::custom(e.to_string())))
287 .map(Self)
288 }
289}
290
291impl PartialEq<&str> for OwnedMemberName {
292 fn eq(&self, other: &&str) -> bool {
293 self.as_str() == *other
294 }
295}
296
297impl PartialEq<MemberName<'_>> for OwnedMemberName {
298 fn eq(&self, other: &MemberName<'_>) -> bool {
299 self.0 == *other
300 }
301}
302
303impl Debug for OwnedMemberName {
304 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
305 f.debug_tuple("OwnedMemberName")
306 .field(&self.as_str())
307 .finish()
308 }
309}
310
311impl Display for OwnedMemberName {
312 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
313 Display::fmt(&MemberName::from(self), f)
314 }
315}
316
317impl NoneValue for OwnedMemberName {
318 type NoneType = <MemberName<'static> as NoneValue>::NoneType;
319
320 fn null_value() -> Self::NoneType {
321 MemberName::null_value()
322 }
323}