1use crate::ffi;
2use super::*;
3use super::check;
4use crate::strings::{Signature, Path, Member, ErrorName, Interface};
5use std::{ptr, any, mem};
6use std::ffi::CStr;
7use std::os::raw::{c_void, c_char, c_int};
8use std::fs::File;
9
10
11fn arg_append_basic<T>(i: *mut ffi::DBusMessageIter, arg_type: ArgType, v: T) {
12 let p: *const c_void = &v as *const _ as *const c_void;
13 unsafe {
14 check(f:"dbus_message_iter_append_basic", i:ffi::dbus_message_iter_append_basic(iter:i, t:arg_type as c_int, value:p));
15 };
16}
17
18fn arg_get_basic<T>(i: *mut ffi::DBusMessageIter, arg_type: ArgType) -> Option<T> {
19 unsafe {
20 if ffi::dbus_message_iter_get_arg_type(iter:i) != arg_type as c_int { return None };
21 let mut c: MaybeUninit = mem::MaybeUninit::uninit();
22 ffi::dbus_message_iter_get_basic(iter:i, &mut c as *mut _ as *mut c_void);
23 Some(c.assume_init())
24 }
25}
26
27fn arg_append_str(i: *mut ffi::DBusMessageIter, arg_type: ArgType, v: &CStr) {
28 let p: *const i8 = v.as_ptr();
29 let q: *const c_void = &p as *const _ as *const c_void;
30 unsafe {
31 check(f:"dbus_message_iter_append_basic", i:ffi::dbus_message_iter_append_basic(iter:i, t:arg_type as c_int, value:q));
32 };
33}
34
35unsafe fn arg_get_str<'a>(i: *mut ffi::DBusMessageIter, arg_type: ArgType) -> Option<&'a CStr> {
36 if ffi::dbus_message_iter_get_arg_type(iter:i) != arg_type as c_int { return None };
37 let mut p: *mut i8 = ptr::null_mut();
38 ffi::dbus_message_iter_get_basic(iter:i, &mut p as *mut _ as *mut c_void);
39 Some(CStr::from_ptr(p as *const c_char))
40}
41
42
43
44
45// Implementation for basic types.
46
47macro_rules! integer_impl {
48 ($t: ident, $s: ident, $f: expr, $i: ident, $ii: expr, $u: ident, $uu: expr, $fff: ident, $ff: expr) => {
49
50impl Arg for $t {
51 const ARG_TYPE: ArgType = ArgType::$s;
52 #[inline]
53 fn signature() -> Signature<'static> { unsafe { Signature::from_slice_unchecked($f) } }
54}
55
56impl Append for $t {
57 fn append_by_ref(&self, i: &mut IterAppend) { arg_append_basic(&mut i.0, ArgType::$s, *self) }
58}
59
60impl<'a> Get<'a> for $t {
61 fn get(i: &mut Iter) -> Option<Self> { arg_get_basic(&mut i.0, ArgType::$s) }
62}
63
64impl RefArg for $t {
65 #[inline]
66 fn arg_type(&self) -> ArgType { ArgType::$s }
67 #[inline]
68 fn signature(&self) -> Signature<'static> { unsafe { Signature::from_slice_unchecked($f) } }
69 #[inline]
70 fn append(&self, i: &mut IterAppend) { arg_append_basic(&mut i.0, ArgType::$s, *self) }
71 #[inline]
72 fn as_any(&self) -> &dyn any::Any { self }
73 #[inline]
74 fn as_any_mut(&mut self) -> &mut dyn any::Any { self }
75 #[inline]
76 fn as_i64(&self) -> Option<i64> { let $i = *self; $ii }
77 #[inline]
78 fn as_u64(&self) -> Option<u64> { let $u = *self; $uu }
79 #[inline]
80 fn as_f64(&self) -> Option<f64> { let $fff = *self; $ff }
81 #[inline]
82 fn box_clone(&self) -> Box<dyn RefArg + 'static> { Box::new(self.clone()) }
83 fn array_clone(v: &[Self]) -> Option<Box<dyn RefArg + 'static>> where Self: Sized { Some(Box::new(v.to_vec())) }
84}
85
86impl DictKey for $t {}
87unsafe impl FixedArray for $t {}
88
89}} // End of macro_rules
90
91integer_impl!(u8, Byte, "y\0", i, Some(i as i64), u, Some(u as u64), f, Some(f as f64));
92integer_impl!(i16, Int16, "n\0", i, Some(i as i64), _u, None, f, Some(f as f64));
93integer_impl!(u16, UInt16, "q\0", i, Some(i as i64), u, Some(u as u64), f, Some(f as f64));
94integer_impl!(i32, Int32, "i\0", i, Some(i as i64), _u, None, f, Some(f as f64));
95integer_impl!(u32, UInt32, "u\0", i, Some(i as i64), u, Some(u as u64), f, Some(f as f64));
96integer_impl!(i64, Int64, "x\0", i, Some(i), _u, None, _f, None);
97integer_impl!(u64, UInt64, "t\0", _i, None, u, Some(u as u64), _f, None);
98
99
100macro_rules! refarg_impl {
101 ($t: ty, $i: ident, $ii: expr, $ss: expr, $uu: expr, $ff: expr) => {
102
103impl RefArg for $t {
104 #[inline]
105 fn arg_type(&self) -> ArgType { <$t as Arg>::ARG_TYPE }
106 #[inline]
107 fn signature(&self) -> Signature<'static> { <$t as Arg>::signature() }
108 #[inline]
109 fn append(&self, i: &mut IterAppend) { <$t as Append>::append_by_ref(self, i) }
110 #[inline]
111 fn as_any(&self) -> &dyn any::Any { self }
112 #[inline]
113 fn as_any_mut(&mut self) -> &mut dyn any::Any { self }
114 #[inline]
115 fn as_i64(&self) -> Option<i64> { let $i = self; $ii }
116 #[inline]
117 fn as_u64(&self) -> Option<u64> { let $i = self; $uu }
118 #[inline]
119 fn as_f64(&self) -> Option<f64> { let $i = self; $ff }
120 #[inline]
121 fn as_str(&self) -> Option<&str> { let $i = self; $ss }
122 #[inline]
123 fn box_clone(&self) -> Box<dyn RefArg + 'static> { Box::new(self.clone()) }
124 fn array_clone(v: &[Self]) -> Option<Box<dyn RefArg + 'static>> where Self: Sized { Some(Box::new(v.to_vec())) }
125
126}
127
128 }
129}
130
131
132impl Arg for bool {
133 const ARG_TYPE: ArgType = ArgType::Boolean;
134 fn signature() -> Signature<'static> { unsafe { Signature::from_slice_unchecked("b\0") } }
135}
136impl Append for bool {
137 fn append_by_ref(&self, i: &mut IterAppend) { arg_append_basic(&mut i.0, ArgType::Boolean, v:if *self {1} else {0}) }
138}
139impl DictKey for bool {}
140impl<'a> Get<'a> for bool {
141 fn get(i: &mut Iter) -> Option<Self> { arg_get_basic::<u32>(&mut i.0, ArgType::Boolean).map(|q: u32| q != 0) }
142}
143
144refarg_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 }));
145
146impl Arg for f64 {
147 const ARG_TYPE: ArgType = ArgType::Double;
148 fn signature() -> Signature<'static> { unsafe { Signature::from_slice_unchecked("d\0") } }
149}
150impl Append for f64 {
151 fn append_by_ref(&self, i: &mut IterAppend) { arg_append_basic(&mut i.0, ArgType::Double, *self) }
152}
153impl DictKey for f64 {}
154impl<'a> Get<'a> for f64 {
155 fn get(i: &mut Iter) -> Option<Self> { arg_get_basic(&mut i.0, ArgType::Double) }
156}
157unsafe impl FixedArray for f64 {}
158
159refarg_impl!(f64, _i, None, None, None, Some(*_i));
160
161/// Represents a D-Bus string.
162impl<'a> Arg for &'a str {
163 const ARG_TYPE: ArgType = ArgType::String;
164 fn signature() -> Signature<'static> { unsafe { Signature::from_slice_unchecked("s\0") } }
165}
166
167impl<'a> Append for &'a str {
168 fn append_by_ref(&self, i: &mut IterAppend) {
169 use std::borrow::Cow;
170 let b: &[u8] = self.as_bytes();
171 let v: Cow<[u8]> = if !b.is_empty() && b[b.len()-1] == 0 { Cow::Borrowed(b) }
172 else {
173 let mut bb: Vec<u8> = b.into();
174 bb.push(0);
175 Cow::Owned(bb)
176 };
177 let z: &CStr = unsafe { CStr::from_ptr(v.as_ptr() as *const c_char) };
178 arg_append_str(&mut i.0, ArgType::String, &z)
179 }
180}
181impl<'a> DictKey for &'a str {}
182impl<'a> Get<'a> for &'a str {
183 fn get(i: &mut Iter<'a>) -> Option<&'a str> { unsafeOption<&CStr> { arg_get_str(&mut i.0, ArgType::String) }
184 .and_then(|s: &CStr| s.to_str().ok()) }
185}
186
187impl<'a> Arg for String {
188 const ARG_TYPE: ArgType = ArgType::String;
189 fn signature() -> Signature<'static> { unsafe { Signature::from_slice_unchecked("s\0") } }
190}
191impl<'a> Append for String {
192 fn append(mut self, i: &mut IterAppend) {
193 self.push_str(string:"\0");
194 let s: &str = &self;
195 s.append(ia:i)
196 }
197 fn append_by_ref(&self, i: &mut IterAppend) {
198 (&**self).append_by_ref(i)
199 }
200}
201impl<'a> DictKey for String {}
202impl<'a> Get<'a> for String {
203 fn get(i: &mut Iter<'a>) -> Option<String> { <&str>::get(i).map(String::from) }
204}
205
206refarg_impl!(String, _i, None, Some(&_i), None, None);
207
208/// Represents a D-Bus string.
209impl<'a> Arg for &'a CStr {
210 const ARG_TYPE: ArgType = ArgType::String;
211 fn signature() -> Signature<'static> { unsafe { Signature::from_slice_unchecked("s\0") } }
212}
213
214/*
215/// Note: Will give D-Bus errors in case the CStr is not valid UTF-8.
216impl<'a> Append for &'a CStr {
217 fn append(self, i: &mut IterAppend) {
218 arg_append_str(&mut i.0, Self::arg_type(), &self)
219 }
220}
221*/
222
223impl<'a> DictKey for &'a CStr {}
224impl<'a> Get<'a> for &'a CStr {
225 fn get(i: &mut Iter<'a>) -> Option<&'a CStr> { unsafe { arg_get_str(&mut i.0, Self::ARG_TYPE) }}
226}
227
228impl Arg for OwnedFd {
229 const ARG_TYPE: ArgType = ArgType::UnixFd;
230 fn signature() -> Signature<'static> { unsafe { Signature::from_slice_unchecked("h\0") } }
231}
232impl Append for OwnedFd {
233 #[cfg(unix)]
234 fn append_by_ref(&self, i: &mut IterAppend) {
235 arg_append_basic(&mut i.0, ArgType::UnixFd, self.as_raw_fd())
236 }
237 #[cfg(windows)]
238 fn append_by_ref(&self, _i: &mut IterAppend) {
239 panic!("File descriptor passing not available on Windows");
240 }
241}
242impl DictKey for OwnedFd {}
243impl<'a> Get<'a> for OwnedFd {
244 #[cfg(unix)]
245 fn get(i: &mut Iter) -> Option<Self> {
246 arg_get_basic(&mut i.0, ArgType::UnixFd).map(|fd: i32| unsafe { OwnedFd::from_raw_fd(fd) })
247 }
248 #[cfg(windows)]
249 fn get(_i: &mut Iter) -> Option<Self> {
250 None
251 }
252}
253
254#[cfg(all(unix, feature = "io-lifetimes"))]
255impl Arg for io_lifetimes::OwnedFd {
256 const ARG_TYPE: ArgType = ArgType::UnixFd;
257 fn signature() -> Signature<'static> { unsafe { Signature::from_slice_unchecked("h\0") } }
258}
259#[cfg(all(unix, feature = "io-lifetimes"))]
260impl Append for io_lifetimes::OwnedFd {
261 fn append_by_ref(&self, i: &mut IterAppend) {
262 arg_append_basic(&mut i.0, ArgType::UnixFd, self.as_raw_fd())
263 }
264}
265#[cfg(all(unix, feature = "io-lifetimes"))]
266impl DictKey for io_lifetimes::OwnedFd {}
267#[cfg(all(unix, feature = "io-lifetimes"))]
268impl<'a> Get<'a> for io_lifetimes::OwnedFd {
269 fn get(i: &mut Iter) -> Option<Self> {
270 arg_get_basic(&mut i.0, ArgType::UnixFd).map(|fd| unsafe { io_lifetimes::OwnedFd::from_raw_fd(fd) })
271 }
272}
273
274#[cfg(unix)]
275impl RefArg for OwnedFd {
276 #[inline]
277 fn arg_type(&self) -> ArgType { <Self as Arg>::ARG_TYPE }
278 #[inline]
279 fn signature(&self) -> Signature<'static> { <Self as Arg>::signature() }
280 #[inline]
281 fn append(&self, i: &mut IterAppend) { <Self as Append>::append_by_ref(self, i) }
282 #[inline]
283 fn as_any(&self) -> &dyn any::Any { self }
284 #[inline]
285 fn as_any_mut(&mut self) -> &mut dyn any::Any { self }
286 #[inline]
287 fn as_i64(&self) -> Option<i64> { Some(self.as_raw_fd() as i64) }
288 #[inline]
289 fn box_clone(&self) -> Box<dyn RefArg + 'static> { Box::new(self.try_clone().unwrap()) }
290}
291
292#[cfg(windows)]
293refarg_impl!(OwnedFd, _i, None, None, None, None);
294
295impl Arg for File {
296 const ARG_TYPE: ArgType = ArgType::UnixFd;
297 fn signature() -> Signature<'static> { unsafe { Signature::from_slice_unchecked("h\0") } }
298}
299impl Append for File {
300 #[cfg(unix)]
301 fn append_by_ref(&self, i: &mut IterAppend) {
302 arg_append_basic(&mut i.0, ArgType::UnixFd, self.as_raw_fd())
303 }
304 #[cfg(windows)]
305 fn append_by_ref(&self, _i: &mut IterAppend) {
306 panic!("File descriptor passing not available on Windows");
307 }
308}
309impl DictKey for File {}
310impl<'a> Get<'a> for File {
311 #[cfg(unix)]
312 fn get(i: &mut Iter) -> Option<Self> {
313 arg_get_basic(&mut i.0, ArgType::UnixFd).map(|fd: i32| unsafe { File::from_raw_fd(fd) })
314 }
315 #[cfg(windows)]
316 fn get(_i: &mut Iter) -> Option<Self> {
317 None
318 }
319}
320
321impl RefArg for File {
322 #[inline]
323 fn arg_type(&self) -> ArgType { <File as Arg>::ARG_TYPE }
324 #[inline]
325 fn signature(&self) -> Signature<'static> { <File as Arg>::signature() }
326 #[inline]
327 fn append(&self, i: &mut IterAppend) { <File as Append>::append_by_ref(self, i) }
328 #[inline]
329 fn as_any(&self) -> &dyn any::Any { self }
330 #[inline]
331 fn as_any_mut(&mut self) -> &mut dyn any::Any { self }
332 #[cfg(unix)]
333 #[inline]
334 fn as_i64(&self) -> Option<i64> { Some(self.as_raw_fd() as i64) }
335 #[inline]
336 fn box_clone(&self) -> Box<dyn RefArg + 'static> { Box::new(self.try_clone().unwrap()) }
337}
338
339#[cfg(all(unix, feature = "io-lifetimes"))]
340impl RefArg for io_lifetimes::OwnedFd {
341 #[inline]
342 fn arg_type(&self) -> ArgType { <Self as Arg>::ARG_TYPE }
343 #[inline]
344 fn signature(&self) -> Signature<'static> { <Self as Arg>::signature() }
345 #[inline]
346 fn append(&self, i: &mut IterAppend) { <Self as Append>::append_by_ref(self, i) }
347 #[inline]
348 fn as_any(&self) -> &dyn any::Any { self }
349 #[inline]
350 fn as_any_mut(&mut self) -> &mut dyn any::Any { self }
351 #[cfg(unix)]
352 #[inline]
353 fn as_i64(&self) -> Option<i64> { Some(self.as_raw_fd() as i64) }
354 #[inline]
355 fn box_clone(&self) -> Box<dyn RefArg + 'static> { Box::new(self.try_clone().unwrap()) }
356}
357
358
359macro_rules! string_impl {
360 ($t: ident, $s: ident, $f: expr) => {
361
362impl<'a> Arg for $t<'a> {
363 const ARG_TYPE: ArgType = ArgType::$s;
364 fn signature() -> Signature<'static> { unsafe { Signature::from_slice_unchecked($f) } }
365}
366
367impl RefArg for $t<'static> {
368 fn arg_type(&self) -> ArgType { ArgType::$s }
369 fn signature(&self) -> Signature<'static> { unsafe { Signature::from_slice_unchecked($f) } }
370 fn append(&self, i: &mut IterAppend) { arg_append_str(&mut i.0, ArgType::$s, self.as_cstr()) }
371 #[inline]
372 fn as_any(&self) -> &dyn any::Any { self }
373 #[inline]
374 fn as_any_mut(&mut self) -> &mut dyn any::Any { self }
375 #[inline]
376 fn as_str(&self) -> Option<&str> { Some(self) }
377 #[inline]
378 fn box_clone(&self) -> Box<dyn RefArg + 'static> { Box::new(self.clone().into_static()) }
379 fn array_clone(v: &[Self]) -> Option<Box<dyn RefArg + 'static>> where Self: Sized { Some(Box::new(v.to_vec())) }
380}
381
382impl<'a> DictKey for $t<'a> {}
383
384impl<'a> Append for $t<'a> {
385 fn append_by_ref(&self, i: &mut IterAppend) {
386 arg_append_str(&mut i.0, ArgType::$s, self.as_cstr())
387 }
388}
389
390/*
391
392Unfortunately, this does not work because it conflicts with getting a $t<'static>.
393
394impl<'a> Get<'a> for $t<'a> {
395 fn get(i: &mut Iter<'a>) -> Option<$t<'a>> { unsafe { arg_get_str(&mut i.0, ArgType::$s) }
396 .map(|s| unsafe { $t::from_slice_unchecked(s.to_bytes_with_nul()) } ) }
397}
398*/
399
400impl<'a> Get<'a> for $t<'static> {
401 fn get(i: &mut Iter<'a>) -> Option<$t<'static>> { unsafe {
402 let c = arg_get_str(&mut i.0, ArgType::$s)?;
403 let s = std::str::from_utf8(c.to_bytes_with_nul()).ok()?;
404 Some($t::from_slice_unchecked(s).into_static())
405 }}
406}
407
408
409 }
410}
411
412string_impl!(Interface, String, "s\0");
413string_impl!(ErrorName, String, "s\0");
414string_impl!(Member, String, "s\0");
415string_impl!(Path, ObjectPath, "o\0");
416string_impl!(Signature, Signature, "g\0");
417