usesuper::*; use {Signature, Path, Message, ffi, OwnedFd}; use std::marker::PhantomData; use std::{ptr, mem, any, fmt}; usesuper::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)
];
fn array_append<T: Arg, F: FnMut(&T, &mut IterAppend)>(z: &[T], i: &<span style='color:red'>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.0as 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: 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 };
letmut v = ptr::null_mut(); letmut i = 0;
ffi::dbus_message_iter_get_fixed_array(&mut si.0, &='color:red'>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. pubstruct Dict<'a, K: DictKey, V: Arg, I>(I, PhantomData<(&'a Message, *const K, *const V)>);
#[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. pubstruct 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. pubfn new<J: IntoIterator<IntoIter=I, Item=T>>(j: J) -> Array<'a, T, I> { Array(j.into_iter(), PhantomData) }
}
impl<'a, T: Get<'a>> Iterator for Array<'a, T, Iter<'a>> { type Item = T; fn next(&mutself) -> 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 whereSelf: 'static { self } #[inline] fn as_any_mut(&mutself) -> &mut any::Any whereSelf: 'static { self }
// 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> { letmut si = i.recurse(ArgType::Array).unwrap(); let inner_sig = si.signature(); let data = si.collect::<Vec<_>>(); Box::new(InternalArray { data, inner_sig })
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.