/rust/registry/src/index.crates.io-6f17d22bba15001f/dbus-0.9.7/src/strings.rs
Line | Count | Source (jump to first uncovered line) |
1 | | //! This module contains strings with a specific format, such as a valid |
2 | | //! Interface name, a valid Error name, etc. |
3 | | //! |
4 | | //! (The internal representation of these strings are `Cow<str>`, but with a \0 byte |
5 | | //! at the end to use it libdbus calls without extra allocations. This is usually nothing |
6 | | //! you have to worry about.) |
7 | | |
8 | | use std::{str, fmt, ops, default, hash}; |
9 | | use std::ffi::{CStr, CString}; |
10 | | use std::borrow::{Borrow, Cow}; |
11 | | use std::os::raw::c_char; |
12 | | |
13 | | #[cfg(not(feature = "no-string-validation"))] |
14 | | use crate::Error; |
15 | | #[cfg(not(feature = "no-string-validation"))] |
16 | | use crate::ffi; |
17 | | |
18 | | macro_rules! cstring_wrapper { |
19 | | ($t: ident, $s: ident) => { |
20 | | |
21 | | impl<'m> $t<'m> { |
22 | | #[cfg(feature = "no-string-validation")] |
23 | | fn check_valid(_: *const c_char) -> Result<(), String> { Ok(()) } |
24 | | |
25 | | #[cfg(not(feature = "no-string-validation"))] |
26 | 0 | fn check_valid(c: *const c_char) -> Result<(), String> { |
27 | 0 | let mut e = Error::empty(); |
28 | 0 | let b = unsafe { ffi::$s(c, e.get_mut()) }; |
29 | 0 | if b != 0 { Ok(()) } else { Err(e.message().unwrap().into()) } |
30 | 0 | } Unexecuted instantiation: <dbus::strings::Signature>::check_valid Unexecuted instantiation: <dbus::strings::Path>::check_valid Unexecuted instantiation: <dbus::strings::Member>::check_valid Unexecuted instantiation: <dbus::strings::Interface>::check_valid Unexecuted instantiation: <dbus::strings::BusName>::check_valid Unexecuted instantiation: <dbus::strings::ErrorName>::check_valid |
31 | | |
32 | | /// Creates a new instance of this struct. |
33 | | /// |
34 | | /// Note: If the no-string-validation feature is activated, this string |
35 | | /// will not be checked for conformance with the D-Bus specification. |
36 | 0 | pub fn new<S: Into<String>>(s: S) -> Result<$t<'m>, String> { |
37 | 0 | let mut s = s.into(); |
38 | 0 | s.push_str("\0"); |
39 | 0 | unsafe { $t::check_valid(CStr::from_bytes_with_nul_unchecked(s.as_bytes()).as_ptr() as *const c_char)?; } |
40 | 0 | Ok(Self(Cow::Owned(s))) |
41 | 0 | } Unexecuted instantiation: <dbus::strings::Signature>::new::<alloc::string::String> Unexecuted instantiation: <dbus::strings::Signature>::new::<&str> Unexecuted instantiation: <dbus::strings::Path>::new::<alloc::string::String> Unexecuted instantiation: <dbus::strings::Path>::new::<&str> Unexecuted instantiation: <dbus::strings::Member>::new::<alloc::string::String> Unexecuted instantiation: <dbus::strings::Member>::new::<&str> Unexecuted instantiation: <dbus::strings::Interface>::new::<alloc::string::String> Unexecuted instantiation: <dbus::strings::Interface>::new::<&str> Unexecuted instantiation: <dbus::strings::BusName>::new::<alloc::string::String> Unexecuted instantiation: <dbus::strings::BusName>::new::<&str> Unexecuted instantiation: <dbus::strings::ErrorName>::new::<alloc::string::String> Unexecuted instantiation: <dbus::strings::ErrorName>::new::<&str> |
42 | | |
43 | | /// Creates a new instance of this struct. If you end it with \0, |
44 | | /// it can borrow the slice without extra allocation. |
45 | | /// |
46 | | /// Note: If the no-string-validation feature is activated, this string |
47 | | /// will not be checked for conformance with the D-Bus specification. |
48 | 0 | pub fn from_slice(s: &'m str) -> Result<$t<'m>, String> { |
49 | 0 | let ss = s.as_bytes(); |
50 | 0 | if ss.len() == 0 || ss[ss.len()-1] != 0 { return $t::new(s) }; |
51 | 0 | $t::check_valid(s.as_ptr() as *const c_char).map(|_| { |
52 | 0 | unsafe { Self::from_slice_unchecked(s) } |
53 | 0 | }) Unexecuted instantiation: <dbus::strings::Signature>::from_slice::{closure#0} Unexecuted instantiation: <dbus::strings::Path>::from_slice::{closure#0} Unexecuted instantiation: <dbus::strings::Member>::from_slice::{closure#0} Unexecuted instantiation: <dbus::strings::Interface>::from_slice::{closure#0} Unexecuted instantiation: <dbus::strings::BusName>::from_slice::{closure#0} Unexecuted instantiation: <dbus::strings::ErrorName>::from_slice::{closure#0} |
54 | 0 | } Unexecuted instantiation: <dbus::strings::Signature>::from_slice Unexecuted instantiation: <dbus::strings::Path>::from_slice Unexecuted instantiation: <dbus::strings::Member>::from_slice Unexecuted instantiation: <dbus::strings::Interface>::from_slice Unexecuted instantiation: <dbus::strings::BusName>::from_slice Unexecuted instantiation: <dbus::strings::ErrorName>::from_slice |
55 | | |
56 | | /// This function creates a new instance of this struct, without checking. |
57 | | /// It's up to you to guarantee that s ends with a \0 and is valid. |
58 | 0 | pub unsafe fn from_slice_unchecked(s: &'m str) -> $t<'m> { |
59 | 0 | let ss = s.as_bytes(); |
60 | 0 | debug_assert!(ss[ss.len()-1] == 0); |
61 | 0 | $t(Cow::Borrowed(s)) |
62 | 0 | } Unexecuted instantiation: <dbus::strings::ErrorName>::from_slice_unchecked Unexecuted instantiation: <dbus::strings::BusName>::from_slice_unchecked Unexecuted instantiation: <dbus::strings::Path>::from_slice_unchecked Unexecuted instantiation: <dbus::strings::Interface>::from_slice_unchecked Unexecuted instantiation: <dbus::strings::Member>::from_slice_unchecked Unexecuted instantiation: <dbus::strings::Signature>::from_slice_unchecked |
63 | | |
64 | | /// View this struct as a CStr. |
65 | | /// |
66 | | /// Note: As of dbus 0.9, this is made private to be able to make it easier for a potential |
67 | | /// native implementation using "str" instead of "cstr". |
68 | 0 | pub (crate) fn as_cstr(&self) -> &CStr { |
69 | 0 | unsafe { |
70 | 0 | CStr::from_bytes_with_nul_unchecked(self.0.as_bytes()) |
71 | 0 | } |
72 | 0 | } Unexecuted instantiation: <dbus::strings::BusName>::as_cstr Unexecuted instantiation: <dbus::strings::Path>::as_cstr Unexecuted instantiation: <dbus::strings::Member>::as_cstr Unexecuted instantiation: <dbus::strings::Interface>::as_cstr Unexecuted instantiation: <dbus::strings::ErrorName>::as_cstr Unexecuted instantiation: <dbus::strings::Signature>::as_cstr |
73 | | |
74 | | #[allow(dead_code)] |
75 | 0 | pub (crate) fn as_ptr(&self) -> *const c_char { self.as_cstr().as_ptr() } Unexecuted instantiation: <dbus::strings::Path>::as_ptr Unexecuted instantiation: <dbus::strings::Member>::as_ptr Unexecuted instantiation: <dbus::strings::Interface>::as_ptr Unexecuted instantiation: <dbus::strings::BusName>::as_ptr Unexecuted instantiation: <dbus::strings::ErrorName>::as_ptr Unexecuted instantiation: <dbus::strings::Signature>::as_ptr |
76 | | |
77 | | /// Makes sure this string does not contain borrows. |
78 | 0 | pub fn into_static(self) -> $t<'static> { |
79 | 0 | $t(Cow::Owned(self.0.into_owned())) |
80 | 0 | } Unexecuted instantiation: <dbus::strings::Signature>::into_static Unexecuted instantiation: <dbus::strings::Path>::into_static Unexecuted instantiation: <dbus::strings::Member>::into_static Unexecuted instantiation: <dbus::strings::Interface>::into_static Unexecuted instantiation: <dbus::strings::BusName>::into_static Unexecuted instantiation: <dbus::strings::ErrorName>::into_static |
81 | | |
82 | | /// Converts this struct to a CString. |
83 | 0 | pub fn into_cstring(self) -> CString { |
84 | 0 | // Change this when https://github.com/rust-lang/rust/issues/73179 is on stable. |
85 | 0 | let mut x: Vec<u8> = self.0.into_owned().into(); |
86 | 0 | x.pop(); |
87 | 0 | CString::new(x).unwrap() |
88 | 0 | } Unexecuted instantiation: <dbus::strings::Signature>::into_cstring Unexecuted instantiation: <dbus::strings::Path>::into_cstring Unexecuted instantiation: <dbus::strings::Member>::into_cstring Unexecuted instantiation: <dbus::strings::Interface>::into_cstring Unexecuted instantiation: <dbus::strings::BusName>::into_cstring Unexecuted instantiation: <dbus::strings::ErrorName>::into_cstring |
89 | | } |
90 | | |
91 | | /* |
92 | | /// #Panics |
93 | | /// |
94 | | /// If given string is not valid. |
95 | | /// impl<S: Into<Vec<u8>>> From<S> for $t { fn from(s: S) -> $t { $t::new(s).unwrap() } } |
96 | | */ |
97 | | |
98 | | /// #Panics |
99 | | /// |
100 | | /// If given string is not valid. |
101 | 0 | impl<'m> From<String> for $t<'m> { fn from(s: String) -> $t<'m> { $t::new(s).unwrap() } } Unexecuted instantiation: <dbus::strings::Signature as core::convert::From<alloc::string::String>>::from Unexecuted instantiation: <dbus::strings::Path as core::convert::From<alloc::string::String>>::from Unexecuted instantiation: <dbus::strings::Member as core::convert::From<alloc::string::String>>::from Unexecuted instantiation: <dbus::strings::Interface as core::convert::From<alloc::string::String>>::from Unexecuted instantiation: <dbus::strings::BusName as core::convert::From<alloc::string::String>>::from Unexecuted instantiation: <dbus::strings::ErrorName as core::convert::From<alloc::string::String>>::from |
102 | | |
103 | | /// #Panics |
104 | | /// |
105 | | /// If given string is not valid. |
106 | 0 | impl<'m> From<&'m String> for $t<'m> { fn from(s: &'m String) -> $t<'m> { $t::from_slice(s).unwrap() } } Unexecuted instantiation: <dbus::strings::Signature as core::convert::From<&alloc::string::String>>::from Unexecuted instantiation: <dbus::strings::Path as core::convert::From<&alloc::string::String>>::from Unexecuted instantiation: <dbus::strings::Member as core::convert::From<&alloc::string::String>>::from Unexecuted instantiation: <dbus::strings::Interface as core::convert::From<&alloc::string::String>>::from Unexecuted instantiation: <dbus::strings::BusName as core::convert::From<&alloc::string::String>>::from Unexecuted instantiation: <dbus::strings::ErrorName as core::convert::From<&alloc::string::String>>::from |
107 | | |
108 | | /// #Panics |
109 | | /// |
110 | | /// If given string is not valid. |
111 | 0 | impl<'m> From<&'m str> for $t<'m> { fn from(s: &'m str) -> $t<'m> { $t::from_slice(s).unwrap() } } Unexecuted instantiation: <dbus::strings::Signature as core::convert::From<&str>>::from Unexecuted instantiation: <dbus::strings::Path as core::convert::From<&str>>::from Unexecuted instantiation: <dbus::strings::Member as core::convert::From<&str>>::from Unexecuted instantiation: <dbus::strings::Interface as core::convert::From<&str>>::from Unexecuted instantiation: <dbus::strings::BusName as core::convert::From<&str>>::from Unexecuted instantiation: <dbus::strings::ErrorName as core::convert::From<&str>>::from |
112 | | |
113 | | /// #Panics |
114 | | /// |
115 | | /// If given string is not valid. |
116 | | impl<'m> From<&'m CStr> for $t<'m> { |
117 | 0 | fn from(s: &'m CStr) -> $t<'m> { |
118 | 0 | let x = str::from_utf8(s.to_bytes_with_nul()).unwrap(); |
119 | 0 | $t::from_slice(x).unwrap() |
120 | 0 | } Unexecuted instantiation: <dbus::strings::Signature as core::convert::From<&core::ffi::c_str::CStr>>::from Unexecuted instantiation: <dbus::strings::Path as core::convert::From<&core::ffi::c_str::CStr>>::from Unexecuted instantiation: <dbus::strings::Member as core::convert::From<&core::ffi::c_str::CStr>>::from Unexecuted instantiation: <dbus::strings::Interface as core::convert::From<&core::ffi::c_str::CStr>>::from Unexecuted instantiation: <dbus::strings::BusName as core::convert::From<&core::ffi::c_str::CStr>>::from Unexecuted instantiation: <dbus::strings::ErrorName as core::convert::From<&core::ffi::c_str::CStr>>::from |
121 | | } |
122 | | |
123 | 0 | impl<'m> From<$t<'m>> for CString { fn from(s: $t<'m>) -> CString { s.into_cstring() } } Unexecuted instantiation: <alloc::ffi::c_str::CString as core::convert::From<dbus::strings::Signature>>::from Unexecuted instantiation: <alloc::ffi::c_str::CString as core::convert::From<dbus::strings::Path>>::from Unexecuted instantiation: <alloc::ffi::c_str::CString as core::convert::From<dbus::strings::Member>>::from Unexecuted instantiation: <alloc::ffi::c_str::CString as core::convert::From<dbus::strings::Interface>>::from Unexecuted instantiation: <alloc::ffi::c_str::CString as core::convert::From<dbus::strings::BusName>>::from Unexecuted instantiation: <alloc::ffi::c_str::CString as core::convert::From<dbus::strings::ErrorName>>::from |
124 | | |
125 | | |
126 | | /// #Panics |
127 | | /// |
128 | | /// If given string is not valid. |
129 | | impl<'m> From<Cow<'m, str>> for $t<'m> { |
130 | 0 | fn from(s: Cow<'m, str>) -> $t<'m> { |
131 | 0 | match s { |
132 | 0 | Cow::Borrowed(z) => z.into(), |
133 | 0 | Cow::Owned(z) => z.into(), |
134 | | } |
135 | 0 | } Unexecuted instantiation: <dbus::strings::Signature as core::convert::From<alloc::borrow::Cow<str>>>::from Unexecuted instantiation: <dbus::strings::Path as core::convert::From<alloc::borrow::Cow<str>>>::from Unexecuted instantiation: <dbus::strings::Member as core::convert::From<alloc::borrow::Cow<str>>>::from Unexecuted instantiation: <dbus::strings::Interface as core::convert::From<alloc::borrow::Cow<str>>>::from Unexecuted instantiation: <dbus::strings::BusName as core::convert::From<alloc::borrow::Cow<str>>>::from Unexecuted instantiation: <dbus::strings::ErrorName as core::convert::From<alloc::borrow::Cow<str>>>::from |
136 | | } |
137 | | |
138 | | impl<'inner, 'm: 'inner> From<&'m $t<'inner>> for $t<'m> { |
139 | 0 | fn from(borrow: &'m $t<'inner>) -> $t<'m> { |
140 | 0 | $t(Cow::Borrowed(borrow.0.borrow())) |
141 | 0 | } Unexecuted instantiation: <dbus::strings::ErrorName as core::convert::From<&dbus::strings::ErrorName>>::from Unexecuted instantiation: <dbus::strings::Signature as core::convert::From<&dbus::strings::Signature>>::from Unexecuted instantiation: <dbus::strings::Path as core::convert::From<&dbus::strings::Path>>::from Unexecuted instantiation: <dbus::strings::Member as core::convert::From<&dbus::strings::Member>>::from Unexecuted instantiation: <dbus::strings::Interface as core::convert::From<&dbus::strings::Interface>>::from Unexecuted instantiation: <dbus::strings::BusName as core::convert::From<&dbus::strings::BusName>>::from |
142 | | } |
143 | | |
144 | | impl<'m> ops::Deref for $t<'m> { |
145 | | type Target = str; |
146 | 0 | fn deref(&self) -> &str { self.0.split_at(self.0.len()-1).0 } Unexecuted instantiation: <dbus::strings::Signature as core::ops::deref::Deref>::deref Unexecuted instantiation: <dbus::strings::Path as core::ops::deref::Deref>::deref Unexecuted instantiation: <dbus::strings::Member as core::ops::deref::Deref>::deref Unexecuted instantiation: <dbus::strings::Interface as core::ops::deref::Deref>::deref Unexecuted instantiation: <dbus::strings::BusName as core::ops::deref::Deref>::deref Unexecuted instantiation: <dbus::strings::ErrorName as core::ops::deref::Deref>::deref |
147 | | } |
148 | | |
149 | | impl<'m> fmt::Display for $t<'m> { |
150 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
151 | 0 | <str as fmt::Display>::fmt(&*self, f) |
152 | 0 | } Unexecuted instantiation: <dbus::strings::Signature as core::fmt::Display>::fmt Unexecuted instantiation: <dbus::strings::Path as core::fmt::Display>::fmt Unexecuted instantiation: <dbus::strings::Member as core::fmt::Display>::fmt Unexecuted instantiation: <dbus::strings::Interface as core::fmt::Display>::fmt Unexecuted instantiation: <dbus::strings::BusName as core::fmt::Display>::fmt Unexecuted instantiation: <dbus::strings::ErrorName as core::fmt::Display>::fmt |
153 | | } |
154 | | |
155 | | /* |
156 | | As of dbus 0.9, this has been removed to prepare for a potential native implementation. |
157 | | impl<'m> AsRef<CStr> for $t<'m> { |
158 | | fn as_ref(&self) -> &CStr { &self.0 } |
159 | | } |
160 | | */ |
161 | | |
162 | | impl<'m> hash::Hash for $t<'m> { |
163 | 0 | fn hash<H: hash::Hasher>(&self, state: &mut H) { |
164 | 0 | self.0.hash(state); |
165 | 0 | } Unexecuted instantiation: <dbus::strings::Signature as core::hash::Hash>::hash::<std::hash::random::DefaultHasher> Unexecuted instantiation: <dbus::strings::Path as core::hash::Hash>::hash::<std::hash::random::DefaultHasher> Unexecuted instantiation: <dbus::strings::Member as core::hash::Hash>::hash::<_> Unexecuted instantiation: <dbus::strings::Interface as core::hash::Hash>::hash::<_> Unexecuted instantiation: <dbus::strings::BusName as core::hash::Hash>::hash::<_> Unexecuted instantiation: <dbus::strings::ErrorName as core::hash::Hash>::hash::<_> |
166 | | } |
167 | | |
168 | | }} |
169 | | |
170 | | /// A wrapper around a string that is guaranteed to be |
171 | | /// a valid (single) D-Bus type signature. |
172 | | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] |
173 | | pub struct Signature<'a>(Cow<'a, str>); |
174 | | |
175 | | cstring_wrapper!(Signature, dbus_signature_validate_single); |
176 | | |
177 | | impl Signature<'static> { |
178 | | /// Makes a D-Bus signature that corresponds to A. |
179 | 0 | pub fn make<A: super::arg::Arg>() -> Signature<'static> { A::signature() } |
180 | | } |
181 | | |
182 | | /// A wrapper around a string that is guaranteed to be |
183 | | /// a valid D-Bus object path. |
184 | | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] |
185 | | pub struct Path<'a>(Cow<'a, str>); |
186 | | |
187 | | cstring_wrapper!(Path, dbus_validate_path); |
188 | | |
189 | | // This is needed so one can make arrays of paths easily |
190 | | impl<'a> default::Default for Path<'a> { |
191 | 0 | fn default() -> Path<'a> { Path(Cow::Borrowed("/\0")) } |
192 | | } |
193 | | |
194 | | /// A wrapper around a string that is guaranteed to be |
195 | | /// a valid D-Bus member, i e, a signal or method name. |
196 | | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] |
197 | | pub struct Member<'a>(Cow<'a, str>); |
198 | | |
199 | | cstring_wrapper!(Member, dbus_validate_member); |
200 | | |
201 | | /// A wrapper around a string that is guaranteed to be |
202 | | /// a valid D-Bus interface name. |
203 | | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] |
204 | | pub struct Interface<'a>(Cow<'a, str>); |
205 | | |
206 | | cstring_wrapper!(Interface, dbus_validate_interface); |
207 | | |
208 | | /// A wrapper around a string that is guaranteed to be |
209 | | /// a valid D-Bus bus name. |
210 | | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] |
211 | | pub struct BusName<'a>(Cow<'a, str>); |
212 | | |
213 | | cstring_wrapper!(BusName, dbus_validate_bus_name); |
214 | | |
215 | | /// A wrapper around a string that is guaranteed to be |
216 | | /// a valid D-Bus error name. |
217 | | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] |
218 | | pub struct ErrorName<'a>(Cow<'a, str>); |
219 | | |
220 | | cstring_wrapper!(ErrorName, dbus_validate_error_name); |
221 | | |
222 | | #[test] |
223 | | fn some_path() { |
224 | | let p1: Path = "/valid".into(); |
225 | | let p2 = Path::new("##invalid##"); |
226 | | assert_eq!(p1, Path(Cow::Borrowed("/valid\0"))); |
227 | | #[cfg(not(feature = "no-string-validation"))] |
228 | | assert_eq!(p2, Err("Object path was not valid: '##invalid##'".into())); |
229 | | #[cfg(feature = "no-string-validation")] |
230 | | assert_eq!(p2, Ok(Path(Cow::Borrowed("##invalid##\0")))); |
231 | | } |
232 | | |
233 | | #[test] |
234 | | fn reborrow_path() { |
235 | | let p1 = Path::from("/valid"); |
236 | | let p2 = p1.clone(); |
237 | | { |
238 | | let p2_borrow: &Path = &p2; |
239 | | let p3 = Path::from(p2_borrow); |
240 | | // Check path created from borrow |
241 | | assert_eq!(p2, p3); |
242 | | } |
243 | | // Check path that was previously borrowed |
244 | | assert_eq!(p1, p2); |
245 | | } |
246 | | |
247 | | #[test] |
248 | | fn make_sig() { |
249 | | assert_eq!(&*Signature::make::<(&str, u8)>(), "(sy)"); |
250 | | } |