1 // CString wrappers.
2 
3 use ffi;
4 use std::{str, fmt, ops, default};
5 use std::ffi::{CStr, CString};
6 use Error;
7 
8 macro_rules! cstring_wrapper {
9     ($t: ident, $s: ident) => {
10 
11 
12 impl $t {
13     /// Creates a new instance of this struct.
14     pub fn new<S: Into<Vec<u8>>>(s: S) -> Result<$t, String> {
15         let c = try!(CString::new(s).map_err(|e| e.to_string()));
16         let mut e = Error::empty();
17         let b = unsafe { ffi::$s(c.as_ptr(), e.get_mut()) };
18         if b != 0 { Ok($t(c)) } else { Err(e.message().unwrap().into()) }
19     }
20 }
21 
22 /*
23 /// #Panics
24 ///
25 /// If given string is not valid.
26 /// impl<S: Into<Vec<u8>>> From<S> for $t { fn from(s: S) -> $t { $t::new(s).unwrap() } }
27 */
28 
29 /// #Panics
30 ///
31 /// If given string is not valid.
32 impl<'a> From<String> for $t { fn from(s: String) -> $t { $t::new(s).unwrap() } }
33 
34 /// #Panics
35 ///
36 /// If given string is not valid.
37 impl<'a> From<&'a String> for $t { fn from(s: &'a String) -> $t { $t::new(s.clone()).unwrap() } }
38 
39 /// #Panics
40 ///
41 /// If given string is not valid.
42 impl<'a> From<&'a str> for $t { fn from(s: &'a str) -> $t { $t::new(s).unwrap() } }
43 
44 
45 impl ops::Deref for $t {
46     type Target = str;
47     fn deref(&self) -> &str { str::from_utf8(self.0.to_bytes()).unwrap() }
48 }
49 
50 impl fmt::Display for $t {
51     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
52         let s: &str = &self;
53         (&s as &fmt::Display).fmt(f)
54     }
55 }
56 
57 impl AsRef<CStr> for $t {
58     fn as_ref(&self) -> &CStr { &self.0 }
59 }
60 
61 }}
62 
63 /// A wrapper around a string that is guaranteed to be
64 /// a valid (single) D-Bus type signature. Supersedes TypeSig.
65 #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
66 pub struct Signature(CString);
67 
68 cstring_wrapper!(Signature, dbus_signature_validate_single);
69 
70 /// A wrapper around a string that is guaranteed to be
71 /// a valid D-Bus object path.
72 #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
73 pub struct Path(CString);
74 
75 cstring_wrapper!(Path, dbus_validate_path);
76 
77 // This is needed so one can make arrays of paths easily
78 impl default::Default for Path {
default() -> Path79     fn default() -> Path { Path(CString::new("/").unwrap()) }
80 }
81 
82 /// A wrapper around a string that is guaranteed to be
83 /// a valid D-Bus member, i e, a signal or method name.
84 #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
85 pub struct Member(CString);
86 
87 cstring_wrapper!(Member, dbus_validate_member);
88 
89 /// A wrapper around a string that is guaranteed to be
90 /// a valid D-Bus interface name.
91 #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
92 pub struct Interface(CString);
93 
94 cstring_wrapper!(Interface, dbus_validate_interface);
95 
96 /// A wrapper around a string that is guaranteed to be
97 /// a valid D-Bus bus name.
98 #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
99 pub struct BusName(CString);
100 
101 cstring_wrapper!(BusName, dbus_validate_bus_name);
102 
103 /// A wrapper around a string that is guaranteed to be
104 /// a valid D-Bus bus name.
105 #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
106 pub struct ErrorName(CString);
107 
108 cstring_wrapper!(ErrorName, dbus_validate_error_name);
109 
110 #[test]
some_path()111 fn some_path() {
112     let p1: Path = "/valid".into();
113     let p2 = Path::new("##invalid##");
114     assert_eq!(p1, Path(CString::new("/valid").unwrap()));
115     assert_eq!(p2, Err("Object path was not valid: '##invalid##'".into()));
116 }
117