summaryrefslogtreecommitdiffstats
path: root/third_party/rust/dbus/src/arg
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/dbus/src/arg')
-rw-r--r--third_party/rust/dbus/src/arg/array_impl.rs483
-rw-r--r--third_party/rust/dbus/src/arg/basic_impl.rs308
-rw-r--r--third_party/rust/dbus/src/arg/mod.rs440
-rw-r--r--third_party/rust/dbus/src/arg/msgarg.rs426
-rw-r--r--third_party/rust/dbus/src/arg/variantstruct_impl.rs242
5 files changed, 1899 insertions, 0 deletions
diff --git a/third_party/rust/dbus/src/arg/array_impl.rs b/third_party/rust/dbus/src/arg/array_impl.rs
new file mode 100644
index 0000000000..8bccf347a4
--- /dev/null
+++ b/third_party/rust/dbus/src/arg/array_impl.rs
@@ -0,0 +1,483 @@
+use super::*;
+use {Signature, Path, Message, ffi, OwnedFd};
+use std::marker::PhantomData;
+use std::{ptr, mem, any, fmt};
+use super::check;
+use std::ffi::{CString};
+use std::os::raw::{c_void, c_int};
+use std::collections::HashMap;
+use std::hash::Hash;
+
+// Map DBus-Type -> Alignment. Copied from _dbus_marshal_write_fixed_multi in
+// http://dbus.freedesktop.org/doc/api/html/dbus-marshal-basic_8c_source.html#l01020
+// Note that Rust booleans are one byte, dbus booleans are four bytes!
+const FIXED_ARRAY_ALIGNMENTS: [(ArgType, usize); 9] = [
+ (ArgType::Byte, 1),
+ (ArgType::Int16, 2),
+ (ArgType::UInt16, 2),
+ (ArgType::UInt32, 4),
+ (ArgType::Int32, 4),
+ (ArgType::Boolean, 4),
+ (ArgType::Int64, 8),
+ (ArgType::UInt64, 8),
+ (ArgType::Double, 8)
+];
+
+/// Represents a D-Bus array.
+impl<'a, T: Arg> Arg for &'a [T] {
+ const ARG_TYPE: ArgType = ArgType::Array;
+ fn signature() -> Signature<'static> { Signature::from(format!("a{}", T::signature())) }
+}
+
+fn array_append<T: Arg, F: FnMut(&T, &mut IterAppend)>(z: &[T], i: &mut IterAppend, mut f: F) {
+ let zptr = z.as_ptr();
+ let zlen = z.len() as i32;
+
+ // Can we do append_fixed_array?
+ let a = (T::ARG_TYPE, mem::size_of::<T>());
+ let can_fixed_array = (zlen > 1) && (z.len() == zlen as usize) && FIXED_ARRAY_ALIGNMENTS.iter().any(|&v| v == a);
+
+ i.append_container(ArgType::Array, Some(T::signature().as_cstr()), |s|
+ if can_fixed_array { unsafe { check("dbus_message_iter_append_fixed_array",
+ ffi::dbus_message_iter_append_fixed_array(&mut s.0, a.0 as c_int, &zptr as *const _ as *const c_void, zlen)) }}
+ else { for arg in z { f(arg, s); }}
+ );
+}
+
+/// Appends a D-Bus array. Note: In case you have a large array of a type that implements FixedArray,
+/// using this method will be more efficient than using an Array.
+impl<'a, T: Arg + Append + Clone> Append for &'a [T] {
+ fn append(self, i: &mut IterAppend) {
+ array_append(self, i, |arg, s| arg.clone().append(s));
+ }
+}
+
+impl<'a, T: Arg + RefArg> RefArg for &'a [T] {
+ fn arg_type(&self) -> ArgType { ArgType::Array }
+ fn signature(&self) -> Signature<'static> { Signature::from(format!("a{}", <T as Arg>::signature())) }
+ fn append(&self, i: &mut IterAppend) {
+ array_append(self, i, |arg, s| (arg as &RefArg).append(s));
+ }
+ #[inline]
+ fn as_any(&self) -> &any::Any where Self: 'static { self }
+ #[inline]
+ fn as_any_mut(&mut self) -> &mut any::Any where Self: 'static { self }
+
+ fn box_clone(&self) -> Box<RefArg + 'static> {
+ Box::new(InternalArray {
+ inner_sig: <T as Arg>::signature(),
+ data: self.iter().map(|x| x.box_clone()).collect(),
+ })
+ }
+}
+
+impl<T: Arg + RefArg> RefArg for Vec<T> {
+ fn arg_type(&self) -> ArgType { ArgType::Array }
+ fn signature(&self) -> Signature<'static> { Signature::from(format!("a{}", <T as Arg>::signature())) }
+ fn append(&self, i: &mut IterAppend) {
+ array_append(&self, i, |arg, s| (arg as &RefArg).append(s));
+ }
+ #[inline]
+ fn as_any(&self) -> &any::Any where Self: 'static { self }
+ #[inline]
+ fn as_any_mut(&mut self) -> &mut any::Any where Self: 'static { self }
+ fn as_iter<'a>(&'a self) -> Option<Box<Iterator<Item=&'a RefArg> + 'a>> {
+ Some(Box::new(self.iter().map(|b| b as &RefArg)))
+ }
+ #[inline]
+ fn box_clone(&self) -> Box<RefArg + 'static> { (&**self).box_clone() }
+}
+
+
+impl<'a, T: FixedArray> Get<'a> for &'a [T] {
+ fn get(i: &mut Iter<'a>) -> Option<&'a [T]> {
+ debug_assert!(FIXED_ARRAY_ALIGNMENTS.iter().any(|&v| v == (T::ARG_TYPE, mem::size_of::<T>())));
+ i.recurse(Self::ARG_TYPE).and_then(|mut si| unsafe {
+ let etype = ffi::dbus_message_iter_get_element_type(&mut i.0);
+
+ if etype != T::ARG_TYPE as c_int { return None };
+
+ let mut v = ptr::null_mut();
+ let mut i = 0;
+ ffi::dbus_message_iter_get_fixed_array(&mut si.0, &mut v as *mut _ as *mut c_void, &mut i);
+ if v == ptr::null_mut() {
+ assert_eq!(i, 0);
+ Some(&[][..])
+ } else {
+ Some(::std::slice::from_raw_parts(v, i as usize))
+ }
+ })
+ }
+}
+
+
+#[derive(Copy, Clone, Debug)]
+/// Append a D-Bus dict type (i e, an array of dict entries).
+///
+/// See the argument guide and module level documentation for details and alternatives.
+pub struct Dict<'a, K: DictKey, V: Arg, I>(I, PhantomData<(&'a Message, *const K, *const V)>);
+
+impl<'a, K: DictKey, V: Arg, I> Dict<'a, K, V, I> {
+ fn entry_sig() -> String { format!("{{{}{}}}", K::signature(), V::signature()) }
+}
+
+impl<'a, K: 'a + DictKey, V: 'a + Append + Arg, I: Iterator<Item=(K, V)>> Dict<'a, K, V, I> {
+ /// Creates a new Dict from an iterator. The iterator is consumed when appended.
+ pub fn new<J: IntoIterator<IntoIter=I, Item=(K, V)>>(j: J) -> Dict<'a, K, V, I> { Dict(j.into_iter(), PhantomData) }
+}
+
+impl<'a, K: DictKey, V: Arg, I> Arg for Dict<'a, K, V, I> {
+ const ARG_TYPE: ArgType = ArgType::Array;
+ fn signature() -> Signature<'static> {
+ Signature::from(format!("a{}", Self::entry_sig())) }
+}
+
+impl<'a, K: 'a + DictKey + Append, V: 'a + Append + Arg, I: Iterator<Item=(K, V)>> Append for Dict<'a, K, V, I> {
+ fn append(self, i: &mut IterAppend) {
+ let z = self.0;
+ i.append_container(Self::ARG_TYPE, Some(&CString::new(Self::entry_sig()).unwrap()), |s| for (k, v) in z {
+ s.append_container(ArgType::DictEntry, None, |ss| {
+ k.append(ss);
+ v.append(ss);
+ })
+ });
+ }
+}
+
+
+impl<'a, K: DictKey + Get<'a>, V: Arg + Get<'a>> Get<'a> for Dict<'a, K, V, Iter<'a>> {
+ fn get(i: &mut Iter<'a>) -> Option<Self> {
+ i.recurse(Self::ARG_TYPE).map(|si| Dict(si, PhantomData))
+ // TODO: Verify full element signature?
+ }
+}
+
+impl<'a, K: DictKey + Get<'a>, V: Arg + Get<'a>> Iterator for Dict<'a, K, V, Iter<'a>> {
+ type Item = (K, V);
+ fn next(&mut self) -> Option<(K, V)> {
+ let i = self.0.recurse(ArgType::DictEntry).and_then(|mut si| {
+ let k = si.get();
+ if k.is_none() { return None };
+ assert!(si.next());
+ let v = si.get();
+ if v.is_none() { return None };
+ Some((k.unwrap(), v.unwrap()))
+ });
+ self.0.next();
+ i
+ }
+}
+
+impl<K: DictKey, V: Arg> Arg for HashMap<K, V> {
+ const ARG_TYPE: ArgType = ArgType::Array;
+ fn signature() -> Signature<'static> {
+ Signature::from(format!("a{{{}{}}}", K::signature(), V::signature())) }
+}
+
+impl<K: DictKey + Append + Eq + Hash, V: Arg + Append> Append for HashMap<K, V> {
+ fn append(self, i: &mut IterAppend) {
+ Dict::new(self.into_iter()).append(i);
+ }
+}
+
+impl<'a, K: DictKey + Get<'a> + Eq + Hash, V: Arg + Get<'a>> Get<'a> for HashMap<K, V> {
+ fn get(i: &mut Iter<'a>) -> Option<Self> {
+ // TODO: Full element signature is not verified.
+ Dict::get(i).map(|d| d.into_iter().collect())
+ }
+}
+
+impl<K: DictKey + RefArg + Eq + Hash, V: RefArg + Arg> RefArg for HashMap<K, V> {
+ fn arg_type(&self) -> ArgType { ArgType::Array }
+ fn signature(&self) -> Signature<'static> { format!("a{{{}{}}}", <K as Arg>::signature(), <V as Arg>::signature()).into() }
+ fn append(&self, i: &mut IterAppend) {
+ let sig = CString::new(format!("{{{}{}}}", <K as Arg>::signature(), <V as Arg>::signature())).unwrap();
+ i.append_container(ArgType::Array, Some(&sig), |s| for (k, v) in self {
+ s.append_container(ArgType::DictEntry, None, |ss| {
+ k.append(ss);
+ v.append(ss);
+ })
+ });
+ }
+ #[inline]
+ fn as_any(&self) -> &any::Any where Self: 'static { self }
+ #[inline]
+ fn as_any_mut(&mut self) -> &mut any::Any where Self: 'static { self }
+ fn as_iter<'b>(&'b self) -> Option<Box<Iterator<Item=&'b RefArg> + 'b>> {
+ Some(Box::new(self.iter().flat_map(|(k, v)| vec![k as &RefArg, v as &RefArg].into_iter())))
+ }
+ #[inline]
+ fn box_clone(&self) -> Box<RefArg + 'static> {
+ Box::new(InternalDict {
+ outer_sig: self.signature(),
+ data: self.iter().map(|(k, v)| (k.box_clone(), v.box_clone())).collect(),
+ })
+ }
+}
+
+impl<T: Arg> Arg for Vec<T> {
+ const ARG_TYPE: ArgType = ArgType::Array;
+ fn signature() -> Signature<'static> { Signature::from(format!("a{}", T::signature())) }
+}
+
+impl<T: Arg + Append> Append for Vec<T> {
+ fn append(self, i: &mut IterAppend) {
+ Array::new(self).append(i);
+ }
+}
+
+impl<'a, T: Arg + Get<'a>> Get<'a> for Vec<T> {
+ fn get(i: &mut Iter<'a>) -> Option<Self> {
+ <Array<T, Iter<'a>>>::get(i).map(|a| a.collect())
+ }
+}
+
+
+#[derive(Copy, Clone, Debug)]
+/// Represents a D-Bus Array. Maximum flexibility (wraps an iterator of items to append).
+///
+/// See the argument guide and module level documentation for details and alternatives.
+pub struct Array<'a, T, I>(I, PhantomData<(*const T, &'a Message)>);
+
+impl<'a, T: 'a, I: Iterator<Item=T>> Array<'a, T, I> {
+ /// Creates a new Array from an iterator. The iterator is consumed when appending.
+ pub fn new<J: IntoIterator<IntoIter=I, Item=T>>(j: J) -> Array<'a, T, I> { Array(j.into_iter(), PhantomData) }
+}
+
+impl<'a, T: Arg, I> Arg for Array<'a, T, I> {
+ const ARG_TYPE: ArgType = ArgType::Array;
+ fn signature() -> Signature<'static> { Signature::from(format!("a{}", T::signature())) }
+}
+
+impl<'a, T: 'a + Arg + Append, I: Iterator<Item=T>> Append for Array<'a, T, I> {
+ fn append(self, i: &mut IterAppend) {
+ let z = self.0;
+ i.append_container(ArgType::Array, Some(T::signature().as_cstr()), |s| for arg in z { arg.append(s) });
+ }
+}
+
+impl<'a, T: Arg + Get<'a>> Get<'a> for Array<'a, T, Iter<'a>> {
+ fn get(i: &mut Iter<'a>) -> Option<Array<'a, T, Iter<'a>>> {
+ i.recurse(Self::ARG_TYPE).map(|si| Array(si, PhantomData))
+ // TODO: Verify full element signature?
+ }
+}
+
+impl<'a, T: Get<'a>> Iterator for Array<'a, T, Iter<'a>> {
+ type Item = T;
+ fn next(&mut self) -> Option<T> {
+ let i = self.0.get();
+ self.0.next();
+ i
+ }
+}
+
+// Due to the strong typing here; RefArg is implemented only for T's that are both Arg and RefArg.
+// We need Arg for this to work for empty arrays (we can't get signature from first element if there is no elements).
+// We need RefArg for non-consuming append.
+impl<'a, T: 'a + Arg + fmt::Debug + RefArg, I: fmt::Debug + Clone + Iterator<Item=&'a T>> RefArg for Array<'static, T, I> {
+ fn arg_type(&self) -> ArgType { ArgType::Array }
+ fn signature(&self) -> Signature<'static> { Signature::from(format!("a{}", <T as Arg>::signature())) }
+ fn append(&self, i: &mut IterAppend) {
+ let z = self.0.clone();
+ i.append_container(ArgType::Array, Some(<T as Arg>::signature().as_cstr()), |s|
+ for arg in z { (arg as &RefArg).append(s) }
+ );
+ }
+ #[inline]
+ fn as_any(&self) -> &any::Any where Self: 'static { self }
+ #[inline]
+ fn as_any_mut(&mut self) -> &mut any::Any where Self: 'static { self }
+
+ fn box_clone(&self) -> Box<RefArg + 'static> {
+ Box::new(InternalArray {
+ inner_sig: <T as Arg>::signature(),
+ data: self.0.clone().map(|x| x.box_clone()).collect(),
+ })
+ }
+}
+
+fn get_fixed_array_refarg<'a, T: FixedArray + Clone + RefArg>(i: &mut Iter<'a>) -> Box<RefArg> {
+ let s = <&[T]>::get(i).unwrap();
+ Box::new(s.to_vec())
+}
+
+fn get_var_array_refarg<'a, T: 'static + RefArg + Arg, F: FnMut(&mut Iter<'a>) -> Option<T>>
+ (i: &mut Iter<'a>, mut f: F) -> Box<RefArg> {
+ let mut v: Vec<T> = vec!(); // dbus_message_iter_get_element_count might be O(n), better not use it
+ let mut si = i.recurse(ArgType::Array).unwrap();
+ while let Some(q) = f(&mut si) { v.push(q); si.next(); }
+ Box::new(v)
+}
+
+
+#[derive(Debug)]
+struct InternalDict<K> {
+ data: Vec<(K, Box<RefArg>)>,
+ outer_sig: Signature<'static>,
+}
+
+fn get_dict_refarg<'a, K, F: FnMut(&mut Iter<'a>) -> Option<K>>(i: &mut Iter<'a>, mut f: F) -> Box<RefArg>
+ where K: DictKey + 'static + RefArg + Clone
+ {
+ let mut data = vec!();
+ let outer_sig = i.signature();
+ let mut si = i.recurse(ArgType::Array).unwrap();
+ while let Some(mut d) = si.recurse(ArgType::DictEntry) {
+ let k = f(&mut d).unwrap();
+ d.next();
+ data.push((k, d.get_refarg().unwrap()));
+ si.next();
+ }
+ Box::new(InternalDict { data, outer_sig })
+}
+
+// This only happens from box_clone
+impl RefArg for InternalDict<Box<RefArg>> {
+ fn arg_type(&self) -> ArgType { ArgType::Array }
+ fn signature(&self) -> Signature<'static> { self.outer_sig.clone() }
+ fn append(&self, i: &mut IterAppend) {
+ let inner_sig = &self.outer_sig.as_cstr().to_bytes_with_nul()[1..];
+ let inner_sig = CStr::from_bytes_with_nul(inner_sig).unwrap();
+ i.append_container(ArgType::Array, Some(inner_sig), |s| for (k, v) in &self.data {
+ s.append_container(ArgType::DictEntry, None, |ss| {
+ k.append(ss);
+ v.append(ss);
+ })
+ });
+ }
+ #[inline]
+ fn as_any(&self) -> &any::Any where Self: 'static { self }
+ #[inline]
+ fn as_any_mut(&mut self) -> &mut any::Any where Self: 'static { self }
+ fn as_iter<'b>(&'b self) -> Option<Box<Iterator<Item=&'b RefArg> + 'b>> {
+ Some(Box::new(self.data.iter().flat_map(|(k, v)| vec![k as &RefArg, v as &RefArg].into_iter())))
+ }
+ #[inline]
+ fn box_clone(&self) -> Box<RefArg + 'static> {
+ Box::new(InternalDict {
+ data: self.data.iter().map(|(k, v)| (k.box_clone(), v.box_clone())).collect(),
+ outer_sig: self.outer_sig.clone(),
+ })
+ }
+}
+
+
+impl<K: DictKey + RefArg + Clone + 'static> RefArg for InternalDict<K> {
+ fn arg_type(&self) -> ArgType { ArgType::Array }
+ fn signature(&self) -> Signature<'static> { self.outer_sig.clone() }
+ fn append(&self, i: &mut IterAppend) {
+ let inner_sig = &self.outer_sig.as_cstr().to_bytes_with_nul()[1..];
+ let inner_sig = CStr::from_bytes_with_nul(inner_sig).unwrap();
+ i.append_container(ArgType::Array, Some(inner_sig), |s| for (k, v) in &self.data {
+ s.append_container(ArgType::DictEntry, None, |ss| {
+ k.append(ss);
+ v.append(ss);
+ })
+ });
+ }
+ #[inline]
+ fn as_any(&self) -> &any::Any where Self: 'static { self }
+ #[inline]
+ fn as_any_mut(&mut self) -> &mut any::Any where Self: 'static { self }
+ fn as_iter<'b>(&'b self) -> Option<Box<Iterator<Item=&'b RefArg> + 'b>> {
+ Some(Box::new(self.data.iter().flat_map(|(k, v)| vec![k as &RefArg, v as &RefArg].into_iter())))
+ }
+ #[inline]
+ fn box_clone(&self) -> Box<RefArg + 'static> {
+ Box::new(InternalDict {
+ data: self.data.iter().map(|(k, v)| (k.clone(), v.box_clone())).collect(),
+ outer_sig: self.outer_sig.clone(),
+ })
+ }
+}
+
+
+// Fallback for Arrays of Arrays and Arrays of Structs.
+// We store the signature manually here and promise that it is correct for all elements
+// has that signature.
+#[derive(Debug)]
+struct InternalArray {
+ data: Vec<Box<RefArg>>,
+ inner_sig: Signature<'static>,
+}
+
+fn get_internal_array<'a>(i: &mut Iter<'a>) -> Box<RefArg> {
+ let mut si = i.recurse(ArgType::Array).unwrap();
+ let inner_sig = si.signature();
+ let data = si.collect::<Vec<_>>();
+ Box::new(InternalArray { data, inner_sig })
+}
+
+impl RefArg for InternalArray {
+ fn arg_type(&self) -> ArgType { ArgType::Array }
+ fn signature(&self) -> Signature<'static> { Signature::from(format!("a{}", self.inner_sig)) }
+ fn append(&self, i: &mut IterAppend) {
+ i.append_container(ArgType::Array, Some(self.inner_sig.as_cstr()), |s|
+ for arg in &self.data { (arg as &RefArg).append(s) }
+ );
+ }
+ #[inline]
+ fn as_any(&self) -> &any::Any where Self: 'static { self }
+ #[inline]
+ fn as_any_mut(&mut self) -> &mut any::Any where Self: 'static { self }
+ fn as_iter<'a>(&'a self) -> Option<Box<Iterator<Item=&'a RefArg> + 'a>> {
+ Some(Box::new(self.data.iter().map(|b| b as &RefArg)))
+ }
+ #[inline]
+ fn box_clone(&self) -> Box<RefArg + 'static> {
+ Box::new(InternalArray {
+ data: self.data.iter().map(|x| x.box_clone()).collect(),
+ inner_sig: self.inner_sig.clone(),
+ })
+ }
+}
+
+pub fn get_array_refarg<'a>(i: &mut Iter<'a>) -> Box<RefArg> {
+ debug_assert!(i.arg_type() == ArgType::Array);
+ let etype = ArgType::from_i32(unsafe { ffi::dbus_message_iter_get_element_type(&mut i.0) } as i32).unwrap();
+
+ let x = match etype {
+ ArgType::Byte => get_fixed_array_refarg::<u8>(i),
+ ArgType::Int16 => get_fixed_array_refarg::<i16>(i),
+ ArgType::UInt16 => get_fixed_array_refarg::<u16>(i),
+ ArgType::Int32 => get_fixed_array_refarg::<i32>(i),
+ ArgType::UInt32 => get_fixed_array_refarg::<u32>(i),
+ ArgType::Int64 => get_fixed_array_refarg::<i64>(i),
+ ArgType::UInt64 => get_fixed_array_refarg::<u64>(i),
+ ArgType::Double => get_fixed_array_refarg::<f64>(i),
+ ArgType::String => get_var_array_refarg::<String, _>(i, |si| si.get()),
+ ArgType::ObjectPath => get_var_array_refarg::<Path<'static>, _>(i, |si| si.get::<Path>().map(|s| s.into_static())),
+ ArgType::Signature => get_var_array_refarg::<Signature<'static>, _>(i, |si| si.get::<Signature>().map(|s| s.into_static())),
+ ArgType::Variant => get_var_array_refarg::<Variant<Box<RefArg>>, _>(i, |si| Variant::new_refarg(si)),
+ ArgType::Boolean => get_var_array_refarg::<bool, _>(i, |si| si.get()),
+ ArgType::Invalid => panic!("Array with Invalid ArgType"),
+ ArgType::Array => get_internal_array(i),
+ ArgType::DictEntry => {
+ let key = ArgType::from_i32(i.signature().as_bytes()[2] as i32).unwrap(); // The third character, after "a{", is our key.
+ match key {
+ ArgType::Byte => get_dict_refarg::<u8, _>(i, |si| si.get()),
+ ArgType::Int16 => get_dict_refarg::<i16, _>(i, |si| si.get()),
+ ArgType::UInt16 => get_dict_refarg::<u16, _>(i, |si| si.get()),
+ ArgType::Int32 => get_dict_refarg::<i32, _>(i, |si| si.get()),
+ ArgType::UInt32 => get_dict_refarg::<u32, _>(i, |si| si.get()),
+ ArgType::Int64 => get_dict_refarg::<i64, _>(i, |si| si.get()),
+ ArgType::UInt64 => get_dict_refarg::<u64, _>(i, |si| si.get()),
+ ArgType::Double => get_dict_refarg::<f64, _>(i, |si| si.get()),
+ ArgType::Boolean => get_dict_refarg::<bool, _>(i, |si| si.get()),
+ // ArgType::UnixFd => get_dict_refarg::<OwnedFd, _>(i, |si| si.get()),
+ ArgType::String => get_dict_refarg::<String, _>(i, |si| si.get()),
+ ArgType::ObjectPath => get_dict_refarg::<Path<'static>, _>(i, |si| si.get::<Path>().map(|s| s.into_static())),
+ ArgType::Signature => get_dict_refarg::<Signature<'static>, _>(i, |si| si.get::<Signature>().map(|s| s.into_static())),
+ _ => panic!("Array with invalid dictkey ({:?})", key),
+ }
+ }
+ ArgType::UnixFd => get_var_array_refarg::<OwnedFd, _>(i, |si| si.get()),
+ ArgType::Struct => get_internal_array(i),
+ };
+
+ debug_assert_eq!(i.signature(), x.signature());
+ x
+}
+
+
diff --git a/third_party/rust/dbus/src/arg/basic_impl.rs b/third_party/rust/dbus/src/arg/basic_impl.rs
new file mode 100644
index 0000000000..66d2a0ee74
--- /dev/null
+++ b/third_party/rust/dbus/src/arg/basic_impl.rs
@@ -0,0 +1,308 @@
+use ffi;
+use super::*;
+use super::check;
+use {Signature, Path, OwnedFd};
+use std::{ptr, any, mem};
+use std::ffi::CStr;
+use std::os::raw::{c_void, c_char, c_int};
+
+
+fn arg_append_basic<T>(i: *mut ffi::DBusMessageIter, arg_type: ArgType, v: T) {
+ let p = &v as *const _ as *const c_void;
+ unsafe {
+ check("dbus_message_iter_append_basic", ffi::dbus_message_iter_append_basic(i, arg_type as c_int, p));
+ };
+}
+
+fn arg_get_basic<T>(i: *mut ffi::DBusMessageIter, arg_type: ArgType) -> Option<T> {
+ unsafe {
+ let mut c: T = mem::zeroed();
+ if ffi::dbus_message_iter_get_arg_type(i) != arg_type as c_int { return None };
+ ffi::dbus_message_iter_get_basic(i, &mut c as *mut _ as *mut c_void);
+ Some(c)
+ }
+}
+
+fn arg_append_f64(i: *mut ffi::DBusMessageIter, arg_type: ArgType, v: f64) {
+ let p = &v as *const _ as *const c_void;
+ unsafe {
+ check("dbus_message_iter_append_basic", ffi::dbus_message_iter_append_basic(i, arg_type as c_int, p));
+ };
+}
+
+fn arg_get_f64(i: *mut ffi::DBusMessageIter, arg_type: ArgType) -> Option<f64> {
+ let mut c = 0f64;
+ unsafe {
+ if ffi::dbus_message_iter_get_arg_type(i) != arg_type as c_int { return None };
+ ffi::dbus_message_iter_get_basic(i, &mut c as *mut _ as *mut c_void);
+ }
+ Some(c)
+}
+
+fn arg_append_str(i: *mut ffi::DBusMessageIter, arg_type: ArgType, v: &CStr) {
+ let p = v.as_ptr();
+ let q = &p as *const _ as *const c_void;
+ unsafe {
+ check("dbus_message_iter_append_basic", ffi::dbus_message_iter_append_basic(i, arg_type as c_int, q));
+ };
+}
+
+unsafe fn arg_get_str<'a>(i: *mut ffi::DBusMessageIter, arg_type: ArgType) -> Option<&'a CStr> {
+ if ffi::dbus_message_iter_get_arg_type(i) != arg_type as c_int { return None };
+ let mut p = ptr::null_mut();
+ ffi::dbus_message_iter_get_basic(i, &mut p as *mut _ as *mut c_void);
+ Some(CStr::from_ptr(p as *const c_char))
+}
+
+
+
+
+// Implementation for basic types.
+
+macro_rules! integer_impl {
+ ($t: ident, $s: ident, $f: expr, $i: ident, $ii: expr, $u: ident, $uu: expr, $fff: ident, $ff: expr) => {
+
+impl Arg for $t {
+ const ARG_TYPE: ArgType = ArgType::$s;
+ #[inline]
+ fn signature() -> Signature<'static> { unsafe { Signature::from_slice_unchecked($f) } }
+}
+
+impl Append for $t {
+ fn append(self, i: &mut IterAppend) { arg_append_basic(&mut i.0, ArgType::$s, self) }
+}
+
+impl<'a> Get<'a> for $t {
+ fn get(i: &mut Iter) -> Option<Self> { arg_get_basic(&mut i.0, ArgType::$s) }
+}
+
+impl RefArg for $t {
+ #[inline]
+ fn arg_type(&self) -> ArgType { ArgType::$s }
+ #[inline]
+ fn signature(&self) -> Signature<'static> { unsafe { Signature::from_slice_unchecked($f) } }
+ #[inline]
+ fn append(&self, i: &mut IterAppend) { arg_append_basic(&mut i.0, ArgType::$s, *self) }
+ #[inline]
+ fn as_any(&self) -> &any::Any { self }
+ #[inline]
+ fn as_any_mut(&mut self) -> &mut any::Any { self }
+ #[inline]
+ fn as_i64(&self) -> Option<i64> { let $i = *self; $ii }
+ #[inline]
+ fn as_u64(&self) -> Option<u64> { let $u = *self; $uu }
+ #[inline]
+ fn as_f64(&self) -> Option<f64> { let $fff = *self; $ff }
+ #[inline]
+ fn box_clone(&self) -> Box<RefArg + 'static> { Box::new(self.clone()) }
+}
+
+impl DictKey for $t {}
+unsafe impl FixedArray for $t {}
+
+}} // End of macro_rules
+
+integer_impl!(u8, Byte, b"y\0", i, Some(i as i64), u, Some(u as u64), f, Some(f as f64));
+integer_impl!(i16, Int16, b"n\0", i, Some(i as i64), _u, None, f, Some(f as f64));
+integer_impl!(u16, UInt16, b"q\0", i, Some(i as i64), u, Some(u as u64), f, Some(f as f64));
+integer_impl!(i32, Int32, b"i\0", i, Some(i as i64), _u, None, f, Some(f as f64));
+integer_impl!(u32, UInt32, b"u\0", i, Some(i as i64), u, Some(u as u64), f, Some(f as f64));
+integer_impl!(i64, Int64, b"x\0", i, Some(i), _u, None, _f, None);
+integer_impl!(u64, UInt64, b"t\0", _i, None, u, Some(u as u64), _f, None);
+
+
+macro_rules! refarg_impl {
+ ($t: ty, $i: ident, $ii: expr, $ss: expr, $uu: expr, $ff: expr) => {
+
+impl RefArg for $t {
+ #[inline]
+ fn arg_type(&self) -> ArgType { <$t as Arg>::ARG_TYPE }
+ #[inline]
+ fn signature(&self) -> Signature<'static> { <$t as Arg>::signature() }
+ #[inline]
+ fn append(&self, i: &mut IterAppend) { <$t as Append>::append(self.clone(), i) }
+ #[inline]
+ fn as_any(&self) -> &any::Any { self }
+ #[inline]
+ fn as_any_mut(&mut self) -> &mut any::Any { self }
+ #[inline]
+ fn as_i64(&self) -> Option<i64> { let $i = self; $ii }
+ #[inline]
+ fn as_u64(&self) -> Option<u64> { let $i = self; $uu }
+ #[inline]
+ fn as_f64(&self) -> Option<f64> { let $i = self; $ff }
+ #[inline]
+ fn as_str(&self) -> Option<&str> { let $i = self; $ss }
+ #[inline]
+ fn box_clone(&self) -> Box<RefArg + 'static> { Box::new(self.clone()) }
+}
+
+ }
+}
+
+
+impl Arg for bool {
+ const ARG_TYPE: ArgType = ArgType::Boolean;
+ fn signature() -> Signature<'static> { unsafe { Signature::from_slice_unchecked(b"b\0") } }
+}
+impl Append for bool {
+ fn append(self, i: &mut IterAppend) { arg_append_basic(&mut i.0, ArgType::Boolean, if self {1} else {0}) }
+}
+impl DictKey for bool {}
+impl<'a> Get<'a> for bool {
+ fn get(i: &mut Iter) -> Option<Self> { arg_get_basic::<u32>(&mut i.0, ArgType::Boolean).map(|q| q != 0) }
+}
+
+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 }));
+
+impl Arg for f64 {
+ const ARG_TYPE: ArgType = ArgType::Double;
+ fn signature() -> Signature<'static> { unsafe { Signature::from_slice_unchecked(b"d\0") } }
+}
+impl Append for f64 {
+ fn append(self, i: &mut IterAppend) { arg_append_f64(&mut i.0, ArgType::Double, self) }
+}
+impl DictKey for f64 {}
+impl<'a> Get<'a> for f64 {
+ fn get(i: &mut Iter) -> Option<Self> { arg_get_f64(&mut i.0, ArgType::Double) }
+}
+unsafe impl FixedArray for f64 {}
+
+refarg_impl!(f64, _i, None, None, None, Some(*_i));
+
+/// Represents a D-Bus string.
+impl<'a> Arg for &'a str {
+ const ARG_TYPE: ArgType = ArgType::String;
+ fn signature() -> Signature<'static> { unsafe { Signature::from_slice_unchecked(b"s\0") } }
+}
+
+impl<'a> Append for &'a str {
+ fn append(self, i: &mut IterAppend) {
+ use std::borrow::Cow;
+ let b: &[u8] = self.as_bytes();
+ let v: Cow<[u8]> = if b.len() > 0 && b[b.len()-1] == 0 { Cow::Borrowed(b) }
+ else {
+ let mut bb: Vec<u8> = b.into();
+ bb.push(0);
+ Cow::Owned(bb)
+ };
+ let z = unsafe { CStr::from_ptr(v.as_ptr() as *const c_char) };
+ arg_append_str(&mut i.0, ArgType::String, &z)
+ }
+}
+impl<'a> DictKey for &'a str {}
+impl<'a> Get<'a> for &'a str {
+ fn get(i: &mut Iter<'a>) -> Option<&'a str> { unsafe { arg_get_str(&mut i.0, ArgType::String) }
+ .and_then(|s| s.to_str().ok()) }
+}
+
+impl<'a> Arg for String {
+ const ARG_TYPE: ArgType = ArgType::String;
+ fn signature() -> Signature<'static> { unsafe { Signature::from_slice_unchecked(b"s\0") } }
+}
+impl<'a> Append for String {
+ fn append(mut self, i: &mut IterAppend) {
+ self.push_str("\0");
+ let s: &str = &self;
+ s.append(i)
+ }
+}
+impl<'a> DictKey for String {}
+impl<'a> Get<'a> for String {
+ fn get(i: &mut Iter<'a>) -> Option<String> { <&str>::get(i).map(|s| String::from(s)) }
+}
+
+refarg_impl!(String, _i, None, Some(&_i), None, None);
+
+/// Represents a D-Bus string.
+impl<'a> Arg for &'a CStr {
+ const ARG_TYPE: ArgType = ArgType::String;
+ fn signature() -> Signature<'static> { unsafe { Signature::from_slice_unchecked(b"s\0") } }
+}
+
+/*
+/// Note: Will give D-Bus errors in case the CStr is not valid UTF-8.
+impl<'a> Append for &'a CStr {
+ fn append(self, i: &mut IterAppend) {
+ arg_append_str(&mut i.0, Self::arg_type(), &self)
+ }
+}
+*/
+
+impl<'a> DictKey for &'a CStr {}
+impl<'a> Get<'a> for &'a CStr {
+ fn get(i: &mut Iter<'a>) -> Option<&'a CStr> { unsafe { arg_get_str(&mut i.0, Self::ARG_TYPE) }}
+}
+
+impl Arg for OwnedFd {
+ const ARG_TYPE: ArgType = ArgType::UnixFd;
+ fn signature() -> Signature<'static> { unsafe { Signature::from_slice_unchecked(b"h\0") } }
+}
+impl Append for OwnedFd {
+ fn append(self, i: &mut IterAppend) {
+ use std::os::unix::io::AsRawFd;
+ arg_append_basic(&mut i.0, ArgType::UnixFd, self.as_raw_fd())
+ }
+}
+impl DictKey for OwnedFd {}
+impl<'a> Get<'a> for OwnedFd {
+ fn get(i: &mut Iter) -> Option<Self> {
+ arg_get_basic(&mut i.0, ArgType::UnixFd).map(|q| OwnedFd::new(q))
+ }
+}
+
+refarg_impl!(OwnedFd, _i, { use std::os::unix::io::AsRawFd; Some(_i.as_raw_fd() as i64) }, None, None, None);
+
+macro_rules! string_impl {
+ ($t: ident, $s: ident, $f: expr) => {
+
+impl<'a> Arg for $t<'a> {
+ const ARG_TYPE: ArgType = ArgType::$s;
+ fn signature() -> Signature<'static> { unsafe { Signature::from_slice_unchecked($f) } }
+}
+
+impl RefArg for $t<'static> {
+ fn arg_type(&self) -> ArgType { ArgType::$s }
+ fn signature(&self) -> Signature<'static> { unsafe { Signature::from_slice_unchecked($f) } }
+ fn append(&self, i: &mut IterAppend) { arg_append_str(&mut i.0, ArgType::$s, self.as_cstr()) }
+ #[inline]
+ fn as_any(&self) -> &any::Any { self }
+ #[inline]
+ fn as_any_mut(&mut self) -> &mut any::Any { self }
+ #[inline]
+ fn as_str(&self) -> Option<&str> { Some(self) }
+ #[inline]
+ fn box_clone(&self) -> Box<RefArg + 'static> { Box::new(self.clone().into_static()) }
+}
+
+impl<'a> DictKey for $t<'a> {}
+
+impl<'a> Append for $t<'a> {
+ fn append(self, i: &mut IterAppend) {
+ arg_append_str(&mut i.0, ArgType::$s, self.as_cstr())
+ }
+}
+
+/*
+
+Unfortunately, this does not work because it conflicts with getting a $t<'static>.
+
+impl<'a> Get<'a> for $t<'a> {
+ fn get(i: &mut Iter<'a>) -> Option<$t<'a>> { unsafe { arg_get_str(&mut i.0, ArgType::$s) }
+ .map(|s| unsafe { $t::from_slice_unchecked(s.to_bytes_with_nul()) } ) }
+}
+*/
+
+impl<'a> Get<'a> for $t<'static> {
+ fn get(i: &mut Iter<'a>) -> Option<$t<'static>> { unsafe {
+ arg_get_str(&mut i.0, ArgType::$s).map(|s| $t::from_slice_unchecked(s.to_bytes_with_nul()).into_static())
+ }}
+}
+
+
+ }
+}
+
+string_impl!(Path, ObjectPath, b"o\0");
+string_impl!(Signature, Signature, b"g\0");
+
diff --git a/third_party/rust/dbus/src/arg/mod.rs b/third_party/rust/dbus/src/arg/mod.rs
new file mode 100644
index 0000000000..737960b4b8
--- /dev/null
+++ b/third_party/rust/dbus/src/arg/mod.rs
@@ -0,0 +1,440 @@
+//! Types and traits for easily getting a message's arguments, or appening a message with arguments.
+//!
+//! Also see the arguments guide (in the examples directory).
+//!
+//! A message has `read1`, `read2` etc, and `append1`, `append2` etc, which is your
+//! starting point into this module's types.
+//!
+//! **Append a**:
+//!
+//! `bool, u8, u16, u32, u64, i16, i32, i64, f64` - the corresponding D-Bus basic type
+//!
+//! `&str` - a D-Bus string. D-Bus strings do not allow null characters, so
+//! if the string contains null characters, it will be cropped
+//! to only include the data before the null character. (Tip: This allows for skipping an
+//! allocation by writing a string literal which ends with a null character.)
+//!
+//! `&[T] where T: Append` - a D-Bus array. Note: can use an efficient fast-path in case of
+//! T being an FixedArray type.
+//!
+//! `Array<T, I> where T: Append, I: Iterator<Item=T>` - a D-Bus array, maximum flexibility.
+//!
+//! `Variant<T> where T: Append` - a D-Bus variant.
+//!
+//! `(T1, T2) where T1: Append, T2: Append` - tuples are D-Bus structs. Implemented up to 12.
+//!
+//! `Dict<K, V, I> where K: Append + DictKey, V: Append, I: Iterator<Item=(&K, &V)>` - A D-Bus dict (array of dict entries).
+//!
+//! `Path` - a D-Bus object path.
+//!
+//! `Signature` - a D-Bus signature.
+//!
+//! `OwnedFd` - shares the file descriptor with the remote side.
+//!
+//! **Get / read a**:
+//!
+//! `bool, u8, u16, u32, u64, i16, i32, i64, f64` - the corresponding D-Bus basic type
+//!
+//! `&str`, `&CStr` - a D-Bus string. D-Bus strings are always UTF-8 and do not contain null characters.
+//!
+//! `&[T] where T: FixedArray` - a D-Bus array of integers or f64.
+//!
+//! `Array<T, Iter> where T: Get` - a D-Bus array, maximum flexibility. Implements Iterator so you can easily
+//! collect it into, e g, a `Vec`.
+//!
+//! `Variant<T> where T: Get` - a D-Bus variant. Use this type of Variant if you know the inner type.
+//!
+//! `Variant<Iter>` - a D-Bus variant. This type of Variant allows you to examine the inner type.
+//!
+//! `(T1, T2) where T1: Get, T2: Get` - tuples are D-Bus structs. Implemented up to 12.
+//!
+//! `Dict<K, V, Iter> where K: Get + DictKey, V: Get` - A D-Bus dict (array of dict entries). Implements Iterator so you can easily
+//! collect it into, e g, a `HashMap`.
+//!
+//! `Path` - a D-Bus object path.
+//!
+//! `Signature` - a D-Bus signature.
+//!
+//! `OwnedFd` - a file descriptor sent from the remote side.
+//!
+
+mod msgarg;
+mod basic_impl;
+mod variantstruct_impl;
+mod array_impl;
+
+pub use self::msgarg::{Arg, FixedArray, Get, DictKey, Append, RefArg, AppendAll, ReadAll, cast, cast_mut};
+pub use self::array_impl::{Array, Dict};
+pub use self::variantstruct_impl::Variant;
+
+use std::{fmt, mem, ptr, error};
+use {ffi, Message, Signature, Path, OwnedFd};
+use std::ffi::{CStr, CString};
+use std::os::raw::{c_void, c_int};
+
+
+fn check(f: &str, i: u32) { if i == 0 { panic!("D-Bus error: '{}' failed", f) }}
+
+fn ffi_iter() -> ffi::DBusMessageIter { unsafe { mem::zeroed() }}
+
+#[derive(Clone, Copy)]
+/// Helper struct for appending one or more arguments to a Message.
+pub struct IterAppend<'a>(ffi::DBusMessageIter, &'a Message);
+
+impl<'a> IterAppend<'a> {
+ /// Creates a new IterAppend struct.
+ pub fn new(m: &'a mut Message) -> IterAppend<'a> {
+ let mut i = ffi_iter();
+ unsafe { ffi::dbus_message_iter_init_append(m.ptr(), &mut i) };
+ IterAppend(i, m)
+ }
+
+ /// Appends the argument.
+ pub fn append<T: Append>(&mut self, a: T) { a.append(self) }
+
+ fn append_container<F: FnOnce(&mut IterAppend<'a>)>(&mut self, arg_type: ArgType, sig: Option<&CStr>, f: F) {
+ let mut s = IterAppend(ffi_iter(), self.1);
+ let p = sig.map(|s| s.as_ptr()).unwrap_or(ptr::null());
+ check("dbus_message_iter_open_container",
+ unsafe { ffi::dbus_message_iter_open_container(&mut self.0, arg_type as c_int, p, &mut s.0) });
+ f(&mut s);
+ check("dbus_message_iter_close_container",
+ unsafe { ffi::dbus_message_iter_close_container(&mut self.0, &mut s.0) });
+ }
+
+ /// Low-level function to append a variant.
+ ///
+ /// Use in case the `Variant` struct is not flexible enough -
+ /// the easier way is to just call e g "append1" on a message and supply a `Variant` parameter.
+ ///
+ /// In order not to get D-Bus errors: during the call to "f" you need to call "append" on
+ /// the supplied `IterAppend` exactly once,
+ /// and with a value which has the same signature as inner_sig.
+ pub fn append_variant<F: FnOnce(&mut IterAppend<'a>)>(&mut self, inner_sig: &Signature, f: F) {
+ self.append_container(ArgType::Variant, Some(inner_sig.as_cstr()), f)
+ }
+
+ /// Low-level function to append an array.
+ ///
+ /// Use in case the `Array` struct is not flexible enough -
+ /// the easier way is to just call e g "append1" on a message and supply an `Array` parameter.
+ ///
+ /// In order not to get D-Bus errors: during the call to "f", you should only call "append" on
+ /// the supplied `IterAppend` with values which has the same signature as inner_sig.
+ pub fn append_array<F: FnOnce(&mut IterAppend<'a>)>(&mut self, inner_sig: &Signature, f: F) {
+ self.append_container(ArgType::Array, Some(inner_sig.as_cstr()), f)
+ }
+
+ /// Low-level function to append a struct.
+ ///
+ /// Use in case tuples are not flexible enough -
+ /// the easier way is to just call e g "append1" on a message and supply a tuple parameter.
+ pub fn append_struct<F: FnOnce(&mut IterAppend<'a>)>(&mut self, f: F) {
+ self.append_container(ArgType::Struct, None, f)
+ }
+
+ /// Low-level function to append a dict entry.
+ ///
+ /// Use in case the `Dict` struct is not flexible enough -
+ /// the easier way is to just call e g "append1" on a message and supply a `Dict` parameter.
+ ///
+ /// In order not to get D-Bus errors: during the call to "f", you should call "append" once
+ /// for the key, then once for the value. You should only call this function for a subiterator
+ /// you got from calling "append_dict", and signatures need to match what you specified in "append_dict".
+ pub fn append_dict_entry<F: FnOnce(&mut IterAppend<'a>)>(&mut self, f: F) {
+ self.append_container(ArgType::DictEntry, None, f)
+ }
+
+ /// Low-level function to append a dict.
+ ///
+ /// Use in case the `Dict` struct is not flexible enough -
+ /// the easier way is to just call e g "append1" on a message and supply a `Dict` parameter.
+ ///
+ /// In order not to get D-Bus errors: during the call to "f", you should only call "append_dict_entry"
+ /// for the subiterator - do this as many times as the number of dict entries.
+ pub fn append_dict<F: FnOnce(&mut IterAppend<'a>)>(&mut self, key_sig: &Signature, value_sig: &Signature, f: F) {
+ let sig = format!("{{{}{}}}", key_sig, value_sig);
+ self.append_container(Array::<bool,()>::ARG_TYPE, Some(&CString::new(sig).unwrap()), f);
+ }
+}
+
+
+
+#[derive(Clone, Copy)]
+/// Helper struct for retrieve one or more arguments from a Message.
+pub struct Iter<'a>(ffi::DBusMessageIter, &'a Message, u32);
+
+impl<'a> Iter<'a> {
+ /// Creates a new struct for iterating over the arguments of a message, starting with the first argument.
+ pub fn new(m: &'a Message) -> Iter<'a> {
+ let mut i = ffi_iter();
+ unsafe { ffi::dbus_message_iter_init(m.ptr(), &mut i) };
+ Iter(i, m, 0)
+ }
+
+ /// Returns the current argument, if T is the argument type. Otherwise returns None.
+ pub fn get<T: Get<'a>>(&mut self) -> Option<T> {
+ T::get(self)
+ }
+
+ /// Returns the current argument as a trait object (experimental).
+ ///
+ /// Note: For the more complex arguments (arrays / dicts / structs, and especially
+ /// combinations thereof), their internal representations are still a bit in flux.
+ /// Instead, use as_iter() to read the values of those.
+ ///
+ /// The rest are unlikely to change - Variants are `Variant<Box<RefArg>>`, strings are `String`,
+ /// paths are `Path<'static>`, signatures are `Signature<'static>`, Int32 are `i32s` and so on.
+ pub fn get_refarg(&mut self) -> Option<Box<RefArg + 'static>> {
+ Some(match self.arg_type() {
+ ArgType::Array => array_impl::get_array_refarg(self),
+ ArgType::Variant => Box::new(Variant::new_refarg(self).unwrap()),
+ ArgType::Boolean => Box::new(self.get::<bool>().unwrap()),
+ ArgType::Invalid => return None,
+ ArgType::String => Box::new(self.get::<String>().unwrap()),
+ ArgType::DictEntry => unimplemented!(),
+ ArgType::Byte => Box::new(self.get::<u8>().unwrap()),
+ ArgType::Int16 => Box::new(self.get::<i16>().unwrap()),
+ ArgType::UInt16 => Box::new(self.get::<u16>().unwrap()),
+ ArgType::Int32 => Box::new(self.get::<i32>().unwrap()),
+ ArgType::UInt32 => Box::new(self.get::<u32>().unwrap()),
+ ArgType::Int64 => Box::new(self.get::<i64>().unwrap()),
+ ArgType::UInt64 => Box::new(self.get::<u64>().unwrap()),
+ ArgType::Double => Box::new(self.get::<f64>().unwrap()),
+ ArgType::UnixFd => Box::new(self.get::<OwnedFd>().unwrap()),
+ ArgType::Struct => Box::new(self.recurse(ArgType::Struct).unwrap().collect::<Vec<_>>()),
+ ArgType::ObjectPath => Box::new(self.get::<Path>().unwrap().into_static()),
+ ArgType::Signature => Box::new(self.get::<Signature>().unwrap().into_static()),
+ })
+ }
+
+ /// Returns the type signature for the current argument.
+ pub fn signature(&mut self) -> Signature<'static> {
+ unsafe {
+ let c = ffi::dbus_message_iter_get_signature(&mut self.0);
+ assert!(c != ptr::null_mut());
+ let cc = CStr::from_ptr(c);
+ let r = Signature::new(cc.to_bytes());
+ ffi::dbus_free(c as *mut c_void);
+ r.unwrap()
+ }
+ }
+
+ /// The raw arg_type for the current item.
+ ///
+ /// Unlike Arg::arg_type, this requires access to self and is not a static method.
+ /// You can match this against Arg::arg_type for different types to understand what type the current item is.
+ /// In case you're past the last argument, this function will return 0.
+ pub fn arg_type(&mut self) -> ArgType {
+ let s = unsafe { ffi::dbus_message_iter_get_arg_type(&mut self.0) };
+ ArgType::from_i32(s as i32).unwrap()
+ }
+
+ /// Returns false if there are no more items.
+ pub fn next(&mut self) -> bool {
+ self.2 += 1;
+ unsafe { ffi::dbus_message_iter_next(&mut self.0) != 0 }
+ }
+
+ /// Wrapper around `get` and `next`. Calls `get`, and then `next` if `get` succeeded.
+ ///
+ /// Also returns a `Result` rather than an `Option` to give an error if successful.
+ ///
+ /// # Example
+ /// ```ignore
+ /// struct ServiceBrowserItemNew {
+ /// interface: i32,
+ /// protocol: i32,
+ /// name: String,
+ /// item_type: String,
+ /// domain: String,
+ /// flags: u32,
+ /// }
+ ///
+ /// fn service_browser_item_new_msg(m: &Message) -> Result<ServiceBrowserItemNew, TypeMismatchError> {
+ /// let mut iter = m.iter_init();
+ /// Ok(ServiceBrowserItemNew {
+ /// interface: iter.read()?,
+ /// protocol: iter.read()?,
+ /// name: iter.read()?,
+ /// item_type: iter.read()?,
+ /// domain: iter.read()?,
+ /// flags: iter.read()?,
+ /// })
+ /// }
+ /// ```
+ pub fn read<T: Arg + Get<'a>>(&mut self) -> Result<T, TypeMismatchError> {
+ let r = try!(self.get().ok_or_else(||
+ TypeMismatchError { expected: T::ARG_TYPE, found: self.arg_type(), position: self.2 }));
+ self.next();
+ Ok(r)
+ }
+
+ /// If the current argument is a container of the specified arg_type, then a new
+ /// Iter is returned which is for iterating over the contents inside the container.
+ ///
+ /// Primarily for internal use (the "get" function is more ergonomic), but could be
+ /// useful for recursing into containers with unknown types.
+ pub fn recurse(&mut self, arg_type: ArgType) -> Option<Iter<'a>> {
+ let containers = [ArgType::Array, ArgType::DictEntry, ArgType::Struct, ArgType::Variant];
+ if !containers.iter().any(|&t| t == arg_type) { return None; }
+
+ let mut subiter = ffi_iter();
+ unsafe {
+ if ffi::dbus_message_iter_get_arg_type(&mut self.0) != arg_type as c_int { return None };
+ ffi::dbus_message_iter_recurse(&mut self.0, &mut subiter)
+ }
+ Some(Iter(subiter, self.1, 0))
+ }
+}
+
+impl<'a> fmt::Debug for Iter<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let mut z = self.clone();
+ let mut t = f.debug_tuple("Iter");
+ loop {
+ t.field(&z.arg_type());
+ if !z.next() { break }
+ }
+ t.finish()
+ }
+}
+
+impl<'a> Iterator for Iter<'a> {
+ type Item = Box<RefArg + 'static>;
+ fn next(&mut self) -> Option<Self::Item> {
+ let r = self.get_refarg();
+ if r.is_some() { self.next(); }
+ r
+ }
+}
+
+/// Type of Argument
+///
+/// use this to figure out, e g, which type of argument is at the current position of Iter.
+#[repr(u8)]
+#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
+pub enum ArgType {
+ /// Dicts are Arrays of dict entries, so Dict types will have Array as ArgType.
+ Array = ffi::DBUS_TYPE_ARRAY as u8,
+ /// Variant
+ Variant = ffi::DBUS_TYPE_VARIANT as u8,
+ /// bool
+ Boolean = ffi::DBUS_TYPE_BOOLEAN as u8,
+ /// Invalid arg type - this is also the ArgType returned when there are no more arguments available.
+ Invalid = ffi::DBUS_TYPE_INVALID as u8,
+ /// String
+ String = ffi::DBUS_TYPE_STRING as u8,
+ /// Dict entry; you'll usually not encounter this one as dicts are arrays of dict entries.
+ DictEntry = ffi::DBUS_TYPE_DICT_ENTRY as u8,
+ /// u8
+ Byte = ffi::DBUS_TYPE_BYTE as u8,
+ /// i16
+ Int16 = ffi::DBUS_TYPE_INT16 as u8,
+ /// u16
+ UInt16 = ffi::DBUS_TYPE_UINT16 as u8,
+ /// i32
+ Int32 = ffi::DBUS_TYPE_INT32 as u8,
+ /// u32
+ UInt32 = ffi::DBUS_TYPE_UINT32 as u8,
+ /// i64
+ Int64 = ffi::DBUS_TYPE_INT64 as u8,
+ /// u64
+ UInt64 = ffi::DBUS_TYPE_UINT64 as u8,
+ /// f64
+ Double = ffi::DBUS_TYPE_DOUBLE as u8,
+ /// OwnedFd
+ UnixFd = ffi::DBUS_TYPE_UNIX_FD as u8,
+ /// Use tuples or Vec<Box<RefArg>> to read/write structs.
+ Struct = ffi::DBUS_TYPE_STRUCT as u8,
+ /// Path
+ ObjectPath = ffi::DBUS_TYPE_OBJECT_PATH as u8,
+ /// Signature
+ Signature = ffi::DBUS_TYPE_SIGNATURE as u8,
+}
+
+const ALL_ARG_TYPES: [(ArgType, &'static str); 18] =
+ [(ArgType::Variant, "Variant"),
+ (ArgType::Array, "Array/Dict"),
+ (ArgType::Struct, "Struct"),
+ (ArgType::String, "String"),
+ (ArgType::DictEntry, "Dict entry"),
+ (ArgType::ObjectPath, "Path"),
+ (ArgType::Signature, "Signature"),
+ (ArgType::UnixFd, "OwnedFd"),
+ (ArgType::Boolean, "bool"),
+ (ArgType::Byte, "u8"),
+ (ArgType::Int16, "i16"),
+ (ArgType::Int32, "i32"),
+ (ArgType::Int64, "i64"),
+ (ArgType::UInt16, "u16"),
+ (ArgType::UInt32, "u32"),
+ (ArgType::UInt64, "u64"),
+ (ArgType::Double, "f64"),
+ (ArgType::Invalid, "nothing")];
+
+impl ArgType {
+ /// A str corresponding to the name of a Rust type.
+ pub fn as_str(self) -> &'static str {
+ ALL_ARG_TYPES.iter().skip_while(|a| a.0 != self).next().unwrap().1
+ }
+
+ /// Converts an i32 to an ArgType (or an error).
+ pub fn from_i32(i: i32) -> Result<ArgType, String> {
+ for &(a, _) in &ALL_ARG_TYPES {
+ if a as i32 == i { return Ok(a); }
+ }
+ Err(format!("Invalid ArgType {} ({})", i, i as u8 as char))
+ }
+}
+
+
+/// Error struct to indicate a D-Bus argument type mismatch.
+///
+/// Might be returned from `iter::read()`.
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub struct TypeMismatchError {
+ expected: ArgType,
+ found: ArgType,
+ position: u32,
+}
+
+impl TypeMismatchError {
+ /// The ArgType we were trying to read, but failed
+ pub fn expected_arg_type(&self) -> ArgType { self.expected }
+
+ /// The ArgType we should have been trying to read, if we wanted the read to succeed
+ pub fn found_arg_type(&self) -> ArgType { self.found }
+
+ /// At what argument was the error found?
+ ///
+ /// Returns 0 for first argument, 1 for second argument, etc.
+ pub fn pos(&self) -> u32 { self.position }
+}
+
+impl error::Error for TypeMismatchError {
+ fn description(&self) -> &str { "D-Bus argument type mismatch" }
+ fn cause(&self) -> Option<&error::Error> { None }
+}
+
+impl fmt::Display for TypeMismatchError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{} at position {}: expected {}, found {}",
+ (self as &error::Error).description(),
+ self.position, self.expected.as_str(),
+ if self.expected == self.found { "same but still different somehow" } else { self.found.as_str() }
+ )
+ }
+}
+
+
+#[allow(dead_code)]
+fn test_compile() {
+ let mut q = IterAppend::new(unsafe { mem::transmute(0usize) });
+
+ q.append(5u8);
+ q.append(Array::new(&[5u8, 6, 7]));
+ q.append((8u8, &[9u8, 6, 7][..]));
+ q.append(Variant((6u8, 7u8)));
+}
+
diff --git a/third_party/rust/dbus/src/arg/msgarg.rs b/third_party/rust/dbus/src/arg/msgarg.rs
new file mode 100644
index 0000000000..3309c35e65
--- /dev/null
+++ b/third_party/rust/dbus/src/arg/msgarg.rs
@@ -0,0 +1,426 @@
+#![allow(dead_code)]
+
+use {Signature, Message, arg::TypeMismatchError};
+use std::{fmt, any};
+use std::sync::Arc;
+use std::rc::Rc;
+
+use super::{Iter, IterAppend, ArgType};
+
+/// Types that can represent a D-Bus message argument implement this trait.
+///
+/// Types should also implement either Append or Get to be useful.
+pub trait Arg {
+ /// The corresponding D-Bus argument type code.
+ const ARG_TYPE: ArgType;
+ /// The corresponding D-Bus argument type code; just returns ARG_TYPE.
+ ///
+ /// For backwards compatibility.
+ #[deprecated(note = "Use associated constant ARG_TYPE instead")]
+ fn arg_type() -> ArgType { return Self::ARG_TYPE; }
+ /// The corresponding D-Bus type signature for this type.
+ fn signature() -> Signature<'static>;
+}
+
+/// Types that can be appended to a message as arguments implement this trait.
+pub trait Append: Sized {
+ /// Performs the append operation.
+ fn append(self, &mut IterAppend);
+}
+
+/// Helper trait to append many arguments to a message.
+pub trait AppendAll: Sized {
+ /// Performs the append operation.
+ fn append(self, &mut IterAppend);
+}
+
+/// Types that can be retrieved from a message as arguments implement this trait.
+pub trait Get<'a>: Sized {
+ /// Performs the get operation.
+ fn get(i: &mut Iter<'a>) -> Option<Self>;
+}
+
+/// Helper trait to read all arguments from a message.
+pub trait ReadAll: Sized {
+ /// Performs the read operation.
+ fn read(i: &mut Iter) -> Result<Self, TypeMismatchError>;
+}
+
+
+/// Object safe version of Arg + Append + Get.
+pub trait RefArg: fmt::Debug {
+ /// The corresponding D-Bus argument type code.
+ fn arg_type(&self) -> ArgType;
+ /// The corresponding D-Bus type signature for this type.
+ fn signature(&self) -> Signature<'static>;
+ /// Performs the append operation.
+ fn append(&self, &mut IterAppend);
+ /// Transforms this argument to Any (which can be downcasted to read the current value).
+ ///
+ /// Note: The internal representation of complex types (Array, Dict, Struct) is unstable
+ /// and as_any should not be relied upon for these types. Use as_iter instead.
+ fn as_any(&self) -> &any::Any where Self: 'static;
+ /// Transforms this argument to Any (which can be downcasted to read the current value).
+ ///
+ /// Note: The internal representation of complex types (Array, Dict, Struct) is unstable
+ /// and as_any should not be relied upon for these types. Use as_iter instead.
+ ///
+ /// # Panic
+ /// Will panic if the interior cannot be made mutable, e g, if encapsulated
+ /// inside a Rc with a reference count > 1.
+ fn as_any_mut(&mut self) -> &mut any::Any where Self: 'static;
+ /// Try to read the argument as an i64.
+ ///
+ /// Works for: Boolean, Byte, Int16, UInt16, Int32, UInt32, Int64, UnixFd.
+ #[inline]
+ fn as_i64(&self) -> Option<i64> { None }
+ /// Try to read the argument as an u64.
+ ///
+ /// Works for: Boolean, Byte, Int16, UInt16, Int32, UInt32, UInt64.
+ #[inline]
+ fn as_u64(&self) -> Option<u64> { None }
+ /// Try to read the argument as an f64.
+ ///
+ /// Works for: Boolean, Byte, Int16, UInt16, Int32, UInt32, Double.
+ #[inline]
+ fn as_f64(&self) -> Option<f64> { None }
+ /// Try to read the argument as a str.
+ ///
+ /// Works for: String, ObjectPath, Signature.
+ #[inline]
+ fn as_str(&self) -> Option<&str> { None }
+ /// Try to read the argument as an iterator.
+ ///
+ /// Works for: Array/Dict, Struct, Variant.
+ #[inline]
+ fn as_iter<'a>(&'a self) -> Option<Box<Iterator<Item=&'a RefArg> + 'a>> { None }
+ /// Deep clone of the RefArg, causing the result to be 'static.
+ ///
+ /// Usable as an escape hatch in case of lifetime problems with RefArg.
+ ///
+ /// In case of complex types (Array, Dict, Struct), the clone is not guaranteed
+ /// to have the same internal representation as the original.
+ fn box_clone(&self) -> Box<RefArg + 'static> { unimplemented!() /* Needed for backwards comp */ }
+}
+
+impl<'a> Get<'a> for Box<RefArg> {
+ fn get(i: &mut Iter<'a>) -> Option<Self> { i.get_refarg() }
+}
+
+/// Cast a RefArg as a specific type (shortcut for any + downcast)
+#[inline]
+pub fn cast<'a, T: 'static>(a: &'a (RefArg + 'static)) -> Option<&'a T> { a.as_any().downcast_ref() }
+
+/// Cast a RefArg as a specific type (shortcut for any_mut + downcast_mut)
+///
+/// # Panic
+/// Will panic if the interior cannot be made mutable, e g, if encapsulated
+/// inside a Rc with a reference count > 1.
+#[inline]
+pub fn cast_mut<'a, T: 'static>(a: &'a mut (RefArg + 'static)) -> Option<&'a mut T> { a.as_any_mut().downcast_mut() }
+
+/// If a type implements this trait, it means the size and alignment is the same
+/// as in D-Bus. This means that you can quickly append and get slices of this type.
+///
+/// Note: Booleans do not implement this trait because D-Bus booleans are 4 bytes and Rust booleans are 1 byte.
+pub unsafe trait FixedArray: Arg + 'static + Clone + Copy {}
+
+/// Types that can be used as keys in a dict type implement this trait.
+pub trait DictKey: Arg {}
+
+
+
+/// Simple lift over reference to value - this makes some iterators more ergonomic to use
+impl<'a, T: Arg> Arg for &'a T {
+ const ARG_TYPE: ArgType = T::ARG_TYPE;
+ fn signature() -> Signature<'static> { T::signature() }
+}
+impl<'a, T: Append + Clone> Append for &'a T {
+ fn append(self, i: &mut IterAppend) { self.clone().append(i) }
+}
+impl<'a, T: DictKey> DictKey for &'a T {}
+
+impl<'a, T: RefArg + ?Sized> RefArg for &'a T {
+ #[inline]
+ fn arg_type(&self) -> ArgType { (&**self).arg_type() }
+ #[inline]
+ fn signature(&self) -> Signature<'static> { (&**self).signature() }
+ #[inline]
+ fn append(&self, i: &mut IterAppend) { (&**self).append(i) }
+ #[inline]
+ fn as_any(&self) -> &any::Any where T: 'static { (&**self).as_any() }
+ #[inline]
+ fn as_any_mut(&mut self) -> &mut any::Any where T: 'static { unreachable!() }
+ #[inline]
+ fn as_i64(&self) -> Option<i64> { (&**self).as_i64() }
+ #[inline]
+ fn as_u64(&self) -> Option<u64> { (&**self).as_u64() }
+ #[inline]
+ fn as_f64(&self) -> Option<f64> { (&**self).as_f64() }
+ #[inline]
+ fn as_str(&self) -> Option<&str> { (&**self).as_str() }
+ #[inline]
+ fn as_iter<'b>(&'b self) -> Option<Box<Iterator<Item=&'b RefArg> + 'b>> { (&**self).as_iter() }
+ #[inline]
+ fn box_clone(&self) -> Box<RefArg + 'static> { (&**self).box_clone() }
+}
+
+
+
+macro_rules! deref_impl {
+ ($t: ident, $ss: ident, $make_mut: expr) => {
+
+impl<T: RefArg + ?Sized> RefArg for $t<T> {
+ #[inline]
+ fn arg_type(&self) -> ArgType { (&**self).arg_type() }
+ #[inline]
+ fn signature(&self) -> Signature<'static> { (&**self).signature() }
+ #[inline]
+ fn append(&self, i: &mut IterAppend) { (&**self).append(i) }
+ #[inline]
+ fn as_any(&self) -> &any::Any where T: 'static { (&**self).as_any() }
+ #[inline]
+ fn as_any_mut<'a>(&'a mut $ss) -> &'a mut any::Any where T: 'static { $make_mut.as_any_mut() }
+ #[inline]
+ fn as_i64(&self) -> Option<i64> { (&**self).as_i64() }
+ #[inline]
+ fn as_u64(&self) -> Option<u64> { (&**self).as_u64() }
+ #[inline]
+ fn as_f64(&self) -> Option<f64> { (&**self).as_f64() }
+ #[inline]
+ fn as_str(&self) -> Option<&str> { (&**self).as_str() }
+ #[inline]
+ fn as_iter<'a>(&'a self) -> Option<Box<Iterator<Item=&'a RefArg> + 'a>> { (&**self).as_iter() }
+ #[inline]
+ fn box_clone(&self) -> Box<RefArg + 'static> { (&**self).box_clone() }
+}
+impl<T: DictKey> DictKey for $t<T> {}
+
+impl<T: Arg> Arg for $t<T> {
+ const ARG_TYPE: ArgType = T::ARG_TYPE;
+ fn signature() -> Signature<'static> { T::signature() }
+}
+impl<'a, T: Get<'a>> Get<'a> for $t<T> {
+ fn get(i: &mut Iter<'a>) -> Option<Self> { T::get(i).map(|v| $t::new(v)) }
+}
+
+ }
+}
+
+impl<T: Append> Append for Box<T> {
+ fn append(self, i: &mut IterAppend) { let q: T = *self; q.append(i) }
+}
+
+deref_impl!(Box, self, &mut **self );
+deref_impl!(Rc, self, Rc::get_mut(self).unwrap());
+deref_impl!(Arc, self, Arc::get_mut(self).unwrap());
+
+/// Internal trait to help generics. Implemented for (), (A1), (A1, A2) and so on (where A1: Arg, A2: Arg etc).
+///
+/// You would probably not use this trait directly, instead use generic functions which
+/// take ArgBuilder as an argument. It helps reading and appending multiple arguments
+/// to/from a message in one go.
+pub trait ArgBuilder: Sized {
+ /// A tuple of &static str. Used for introspection.
+ type strs;
+ /// Low-level introspection helper method.
+ fn strs_sig<F: FnMut(&'static str, Signature<'static>)>(a: Self::strs, f: F);
+ /// Low-level method to read arguments from a message.
+ fn read(msg: &Message) -> Result<Self, TypeMismatchError>;
+ /// Low-level method to append arguments to a message.
+ fn append(self, msg: &mut Message);
+}
+
+impl ArgBuilder for () {
+ type strs = ();
+ fn strs_sig<F: FnMut(&'static str, Signature<'static>)>(_: Self::strs, _: F) {}
+ fn read(_: &Message) -> Result<Self, TypeMismatchError> { Ok(()) }
+ fn append(self, _: &mut Message) {}
+}
+
+macro_rules! argbuilder_impl {
+ ($($n: ident $t: ident $s: ty,)+) => {
+
+impl<$($t: Arg + Append + for<'z> Get<'z>),*> ArgBuilder for ($($t,)*) {
+ type strs = ($(&'static $s,)*);
+ fn strs_sig<Q: FnMut(&'static str, Signature<'static>)>(z: Self::strs, mut q: Q) {
+ let ( $($n,)*) = z;
+ $( q($n, $t::signature()); )*
+ }
+
+ fn read(msg: &Message) -> Result<Self, TypeMismatchError> {
+ let mut ii = msg.iter_init();
+ $( let $n = ii.read()?; )*
+ Ok(($( $n, )* ))
+ }
+
+ fn append(self, msg: &mut Message) {
+ let ( $($n,)*) = self;
+ let mut ia = IterAppend::new(msg);
+ $( ia.append($n); )*
+ }
+}
+
+impl<$($t: Append),*> AppendAll for ($($t,)*) {
+ fn append(self, ia: &mut IterAppend) {
+ let ( $($n,)*) = self;
+ $( ia.append($n); )*
+ }
+}
+
+impl<$($t: Arg + for<'z> Get<'z>),*> ReadAll for ($($t,)*) {
+ fn read(ii: &mut Iter) -> Result<Self, TypeMismatchError> {
+ $( let $n = ii.read()?; )*
+ Ok(($( $n, )* ))
+ }
+}
+
+
+ }
+}
+
+argbuilder_impl!(a A str,);
+argbuilder_impl!(a A str, b B str,);
+argbuilder_impl!(a A str, b B str, c C str,);
+argbuilder_impl!(a A str, b B str, c C str, d D str,);
+argbuilder_impl!(a A str, b B str, c C str, d D str, e E str,);
+argbuilder_impl!(a A str, b B str, c C str, d D str, e E str, f F str,);
+argbuilder_impl!(a A str, b B str, c C str, d D str, e E str, f F str, g G str,);
+argbuilder_impl!(a A str, b B str, c C str, d D str, e E str, f F str, g G str, h H str,);
+argbuilder_impl!(a A str, b B str, c C str, d D str, e E str, f F str, g G str, h H str, i I str,);
+argbuilder_impl!(a A str, b B str, c C str, d D str, e E str, f F str, g G str, h H str, i I str, j J str,);
+
+
+
+#[cfg(test)]
+mod test {
+ extern crate tempdir;
+
+ use {Connection, ConnectionItem, Message, BusType, Path, Signature};
+ use arg::{Array, Variant, Dict, Iter, ArgType, TypeMismatchError, RefArg, cast};
+
+ use std::collections::HashMap;
+
+ #[test]
+ fn refarg() {
+ let c = Connection::get_private(BusType::Session).unwrap();
+ c.register_object_path("/mooh").unwrap();
+ let m = Message::new_method_call(&c.unique_name(), "/mooh", "com.example.hello", "Hello").unwrap();
+
+ let mut vv: Vec<Variant<Box<RefArg>>> = vec!();
+ vv.push(Variant(Box::new(5i32)));
+ vv.push(Variant(Box::new(String::from("Hello world"))));
+ let m = m.append_ref(&vv);
+
+ let (f1, f2) = (false, 7u64);
+ let mut v: Vec<&RefArg> = vec!();
+ v.push(&f1);
+ v.push(&f2);
+ let m = m.append_ref(&v);
+ let vi32 = vec![7i32, 9i32];
+ let vstr: Vec<String> = ["This", "is", "dbus", "rs"].iter().map(|&s| s.into()).collect();
+ let m = m.append_ref(&[&vi32 as &RefArg, &vstr as &RefArg]);
+ let mut map = HashMap::new();
+ map.insert(true, String::from("Yes"));
+ map.insert(false, String::from("No"));
+ let m = m.append_ref(&[&map as &RefArg, &1.5f64 as &RefArg]);
+
+ c.send(m).unwrap();
+
+ for n in c.iter(1000) {
+ if let ConnectionItem::MethodCall(m) = n {
+ let rv: Vec<Box<RefArg + 'static>> = m.iter_init().collect();
+ println!("Receiving {:?}", rv);
+ let rv0: &Variant<Box<RefArg>> = cast(&rv[0]).unwrap();
+ let rv00: &i32 = cast(&rv0.0).unwrap();
+ assert_eq!(rv00, &5i32);
+ assert_eq!(Some(&false), rv[2].as_any().downcast_ref::<bool>());
+ assert_eq!(Some(&vi32), rv[4].as_any().downcast_ref::<Vec<i32>>());
+ assert_eq!(Some(&vstr), rv[5].as_any().downcast_ref::<Vec<String>>());
+ let mut diter = rv[6].as_iter().unwrap();
+ {
+ let mut mmap: HashMap<bool, String> = HashMap::new();
+ while let Some(k) = diter.next() {
+ let x: String = diter.next().unwrap().as_str().unwrap().into();
+ mmap.insert(*cast::<bool>(&k.box_clone()).unwrap(), x);
+ }
+ assert_eq!(mmap[&true], "Yes");
+ }
+ let mut iter = rv[6].as_iter().unwrap();
+ assert!(iter.next().unwrap().as_i64().is_some());
+ assert!(iter.next().unwrap().as_str().is_some());
+ assert!(iter.next().unwrap().as_str().is_none());
+ assert!(iter.next().unwrap().as_i64().is_none());
+ assert!(iter.next().is_none());
+ assert!(rv[7].as_f64().unwrap() > 1.0);
+ assert!(rv[7].as_f64().unwrap() < 2.0);
+ break;
+ }
+ }
+ }
+
+ #[test]
+ fn message_types() {
+ let c = Connection::get_private(BusType::Session).unwrap();
+ c.register_object_path("/hello").unwrap();
+ let m = Message::new_method_call(&c.unique_name(), "/hello", "com.example.hello", "Hello").unwrap();
+ let m = m.append1(2000u16);
+ let m = m.append1(Array::new(&vec![129u8, 5, 254]));
+ let m = m.append2(Variant(&["Hello", "world"][..]), &[32768u16, 16u16, 12u16][..]);
+ let m = m.append3(-1i32, &*format!("Hello world"), -3.14f64);
+ let m = m.append1((256i16, Variant(18_446_744_073_709_551_615u64)));
+ let m = m.append2(Path::new("/a/valid/path").unwrap(), Signature::new("a{sv}").unwrap());
+ let mut z = HashMap::new();
+ z.insert(123543u32, true);
+ z.insert(0u32, false);
+ let m = m.append1(Dict::new(&z));
+ let sending = format!("{:?}", m.iter_init());
+ println!("Sending {}", sending);
+ c.send(m).unwrap();
+
+ for n in c.iter(1000) {
+ match n {
+ ConnectionItem::MethodCall(m) => {
+ use super::Arg;
+ let receiving = format!("{:?}", m.iter_init());
+ println!("Receiving {}", receiving);
+ assert_eq!(sending, receiving);
+
+ assert_eq!(2000u16, m.get1().unwrap());
+ assert_eq!(m.get2(), (Some(2000u16), Some(&[129u8, 5, 254][..])));
+ assert_eq!(m.read2::<u16, bool>().unwrap_err(),
+ TypeMismatchError { position: 1, found: ArgType::Array, expected: ArgType::Boolean });
+
+ let mut g = m.iter_init();
+ let e = g.read::<u32>().unwrap_err();
+ assert_eq!(e.pos(), 0);
+ assert_eq!(e.expected_arg_type(), ArgType::UInt32);
+ assert_eq!(e.found_arg_type(), ArgType::UInt16);
+
+ assert!(g.next() && g.next());
+ let v: Variant<Iter> = g.get().unwrap();
+ let mut viter = v.0;
+ assert_eq!(viter.arg_type(), Array::<&str,()>::ARG_TYPE);
+ let a: Array<&str, _> = viter.get().unwrap();
+ assert_eq!(a.collect::<Vec<&str>>(), vec!["Hello", "world"]);
+
+ assert!(g.next());
+ assert_eq!(g.get::<u16>(), None); // It's an array, not a single u16
+ assert!(g.next() && g.next() && g.next() && g.next());
+
+ assert_eq!(g.get(), Some((256i16, Variant(18_446_744_073_709_551_615u64))));
+ assert!(g.next());
+ assert_eq!(g.get(), Some(Path::new("/a/valid/path").unwrap()));
+ assert!(g.next());
+ assert_eq!(g.get(), Some(Signature::new("a{sv}").unwrap()));
+ assert!(g.next());
+ let d: Dict<u32, bool, _> = g.get().unwrap();
+ let z2: HashMap<_, _> = d.collect();
+ assert_eq!(z, z2);
+ break;
+ }
+ _ => println!("Got {:?}", n),
+ }
+ }
+ }
+}
diff --git a/third_party/rust/dbus/src/arg/variantstruct_impl.rs b/third_party/rust/dbus/src/arg/variantstruct_impl.rs
new file mode 100644
index 0000000000..d58c99e098
--- /dev/null
+++ b/third_party/rust/dbus/src/arg/variantstruct_impl.rs
@@ -0,0 +1,242 @@
+use super::*;
+use {message, Signature};
+use std::any;
+
+#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq, Ord, PartialOrd)]
+/// A simple wrapper to specify a D-Bus variant.
+///
+/// See the argument guide and module level documentation for details and examples.
+pub struct Variant<T>(pub T);
+
+impl Variant<Box<RefArg>> {
+ /// Creates a new refarg from an Iter. Mainly for internal use.
+ pub fn new_refarg<'a>(i: &mut Iter<'a>) -> Option<Self> {
+ i.recurse(ArgType::Variant).and_then(|mut si| si.get_refarg()).map(|v| Variant(v))
+ }
+}
+
+impl Default for Variant<Box<RefArg>> {
+ // This is a bit silly, because there is no such thing as a default argument.
+ // Unfortunately due to a design mistake while making the SignalArgs trait, we'll
+ // have to work around that by adding a default implementation here.
+ // https://github.com/diwic/dbus-rs/issues/136
+ fn default() -> Self { Variant(Box::new(0u8) as Box<RefArg>) }
+}
+
+impl<T:Default> Default for Variant<T> {
+ fn default() -> Self { Variant(T::default()) }
+}
+
+
+impl<T> Arg for Variant<T> {
+ const ARG_TYPE: ArgType = ArgType::Variant;
+ fn signature() -> Signature<'static> { unsafe { Signature::from_slice_unchecked(b"v\0") } }
+}
+
+impl<T: Arg + Append> Append for Variant<T> {
+ fn append(self, i: &mut IterAppend) {
+ let z = self.0;
+ i.append_container(ArgType::Variant, Some(T::signature().as_cstr()), |s| z.append(s));
+ }
+}
+
+impl Append for Variant<message::MessageItem> {
+ fn append(self, i: &mut IterAppend) {
+ let z = self.0;
+ let asig = z.signature();
+ let sig = asig.as_cstr();
+ i.append_container(ArgType::Variant, Some(&sig), |s| z.append(s));
+ }
+}
+
+impl Append for Variant<Box<RefArg>> {
+ fn append(self, i: &mut IterAppend) {
+ let z = self.0;
+ i.append_container(ArgType::Variant, Some(z.signature().as_cstr()), |s| z.append(s));
+ }
+}
+
+impl<'a, T: Get<'a>> Get<'a> for Variant<T> {
+ fn get(i: &mut Iter<'a>) -> Option<Variant<T>> {
+ i.recurse(ArgType::Variant).and_then(|mut si| si.get().map(|v| Variant(v)))
+ }
+}
+
+impl<'a> Get<'a> for Variant<Iter<'a>> {
+ fn get(i: &mut Iter<'a>) -> Option<Variant<Iter<'a>>> {
+ i.recurse(ArgType::Variant).map(|v| Variant(v))
+ }
+}
+/*
+impl<'a> Get<'a> for Variant<Box<RefArg>> {
+ fn get(i: &mut Iter<'a>) -> Option<Variant<Box<RefArg>>> {
+ i.recurse(ArgType::Variant).and_then(|mut si| si.get_refarg().map(|v| Variant(v)))
+ }
+}
+*/
+impl<T: RefArg> RefArg for Variant<T> {
+ fn arg_type(&self) -> ArgType { ArgType::Variant }
+ fn signature(&self) -> Signature<'static> { unsafe { Signature::from_slice_unchecked(b"v\0") } }
+ fn append(&self, i: &mut IterAppend) {
+ let z = &self.0;
+ i.append_container(ArgType::Variant, Some(z.signature().as_cstr()), |s| z.append(s));
+ }
+ #[inline]
+ fn as_any(&self) -> &any::Any where T: 'static { self }
+ #[inline]
+ fn as_any_mut(&mut self) -> &mut any::Any where T: 'static { self }
+ #[inline]
+ fn as_i64(&self) -> Option<i64> { self.0.as_i64() }
+ #[inline]
+ fn as_u64(&self) -> Option<u64> { self.0.as_u64() }
+ #[inline]
+ fn as_f64(&self) -> Option<f64> { self.0.as_f64() }
+ #[inline]
+ fn as_str(&self) -> Option<&str> { self.0.as_str() }
+ #[inline]
+ fn as_iter<'a>(&'a self) -> Option<Box<Iterator<Item=&'a RefArg> + 'a>> {
+ use std::iter;
+ let z: &RefArg = &self.0;
+ Some(Box::new(iter::once(z)))
+ }
+ #[inline]
+ fn box_clone(&self) -> Box<RefArg + 'static> { Box::new(Variant(self.0.box_clone())) }
+}
+
+macro_rules! struct_impl {
+ ( $($n: ident $t: ident,)+ ) => {
+
+/// Tuples are represented as D-Bus structs.
+impl<$($t: Arg),*> Arg for ($($t,)*) {
+ const ARG_TYPE: ArgType = ArgType::Struct;
+ fn signature() -> Signature<'static> {
+ let mut s = String::from("(");
+ $( s.push_str(&$t::signature()); )*
+ s.push_str(")");
+ Signature::from(s)
+ }
+}
+
+impl<$($t: Append),*> Append for ($($t,)*) {
+ fn append(self, i: &mut IterAppend) {
+ let ( $($n,)*) = self;
+ i.append_container(ArgType::Struct, None, |s| { $( $n.append(s); )* });
+ }
+}
+
+impl<'a, $($t: Get<'a>),*> Get<'a> for ($($t,)*) {
+ fn get(i: &mut Iter<'a>) -> Option<Self> {
+ let si = i.recurse(ArgType::Struct);
+ if si.is_none() { return None; }
+ let mut si = si.unwrap();
+ let mut _valid_item = true;
+ $(
+ if !_valid_item { return None; }
+ let $n: Option<$t> = si.get();
+ if $n.is_none() { return None; }
+ _valid_item = si.next();
+ )*
+ Some(($( $n.unwrap(), )* ))
+ }
+}
+
+impl<$($t: RefArg),*> RefArg for ($($t,)*) {
+ fn arg_type(&self) -> ArgType { ArgType::Struct }
+ fn signature(&self) -> Signature<'static> {
+ let &( $(ref $n,)*) = self;
+ let mut s = String::from("(");
+ $( s.push_str(&$n.signature()); )*
+ s.push_str(")");
+ Signature::from(s)
+ }
+ fn append(&self, i: &mut IterAppend) {
+ let &( $(ref $n,)*) = self;
+ i.append_container(ArgType::Struct, None, |s| { $( $n.append(s); )* });
+ }
+ fn as_any(&self) -> &any::Any where Self: 'static { self }
+ fn as_any_mut(&mut self) -> &mut any::Any where Self: 'static { self }
+ fn as_iter<'a>(&'a self) -> Option<Box<Iterator<Item=&'a RefArg> + 'a>> {
+ let &( $(ref $n,)*) = self;
+ let v = vec!(
+ $( $n as &RefArg, )*
+ );
+ Some(Box::new(v.into_iter()))
+ }
+ #[inline]
+ fn box_clone(&self) -> Box<RefArg + 'static> {
+ let &( $(ref $n,)*) = self;
+ let mut z = vec!();
+ $( z.push($n.box_clone()); )*
+ Box::new(z)
+ }
+}
+
+
+}} // macro_rules end
+
+struct_impl!(a A,);
+struct_impl!(a A, b B,);
+struct_impl!(a A, b B, c C,);
+struct_impl!(a A, b B, c C, d D,);
+struct_impl!(a A, b B, c C, d D, e E,);
+struct_impl!(a A, b B, c C, d D, e E, f F,);
+struct_impl!(a A, b B, c C, d D, e E, f F, g G,);
+struct_impl!(a A, b B, c C, d D, e E, f F, g G, h H,);
+struct_impl!(a A, b B, c C, d D, e E, f F, g G, h H, i I,);
+struct_impl!(a A, b B, c C, d D, e E, f F, g G, h H, i I, j J,);
+struct_impl!(a A, b B, c C, d D, e E, f F, g G, h H, i I, j J, k K,);
+struct_impl!(a A, b B, c C, d D, e E, f F, g G, h H, i I, j J, k K, l L,);
+
+impl RefArg for Vec<Box<RefArg>> {
+ fn arg_type(&self) -> ArgType { ArgType::Struct }
+ fn signature(&self) -> Signature<'static> {
+ let mut s = String::from("(");
+ for z in self {
+ s.push_str(&z.signature());
+ }
+ s.push_str(")");
+ Signature::from(s)
+ }
+ fn append(&self, i: &mut IterAppend) {
+ i.append_container(ArgType::Struct, None, |s| {
+ for z in self { z.append(s); }
+ });
+ }
+ #[inline]
+ fn as_any(&self) -> &any::Any where Self: 'static { self }
+ #[inline]
+ fn as_any_mut(&mut self) -> &mut any::Any where Self: 'static { self }
+ fn as_iter<'a>(&'a self) -> Option<Box<Iterator<Item=&'a RefArg> + 'a>> {
+ Some(Box::new(self.iter().map(|b| &**b)))
+ }
+ #[inline]
+ fn box_clone(&self) -> Box<RefArg + 'static> {
+ let t: Vec<Box<RefArg + 'static>> = self.iter().map(|x| x.box_clone()).collect();
+ Box::new(t)
+ }
+}
+
+impl Append for message::MessageItem {
+ fn append(self, i: &mut IterAppend) {
+ message::append_messageitem(&mut i.0, &self)
+ }
+}
+
+impl<'a> Get<'a> for message::MessageItem {
+ fn get(i: &mut Iter<'a>) -> Option<Self> {
+ message::get_messageitem(&mut i.0)
+ }
+}
+
+impl RefArg for message::MessageItem {
+ fn arg_type(&self) -> ArgType { ArgType::from_i32(self.array_type()).unwrap() }
+ fn signature(&self) -> Signature<'static> { message::MessageItem::signature(&self) }
+ fn append(&self, i: &mut IterAppend) { message::append_messageitem(&mut i.0, self) }
+ #[inline]
+ fn as_any(&self) -> &any::Any where Self: 'static { self }
+ #[inline]
+ fn as_any_mut(&mut self) -> &mut any::Any where Self: 'static { self }
+ #[inline]
+ fn box_clone(&self) -> Box<RefArg + 'static> { Box::new(self.clone()) }
+}
+