1use super::*;
2use crate::{Message, ffi};
3use crate::strings::{Signature, Path};
4use std::marker::PhantomData;
5use std::{ptr, mem, any, fmt};
6use super::check;
7use std::ffi::{CString};
8use std::os::raw::{c_void, c_int};
9use std::collections::{HashMap, BTreeMap};
10use std::hash::{Hash, BuildHasher};
11
12// Map DBus-Type -> Alignment. Copied from _dbus_marshal_write_fixed_multi in
13// http://dbus.freedesktop.org/doc/api/html/dbus-marshal-basic_8c_source.html#l01020
14// Note that Rust booleans are one byte, dbus booleans are four bytes!
15const FIXED_ARRAY_ALIGNMENTS: [(ArgType, usize); 9] = [
16 (ArgType::Byte, 1),
17 (ArgType::Int16, 2),
18 (ArgType::UInt16, 2),
19 (ArgType::UInt32, 4),
20 (ArgType::Int32, 4),
21 (ArgType::Boolean, 4),
22 (ArgType::Int64, 8),
23 (ArgType::UInt64, 8),
24 (ArgType::Double, 8)
25];
26
27/// Represents a D-Bus array.
28impl<'a, T: Arg> Arg for &'a [T] {
29 const ARG_TYPE: ArgType = ArgType::Array;
30 fn signature() -> Signature<'static> { Signature::from(format!("a{}", T::signature())) }
31}
32
33fn array_append<T: Arg, F: FnMut(&T, &mut IterAppend)>(z: &[T], i: &mut IterAppend, mut f: F) {
34 let zptr: *const T = z.as_ptr();
35 let zlen: i32 = z.len() as i32;
36
37 // Can we do append_fixed_array?
38 let a: (ArgType, {unknown}) = (T::ARG_TYPE, mem::size_of::<T>());
39 let can_fixed_array: bool = (zlen > 1) && (z.len() == zlen as usize) && FIXED_ARRAY_ALIGNMENTS.iter().any(|&v| v == a);
40
41 i.append_container(ArgType::Array, sig:Some(T::signature().as_cstr()), |s|
42 if can_fixed_array { unsafe { check(f:"dbus_message_iter_append_fixed_array",
43 i:ffi::dbus_message_iter_append_fixed_array(&mut s.0, element_type:a.0 as c_int, &zptr as *const _ as *const c_void, n_elements:zlen)) }}
44 else { for arg: &T in z { f(arg, s); }}
45 );
46}
47
48/// Appends a D-Bus array. Note: In case you have a large array of a type that implements FixedArray,
49/// using this method will be more efficient than using an Array.
50impl<'a, T: Arg + Append + Clone> Append for &'a [T] {
51 fn append_by_ref(&self, i: &mut IterAppend) {
52 array_append(self, i, |arg, s: &mut IterAppend<'_>| arg.clone().append(s));
53 }
54}
55
56impl<'a, T: Arg + RefArg> RefArg for &'a [T] {
57 fn arg_type(&self) -> ArgType { ArgType::Array }
58 fn signature(&self) -> Signature<'static> { Signature::from(format!("a{}", <T as Arg>::signature())) }
59 fn append(&self, i: &mut IterAppend) {
60 array_append(self, i, |arg: &{unknown}, s: &mut IterAppend<'_>| RefArg::append(self:arg,s));
61 }
62 #[inline]
63 fn as_any(&self) -> &dyn any::Any where Self: 'static { self }
64 #[inline]
65 fn as_any_mut(&mut self) -> &mut dyn any::Any where Self: 'static { self }
66 #[inline]
67 fn as_static_inner(&self, index: usize) -> Option<&(dyn RefArg + 'static)> where Self: 'static {
68 self.get(index).map(|x: &T| x as &dyn RefArg)
69 }
70
71 fn box_clone(&self) -> Box<dyn RefArg + 'static> {
72 T::array_clone(self).unwrap_or_else(|| {
73 Box::new(InternalArray {
74 inner_sig: <T as Arg>::signature(),
75 data: self.iter().map(|x| x.box_clone()).collect(),
76 })
77 })
78 }
79}
80
81impl<T: Arg + RefArg> RefArg for Vec<T> {
82 fn arg_type(&self) -> ArgType { ArgType::Array }
83 fn signature(&self) -> Signature<'static> { Signature::from(format!("a{}", <T as Arg>::signature())) }
84 fn append(&self, i: &mut IterAppend) {
85 array_append(&self, i, |arg: &{unknown}, s: &mut IterAppend<'_>| RefArg::append(self:arg,s));
86 }
87 #[inline]
88 fn as_any(&self) -> &dyn any::Any where Self: 'static { self }
89 #[inline]
90 fn as_any_mut(&mut self) -> &mut dyn any::Any where Self: 'static { self }
91 fn as_iter<'a>(&'a self) -> Option<Box<dyn Iterator<Item=&'a dyn RefArg> + 'a>> {
92 Some(Box::new(self.iter().map(|b| b as &dyn RefArg)))
93 }
94 #[inline]
95 fn as_static_inner(&self, index: usize) -> Option<&(dyn RefArg + 'static)> where Self: 'static {
96 self.get(index).map(|x| x as &dyn RefArg)
97 }
98 #[inline]
99 fn box_clone(&self) -> Box<dyn RefArg + 'static> { (&**self).box_clone() }
100}
101
102
103impl<'a, T: FixedArray> Get<'a> for &'a [T] {
104 fn get(i: &mut Iter<'a>) -> Option<&'a [T]> {
105 debug_assert!(FIXED_ARRAY_ALIGNMENTS.iter().any(|&v| v == (T::ARG_TYPE, mem::size_of::<T>())));
106 i.recurse(Self::ARG_TYPE).and_then(|mut si| unsafe {
107 let etype = ffi::dbus_message_iter_get_element_type(&mut i.0);
108
109 if etype != T::ARG_TYPE as c_int { return None };
110
111 let mut v: *mut T = ptr::null_mut();
112 let mut i: i32 = 0;
113 ffi::dbus_message_iter_get_fixed_array(&mut si.0, &mut v as *mut _ as *mut c_void, &mut i);
114 if v.is_null() {
115 assert_eq!(i, 0);
116 Some(&[][..])
117 } else {
118 Some(::std::slice::from_raw_parts(v, i as usize))
119 }
120 })
121 }
122}
123
124
125#[derive(Copy, Clone, Debug)]
126/// Append a D-Bus dict type (i e, an array of dict entries).
127///
128/// See the argument guide and module level documentation for details and alternatives.
129pub struct Dict<'a, K: DictKey, V: Arg, I>(I, PhantomData<(&'a Message, *const K, *const V)>);
130
131impl<'a, K: DictKey, V: Arg, I> Dict<'a, K, V, I> {
132 fn entry_sig() -> String { format!("{{{}{}}}", K::signature(), V::signature()) }
133}
134
135impl<'a, K: 'a + DictKey, V: 'a + Append + Arg, I: Iterator<Item=(K, V)>> Dict<'a, K, V, I> {
136 /// Creates a new Dict from an iterator.
137 pub fn new<J: IntoIterator<IntoIter=I, Item=(K, V)>>(j: J) -> Dict<'a, K, V, I> { Dict(j.into_iter(), PhantomData) }
138}
139
140impl<'a, K: DictKey, V: Arg, I> Arg for Dict<'a, K, V, I> {
141 const ARG_TYPE: ArgType = ArgType::Array;
142 fn signature() -> Signature<'static> {
143 Signature::from(format!("a{}", Self::entry_sig())) }
144}
145
146impl<'a, K: 'a + DictKey + Append, V: 'a + Append + Arg, I: Iterator<Item=(K, V)> + Clone> Append for Dict<'a, K, V, I> {
147 fn append_by_ref(&self, i: &mut IterAppend) {
148 let z = self.0.clone();
149 i.append_container(Self::ARG_TYPE, sig:Some(&CString::new(Self::entry_sig()).unwrap()), |s| for (k, v) in z {
150 s.append_container(ArgType::DictEntry, None, |ss: &mut IterAppend<'_>| {
151 k.append_by_ref(ss);
152 v.append_by_ref(ss);
153 })
154 });
155 }
156}
157
158
159impl<'a, K: DictKey + Get<'a>, V: Arg + Get<'a>> Get<'a> for Dict<'a, K, V, Iter<'a>> {
160 fn get(i: &mut Iter<'a>) -> Option<Self> {
161 i.recurse(Self::ARG_TYPE).map(|si| Dict(si, PhantomData))
162 // TODO: Verify full element signature?
163 }
164}
165
166impl<'a, K: DictKey + Get<'a>, V: Arg + Get<'a>> Iterator for Dict<'a, K, V, Iter<'a>> {
167 type Item = (K, V);
168 fn next(&mut self) -> Option<(K, V)> {
169 let i = self.0.recurse(ArgType::DictEntry).and_then(|mut si| {
170 let k = si.get();
171 if k.is_none() { return None };
172 assert!(si.next());
173 let v = si.get();
174 if v.is_none() { return None };
175 Some((k.unwrap(), v.unwrap()))
176 });
177 self.0.next();
178 i
179 }
180}
181
182impl<K: DictKey, V: Arg, S: BuildHasher> Arg for HashMap<K, V, S> {
183 const ARG_TYPE: ArgType = ArgType::Array;
184 fn signature() -> Signature<'static> {
185 Signature::from(format!("a{{{}{}}}", K::signature(), V::signature())) }
186}
187
188impl<K: DictKey + Append + Eq + Hash, V: Arg + Append, S: BuildHasher> Append for HashMap<K, V, S> {
189 fn append_by_ref(&self, i: &mut IterAppend) {
190 Dict::new(self.iter()).append_by_ref(i);
191 }
192}
193
194impl<'a, K: DictKey + Get<'a> + Eq + Hash, V: Arg + Get<'a>, S: BuildHasher + Default> Get<'a> for HashMap<K, V, S> {
195 fn get(i: &mut Iter<'a>) -> Option<Self> {
196 // TODO: Full element signature is not verified.
197 Dict::get(i).map(|d| d.collect())
198 }
199}
200
201impl<K: DictKey + RefArg + Eq + Hash, V: RefArg + Arg, S: BuildHasher + Send + Sync> RefArg for HashMap<K, V, S> {
202 fn arg_type(&self) -> ArgType { ArgType::Array }
203 fn signature(&self) -> Signature<'static> { format!("a{{{}{}}}", <K as Arg>::signature(), <V as Arg>::signature()).into() }
204 fn append(&self, i: &mut IterAppend) {
205 let sig = CString::new(format!("{{{}{}}}", <K as Arg>::signature(), <V as Arg>::signature())).unwrap();
206 i.append_container(ArgType::Array, Some(&sig), |s| for (k, v) in self {
207 s.append_container(ArgType::DictEntry, None, |ss| {
208 k.append(ss);
209 v.append(ss);
210 })
211 });
212 }
213 #[inline]
214 fn as_any(&self) -> &dyn any::Any where Self: 'static { self }
215 #[inline]
216 fn as_any_mut(&mut self) -> &mut dyn any::Any where Self: 'static { self }
217 fn as_iter<'b>(&'b self) -> Option<Box<dyn Iterator<Item=&'b dyn RefArg> + 'b>> {
218 Some(Box::new(self.iter().flat_map(|(k, v)| vec![k as &dyn RefArg, v as &dyn RefArg].into_iter())))
219 }
220 #[inline]
221 fn box_clone(&self) -> Box<dyn RefArg + 'static> {
222 Box::new(InternalDict {
223 outer_sig: self.signature(),
224 data: self.iter().map(|(k, v)| (k.box_clone(), v.box_clone())).collect(),
225 })
226 }
227}
228
229impl<K: DictKey, V: Arg> Arg for BTreeMap<K, V> {
230 const ARG_TYPE: ArgType = ArgType::Array;
231 fn signature() -> Signature<'static> {
232 Signature::from(format!("a{{{}{}}}", K::signature(), V::signature())) }
233}
234
235impl<K: DictKey + Append + Eq + Ord, V: Arg + Append> Append for BTreeMap<K, V> {
236 fn append_by_ref(&self, i: &mut IterAppend) {
237 Dict::new(self.iter()).append_by_ref(i);
238 }
239}
240
241impl<'a, K: DictKey + Get<'a> + Eq + Ord, V: Arg + Get<'a>> Get<'a> for BTreeMap<K, V> {
242 fn get(i: &mut Iter<'a>) -> Option<Self> {
243 // TODO: Full element signature is not verified.
244 Dict::get(i).map(|d| d.collect())
245 }
246}
247
248impl<K: DictKey + RefArg + Eq + Ord, V: RefArg + Arg> RefArg for BTreeMap<K, V> {
249 fn arg_type(&self) -> ArgType { ArgType::Array }
250 fn signature(&self) -> Signature<'static> { format!("a{{{}{}}}", <K as Arg>::signature(), <V as Arg>::signature()).into() }
251 fn append(&self, i: &mut IterAppend) {
252 let sig = CString::new(format!("{{{}{}}}", <K as Arg>::signature(), <V as Arg>::signature())).unwrap();
253 i.append_container(ArgType::Array, Some(&sig), |s| for (k, v) in self {
254 s.append_container(ArgType::DictEntry, None, |ss| {
255 k.append(ss);
256 v.append(ss);
257 })
258 });
259 }
260 #[inline]
261 fn as_any(&self) -> &dyn any::Any where Self: 'static { self }
262 #[inline]
263 fn as_any_mut(&mut self) -> &mut dyn any::Any where Self: 'static { self }
264 fn as_iter<'b>(&'b self) -> Option<Box<dyn Iterator<Item=&'b dyn RefArg> + 'b>> {
265 Some(Box::new(self.iter().flat_map(|(k, v)| vec![k as &dyn RefArg, v as &dyn RefArg].into_iter())))
266 }
267 fn box_clone(&self) -> Box<dyn RefArg + 'static> {
268 Box::new(InternalDict {
269 outer_sig: self.signature(),
270 data: self.iter().map(|(k, v)| (k.box_clone(), v.box_clone())).collect(),
271 })
272 }
273}
274
275
276impl<T: Arg> Arg for Vec<T> {
277 const ARG_TYPE: ArgType = ArgType::Array;
278 fn signature() -> Signature<'static> { Signature::from(format!("a{}", T::signature())) }
279}
280
281impl<T: Arg + Append> Append for Vec<T> {
282 fn append_by_ref(&self, i: &mut IterAppend) {
283 Array::new(self).append_by_ref(i);
284 }
285}
286
287impl<'a, T: Arg + Get<'a>> Get<'a> for Vec<T> {
288 fn get(i: &mut Iter<'a>) -> Option<Self> {
289 <Array<T, Iter<'a>>>::get(i).map(|a| a.collect())
290 }
291}
292
293
294#[derive(Copy, Clone, Debug)]
295/// Represents a D-Bus Array. Maximum flexibility (wraps an iterator of items to append).
296///
297/// See the argument guide and module level documentation for details and alternatives.
298pub struct Array<'a, T, I>(I, PhantomData<(fn() -> T, &'a ())>);
299
300impl<'a, T: 'a, I: Iterator<Item=T>> Array<'a, T, I> {
301 /// Creates a new Array from an iterator.
302 pub fn new<J: IntoIterator<IntoIter=I, Item=T>>(j: J) -> Array<'a, T, I> { Array(j.into_iter(), PhantomData) }
303}
304
305impl<'a, T: Arg, I> Arg for Array<'a, T, I> {
306 const ARG_TYPE: ArgType = ArgType::Array;
307 fn signature() -> Signature<'static> { Signature::from(format!("a{}", T::signature())) }
308}
309
310impl<'a, T: 'a + Arg + Append, I: Iterator<Item=T> + Clone> Append for Array<'a, T, I> {
311 fn append_by_ref(&self, i: &mut IterAppend) {
312 let z = self.0.clone();
313 i.append_container(ArgType::Array, sig:Some(T::signature().as_cstr()), |s: &mut IterAppend<'_>| for arg in z { arg.append_by_ref(s) });
314 }
315}
316
317impl<'a, T: Arg + Get<'a>> Get<'a> for Array<'a, T, Iter<'a>> {
318 fn get(i: &mut Iter<'a>) -> Option<Array<'a, T, Iter<'a>>> {
319 i.recurse(Self::ARG_TYPE).map(|si| Array(si, PhantomData))
320 // TODO: Verify full element signature?
321 }
322}
323
324impl<'a, T: Get<'a>> Iterator for Array<'a, T, Iter<'a>> {
325 type Item = T;
326 fn next(&mut self) -> Option<T> {
327 let i = self.0.get();
328 self.0.next();
329 i
330 }
331}
332
333// Due to the strong typing here; RefArg is implemented only for T's that are both Arg and RefArg.
334// We need Arg for this to work for empty arrays (we can't get signature from first element if there is no elements).
335// We need RefArg for box_clone.
336impl<'a, T, I> RefArg for Array<'static, T, I>
337where
338 T: 'a + Arg + RefArg,
339 I: fmt::Debug + Clone + Send + Sync + Iterator<Item=&'a T>
340{
341 fn arg_type(&self) -> ArgType { ArgType::Array }
342 fn signature(&self) -> Signature<'static> { Signature::from(format!("a{}", <T as Arg>::signature())) }
343 fn append(&self, i: &mut IterAppend) {
344 let z = self.0.clone();
345 i.append_container(ArgType::Array, sig:Some(<T as Arg>::signature().as_cstr()), |s: &mut IterAppend<'_>|
346 for arg: &{unknown} in z { RefArg::append(self:arg, s); }
347 );
348 }
349 #[inline]
350 fn as_any(&self) -> &dyn any::Any where Self: 'static { self }
351 #[inline]
352 fn as_any_mut(&mut self) -> &mut dyn any::Any where Self: 'static { self }
353
354 fn box_clone(&self) -> Box<dyn RefArg + 'static> {
355 Box::new(InternalArray {
356 inner_sig: <T as Arg>::signature(),
357 data: self.0.clone().map(|x| x.box_clone()).collect(),
358 })
359 }
360}
361
362fn get_fixed_array_refarg<T: FixedArray + Clone + RefArg>(i: &mut Iter) -> Box<dyn RefArg> {
363 let s = <&[T]>::get(i).unwrap();
364 Box::new(s.to_vec())
365}
366
367fn get_var_array_refarg<'a, T: 'static + RefArg + Arg, F: FnMut(&mut Iter<'a>) -> Option<T>>
368 (i: &mut Iter<'a>, mut f: F) -> Box<dyn RefArg> {
369 let mut v: Vec<T> = vec!(); // dbus_message_iter_get_element_count might be O(n), better not use it
370 let mut si = i.recurse(ArgType::Array).unwrap();
371 while let Some(q) = f(&mut si) { v.push(q); si.next(); }
372 Box::new(v)
373}
374
375fn get_dict_refarg<'a, K, V, KF, VF>(i: &mut Iter<'a>, mut kf: KF, mut vf: VF) -> Box<dyn RefArg>
376where
377 K: DictKey + 'static + RefArg + Clone + Eq + Hash,
378 V: RefArg + Arg + 'static,
379 KF: FnMut(&mut Iter<'a>) -> Option<K>,
380 VF: FnMut(&mut Iter<'a>) -> Option<V>,
381{
382 let mut data: HashMap<K, V> = HashMap::new();
383 let mut si = i.recurse(ArgType::Array).unwrap();
384 while let Some(mut d) = si.recurse(ArgType::DictEntry) {
385 let k: K = kf(&mut d).unwrap();
386 d.next();
387 let v: V = vf(&mut d).unwrap();
388 data.insert(k, v);
389 si.next();
390 }
391 Box::new(data)
392}
393
394#[derive(Debug)]
395struct InternalDict<K> {
396 data: Vec<(K, Box<dyn RefArg>)>,
397 outer_sig: Signature<'static>,
398}
399
400fn get_internal_dict_refarg<'a, K, F: FnMut(&mut Iter<'a>) -> Option<K>>(
401 i: &mut Iter<'a>,
402 mut f: F,
403) -> Box<dyn RefArg>
404where
405 K: DictKey + 'static + RefArg + Clone,
406{
407 let mut data = vec![];
408 let outer_sig: Signature<'static> = i.signature();
409 let mut si = i.recurse(ArgType::Array).unwrap();
410 while let Some(mut d) = si.recurse(ArgType::DictEntry) {
411 let k = f(&mut d).unwrap();
412 d.next();
413 data.push((k, d.get_refarg().unwrap()));
414 si.next();
415 }
416 Box::new(InternalDict { data, outer_sig })
417}
418
419// This only happens from box_clone
420impl RefArg for InternalDict<Box<dyn RefArg>> {
421 fn arg_type(&self) -> ArgType { ArgType::Array }
422 fn signature(&self) -> Signature<'static> { self.outer_sig.clone() }
423 fn append(&self, i: &mut IterAppend) {
424 let inner_sig = &self.outer_sig.as_cstr().to_bytes_with_nul()[1..];
425 let inner_sig = CStr::from_bytes_with_nul(inner_sig).unwrap();
426 i.append_container(ArgType::Array, Some(inner_sig), |s| for (k, v) in &self.data {
427 s.append_container(ArgType::DictEntry, None, |ss| {
428 k.append(ss);
429 v.append(ss);
430 })
431 });
432 }
433 #[inline]
434 fn as_any(&self) -> &dyn any::Any where Self: 'static { self }
435 #[inline]
436 fn as_any_mut(&mut self) -> &mut dyn any::Any where Self: 'static { self }
437 fn as_iter<'b>(&'b self) -> Option<Box<dyn Iterator<Item=&'b dyn RefArg> + 'b>> {
438 Some(Box::new(self.data.iter().flat_map(|(k, v)| vec![k as &dyn RefArg, v as &dyn RefArg].into_iter())))
439 }
440 fn as_static_inner(&self, index: usize) -> Option<&(dyn RefArg + 'static)> where Self: 'static {
441 let (k, v) = self.data.get(index / 2)?;
442 Some(if index & 1 != 0 { v } else { k })
443 }
444 #[inline]
445 fn box_clone(&self) -> Box<dyn RefArg + 'static> {
446 Box::new(InternalDict {
447 data: self.data.iter().map(|(k, v)| (k.box_clone(), v.box_clone())).collect(),
448 outer_sig: self.outer_sig.clone(),
449 })
450 }
451}
452
453
454impl<K: DictKey + RefArg + Clone + 'static> RefArg for InternalDict<K> {
455 fn arg_type(&self) -> ArgType { ArgType::Array }
456 fn signature(&self) -> Signature<'static> { self.outer_sig.clone() }
457 fn append(&self, i: &mut IterAppend) {
458 let inner_sig = &self.outer_sig.as_cstr().to_bytes_with_nul()[1..];
459 let inner_sig = CStr::from_bytes_with_nul(inner_sig).unwrap();
460 i.append_container(ArgType::Array, Some(inner_sig), |s| for (k, v) in &self.data {
461 s.append_container(ArgType::DictEntry, None, |ss| {
462 k.append(ss);
463 v.append(ss);
464 })
465 });
466 }
467 #[inline]
468 fn as_any(&self) -> &dyn any::Any where Self: 'static { self }
469 #[inline]
470 fn as_any_mut(&mut self) -> &mut dyn any::Any where Self: 'static { self }
471 fn as_iter<'b>(&'b self) -> Option<Box<dyn Iterator<Item=&'b dyn RefArg> + 'b>> {
472 Some(Box::new(self.data.iter().flat_map(|(k, v)| vec![k as &dyn RefArg, v as &dyn RefArg].into_iter())))
473 }
474 fn as_static_inner(&self, index: usize) -> Option<&(dyn RefArg + 'static)> where Self: 'static {
475 let (k, v) = self.data.get(index / 2)?;
476 Some(if index & 1 != 0 { v } else { k })
477 }
478 #[inline]
479 fn box_clone(&self) -> Box<dyn RefArg + 'static> {
480 Box::new(InternalDict {
481 data: self.data.iter().map(|(k, v)| (k.clone(), v.box_clone())).collect(),
482 outer_sig: self.outer_sig.clone(),
483 })
484 }
485}
486
487
488// Fallback for Arrays of Arrays and Arrays of Structs.
489// We store the signature manually here and promise that it is correct for all elements
490// has that signature.
491#[derive(Debug)]
492struct InternalArray {
493 data: Vec<Box<dyn RefArg>>,
494 inner_sig: Signature<'static>,
495}
496
497fn get_internal_array(i: &mut Iter) -> Box<dyn RefArg> {
498 let mut si = i.recurse(ArgType::Array).unwrap();
499 let inner_sig: Signature<'static> = si.signature();
500 let data = si.collect::<Vec<_>>();
501 Box::new(InternalArray { data, inner_sig })
502}
503
504impl RefArg for InternalArray {
505 fn arg_type(&self) -> ArgType { ArgType::Array }
506 fn signature(&self) -> Signature<'static> { Signature::from(format!("a{}", self.inner_sig)) }
507 fn append(&self, i: &mut IterAppend) {
508 i.append_container(ArgType::Array, Some(self.inner_sig.as_cstr()), |s|
509 for arg in &self.data { RefArg::append(arg,s) }
510 );
511 }
512 #[inline]
513 fn as_any(&self) -> &dyn any::Any where Self: 'static { self }
514 #[inline]
515 fn as_any_mut(&mut self) -> &mut dyn any::Any where Self: 'static { self }
516 fn as_iter<'a>(&'a self) -> Option<Box<dyn Iterator<Item=&'a dyn RefArg> + 'a>> {
517 Some(Box::new(self.data.iter().map(|b| b as &dyn RefArg)))
518 }
519 fn as_static_inner(&self, index: usize) -> Option<&(dyn RefArg + 'static)> where Self: 'static {
520 self.data.get(index).map(|x| x as &dyn RefArg)
521 }
522 #[inline]
523 fn box_clone(&self) -> Box<dyn RefArg + 'static> {
524 Box::new(InternalArray {
525 data: self.data.iter().map(|x| x.box_clone()).collect(),
526 inner_sig: self.inner_sig.clone(),
527 })
528 }
529}
530
531fn get_dict_refarg_for_value_type<'a, K, KF>(
532 value_type: ArgType,
533 i: &mut Iter<'a>,
534 kf: KF,
535) -> Box<dyn RefArg>
536where
537 K: DictKey + 'static + RefArg + Clone + Eq + Hash,
538 KF: FnMut(&mut Iter<'a>) -> Option<K>,
539{
540 match value_type {
541 ArgType::Variant => {
542 get_dict_refarg::<K, Variant<Box<dyn RefArg>>, KF, _>(i, kf, Variant::new_refarg)
543 }
544 // Most of the following could also use get_dict_refarg to convert to a typed HashMap, but
545 // doing so results in a large binary size increase due to all the generic instances being
546 // instantiated.
547 ArgType::Byte
548 | ArgType::Int16
549 | ArgType::UInt16
550 | ArgType::Int32
551 | ArgType::UInt32
552 | ArgType::Int64
553 | ArgType::UInt64
554 | ArgType::Double
555 | ArgType::String
556 | ArgType::ObjectPath
557 | ArgType::Signature
558 | ArgType::Boolean
559 | ArgType::UnixFd
560 | ArgType::Array
561 | ArgType::Struct => get_internal_dict_refarg::<K, KF>(i, kf),
562 ArgType::DictEntry => panic!("Can't have DictEntry as value for dictionary"),
563 ArgType::Invalid => panic!("Array with invalid dictvalue"),
564 }
565}
566
567pub fn get_array_refarg(i: &mut Iter) -> Box<dyn RefArg> {
568 debug_assert!(i.arg_type() == ArgType::Array);
569 let etype = ArgType::from_i32(unsafe { ffi::dbus_message_iter_get_element_type(&mut i.0) } as i32).unwrap();
570
571 let x = match etype {
572 ArgType::Byte => get_fixed_array_refarg::<u8>(i),
573 ArgType::Int16 => get_fixed_array_refarg::<i16>(i),
574 ArgType::UInt16 => get_fixed_array_refarg::<u16>(i),
575 ArgType::Int32 => get_fixed_array_refarg::<i32>(i),
576 ArgType::UInt32 => get_fixed_array_refarg::<u32>(i),
577 ArgType::Int64 => get_fixed_array_refarg::<i64>(i),
578 ArgType::UInt64 => get_fixed_array_refarg::<u64>(i),
579 ArgType::Double => get_fixed_array_refarg::<f64>(i),
580 ArgType::String => get_var_array_refarg::<String, _>(i, |si| si.get()),
581 ArgType::ObjectPath => get_var_array_refarg::<Path<'static>, _>(i, |si| si.get::<Path>().map(|s| s.into_static())),
582 ArgType::Signature => get_var_array_refarg::<Signature<'static>, _>(i, |si| si.get::<Signature>().map(|s| s.into_static())),
583 ArgType::Variant => get_var_array_refarg::<Variant<Box<dyn RefArg>>, _>(i, |si| Variant::new_refarg(si)),
584 ArgType::Boolean => get_var_array_refarg::<bool, _>(i, |si| si.get()),
585 ArgType::Invalid => panic!("Array with Invalid ArgType"),
586 ArgType::Array => get_internal_array(i),
587 ArgType::DictEntry => {
588 let key = ArgType::from_i32(i.signature().as_bytes()[2] as i32).unwrap(); // The third character, after "a{", is our key.
589 let value = ArgType::from_i32(i.signature().as_bytes()[3] as i32).unwrap(); // The fourth character, after "a{", is our value.
590 match key {
591 ArgType::Byte => get_dict_refarg_for_value_type::<u8, _>(value, i, Iter::get),
592 ArgType::Int16 => get_dict_refarg_for_value_type::<i16, _>(value, i, Iter::get),
593 ArgType::UInt16 => get_dict_refarg_for_value_type::<u16, _>(value, i, Iter::get),
594 ArgType::Int32 => get_dict_refarg_for_value_type::<i32, _>(value, i, Iter::get),
595 ArgType::UInt32 => get_dict_refarg_for_value_type::<u32, _>(value, i, Iter::get),
596 ArgType::Int64 => get_dict_refarg_for_value_type::<i64, _>(value, i, Iter::get),
597 ArgType::UInt64 => get_dict_refarg_for_value_type::<u64, _>(value, i, Iter::get),
598 ArgType::Double => get_internal_dict_refarg::<f64, _>(i, Iter::get),
599 ArgType::Boolean => get_dict_refarg_for_value_type::<bool, _>(value, i, Iter::get),
600 // ArgType::UnixFd => get_dict_refarg::<OwnedFd, _>(i),
601 ArgType::String => get_dict_refarg_for_value_type::<String, _>(value, i, Iter::get),
602 ArgType::ObjectPath => {
603 get_dict_refarg_for_value_type::<Path<'static>, _>(value, i, |si| {
604 si.get::<Path>().map(|s| s.into_static())
605 })
606 }
607 ArgType::Signature => {
608 get_dict_refarg_for_value_type::<Signature<'static>, _>(value, i, |si| {
609 si.get::<Signature>().map(|s| s.into_static())
610 })
611 }
612 _ => panic!("Array with invalid dictkey ({:?})", key),
613 }
614 }
615 ArgType::UnixFd => get_var_array_refarg::<std::fs::File, _>(i, |si| si.get()),
616 ArgType::Struct => get_internal_array(i),
617 };
618
619 debug_assert_eq!(i.signature(), x.signature());
620 x
621}
622