1//! MessageItem - old, enum design that is used as parameters and return values from
2//! method calls, or as data added to a signal.
3//!
4//! Note that the newer generic design (see `arg` module) is, in general, both faster
5//! and smaller than MessageItem, and should be your first hand choice
6//! whenever applicable. There is also a trait object design called `RefArg` in
7//! case the generic design is too inflexible.
8
9use crate::strings::{Signature, Path, Interface, BusName};
10
11use crate::arg;
12use crate::arg::{Iter, IterAppend, Arg, ArgType};
13use crate::arg::OwnedFd;
14use std::ffi::CStr;
15use std::{ops, any};
16
17use crate::{ffidisp::Connection, Message, Error};
18use std::collections::BTreeMap;
19use std::convert::TryFrom;
20
21#[derive(Debug,Copy,Clone)]
22/// Errors that can happen when creating a MessageItem::Array.
23pub enum ArrayError {
24 /// The array is empty.
25 EmptyArray,
26 /// The array is composed of different element types.
27 DifferentElementTypes,
28 /// The supplied signature is not a valid array signature
29 InvalidSignature,
30}
31
32
33/// OwnedFd wrapper for MessageItem
34#[cfg(feature = "stdfd")]
35#[derive(Debug)]
36pub struct MessageItemFd(pub OwnedFd);
37
38#[cfg(feature = "stdfd")]
39mod messageitem_fd_impl {
40 use super::*;
41 impl Clone for MessageItemFd {
42 fn clone(&self) -> Self { MessageItemFd(self.0.try_clone().unwrap()) }
43 }
44
45 impl PartialEq for MessageItemFd {
46 fn eq(&self, _rhs: &Self) -> bool { false }
47 }
48
49 impl PartialOrd for MessageItemFd {
50 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
51 use std::os::fd::AsRawFd;
52 let a = self.0.as_raw_fd();
53 let b = other.0.as_raw_fd();
54 a.partial_cmp(&b)
55 }
56 }
57
58 impl From<OwnedFd> for MessageItem { fn from(i: OwnedFd) -> MessageItem { MessageItem::UnixFd(MessageItemFd(i)) } }
59
60 impl<'a> TryFrom<&'a MessageItem> for &'a OwnedFd {
61 type Error = ();
62 fn try_from(i: &'a MessageItem) -> Result<&'a OwnedFd,()> { if let MessageItem::UnixFd(ref b) = i { Ok(&b.0) } else { Err(()) } }
63 }
64}
65
66#[derive(Debug, Clone, PartialEq, PartialOrd)]
67/// An array of MessageItem where every MessageItem is of the same type.
68pub struct MessageItemArray {
69 v: Vec<MessageItem>,
70 // signature includes the "a"!
71 sig: Signature<'static>,
72}
73
74impl MessageItemArray {
75 /// Creates a new array where every element has the supplied signature.
76 ///
77 /// Signature is the full array signature, not the signature of the element.
78 pub fn new(v: Vec<MessageItem>, sig: Signature<'static>) -> Result<MessageItemArray, ArrayError> {
79 let a = MessageItemArray {v: v, sig: sig };
80 if a.sig.as_bytes()[0] != ffi::DBUS_TYPE_ARRAY as u8 { return Err(ArrayError::InvalidSignature) }
81 {
82 let esig = a.element_signature();
83 for i in &a.v {
84 if i.signature().as_cstr() != esig { return Err(ArrayError::DifferentElementTypes) }
85 }
86 }
87 Ok(a)
88 }
89
90 fn element_signature(&self) -> &CStr {
91 let z = &self.sig.as_cstr().to_bytes_with_nul()[1..];
92 unsafe { CStr::from_bytes_with_nul_unchecked(z) }
93 }
94
95 fn make_sig(m: &MessageItem) -> Signature<'static> {
96 Signature::new(format!("a{}", m.signature())).unwrap()
97 }
98
99 /// Signature of array (full array signature)
100 pub fn signature(&self) -> &Signature<'static> { &self.sig }
101
102 /// Consumes the MessageItemArray in order to allow you to modify the individual items of the array.
103 pub fn into_vec(self) -> Vec<MessageItem> { self.v }
104}
105
106impl ops::Deref for MessageItemArray {
107 type Target = [MessageItem];
108 fn deref(&self) -> &Self::Target { &self.v }
109}
110
111impl arg::Append for MessageItemArray {
112 fn append_by_ref(&self, i: &mut IterAppend) {
113 i.append_container(ArgType::Array, sig:Some(self.element_signature()), |s: &mut IterAppend<'_>| {
114 for a in &self.v { a.append_by_ref(s) }
115 });
116 }
117}
118
119#[derive(Debug, Clone, PartialEq, PartialOrd)]
120/// An array of MessageItem where every MessageItem is of the same type.
121pub struct MessageItemDict {
122 v: Vec<(MessageItem, MessageItem)>,
123 // signature includes the "a"!
124 sig: Signature<'static>,
125}
126
127impl MessageItemDict {
128 /// Creates a new dict where every key and value elements have the supplied signature.
129 pub fn new(v: Vec<(MessageItem, MessageItem)>, keysig: Signature<'static>, valuesig: Signature<'static>) -> Result<MessageItemDict, ArrayError> {
130 let sig: Signature<'static> = Signature::from(format!("a{{{}{}}}", keysig, valuesig));
131 let a: MessageItemDict = MessageItemDict {v: v, sig: sig };
132 for (k, v) in &a.v {
133 if keysig != k.signature() || valuesig != v.signature() {
134 return Err(ArrayError::DifferentElementTypes);
135 }
136 }
137 Ok(a)
138 }
139
140 fn element_signature(&self) -> &CStr {
141 let z: &{unknown} = &self.sig.as_cstr().to_bytes_with_nul()[1..];
142 unsafe { CStr::from_bytes_with_nul_unchecked(z) }
143 }
144
145 /// Signature of array (full array signature)
146 pub fn signature(&self) -> &Signature<'static> { &self.sig }
147
148 /// Consumes the MessageItemDict in order to allow you to modify the individual items of the dict.
149 pub fn into_vec(self) -> Vec<(MessageItem, MessageItem)> { self.v }
150}
151
152impl ops::Deref for MessageItemDict {
153 type Target = [(MessageItem, MessageItem)];
154 fn deref(&self) -> &Self::Target { &self.v }
155}
156
157impl arg::Append for MessageItemDict {
158 fn append_by_ref(&self, i: &mut IterAppend) {
159 i.append_container(ArgType::Array, sig:Some(self.element_signature()), |s| {
160 for (k, v) in &self.v {
161 s.append_container(ArgType::DictEntry, None, |ss: &mut IterAppend<'_>| {
162 k.append_by_ref(ss);
163 v.append_by_ref(ss);
164 });
165 }
166 });
167 }
168}
169
170/// MessageItem - used as parameters and return values from
171/// method calls, or as data added to a signal (old, enum version).
172///
173/// Note that the newer generic design (see `arg` module) is both faster
174/// and less error prone than MessageItem, and should be your first hand choice
175/// whenever applicable.
176#[derive(Debug, PartialEq, PartialOrd, Clone)]
177pub enum MessageItem {
178 /// A D-Bus array requires all elements to be of the same type.
179 /// All elements must match the Signature.
180 Array(MessageItemArray),
181 /// A D-Bus struct allows for values of different types.
182 Struct(Vec<MessageItem>),
183 /// A D-Bus variant is a wrapper around another `MessageItem`, which
184 /// can be of any type.
185 Variant(Box<MessageItem>),
186 /// A D-Bus dictionary. All keys and values are required to be of the same type.
187 /// Not all types can be dictionary keys, but all can be dictionary values.
188 Dict(MessageItemDict),
189 /// A D-Bus objectpath requires its content to be a valid objectpath,
190 /// so this cannot be any string.
191 ObjectPath(Path<'static>),
192 /// A D-Bus signature requires its content to be a valid type signature,
193 /// so this cannot be any string.
194 Signature(Signature<'static>),
195 /// A D-Bus String is zero terminated, so no \0 s in the String, please.
196 /// (D-Bus strings are also - like Rust strings - required to be valid UTF-8.)
197 Str(String),
198 /// A D-Bus boolean type.
199 Bool(bool),
200 /// A D-Bus unsigned 8 bit type.
201 Byte(u8),
202 /// A D-Bus signed 16 bit type.
203 Int16(i16),
204 /// A D-Bus signed 32 bit type.
205 Int32(i32),
206 /// A D-Bus signed 64 bit type.
207 Int64(i64),
208 /// A D-Bus unsigned 16 bit type.
209 UInt16(u16),
210 /// A D-Bus unsigned 32 bit type.
211 UInt32(u32),
212 /// A D-Bus unsigned 64 bit type.
213 UInt64(u64),
214 /// A D-Bus IEEE-754 double-precision floating point type.
215 Double(f64),
216 /// D-Bus allows for sending file descriptors, which can be used to
217 /// set up SHM, unix pipes, or other communication channels.
218 #[cfg(not(feature = "stdfd"))]
219 UnixFd(OwnedFd),
220 /// D-Bus allows for sending file descriptors, which can be used to
221 /// set up SHM, unix pipes, or other communication channels.
222 #[cfg(feature = "stdfd")]
223 UnixFd(MessageItemFd),
224}
225
226impl MessageItem {
227 /// Get the D-Bus Signature for this MessageItem.
228 pub fn signature(&self) -> Signature<'static> {
229 use crate::arg::Variant;
230 match self {
231 MessageItem::Str(_) => <String as Arg>::signature(),
232 MessageItem::Bool(_) => <bool as Arg>::signature(),
233 MessageItem::Byte(_) => <u8 as Arg>::signature(),
234 MessageItem::Int16(_) => <i16 as Arg>::signature(),
235 MessageItem::Int32(_) => <i32 as Arg>::signature(),
236 MessageItem::Int64(_) => <i64 as Arg>::signature(),
237 MessageItem::UInt16(_) => <u16 as Arg>::signature(),
238 MessageItem::UInt32(_) => <u32 as Arg>::signature(),
239 MessageItem::UInt64(_) => <u64 as Arg>::signature(),
240 MessageItem::Double(_) => <f64 as Arg>::signature(),
241 MessageItem::Array(ref a) => a.sig.clone(),
242 MessageItem::Struct(ref s) => Signature::new(format!("({})", s.iter().fold(String::new(), |s, i| s + &*i.signature()))).unwrap(),
243 MessageItem::Variant(_) => <Variant<u8> as Arg>::signature(),
244 MessageItem::Dict(ref a) => a.sig.clone(),
245 MessageItem::ObjectPath(_) => <Path as Arg>::signature(),
246 MessageItem::Signature(_) => <Signature as Arg>::signature(),
247 MessageItem::UnixFd(_) => <std::fs::File as Arg>::signature(),
248 }
249 }
250
251 /// Get the arg type of this MessageItem.
252 pub fn arg_type(&self) -> arg::ArgType {
253 match self {
254 MessageItem::Str(_) => ArgType::String,
255 MessageItem::Bool(_) => ArgType::Boolean,
256 MessageItem::Byte(_) => ArgType::Byte,
257 MessageItem::Int16(_) => ArgType::Int16,
258 MessageItem::Int32(_) => ArgType::Int32,
259 MessageItem::Int64(_) => ArgType::Int64,
260 MessageItem::UInt16(_) => ArgType::UInt16,
261 MessageItem::UInt32(_) => ArgType::UInt32,
262 MessageItem::UInt64(_) => ArgType::UInt64,
263 MessageItem::Double(_) => ArgType::Double,
264 MessageItem::Array(_) => ArgType::Array,
265 MessageItem::Struct(_) => ArgType::Struct,
266 MessageItem::Variant(_) => ArgType::Variant,
267 MessageItem::Dict(_) => ArgType::Array,
268 MessageItem::ObjectPath(_) => ArgType::ObjectPath,
269 MessageItem::Signature(_) => ArgType::Signature,
270 MessageItem::UnixFd(_) => ArgType::UnixFd,
271 }
272 }
273
274 /// Creates a (String, Variant) dictionary from an iterator with Result passthrough (an Err will abort and return that Err)
275 pub fn from_dict<E, I: Iterator<Item=Result<(String, MessageItem),E>>>(i: I) -> Result<MessageItem, E> {
276 let mut v = Vec::new();
277 for r in i {
278 let (s, vv) = r?;
279 v.push((s.into(), Box::new(vv).into()));
280 }
281 Ok(MessageItem::Dict(MessageItemDict::new(v, Signature::new("s").unwrap(), Signature::new("v").unwrap()).unwrap()))
282 }
283
284 /// Creates an MessageItem::Array from a list of MessageItems.
285 ///
286 /// Note: This requires `v` to be non-empty. See also
287 /// `MessageItem::from(&[T])`, which can handle empty arrays as well.
288 pub fn new_array(v: Vec<MessageItem>) -> Result<MessageItem, ArrayError> {
289 if v.is_empty() {
290 return Err(ArrayError::EmptyArray);
291 }
292 let s = MessageItemArray::make_sig(&v[0]);
293 Ok(MessageItem::Array(MessageItemArray::new(v, s)?))
294 }
295
296 /// Creates an MessageItem::Dict from a list of MessageItem pairs.
297 ///
298 /// Note: This requires `v` to be non-empty. See also
299 /// `MessageItem::from(&[(T1, T2)])`, which can handle empty arrays as well.
300 pub fn new_dict(v: Vec<(MessageItem, MessageItem)>) -> Result<MessageItem, ArrayError> {
301 if v.is_empty() {
302 return Err(ArrayError::EmptyArray);
303 }
304 let (s1, s2) = (v[0].0.signature(), v[0].1.signature());
305 Ok(MessageItem::Dict(MessageItemDict::new(v, s1, s2)?))
306 }
307
308 /// Get the inner value of a `MessageItem`
309 ///
310 /// # Example
311 /// ```
312 /// use dbus::arg::messageitem::MessageItem;
313 /// let m: MessageItem = 5i64.into();
314 /// let s: i64 = m.inner().unwrap();
315 /// assert_eq!(s, 5i64);
316 /// ```
317 pub fn inner<'a, T: TryFrom<&'a MessageItem>>(&'a self) -> Result<T, T::Error> {
318 T::try_from(self)
319 }
320
321 /// Get the underlying `MessageItem` of a `MessageItem::Variant`
322 ///
323 /// Nested `MessageItem::Variant`s are unwrapped recursively until a
324 /// non-`Variant` is found.
325 ///
326 /// # Example
327 /// ```
328 /// use dbus::arg::messageitem::MessageItem;
329 /// let nested = MessageItem::Variant(Box::new(6i64.into()));
330 /// let flat: MessageItem = 6i64.into();
331 /// assert_ne!(&nested, &flat);
332 /// assert_eq!(nested.peel(), &flat);
333 /// ```
334 pub fn peel(&self) -> &Self {
335 let mut current = self;
336
337 while let MessageItem::Variant(b) = current {
338 current = &*b;
339 }
340
341 current
342 }
343
344 fn new_array2<D, I>(i: I) -> MessageItem
345 where D: Into<MessageItem>, D: Default, I: Iterator<Item=D> {
346 let v: Vec<MessageItem> = i.map(|ii| ii.into()).collect();
347 let s = {
348 let d;
349 let t = if v.is_empty() { d = D::default().into(); &d } else { &v[0] };
350 MessageItemArray::make_sig(t)
351 };
352 MessageItem::Array(MessageItemArray::new(v, s).unwrap())
353 }
354
355 fn new_dict2<K, V, I>(i: I) -> MessageItem
356 where K: Into<MessageItem> + Default, V: Into<MessageItem> + Default, I: Iterator<Item=(K, V)> {
357 let v: Vec<(MessageItem, MessageItem)> = i.map(|(k, v)| (k.into(), v.into())).collect();
358 let (kt, vt) = if v.is_empty() {
359 let kd = K::default().into();
360 let vd = V::default().into();
361 (kd.signature(), vd.signature())
362 } else { (v[0].0.signature(), v[0].1.signature()) };
363 MessageItem::Dict(MessageItemDict::new(v, kt, vt).unwrap())
364 }
365}
366
367macro_rules! msgitem_convert {
368 ($t: ty, $s: ident) => {
369 impl From<$t> for MessageItem { fn from(i: $t) -> MessageItem { MessageItem::$s(i) } }
370
371 impl<'a> TryFrom<&'a MessageItem> for $t {
372 type Error = ();
373 fn try_from(i: &'a MessageItem) -> Result<$t,()> {
374 if let MessageItem::$s(b) = i.peel() { Ok(*b) } else { Err(()) }
375 }
376 }
377 }
378}
379
380msgitem_convert!(u8, Byte);
381msgitem_convert!(u64, UInt64);
382msgitem_convert!(u32, UInt32);
383msgitem_convert!(u16, UInt16);
384msgitem_convert!(i16, Int16);
385msgitem_convert!(i32, Int32);
386msgitem_convert!(i64, Int64);
387msgitem_convert!(f64, Double);
388msgitem_convert!(bool, Bool);
389
390
391
392/// Create a `MessageItem::Array`.
393impl<'a, T> From<&'a [T]> for MessageItem
394where T: Into<MessageItem> + Clone + Default {
395 fn from(i: &'a [T]) -> MessageItem {
396 MessageItem::new_array2(i.iter().cloned())
397 }
398}
399
400/// Create a `MessageItem::Dict`.
401impl<'a, T1, T2> From<&'a [(T1, T2)]> for MessageItem
402where T1: Into<MessageItem> + Clone + Default, T2: Into<MessageItem> + Clone + Default {
403 fn from(i: &'a [(T1, T2)]) -> MessageItem {
404 MessageItem::new_dict2(i.iter().cloned())
405 }
406}
407
408impl<'a> From<&'a str> for MessageItem { fn from(i: &str) -> MessageItem { MessageItem::Str(i.to_string()) } }
409
410impl From<String> for MessageItem { fn from(i: String) -> MessageItem { MessageItem::Str(i) } }
411
412impl From<Path<'static>> for MessageItem { fn from(i: Path<'static>) -> MessageItem { MessageItem::ObjectPath(i) } }
413
414impl From<Signature<'static>> for MessageItem { fn from(i: Signature<'static>) -> MessageItem { MessageItem::Signature(i) } }
415
416#[cfg(not(feature = "stdfd"))]
417impl From<OwnedFd> for MessageItem { fn from(i: OwnedFd) -> MessageItem { MessageItem::UnixFd(i) } }
418
419#[cfg(unix)]
420impl From<std::fs::File> for MessageItem {
421 fn from(i: std::fs::File) -> MessageItem {
422 use std::os::unix::io::{FromRawFd, IntoRawFd};
423 let fd: OwnedFd = unsafe { OwnedFd::from_raw_fd(i.into_raw_fd()) };
424 fd.into()
425 }
426}
427
428/// Create a `MessageItem::Variant`
429impl From<Box<MessageItem>> for MessageItem {
430 fn from(i: Box<MessageItem>) -> MessageItem { MessageItem::Variant(i) }
431}
432
433impl<'a> TryFrom<&'a MessageItem> for &'a str {
434 type Error = ();
435 fn try_from(i: &'a MessageItem) -> Result<&'a str, Self::Error> {
436 match i.peel() {
437 MessageItem::Str(ref b: &{unknown}) => Ok(b),
438 MessageItem::ObjectPath(ref b: &Path<'static>) => Ok(b),
439 MessageItem::Signature(ref b: &Signature<'static>) => Ok(b),
440 _ => Err(()),
441 }
442 }
443}
444
445impl<'a> TryFrom<&'a MessageItem> for &'a String {
446 type Error = ();
447 fn try_from(i: &'a MessageItem) -> Result<&'a String,()> { if let MessageItem::Str(b: &{unknown}) = i.peel() { Ok(b) } else { Err(()) } }
448}
449
450impl<'a> TryFrom<&'a MessageItem> for &'a Path<'static> {
451 type Error = ();
452 fn try_from(i: &'a MessageItem) -> Result<&'a Path<'static>,()> { if let MessageItem::ObjectPath(b: &Path<'static>) = i.peel() { Ok(b) } else { Err(()) } }
453}
454
455impl<'a> TryFrom<&'a MessageItem> for &'a Signature<'static> {
456 type Error = ();
457 fn try_from(i: &'a MessageItem) -> Result<&'a Signature<'static>,()> { if let MessageItem::Signature(b: &Signature<'static>) = i.peel() { Ok(b) } else { Err(()) } }
458}
459
460impl<'a> TryFrom<&'a MessageItem> for &'a Box<MessageItem> {
461 type Error = ();
462 fn try_from(i: &'a MessageItem) -> Result<&'a Box<MessageItem>,()> { if let MessageItem::Variant(b: &{unknown}) = i { Ok(b) } else { Err(()) } }
463}
464
465impl<'a> TryFrom<&'a MessageItem> for &'a Vec<MessageItem> {
466 type Error = ();
467 fn try_from(i: &'a MessageItem) -> Result<&'a Vec<MessageItem>,()> {
468 match i.peel() {
469 MessageItem::Array(b: &MessageItemArray) => Ok(&b.v),
470 MessageItem::Struct(b: &{unknown}) => Ok(b),
471 _ => Err(()),
472 }
473 }
474}
475
476impl<'a> TryFrom<&'a MessageItem> for &'a [MessageItem] {
477 type Error = ();
478 fn try_from(i: &'a MessageItem) -> Result<&'a [MessageItem],()> { i.inner::<&Vec<MessageItem>>().map(|s| &**s) }
479}
480
481#[cfg(not(feature = "stdfd"))]
482impl<'a> TryFrom<&'a MessageItem> for &'a OwnedFd {
483 type Error = ();
484 fn try_from(i: &'a MessageItem) -> Result<&'a OwnedFd,()> { if let MessageItem::UnixFd(ref b: &OwnedFd) = i { Ok(b) } else { Err(()) } }
485}
486
487impl<'a> TryFrom<&'a MessageItem> for &'a [(MessageItem, MessageItem)] {
488 type Error = ();
489 fn try_from(i: &'a MessageItem) -> Result<&'a [(MessageItem, MessageItem)],()> {
490 if let MessageItem::Dict(ref d: &MessageItemDict) = i { Ok(&*d.v) } else { Err(()) }
491 }
492}
493
494
495impl arg::Append for MessageItem {
496 fn append_by_ref(&self, i: &mut IterAppend) {
497 match self {
498 MessageItem::Str(a) => a.append_by_ref(i),
499 MessageItem::Bool(a) => a.append_by_ref(i),
500 MessageItem::Byte(a) => a.append_by_ref(i),
501 MessageItem::Int16(a) => a.append_by_ref(i),
502 MessageItem::Int32(a) => a.append_by_ref(i),
503 MessageItem::Int64(a) => a.append_by_ref(i),
504 MessageItem::UInt16(a) => a.append_by_ref(i),
505 MessageItem::UInt32(a) => a.append_by_ref(i),
506 MessageItem::UInt64(a) => a.append_by_ref(i),
507 MessageItem::Double(a) => a.append_by_ref(i),
508 MessageItem::Array(a) => a.append_by_ref(i),
509 MessageItem::Struct(a) => i.append_container(ArgType::Struct, None, |s| {
510 for v in a { v.append_by_ref(s); }
511 }),
512 MessageItem::Variant(a) => {
513 i.append_container(ArgType::Variant, Some(a.signature().as_cstr()), |s| a.append_by_ref(s))
514 },
515 MessageItem::Dict(a) => a.append_by_ref(i),
516 MessageItem::ObjectPath(a) => a.append_by_ref(i),
517 MessageItem::Signature(a) => a.append_by_ref(i),
518 #[cfg(not(feature = "stdfd"))]
519 MessageItem::UnixFd(a) => a.append_by_ref(i),
520 #[cfg(feature = "stdfd")]
521 MessageItem::UnixFd(a) => a.0.append_by_ref(i),
522 }
523 }
524}
525
526impl<'a> arg::Get<'a> for MessageItem {
527 fn get(i: &mut Iter<'a>) -> Option<Self> {
528 Some(match i.arg_type() {
529 ArgType::Array => {
530 let mut s = i.recurse(ArgType::Array).unwrap();
531 if i.signature().as_bytes()[1] == b'{' { // Dict
532 let mut v = vec!();
533 while s.arg_type() == ArgType::DictEntry {
534 let mut ss = s.recurse(ArgType::DictEntry).unwrap();
535 let kk = MessageItem::get(&mut ss).unwrap();
536 ss.next();
537 let vv = MessageItem::get(&mut ss).unwrap();
538 v.push((kk, vv));
539 s.next();
540 };
541 MessageItem::Dict(MessageItemDict { v: v, sig: i.signature() })
542 } else {
543 let mut v = vec!();
544 while let Some(mi) = MessageItem::get(&mut s) { v.push(mi); s.next(); };
545 MessageItem::Array(MessageItemArray { v: v, sig: i.signature() })
546 }
547 },
548 ArgType::Variant => MessageItem::Variant({
549 let mut s = i.recurse(ArgType::Variant).unwrap();
550 Box::new(MessageItem::get(&mut s).unwrap())
551 }),
552 ArgType::Boolean => MessageItem::Bool(i.get::<bool>().unwrap()),
553 ArgType::Invalid => return None,
554 ArgType::String => MessageItem::Str(i.get::<String>().unwrap()),
555 ArgType::DictEntry => return None,
556 ArgType::Byte => MessageItem::Byte(i.get::<u8>().unwrap()),
557 ArgType::Int16 => MessageItem::Int16(i.get::<i16>().unwrap()),
558 ArgType::UInt16 => MessageItem::UInt16(i.get::<u16>().unwrap()),
559 ArgType::Int32 => MessageItem::Int32(i.get::<i32>().unwrap()),
560 ArgType::UInt32 => MessageItem::UInt32(i.get::<u32>().unwrap()),
561 ArgType::Int64 => MessageItem::Int64(i.get::<i64>().unwrap()),
562 ArgType::UInt64 => MessageItem::UInt64(i.get::<u64>().unwrap()),
563 ArgType::Double => MessageItem::Double(i.get::<f64>().unwrap()),
564 #[cfg(not(feature = "stdfd"))]
565 ArgType::UnixFd => MessageItem::UnixFd(i.get::<OwnedFd>().unwrap()),
566 #[cfg(feature = "stdfd")]
567 ArgType::UnixFd => MessageItem::UnixFd(MessageItemFd(i.get::<OwnedFd>().unwrap())),
568 ArgType::Struct => MessageItem::Struct({
569 let mut s = i.recurse(ArgType::Struct).unwrap();
570 let mut v = vec!();
571 while let Some(mi) = MessageItem::get(&mut s) { v.push(mi); s.next(); };
572 v
573 }),
574 ArgType::ObjectPath => MessageItem::ObjectPath(i.get::<Path>().unwrap().into_static()),
575 ArgType::Signature => MessageItem::Signature(i.get::<Signature>().unwrap().into_static()),
576 })
577 }
578}
579
580impl arg::RefArg for MessageItem {
581 fn arg_type(&self) -> ArgType { MessageItem::arg_type(&self) }
582 fn signature(&self) -> Signature<'static> { MessageItem::signature(&self) }
583 fn append(&self, i: &mut IterAppend) { arg::Append::append_by_ref(self, i) }
584 #[inline]
585 fn as_any(&self) -> &dyn any::Any where Self: 'static { self }
586 #[inline]
587 fn as_any_mut(&mut self) -> &mut dyn any::Any where Self: 'static { self }
588 #[inline]
589 fn box_clone(&self) -> Box<dyn arg::RefArg + 'static> { Box::new(self.clone()) }
590}
591
592
593impl arg::Append for arg::Variant<MessageItem> {
594 fn append_by_ref(&self, i: &mut IterAppend) {
595 let z: &MessageItem = &self.0;
596 let asig: Signature<'static> = z.signature();
597 let sig: &{unknown} = asig.as_cstr();
598 i.append_container(ArgType::Variant, sig:Some(&sig), |s: &mut IterAppend<'_>| z.append_by_ref(s));
599 }
600}
601
602
603/// Client side properties - get and set properties on a remote application.
604pub struct Props<'a> {
605 name: BusName<'a>,
606 path: Path<'a>,
607 interface: Interface<'a>,
608 timeout_ms: i32,
609 conn: &'a Connection,
610}
611
612impl<'a> Props<'a> {
613 /// Create a new Props.
614 pub fn new<N, P, I>(conn: &'a Connection, name: N, path: P, interface: I, timeout_ms: i32) -> Props<'a>
615 where N: Into<BusName<'a>>, P: Into<Path<'a>>, I: Into<Interface<'a>> {
616 Props {
617 name: name.into(),
618 path: path.into(),
619 interface: interface.into(),
620 timeout_ms: timeout_ms,
621 conn: conn,
622 }
623 }
624
625 /// Get a single property's value.
626 pub fn get(&self, propname: &str) -> Result<MessageItem, Error> {
627 let mut m = Message::method_call(&self.name, &self.path,
628 &"org.freedesktop.DBus.Properties".into(), &"Get".into());
629 m.append_items(&[self.interface.to_string().into(), propname.to_string().into()]);
630 let mut r = self.conn.send_with_reply_and_block(m, self.timeout_ms)?;
631 let reply = r.as_result()?.get_items();
632 if reply.len() == 1 {
633 if let MessageItem::Variant(ref v) = reply[0] {
634 return Ok((**v).clone())
635 }
636 }
637 let f = format!("Invalid reply for property get {}: '{:?}'", propname, reply);
638 Err(Error::new_custom("InvalidReply", &f))
639 }
640
641 /// Set a single property's value.
642 pub fn set(&self, propname: &str, value: MessageItem) -> Result<(), Error> {
643 let mut m = Message::method_call(&self.name, &self.path,
644 &"org.freedesktop.DBus.Properties".into(), &"Set".into());
645 m.append_items(&[self.interface.to_string().into(), propname.to_string().into(), Box::new(value).into()]);
646 let mut r = self.conn.send_with_reply_and_block(m, self.timeout_ms)?;
647 r.as_result()?;
648 Ok(())
649 }
650
651 /// Get a map of all the properties' names and their values.
652 pub fn get_all(&self) -> Result<BTreeMap<String, MessageItem>, Error> {
653 let mut m = Message::method_call(&self.name, &self.path,
654 &"org.freedesktop.DBus.Properties".into(), &"GetAll".into());
655 m.append_items(&[self.interface.to_string().into()]);
656 let mut r = self.conn.send_with_reply_and_block(m, self.timeout_ms)?;
657 let reply = r.as_result()?.get_items();
658
659 (|| {
660 if reply.len() != 1 { return Err(()) };
661 let mut tree = BTreeMap::new();
662 let a: &[(MessageItem, MessageItem)] = reply[0].inner()?;
663 for (k, v) in a.iter() {
664 let (k, v): (&String, &Box<MessageItem>) = (k.inner()?, v.inner()?);
665 tree.insert(k.clone(), *v.clone());
666 }
667 Ok(tree)
668 })().map_err(|_| {
669 let f = format!("Invalid reply for property GetAll: '{:?}'", reply);
670 Error::new_custom("InvalidReply", &f)
671 })
672 }
673}
674
675/// Wrapper around Props that keeps a map of fetched properties.
676pub struct PropHandler<'a> {
677 p: Props<'a>,
678 map: BTreeMap<String, MessageItem>,
679}
680
681impl<'a> PropHandler<'a> {
682 /// Create a new PropHandler from a Props.
683 pub fn new(p: Props) -> PropHandler {
684 PropHandler { p: p, map: BTreeMap::new() }
685 }
686
687 /// Get a map of all the properties' names and their values.
688 pub fn get_all(&mut self) -> Result<(), Error> {
689 self.map = self.p.get_all()?;
690 Ok(())
691 }
692
693 /// Get a mutable reference to the PropHandler's fetched properties.
694 pub fn map_mut(&mut self) -> &mut BTreeMap<String, MessageItem> { &mut self.map }
695
696 /// Get a reference to the PropHandler's fetched properties.
697 pub fn map(&self) -> &BTreeMap<String, MessageItem> { &self.map }
698
699 /// Get a single property's value.
700 pub fn get(&mut self, propname: &str) -> Result<&MessageItem, Error> {
701 let v = self.p.get(propname)?;
702 self.map.insert(propname.to_string(), v);
703 Ok(self.map.get(propname).unwrap())
704 }
705
706 /// Set a single property's value.
707 pub fn set(&mut self, propname: &str, value: MessageItem) -> Result<(), Error> {
708 self.p.set(propname, value.clone())?;
709 self.map.insert(propname.to_string(), value);
710 Ok(())
711 }
712}
713
714
715#[cfg(test)]
716mod test {
717 extern crate tempfile;
718
719 use crate::{Message, MessageType, Path, Signature};
720 use crate::arg::messageitem::MessageItem;
721 use crate::ffidisp::{Connection, BusType};
722
723 #[test]
724 fn unix_fd() {
725 use std::io::prelude::*;
726 use std::io::SeekFrom;
727 use std::fs::OpenOptions;
728
729 let c = Connection::get_private(BusType::Session).unwrap();
730 c.register_object_path("/hello").unwrap();
731 let mut m = Message::new_method_call(&c.unique_name(), "/hello", "com.example.hello", "Hello").unwrap();
732 let tempdir = tempfile::Builder::new().prefix("dbus-rs-test").tempdir().unwrap();
733 let mut filename = tempdir.path().to_path_buf();
734 filename.push("test");
735 println!("Creating file {:?}", filename);
736 let mut file = OpenOptions::new().create(true).read(true).write(true).open(&filename).unwrap();
737 file.write_all(b"z").unwrap();
738 file.seek(SeekFrom::Start(0)).unwrap();
739 #[cfg(unix)]
740 {
741 m.append_items(&[file.into()]);
742 }
743 println!("Sending {:?}", m.get_items());
744 c.send(m).unwrap();
745
746 loop { for n in c.incoming(1000) {
747 if n.msg_type() == MessageType::MethodCall {
748 #[cfg(unix)]
749 {
750 use std::os::unix::io::AsRawFd;
751 let z: crate::arg::OwnedFd = n.read1().unwrap();
752 println!("Got {:?}", z);
753 let mut q: libc::c_char = 100;
754 assert_eq!(1, unsafe { libc::read(z.as_raw_fd(), &mut q as *mut _ as *mut libc::c_void, 1) });
755 assert_eq!(q, 'z' as libc::c_char);
756 }
757 return;
758 } else {
759 println!("Got {:?}", n);
760 }
761 }}
762 }
763
764 #[test]
765 fn message_types() {
766 let c = Connection::get_private(BusType::Session).unwrap();
767 c.register_object_path("/hello").unwrap();
768 let mut m = Message::new_method_call(&c.unique_name(), "/hello", "com.example.hello", "Hello").unwrap();
769 m.append_items(&[
770 2000u16.into(),
771 MessageItem::new_array(vec!(129u8.into())).unwrap(),
772 ["Hello", "world"][..].into(),
773 987654321u64.into(),
774 (-1i32).into(),
775 format!("Hello world").into(),
776 (-3.14f64).into(),
777 MessageItem::Struct(vec!(256i16.into())),
778 Path::new("/some/path").unwrap().into(),
779 MessageItem::new_dict(vec!((123543u32.into(), true.into()).into())).unwrap()
780 ]);
781 let sending = format!("{:?}", m.get_items());
782 println!("Sending {}", sending);
783 c.send(m).unwrap();
784
785 loop { for n in c.incoming(1000) {
786 if n.msg_type() == MessageType::MethodCall {
787 let receiving = format!("{:?}", n.get_items());
788 println!("Receiving {}", receiving);
789 assert_eq!(sending, receiving);
790 return;
791 } else {
792 println!("Got {:?}", n);
793 }
794 }}
795 }
796
797 #[test]
798 fn dict_of_dicts() {
799 use std::collections::BTreeMap;
800
801 let officeactions: BTreeMap<&'static str, MessageItem> = BTreeMap::new();
802 let mut officethings = BTreeMap::new();
803 officethings.insert("pencil", 2u16.into());
804 officethings.insert("paper", 5u16.into());
805 let mut homethings = BTreeMap::new();
806 homethings.insert("apple", 11u16.into());
807 let mut homeifaces = BTreeMap::new();
808 homeifaces.insert("getThings", homethings);
809 let mut officeifaces = BTreeMap::new();
810 officeifaces.insert("getThings", officethings);
811 officeifaces.insert("getActions", officeactions);
812 let mut paths = BTreeMap::new();
813 paths.insert("/hello/office", officeifaces);
814 paths.insert("/hello/home", homeifaces);
815
816 println!("Original treemap: {:?}", paths);
817 let m = MessageItem::new_dict(paths.iter().map(
818 |(path, ifaces)| (MessageItem::ObjectPath(Path::new(*path).unwrap()),
819 MessageItem::new_dict(ifaces.iter().map(
820 |(iface, props)| (iface.to_string().into(),
821 MessageItem::from_dict::<(),_>(props.iter().map(
822 |(name, value)| Ok((name.to_string(), value.clone()))
823 )).unwrap()
824 ).into()
825 ).collect()).unwrap()
826 ).into()
827 ).collect()).unwrap();
828 println!("As MessageItem: {:?}", m);
829 assert_eq!(&*m.signature(), "a{oa{sa{sv}}}");
830
831 let c = Connection::get_private(BusType::Session).unwrap();
832 c.register_object_path("/hello").unwrap();
833 let mut msg = Message::new_method_call(&c.unique_name(), "/hello", "org.freedesktop.DBusObjectManager", "GetManagedObjects").unwrap();
834 msg.append_items(&[m]);
835 let sending = format!("{:?}", msg.get_items());
836 println!("Sending {}", sending);
837 c.send(msg).unwrap();
838
839 loop { for n in c.incoming(1000) {
840 if n.msg_type() == MessageType::MethodCall {
841 let receiving = format!("{:?}", n.get_items());
842 println!("Receiving {}", receiving);
843 assert_eq!(sending, receiving);
844 return;
845 } else {
846 println!("Got {:?}", n);
847 }
848 } }
849 }
850
851 #[test]
852 fn issue24() {
853 let c = Connection::get_private(BusType::Session).unwrap();
854 let mut m = Message::new_method_call("org.test.rust", "/", "org.test.rust", "Test").unwrap();
855
856 let a = MessageItem::from("test".to_string());
857 let b = MessageItem::from("test".to_string());
858 let foo = MessageItem::Struct(vec!(a, b));
859 let bar = foo.clone();
860
861 let args = [MessageItem::new_array(vec!(foo, bar)).unwrap()];
862 println!("{:?}", args);
863
864 m.append_items(&args);
865 c.send(m).unwrap();
866 }
867
868 /* Unfortunately org.freedesktop.DBus has no properties we can use for testing, but hostname1 should be around on most distros. */
869 #[cfg(unix)]
870 #[test]
871 fn test_get_hostname1_prop() {
872 use super::Props;
873
874 let c = Connection::new_system().unwrap();
875 let p = Props::new(&c, "org.freedesktop.hostname1", "/org/freedesktop/hostname1",
876 "org.freedesktop.hostname1", 10000);
877
878 /* Let's use both the get and getall methods and see if we get the same result */
879 let v = p.get("StaticHostname").unwrap();
880 let vall = p.get_all().unwrap();
881 let v2 = vall.get("StaticHostname").unwrap();
882
883 assert_eq!(&v, &*v2);
884 match v {
885 MessageItem::Str(ref s) => { println!("StaticHostname is {}", s); }
886 _ => { panic!("Invalid Get: {:?}", v); }
887 };
888 }
889
890 #[test]
891 fn message_listnames() {
892 let c = Connection::get_private(BusType::Session).unwrap();
893 let m = Message::method_call(&"org.freedesktop.DBus".into(), &"/".into(),
894 &"org.freedesktop.DBus".into(), &"ListNames".into());
895 let r = c.send_with_reply_and_block(m, 2000).unwrap();
896 let reply = r.get_items();
897 println!("{:?}", reply);
898 }
899
900 #[test]
901 fn message_namehasowner() {
902 let c = Connection::get_private(BusType::Session).unwrap();
903 let mut m = Message::new_method_call("org.freedesktop.DBus", "/", "org.freedesktop.DBus", "NameHasOwner").unwrap();
904 m.append_items(&[MessageItem::Str("org.freedesktop.DBus".to_string())]);
905 let r = c.send_with_reply_and_block(m, 2000).unwrap();
906 let reply = r.get_items();
907 println!("{:?}", reply);
908 assert_eq!(reply, vec!(MessageItem::Bool(true)));
909 }
910
911 #[test]
912 fn message_inner_str() {
913 let ob = MessageItem::ObjectPath("/path".into());
914 assert_eq!("/path", ob.inner::<&str>().unwrap());
915
916 let ob = MessageItem::ObjectPath("/path".into());
917 assert_ne!("/path/another", ob.inner::<&str>().unwrap());
918
919 let ob = MessageItem::Str("String".into());
920 assert_eq!("String", ob.inner::<&str>().unwrap());
921
922 let ob = MessageItem::Str("String".into());
923 assert_ne!("StringDiff", ob.inner::<&str>().unwrap());
924
925 let ob = MessageItem::Signature(Signature::make::<i32>());
926 assert_eq!("i", ob.inner::<&str>().unwrap());
927
928 let ob = MessageItem::Signature(Signature::make::<u32>());
929 assert_ne!("i", ob.inner::<&str>().unwrap());
930
931 }
932
933 #[test]
934 fn message_peel() {
935 let flat_str = MessageItem::Str("foobar".into());
936 assert_eq!(flat_str.peel(), &flat_str);
937
938 let flat_path = MessageItem::ObjectPath("/path".into());
939 assert_eq!(flat_path.peel(), &flat_path);
940
941 let flat_sig = MessageItem::Signature(Signature::make::<i32>());
942 assert_eq!(flat_sig.peel(), &flat_sig);
943
944 let flat_int = MessageItem::Int32(1234);
945 assert_eq!(flat_int.peel(), &flat_int);
946
947 let layered_str = MessageItem::Variant(Box::new(flat_str));
948 assert_eq!(layered_str.peel(), &MessageItem::Str("foobar".into()));
949
950 let layered_path = MessageItem::Variant(Box::new(flat_path));
951 assert_eq!(layered_path.peel(), &MessageItem::ObjectPath("/path".into()));
952
953 let layered_sig = MessageItem::Variant(Box::new(flat_sig));
954 assert_eq!(layered_sig.peel(), &MessageItem::Signature(Signature::make::<i32>()));
955
956 let layered_int = MessageItem::Variant(Box::new(flat_int));
957 assert_eq!(layered_int.peel(), &MessageItem::Int32(1234));
958
959 let very_deep =
960 MessageItem::Variant(Box::new(
961 MessageItem::Variant(Box::new(
962 MessageItem::Variant(Box::new(
963 MessageItem::Variant(Box::new(
964 MessageItem::Variant(Box::new(
965 MessageItem::Variant(Box::new(
966 MessageItem::Variant(Box::new(
967 MessageItem::Variant(Box::new(
968 MessageItem::Variant(Box::new(
969 MessageItem::Variant(Box::new(
970 MessageItem::Int32(1234)
971 ))))))))))))))))))));
972
973 assert_eq!(very_deep.peel(), &MessageItem::Int32(1234));
974
975 }
976
977 #[test]
978 fn inner_from_variant() {
979 let msg_u8 = MessageItem::Variant(Box::new(3u8.into()));
980 assert_eq!(msg_u8.inner::<u8>().unwrap(), 3u8);
981
982 let msg_u16 = MessageItem::Variant(Box::new(4u16.into()));
983 assert_eq!(msg_u16.inner::<u16>().unwrap(), 4u16);
984
985 let msg_u32 = MessageItem::Variant(Box::new(5u32.into()));
986 assert_eq!(msg_u32.inner::<u32>().unwrap(), 5u32);
987
988 let msg_u64 = MessageItem::Variant(Box::new(6u64.into()));
989 assert_eq!(msg_u64.inner::<u64>().unwrap(), 6u64);
990
991 let msg_i16 = MessageItem::Variant(Box::new(4i16.into()));
992 assert_eq!(msg_i16.inner::<i16>().unwrap(), 4i16);
993
994 let msg_i32 = MessageItem::Variant(Box::new(5i32.into()));
995 assert_eq!(msg_i32.inner::<i32>().unwrap(), 5i32);
996
997 let msg_i64 = MessageItem::Variant(Box::new(6i64.into()));
998 assert_eq!(msg_i64.inner::<i64>().unwrap(), 6i64);
999
1000 let msg_f64 = MessageItem::Variant(Box::new(6.5f64.into()));
1001 assert_eq!(msg_f64.inner::<f64>().unwrap(), 6.5f64);
1002
1003 let msg_bool = MessageItem::Variant(Box::new(false.into()));
1004 assert_eq!(msg_bool.inner::<bool>().unwrap(), false);
1005
1006 let msg_string = MessageItem::Variant(Box::new("asdf".to_string().into()));
1007 assert_eq!(msg_string.inner::<&String>().unwrap(), "asdf");
1008
1009 let path: Path = "/path".into();
1010 let msg_path = MessageItem::Variant(Box::new(MessageItem::ObjectPath(path.clone())));
1011 assert_eq!(msg_path.inner::<&Path>().unwrap(), &path);
1012
1013 let sig: Signature = "a{si}".into();
1014 let msg_sig = MessageItem::Variant(Box::new(MessageItem::Signature(sig.clone())));
1015 assert_eq!(msg_sig.inner::<&Signature>().unwrap(), &sig);
1016
1017 assert_eq!(msg_string.inner::<&str>().unwrap(), "asdf");
1018 assert_eq!(msg_path.inner::<&str>().unwrap(), "/path");
1019 assert_eq!(msg_sig.inner::<&str>().unwrap(), "a{si}");
1020
1021 }
1022
1023}
1024