1 use ffi;
2 use super::*;
3 use super::check;
4 use {Signature, Path, OwnedFd};
5 use std::{ptr, any, mem};
6 use std::ffi::CStr;
7 use std::os::raw::{c_void, c_char, c_int};
8 
9 
arg_append_basic<T>(i: *mut ffi::DBusMessageIter, arg_type: ArgType, v: T)10 fn arg_append_basic<T>(i: *mut ffi::DBusMessageIter, arg_type: ArgType, v: T) {
11     let p = &v as *const _ as *const c_void;
12     unsafe {
13         check("dbus_message_iter_append_basic", ffi::dbus_message_iter_append_basic(i, arg_type as c_int, p));
14     };
15 }
16 
arg_get_basic<T>(i: *mut ffi::DBusMessageIter, arg_type: ArgType) -> Option<T>17 fn arg_get_basic<T>(i: *mut ffi::DBusMessageIter, arg_type: ArgType) -> Option<T> {
18     unsafe {
19         let mut c: T = mem::zeroed();
20         if ffi::dbus_message_iter_get_arg_type(i) != arg_type as c_int { return None };
21         ffi::dbus_message_iter_get_basic(i, &mut c as *mut _ as *mut c_void);
22         Some(c)
23     }
24 }
25 
arg_append_f64(i: *mut ffi::DBusMessageIter, arg_type: ArgType, v: f64)26 fn arg_append_f64(i: *mut ffi::DBusMessageIter, arg_type: ArgType, v: f64) {
27     let p = &v as *const _ as *const c_void;
28     unsafe {
29         check("dbus_message_iter_append_basic", ffi::dbus_message_iter_append_basic(i, arg_type as c_int, p));
30     };
31 }
32 
arg_get_f64(i: *mut ffi::DBusMessageIter, arg_type: ArgType) -> Option<f64>33 fn arg_get_f64(i: *mut ffi::DBusMessageIter, arg_type: ArgType) -> Option<f64> {
34     let mut c = 0f64;
35     unsafe {
36         if ffi::dbus_message_iter_get_arg_type(i) != arg_type as c_int { return None };
37         ffi::dbus_message_iter_get_basic(i, &mut c as *mut _ as *mut c_void);
38     }
39     Some(c)
40 }
41 
arg_append_str(i: *mut ffi::DBusMessageIter, arg_type: ArgType, v: &CStr)42 fn arg_append_str(i: *mut ffi::DBusMessageIter, arg_type: ArgType, v: &CStr) {
43     let p = v.as_ptr();
44     let q = &p as *const _ as *const c_void;
45     unsafe {
46         check("dbus_message_iter_append_basic", ffi::dbus_message_iter_append_basic(i, arg_type as c_int, q));
47     };
48 }
49 
arg_get_str<'a>(i: *mut ffi::DBusMessageIter, arg_type: ArgType) -> Option<&'a CStr>50 unsafe fn arg_get_str<'a>(i: *mut ffi::DBusMessageIter, arg_type: ArgType) -> Option<&'a CStr> {
51     if ffi::dbus_message_iter_get_arg_type(i) != arg_type as c_int { return None };
52     let mut p = ptr::null_mut();
53     ffi::dbus_message_iter_get_basic(i, &mut p as *mut _ as *mut c_void);
54     Some(CStr::from_ptr(p as *const c_char))
55 }
56 
57 
58 
59 
60 // Implementation for basic types.
61 
62 macro_rules! integer_impl {
63     ($t: ident, $s: ident, $f: expr, $i: ident, $ii: expr, $u: ident, $uu: expr, $fff: ident, $ff: expr) => {
64 
65 impl Arg for $t {
66     const ARG_TYPE: ArgType = ArgType::$s;
67     #[inline]
68     fn signature() -> Signature<'static> { unsafe { Signature::from_slice_unchecked($f) } }
69 }
70 
71 impl Append for $t {
72     fn append(self, i: &mut IterAppend) { arg_append_basic(&mut i.0, ArgType::$s, self) }
73 }
74 
75 impl<'a> Get<'a> for $t {
76     fn get(i: &mut Iter) -> Option<Self> { arg_get_basic(&mut i.0, ArgType::$s) }
77 }
78 
79 impl RefArg for $t {
80     #[inline]
81     fn arg_type(&self) -> ArgType { ArgType::$s }
82     #[inline]
83     fn signature(&self) -> Signature<'static> { unsafe { Signature::from_slice_unchecked($f) } }
84     #[inline]
85     fn append(&self, i: &mut IterAppend) { arg_append_basic(&mut i.0, ArgType::$s, *self) }
86     #[inline]
87     fn as_any(&self) -> &any::Any { self }
88     #[inline]
89     fn as_any_mut(&mut self) -> &mut any::Any { self }
90     #[inline]
91     fn as_i64(&self) -> Option<i64> { let $i = *self; $ii }
92     #[inline]
93     fn as_u64(&self) -> Option<u64> { let $u = *self; $uu }
94     #[inline]
95     fn as_f64(&self) -> Option<f64> { let $fff = *self; $ff }
96     #[inline]
97     fn box_clone(&self) -> Box<RefArg + 'static> { Box::new(self.clone()) }
98 }
99 
100 impl DictKey for $t {}
101 unsafe impl FixedArray for $t {}
102 
103 }} // End of macro_rules
104 
105 integer_impl!(u8, Byte, b"y\0", i, Some(i as i64),    u, Some(u as u64), f, Some(f as f64));
106 integer_impl!(i16, Int16, b"n\0", i, Some(i as i64),  _u, None,          f, Some(f as f64));
107 integer_impl!(u16, UInt16, b"q\0", i, Some(i as i64), u, Some(u as u64), f, Some(f as f64));
108 integer_impl!(i32, Int32, b"i\0", i, Some(i as i64),  _u, None,          f, Some(f as f64));
109 integer_impl!(u32, UInt32, b"u\0", i, Some(i as i64), u, Some(u as u64), f, Some(f as f64));
110 integer_impl!(i64, Int64, b"x\0", i, Some(i),         _u, None,          _f, None);
111 integer_impl!(u64, UInt64, b"t\0", _i, None,          u, Some(u as u64), _f, None);
112 
113 
114 macro_rules! refarg_impl {
115     ($t: ty, $i: ident, $ii: expr, $ss: expr, $uu: expr, $ff: expr) => {
116 
117 impl RefArg for $t {
118     #[inline]
119     fn arg_type(&self) -> ArgType { <$t as Arg>::ARG_TYPE }
120     #[inline]
121     fn signature(&self) -> Signature<'static> { <$t as Arg>::signature() }
122     #[inline]
123     fn append(&self, i: &mut IterAppend) { <$t as Append>::append(self.clone(), i) }
124     #[inline]
125     fn as_any(&self) -> &any::Any { self }
126     #[inline]
127     fn as_any_mut(&mut self) -> &mut any::Any { self }
128     #[inline]
129     fn as_i64(&self) -> Option<i64> { let $i = self; $ii }
130     #[inline]
131     fn as_u64(&self) -> Option<u64> { let $i = self; $uu }
132     #[inline]
133     fn as_f64(&self) -> Option<f64> { let $i = self; $ff }
134     #[inline]
135     fn as_str(&self) -> Option<&str> { let $i = self; $ss }
136     #[inline]
137     fn box_clone(&self) -> Box<RefArg + 'static> { Box::new(self.clone()) }
138 }
139 
140     }
141 }
142 
143 
144 impl Arg for bool {
145     const ARG_TYPE: ArgType = ArgType::Boolean;
signature() -> Signature<'static>146     fn signature() -> Signature<'static> { unsafe { Signature::from_slice_unchecked(b"b\0") } }
147 }
148 impl Append for bool {
append(self, i: &mut IterAppend)149     fn append(self, i: &mut IterAppend) { arg_append_basic(&mut i.0, ArgType::Boolean, if self {1} else {0}) }
150 }
151 impl DictKey for bool {}
152 impl<'a> Get<'a> for bool {
get(i: &mut Iter) -> Option<Self>153     fn get(i: &mut Iter) -> Option<Self> { arg_get_basic::<u32>(&mut i.0, ArgType::Boolean).map(|q| q != 0) }
154 }
155 
156 refarg_impl!(bool, _i, Some(if *_i { 1 } else { 0 }), None, Some(if *_i { 1 as u64 } else { 0 as u64 }), Some(if *_i { 1 as f64 } else { 0 as f64 }));
157 
158 impl Arg for f64 {
159     const ARG_TYPE: ArgType = ArgType::Double;
signature() -> Signature<'static>160     fn signature() -> Signature<'static> { unsafe { Signature::from_slice_unchecked(b"d\0") } }
161 }
162 impl Append for f64 {
append(self, i: &mut IterAppend)163     fn append(self, i: &mut IterAppend) { arg_append_f64(&mut i.0, ArgType::Double, self) }
164 }
165 impl DictKey for f64 {}
166 impl<'a> Get<'a> for f64 {
get(i: &mut Iter) -> Option<Self>167     fn get(i: &mut Iter) -> Option<Self> { arg_get_f64(&mut i.0, ArgType::Double) }
168 }
169 unsafe impl FixedArray for f64 {}
170 
171 refarg_impl!(f64, _i, None, None, None, Some(*_i));
172 
173 /// Represents a D-Bus string.
174 impl<'a> Arg for &'a str {
175     const ARG_TYPE: ArgType = ArgType::String;
signature() -> Signature<'static>176     fn signature() -> Signature<'static> { unsafe { Signature::from_slice_unchecked(b"s\0") } }
177 }
178 
179 impl<'a> Append for &'a str {
append(self, i: &mut IterAppend)180     fn append(self, i: &mut IterAppend) {
181         use std::borrow::Cow;
182         let b: &[u8] = self.as_bytes();
183         let v: Cow<[u8]> = if b.len() > 0 && b[b.len()-1] == 0 { Cow::Borrowed(b) }
184         else {
185             let mut bb: Vec<u8> = b.into();
186             bb.push(0);
187             Cow::Owned(bb)
188         };
189         let z = unsafe { CStr::from_ptr(v.as_ptr() as *const c_char) };
190         arg_append_str(&mut i.0, ArgType::String, &z)
191     }
192 }
193 impl<'a> DictKey for &'a str {}
194 impl<'a> Get<'a> for &'a str {
get(i: &mut Iter<'a>) -> Option<&'a str>195     fn get(i: &mut Iter<'a>) -> Option<&'a str> { unsafe { arg_get_str(&mut i.0, ArgType::String) }
196         .and_then(|s| s.to_str().ok()) }
197 }
198 
199 impl<'a> Arg for String {
200     const ARG_TYPE: ArgType = ArgType::String;
signature() -> Signature<'static>201     fn signature() -> Signature<'static> { unsafe { Signature::from_slice_unchecked(b"s\0") } }
202 }
203 impl<'a> Append for String {
append(mut self, i: &mut IterAppend)204     fn append(mut self, i: &mut IterAppend) {
205         self.push_str("\0");
206         let s: &str = &self;
207         s.append(i)
208     }
209 }
210 impl<'a> DictKey for String {}
211 impl<'a> Get<'a> for String {
get(i: &mut Iter<'a>) -> Option<String>212     fn get(i: &mut Iter<'a>) -> Option<String> { <&str>::get(i).map(|s| String::from(s)) }
213 }
214 
215 refarg_impl!(String, _i, None, Some(&_i), None, None);
216 
217 /// Represents a D-Bus string.
218 impl<'a> Arg for &'a CStr {
219     const ARG_TYPE: ArgType = ArgType::String;
signature() -> Signature<'static>220     fn signature() -> Signature<'static> { unsafe { Signature::from_slice_unchecked(b"s\0") } }
221 }
222 
223 /*
224 /// Note: Will give D-Bus errors in case the CStr is not valid UTF-8.
225 impl<'a> Append for &'a CStr {
226     fn append(self, i: &mut IterAppend) {
227         arg_append_str(&mut i.0, Self::arg_type(), &self)
228     }
229 }
230 */
231 
232 impl<'a> DictKey for &'a CStr {}
233 impl<'a> Get<'a> for &'a CStr {
get(i: &mut Iter<'a>) -> Option<&'a CStr>234     fn get(i: &mut Iter<'a>) -> Option<&'a CStr> { unsafe { arg_get_str(&mut i.0, Self::ARG_TYPE) }}
235 }
236 
237 impl Arg for OwnedFd {
238     const ARG_TYPE: ArgType = ArgType::UnixFd;
signature() -> Signature<'static>239     fn signature() -> Signature<'static> { unsafe { Signature::from_slice_unchecked(b"h\0") } }
240 }
241 impl Append for OwnedFd {
append(self, i: &mut IterAppend)242     fn append(self, i: &mut IterAppend) {
243         use std::os::unix::io::AsRawFd;
244         arg_append_basic(&mut i.0, ArgType::UnixFd, self.as_raw_fd())
245     }
246 }
247 impl DictKey for OwnedFd {}
248 impl<'a> Get<'a> for OwnedFd {
get(i: &mut Iter) -> Option<Self>249     fn get(i: &mut Iter) -> Option<Self> {
250         arg_get_basic(&mut i.0, ArgType::UnixFd).map(|q| OwnedFd::new(q))
251     }
252 }
253 
254 refarg_impl!(OwnedFd, _i, { use std::os::unix::io::AsRawFd; Some(_i.as_raw_fd() as i64) }, None, None, None);
255 
256 macro_rules! string_impl {
257     ($t: ident, $s: ident, $f: expr) => {
258 
259 impl<'a> Arg for $t<'a> {
260     const ARG_TYPE: ArgType = ArgType::$s;
261     fn signature() -> Signature<'static> { unsafe { Signature::from_slice_unchecked($f) } }
262 }
263 
264 impl RefArg for $t<'static> {
265     fn arg_type(&self) -> ArgType { ArgType::$s }
266     fn signature(&self) -> Signature<'static> { unsafe { Signature::from_slice_unchecked($f) } }
267     fn append(&self, i: &mut IterAppend) { arg_append_str(&mut i.0, ArgType::$s, self.as_cstr()) }
268     #[inline]
269     fn as_any(&self) -> &any::Any { self }
270     #[inline]
271     fn as_any_mut(&mut self) -> &mut any::Any { self }
272     #[inline]
273     fn as_str(&self) -> Option<&str> { Some(self) }
274     #[inline]
275     fn box_clone(&self) -> Box<RefArg + 'static> { Box::new(self.clone().into_static()) }
276 }
277 
278 impl<'a> DictKey for $t<'a> {}
279 
280 impl<'a> Append for $t<'a> {
281     fn append(self, i: &mut IterAppend) {
282         arg_append_str(&mut i.0, ArgType::$s, self.as_cstr())
283     }
284 }
285 
286 /*
287 
288 Unfortunately, this does not work because it conflicts with getting a $t<'static>.
289 
290 impl<'a> Get<'a> for $t<'a> {
291     fn get(i: &mut Iter<'a>) -> Option<$t<'a>> { unsafe { arg_get_str(&mut i.0, ArgType::$s) }
292         .map(|s| unsafe { $t::from_slice_unchecked(s.to_bytes_with_nul()) } ) }
293 }
294 */
295 
296 impl<'a> Get<'a> for $t<'static> {
297     fn get(i: &mut Iter<'a>) -> Option<$t<'static>> { unsafe {
298         arg_get_str(&mut i.0, ArgType::$s).map(|s| $t::from_slice_unchecked(s.to_bytes_with_nul()).into_static())
299     }}
300 }
301 
302 
303     }
304 }
305 
306 string_impl!(Path, ObjectPath, b"o\0");
307 string_impl!(Signature, Signature, b"g\0");
308 
309