tokio_dbus/object_path/object_path_buf.rs
1use core::borrow::Borrow;
2use core::fmt;
3use core::hash;
4use core::ops::Deref;
5use core::str::FromStr;
6
7use alloc::borrow::ToOwned;
8use alloc::string::String;
9use alloc::vec::Vec;
10
11use super::{ObjectPath, ObjectPathError, validate};
12
13/// A validated owned object path.
14///
15/// The following rules define a [valid object path]. Implementations must not
16/// send or accept messages with invalid object paths.
17///
18/// [valid object path]: https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-marshaling-object-path
19///
20/// * The path may be of any length.
21/// * The path must begin with an ASCII '/' (integer 47) character, and must
22/// consist of elements separated by slash characters.
23/// * Each element must only contain the ASCII characters `[A-Z][a-z][0-9]_`
24/// * No element may be the empty string.
25/// * Multiple '/' characters cannot occur in sequence.
26/// * A trailing '/' character is not allowed unless the path is the root path
27/// (a single '/' character).
28#[derive(Clone, PartialEq, Eq)]
29#[repr(transparent)]
30pub struct ObjectPathBuf(Vec<u8>);
31
32impl ObjectPathBuf {
33 /// Construct an owned object path from its raw underlying vector.
34 ///
35 /// # Safety
36 ///
37 /// The caller must ensure that the vector contains a valid object path.
38 #[inline]
39 pub(super) unsafe fn from_raw_vec(data: Vec<u8>) -> Self {
40 Self(data)
41 }
42
43 #[inline]
44 fn to_object_path(&self) -> &ObjectPath {
45 // SAFETY: This type ensures during construction that the object path it
46 // contains is valid.
47 unsafe { ObjectPath::new_unchecked(&self.0) }
48 }
49}
50
51/// Construct an owned object path from a vector, taking ownership of its
52/// allocation.
53///
54/// # Examples
55///
56/// ```
57/// use tokio_dbus::{ObjectPath, ObjectPathBuf};
58///
59/// let path = ObjectPathBuf::try_from(b"/org/freedesktop/DBus".to_vec())?;
60/// assert_eq!(&*path, ObjectPath::new("/org/freedesktop/DBus")?);
61///
62/// assert!(ObjectPathBuf::try_from(b"org/freedesktop/DBus".to_vec()).is_err());
63/// # Ok::<_, tokio_dbus::ObjectPathError>(())
64/// ```
65impl TryFrom<Vec<u8>> for ObjectPathBuf {
66 type Error = ObjectPathError;
67
68 #[inline]
69 fn try_from(path: Vec<u8>) -> Result<Self, Self::Error> {
70 if !validate(&path) {
71 return Err(ObjectPathError);
72 }
73
74 Ok(Self(path))
75 }
76}
77
78/// Construct an owned object path from a string, taking ownership of its
79/// allocation.
80///
81/// # Examples
82///
83/// ```
84/// use tokio_dbus::{ObjectPath, ObjectPathBuf};
85///
86/// let path = ObjectPathBuf::try_from(String::from("/org/freedesktop/DBus"))?;
87/// assert_eq!(&*path, ObjectPath::new("/org/freedesktop/DBus")?);
88/// # Ok::<_, tokio_dbus::ObjectPathError>(())
89/// ```
90impl TryFrom<String> for ObjectPathBuf {
91 type Error = ObjectPathError;
92
93 #[inline]
94 fn try_from(path: String) -> Result<Self, Self::Error> {
95 Self::try_from(path.into_bytes())
96 }
97}
98
99/// Construct an owned object path by copying a string.
100///
101/// # Examples
102///
103/// ```
104/// use tokio_dbus::{ObjectPath, ObjectPathBuf};
105///
106/// let path: ObjectPathBuf = "/org/freedesktop/DBus".parse()?;
107/// assert_eq!(&*path, ObjectPath::new("/org/freedesktop/DBus")?);
108/// # Ok::<_, tokio_dbus::ObjectPathError>(())
109/// ```
110impl FromStr for ObjectPathBuf {
111 type Err = ObjectPathError;
112
113 #[inline]
114 fn from_str(path: &str) -> Result<Self, Self::Err> {
115 Ok(ObjectPath::new(path)?.to_owned())
116 }
117}
118
119impl hash::Hash for ObjectPathBuf {
120 #[inline]
121 fn hash<H>(&self, state: &mut H)
122 where
123 H: hash::Hasher,
124 {
125 hash::Hash::hash(&**self, state);
126 }
127}
128
129impl fmt::Display for ObjectPathBuf {
130 #[inline]
131 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
132 fmt::Display::fmt(&**self, f)
133 }
134}
135
136impl fmt::Debug for ObjectPathBuf {
137 #[inline]
138 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139 fmt::Debug::fmt(&**self, f)
140 }
141}
142
143impl Deref for ObjectPathBuf {
144 type Target = ObjectPath;
145
146 #[inline]
147 fn deref(&self) -> &Self::Target {
148 self.to_object_path()
149 }
150}
151
152impl Borrow<ObjectPath> for ObjectPathBuf {
153 #[inline]
154 fn borrow(&self) -> &ObjectPath {
155 self
156 }
157}
158
159impl AsRef<ObjectPath> for ObjectPathBuf {
160 #[inline]
161 fn as_ref(&self) -> &ObjectPath {
162 self
163 }
164}