1#![allow(dead_code)]
2
3use crate::{Signature, arg::TypeMismatchError, arg::Variant};
4use std::{fmt, any};
5use std::sync::Arc;
6// use std::rc::Rc;
7use std::collections::HashMap;
8
9use super::{Iter, IterAppend, ArgType};
10
11/// Types that can represent a D-Bus message argument implement this trait.
12///
13/// Types should also implement either Append or Get to be useful.
14pub trait Arg {
15 /// The corresponding D-Bus argument type code.
16 const ARG_TYPE: ArgType;
17 /// The corresponding D-Bus type signature for this type.
18 fn signature() -> Signature<'static>;
19}
20
21/// Helper trait to introspect many arguments.
22pub trait ArgAll {
23 /// A tuple of &static str. Used for introspection.
24 #[allow(non_camel_case_types)] // Note: This should be changed for 0.9 - but for now, don't break backwards compatibility
25 type strs;
26 /// Enumerates all arguments with their signatures (introspection helper method).
27 fn strs_sig<F: FnMut(&'static str, Signature<'static>)>(a: Self::strs, f: F);
28}
29
30/// Types that can be appended to a message as arguments implement this trait.
31pub trait Append {
32 /// Performs the append operation by consuming self.
33 fn append(self, ia: &mut IterAppend) where Self: Sized { self.append_by_ref(ia) }
34
35 /// Performs the append operation by borrowing self.
36 fn append_by_ref(&self, _: &mut IterAppend);
37}
38
39/// Helper trait to append many arguments to a message.
40pub trait AppendAll {
41 /// Performs the append operation by borrowing self.
42 fn append(&self, _: &mut IterAppend);
43}
44
45/// Types that can be retrieved from a message as arguments implement this trait.
46pub trait Get<'a>: Sized {
47 /// Performs the get operation.
48 fn get(i: &mut Iter<'a>) -> Option<Self>;
49}
50
51/// Helper trait to read all arguments from a message.
52pub trait ReadAll: Sized {
53 /// Performs the read operation.
54 fn read(i: &mut Iter) -> Result<Self, TypeMismatchError>;
55}
56
57
58/// Object safe version of Arg + Append + Get.
59pub trait RefArg: fmt::Debug + Send + Sync {
60 /// The corresponding D-Bus argument type code.
61 fn arg_type(&self) -> ArgType;
62 /// The corresponding D-Bus type signature for this type.
63 fn signature(&self) -> Signature<'static>;
64 /// Performs the append operation.
65 fn append(&self, _: &mut IterAppend);
66 /// Transforms this argument to Any (which can be downcasted to read the current value).
67 ///
68 /// See the argument guide's reference section for which types you can cast to.
69 fn as_any(&self) -> &dyn any::Any where Self: 'static;
70 /// Transforms this argument to Any (which can be downcasted to read the current value).
71 ///
72 /// See the argument guide's reference section for which types you can cast to.
73 /// # Panic
74 /// Will panic if the interior cannot be made mutable, e g, if encapsulated
75 /// inside a Rc with a reference count > 1.
76 fn as_any_mut(&mut self) -> &mut dyn any::Any where Self: 'static;
77 /// Try to read the argument as an i64.
78 ///
79 /// Works for: Boolean, Byte, Int16, UInt16, Int32, UInt32, Int64, UnixFd.
80 #[inline]
81 fn as_i64(&self) -> Option<i64> { None }
82 /// Try to read the argument as an u64.
83 ///
84 /// Works for: Boolean, Byte, Int16, UInt16, Int32, UInt32, UInt64.
85 #[inline]
86 fn as_u64(&self) -> Option<u64> { None }
87 /// Try to read the argument as an f64.
88 ///
89 /// Works for: Boolean, Byte, Int16, UInt16, Int32, UInt32, Double.
90 #[inline]
91 fn as_f64(&self) -> Option<f64> { None }
92 /// Try to read the argument as a str.
93 ///
94 /// Works for: String, ObjectPath, Signature.
95 #[inline]
96 fn as_str(&self) -> Option<&str> { None }
97 /// Try to read the argument as an iterator.
98 ///
99 /// Works for: Array/Dict, Struct, Variant.
100 /// For Dicts, keys and values are interleaved.
101 #[inline]
102 fn as_iter<'a>(&'a self) -> Option<Box<dyn Iterator<Item=&'a dyn RefArg> + 'a>> { None }
103 /// Try to read the inner of an argument, as another argument, specifying an index.
104 ///
105 /// Works for: Variant, Array, Struct, Dict.
106 /// For Dicts, even indices gets a key, odd indices gets a value.
107 #[inline]
108 fn as_static_inner(&self, _index: usize) -> Option<&(dyn RefArg + 'static)> where Self: 'static { None }
109 /// Deep clone of the RefArg, causing the result to be 'static.
110 ///
111 /// Usable as an escape hatch in case of lifetime problems with RefArg.
112 ///
113 /// In case of complex types (Array, Dict, Struct), the clone is not guaranteed
114 /// to have the same internal representation as the original.
115 fn box_clone(&self) -> Box<dyn RefArg + 'static>;
116
117 /// Deep clone of an array.
118 ///
119 /// This method is used internally by box_clone.
120 fn array_clone(_arg: &[Self]) -> Option<Box<dyn RefArg + 'static>> where Self: Sized { None }
121}
122
123impl<'a> Get<'a> for Box<dyn RefArg> {
124 fn get(i: &mut Iter<'a>) -> Option<Self> { i.get_refarg() }
125}
126
127/// Cast a RefArg as a specific type (shortcut for any + downcast)
128///
129/// See the argument guide's reference section for which types you can cast to.
130#[inline]
131pub fn cast<'a, T: 'static>(a: &'a (dyn RefArg + 'static)) -> Option<&'a T> { a.as_any().downcast_ref() }
132
133/// Cast a RefArg as a specific type (shortcut for any_mut + downcast_mut)
134///
135/// See the argument guide's reference section for which types you can cast to.
136///
137/// # Panic
138/// Will panic if the interior cannot be made mutable, e g, if encapsulated
139/// inside a Rc with a reference count > 1.
140#[inline]
141pub fn cast_mut<'a, T: 'static>(a: &'a mut (dyn RefArg + 'static)) -> Option<&'a mut T> { a.as_any_mut().downcast_mut() }
142
143/// The type typically used for a dictionary of properties.
144pub type PropMap = HashMap<String, Variant<Box<dyn RefArg + 'static>>>;
145
146
147/// Descend into a hashmap returned by e g "Properties::get_all" to retrieve the value of a property.
148///
149/// Shortcut for get + cast. Returns None both if the property does not exist, or if it was of a different type.
150/// See the argument guide's reference section for which types you can cast to.
151pub fn prop_cast<'a, T: 'static>(map: &'a PropMap, key: &str) -> Option<&'a T> {
152 map.get(key).and_then(|v: &Variant>| cast(&v.0))
153}
154
155/// If a type implements this trait, it means the size and alignment is the same
156/// as in D-Bus. This means that you can quickly append and get slices of this type.
157///
158/// Note: Booleans do not implement this trait because D-Bus booleans are 4 bytes and Rust booleans are 1 byte.
159pub unsafe trait FixedArray: Arg + 'static + Clone + Copy {}
160
161/// Types that can be used as keys in a dict type implement this trait.
162pub trait DictKey: Arg {}
163
164
165
166/// Simple lift over reference to value - this makes some iterators more ergonomic to use
167impl<'a, T: Arg> Arg for &'a T {
168 const ARG_TYPE: ArgType = T::ARG_TYPE;
169 fn signature() -> Signature<'static> { T::signature() }
170}
171impl<'a, T: Append> Append for &'a T {
172 fn append_by_ref(&self, i: &mut IterAppend) { (&**self).append_by_ref(i) }
173}
174impl<'a, T: DictKey> DictKey for &'a T {}
175
176impl<'a, T: RefArg + ?Sized> RefArg for &'a T {
177 #[inline]
178 fn arg_type(&self) -> ArgType { (&**self).arg_type() }
179 #[inline]
180 fn signature(&self) -> Signature<'static> { (&**self).signature() }
181 #[inline]
182 fn append(&self, i: &mut IterAppend) { (&**self).append(i) }
183 #[inline]
184 fn as_any(&self) -> &dyn any::Any where T: 'static { (&**self).as_any() }
185 #[inline]
186 fn as_any_mut(&mut self) -> &mut dyn any::Any where T: 'static { unreachable!() }
187 #[inline]
188 fn as_i64(&self) -> Option<i64> { (&**self).as_i64() }
189 #[inline]
190 fn as_u64(&self) -> Option<u64> { (&**self).as_u64() }
191 #[inline]
192 fn as_f64(&self) -> Option<f64> { (&**self).as_f64() }
193 #[inline]
194 fn as_str(&self) -> Option<&str> { (&**self).as_str() }
195 #[inline]
196 fn as_iter<'b>(&'b self) -> Option<Box<dyn Iterator<Item=&'b dyn RefArg> + 'b>> { (&**self).as_iter() }
197 #[inline]
198 fn as_static_inner(&self, index: usize) -> Option<&(dyn RefArg + 'static)> where Self: 'static { (&**self).as_static_inner(index) }
199 #[inline]
200 fn box_clone(&self) -> Box<dyn RefArg + 'static> { (&**self).box_clone() }
201}
202
203
204
205macro_rules! deref_impl {
206 ($t: ident, $ss: ident, $make_mut: expr) => {
207
208impl<T: RefArg + ?Sized> RefArg for $t<T> {
209 #[inline]
210 fn arg_type(&self) -> ArgType { (&**self).arg_type() }
211 #[inline]
212 fn signature(&self) -> Signature<'static> { (&**self).signature() }
213 #[inline]
214 fn append(&self, i: &mut IterAppend) { (&**self).append(i) }
215 #[inline]
216 fn as_any(&self) -> &dyn any::Any where T: 'static { (&**self).as_any() }
217 #[inline]
218 fn as_any_mut(&mut $ss) -> &mut dyn any::Any where T: 'static { $make_mut.as_any_mut() }
219 #[inline]
220 fn as_i64(&self) -> Option<i64> { (&**self).as_i64() }
221 #[inline]
222 fn as_u64(&self) -> Option<u64> { (&**self).as_u64() }
223 #[inline]
224 fn as_f64(&self) -> Option<f64> { (&**self).as_f64() }
225 #[inline]
226 fn as_str(&self) -> Option<&str> { (&**self).as_str() }
227 #[inline]
228 fn as_iter<'a>(&'a self) -> Option<Box<dyn Iterator<Item=&'a dyn RefArg> + 'a>> { (&**self).as_iter() }
229 #[inline]
230 fn as_static_inner(&self, index: usize) -> Option<&(dyn RefArg + 'static)> where Self: 'static { (&**self).as_static_inner(index) }
231 #[inline]
232 fn box_clone(&self) -> Box<dyn RefArg + 'static> { (&**self).box_clone() }
233}
234impl<T: DictKey> DictKey for $t<T> {}
235
236impl<T: Arg> Arg for $t<T> {
237 const ARG_TYPE: ArgType = T::ARG_TYPE;
238 fn signature() -> Signature<'static> { T::signature() }
239}
240impl<'a, T: Get<'a>> Get<'a> for $t<T> {
241 fn get(i: &mut Iter<'a>) -> Option<Self> { T::get(i).map($t::new) }
242}
243
244 }
245}
246
247impl<T: Append> Append for Box<T> {
248 fn append_by_ref(&self, i: &mut IterAppend) { (&**self).append_by_ref(i) }
249}
250
251deref_impl!(Box, self, &mut **self );
252// deref_impl!(Rc, self, Rc::get_mut(self).unwrap());
253deref_impl!(Arc, self, Arc::get_mut(self).unwrap());
254
255macro_rules! argall_impl {
256 ($($n: ident $t: ident $s: ty,)+) => {
257
258impl<$($t: Arg),*> ArgAll for ($($t,)*) {
259 type strs = ($(&'static $s,)*);
260 fn strs_sig<Q: FnMut(&'static str, Signature<'static>)>(z: Self::strs, mut q: Q) {
261 let ( $($n,)*) = z;
262 $( q($n, $t::signature()); )*
263 }
264}
265
266impl<$($t: Append),*> AppendAll for ($($t,)*) {
267 fn append(&self, ia: &mut IterAppend) {
268 let ( $($n,)*) = self;
269 $( ia.append($n); )*
270 }
271}
272
273impl<$($t: Arg + for<'z> Get<'z>),*> ReadAll for ($($t,)*) {
274 fn read(ii: &mut Iter) -> Result<Self, TypeMismatchError> {
275 $( let $n = ii.read()?; )*
276 Ok(($( $n, )* ))
277 }
278}
279
280
281 }
282}
283
284impl ArgAll for () {
285 type strs = ();
286 fn strs_sig<F: FnMut(&'static str, Signature<'static>)>(_: Self::strs, _: F) {}
287}
288
289impl AppendAll for () {
290 fn append(&self, _: &mut IterAppend) {}
291}
292
293impl ReadAll for () {
294 fn read(_: &mut Iter) -> Result<Self, TypeMismatchError> {
295 Ok(())
296 }
297}
298
299argall_impl!(a A str,);
300argall_impl!(a A str, b B str,);
301argall_impl!(a A str, b B str, c C str,);
302argall_impl!(a A str, b B str, c C str, d D str,);
303argall_impl!(a A str, b B str, c C str, d D str, e E str,);
304argall_impl!(a A str, b B str, c C str, d D str, e E str, f F str,);
305argall_impl!(a A str, b B str, c C str, d D str, e E str, f F str, g G str,);
306argall_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,);
307argall_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,);
308argall_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,);
309argall_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, k K str,);
310argall_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, k K str, l L str,);
311argall_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, k K str, l L str, m M str,);
312argall_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, k K str, l L str, m M str, n N str,);
313argall_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, k K str, l L str, m M str, n N str, o O str,);
314argall_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, k K str, l L str, m M str, n N str, o O str, p P str,);
315argall_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, k K str, l L str, m M str, n N str, o O str, p P str, r R str,);
316argall_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, k K str, l L str, m M str, n N str, o O str, p P str, r R str, s S str,);
317argall_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, k K str, l L str, m M str, n N str, o O str, p P str, r R str, s S str, t T str,);
318argall_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, k K str, l L str, m M str, n N str, o O str, p P str, r R str, s S str, t T str, u U str,);
319argall_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, k K str, l L str, m M str, n N str, o O str, p P str, r R str, s S str, t T str, u U str, v V str,);
320argall_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, k K str, l L str, m M str, n N str, o O str, p P str, r R str, s S str, t T str, u U str, v V str, w W str,);
321argall_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, k K str, l L str, m M str, n N str, o O str, p P str, r R str, s S str, t T str, u U str, v V str, w W str, x X str,);
322argall_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, k K str, l L str, m M str, n N str, o O str, p P str, r R str, s S str, t T str, u U str, v V str, w W str, x X str, y Y str,);
323argall_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, k K str, l L str, m M str, n N str, o O str, p P str, r R str, s S str, t T str, u U str, v V str, w W str, x X str, y Y str, z Z str,);
324
325
326#[cfg(test)]
327mod test {
328 use crate::{channel::{Channel, BusType}, Message, Path, Signature};
329 use crate::message::MessageType;
330 use crate::arg::{Array, Variant, Dict, Iter, ArgType, TypeMismatchError, RefArg, cast};
331
332 use std::collections::HashMap;
333
334 #[test]
335 fn refarg() {
336 let c = Channel::get_private(BusType::Session).unwrap();
337 let m = Message::new_method_call(c.unique_name().unwrap(), "/mooh", "com.example.hello", "Hello").unwrap();
338
339 let mut vv: Vec<Variant<Box<dyn RefArg>>> = vec!();
340 vv.push(Variant(Box::new(5i32)));
341 vv.push(Variant(Box::new(String::from("Hello world"))));
342 let m = m.append_ref(&vv);
343
344 let (f1, f2) = (false, 7u64);
345 let mut v: Vec<&dyn RefArg> = vec!();
346 v.push(&f1);
347 v.push(&f2);
348 let m = m.append_ref(&v);
349 let vi32 = vec![7i32, 9i32];
350 let vstr: Vec<String> = ["This", "is", "dbus", "rs"].iter().map(|&s| s.into()).collect();
351 let m = m.append_ref(&[&vi32 as &dyn RefArg, &vstr as &dyn RefArg]);
352 let mut map = HashMap::new();
353 map.insert(true, String::from("Yes"));
354 map.insert(false, String::from("No"));
355 let m = m.append_ref(&[&map as &dyn RefArg, &1.5f64 as &dyn RefArg]);
356
357 c.send(m).unwrap();
358
359 loop {
360 if let Some(m) = c.blocking_pop_message(std::time::Duration::from_millis(1000)).unwrap() {
361 if m.msg_type() != MessageType::MethodCall { continue; }
362
363 let rv: Vec<Box<dyn RefArg + 'static>> = m.iter_init().collect();
364 println!("Receiving {:?}", rv);
365 let rv0: &Variant<Box<dyn RefArg>> = cast(&rv[0]).unwrap();
366 let rv00: &i32 = cast(&rv0.0).unwrap();
367 assert_eq!(rv00, &5i32);
368 assert_eq!(Some(&false), rv[2].as_any().downcast_ref::<bool>());
369 assert_eq!(Some(&vi32), rv[4].as_any().downcast_ref::<Vec<i32>>());
370 assert_eq!(Some(&vstr), rv[5].as_any().downcast_ref::<Vec<String>>());
371 let mut diter = rv[6].as_iter().unwrap();
372 {
373 let mut mmap: HashMap<bool, String> = HashMap::new();
374 while let Some(k) = diter.next() {
375 let x: String = diter.next().unwrap().as_str().unwrap().into();
376 mmap.insert(*cast::<bool>(&k.box_clone()).unwrap(), x);
377 }
378 assert_eq!(mmap[&true], "Yes");
379 }
380 let mut iter = rv[6].as_iter().unwrap();
381 assert!(iter.next().unwrap().as_i64().is_some());
382 assert!(iter.next().unwrap().as_str().is_some());
383 assert!(iter.next().unwrap().as_str().is_none());
384 assert!(iter.next().unwrap().as_i64().is_none());
385 assert!(iter.next().is_none());
386 assert!(rv[7].as_f64().unwrap() > 1.0);
387 assert!(rv[7].as_f64().unwrap() < 2.0);
388 break;
389 }
390 }
391 }
392
393 #[test]
394 fn message_types() {
395 let c = Channel::get_private(BusType::Session).unwrap();
396
397 let m = Message::new_method_call(c.unique_name().unwrap(), "/hello", "com.example.hello", "Hello").unwrap();
398 let m = m.append1(2000u16);
399 let m = m.append1(&Array::new(&vec![129u8, 5, 254]));
400 let m = m.append2(Variant(&["Hello", "world"][..]), &[32768u16, 16u16, 12u16][..]);
401 let m = m.append3(-1i32, &*format!("Hello world"), -3.14f64);
402 let m = m.append1((256i16, Variant(18_446_744_073_709_551_615u64)));
403 let m = m.append2(Path::new("/a/valid/path").unwrap(), &Signature::new("a{sv}").unwrap());
404 let mut z = HashMap::new();
405 z.insert(123543u32, true);
406 z.insert(0u32, false);
407 let m = m.append1(Dict::new(&z));
408 let sending = format!("{:?}", m.iter_init());
409 println!("Sending {}", sending);
410 c.send(m).unwrap();
411
412 loop {
413 if let Some(m) = c.blocking_pop_message(std::time::Duration::from_millis(1000)).unwrap() {
414 if m.msg_type() != MessageType::MethodCall { continue; }
415 use super::Arg;
416 let receiving = format!("{:?}", m.iter_init());
417 println!("Receiving {}", receiving);
418 assert_eq!(sending, receiving);
419
420 assert_eq!(2000u16, m.get1().unwrap());
421 assert_eq!(m.get2(), (Some(2000u16), Some(&[129u8, 5, 254][..])));
422 assert_eq!(m.read2::<u16, bool>().unwrap_err(),
423 TypeMismatchError { position: 1, found: ArgType::Array, expected: ArgType::Boolean });
424
425 let mut g = m.iter_init();
426 let e = g.read::<u32>().unwrap_err();
427 assert_eq!(e.pos(), 0);
428 assert_eq!(e.expected_arg_type(), ArgType::UInt32);
429 assert_eq!(e.found_arg_type(), ArgType::UInt16);
430
431 assert!(g.next() && g.next());
432 let v: Variant<Iter> = g.get().unwrap();
433 let mut viter = v.0;
434 assert_eq!(viter.arg_type(), Array::<&str,()>::ARG_TYPE);
435 let a: Array<&str, _> = viter.get().unwrap();
436 assert_eq!(a.collect::<Vec<&str>>(), vec!["Hello", "world"]);
437
438 assert!(g.next());
439 assert_eq!(g.get::<u16>(), None); // It's an array, not a single u16
440 assert!(g.next() && g.next() && g.next() && g.next());
441
442 assert_eq!(g.get(), Some((256i16, Variant(18_446_744_073_709_551_615u64))));
443 assert!(g.next());
444 assert_eq!(g.get(), Some(Path::new("/a/valid/path").unwrap()));
445 assert!(g.next());
446 assert_eq!(g.get(), Some(Signature::new("a{sv}").unwrap()));
447 assert!(g.next());
448 let d: Dict<u32, bool, _> = g.get().unwrap();
449 let z2: HashMap<_, _> = d.collect();
450 assert_eq!(z, z2);
451 break;
452 }
453 }
454 }
455
456 #[test]
457 fn cast_vecs() {
458 let c = Channel::get_private(BusType::Session).unwrap();
459
460 let m = Message::new_method_call(c.unique_name().unwrap(), "/hello", "com.example.hello", "Hello").unwrap();
461 macro_rules! append_array {
462 ($m:expr, $t:ty) => {
463 $m.append1(Variant(&Array::<&$t, _>::new(&vec![Default::default()])))
464 };
465 }
466 let m = append_array!(m, bool);
467 let m = append_array!(m, u8);
468 let m = append_array!(m, u16);
469 let m = append_array!(m, i16);
470 let m = append_array!(m, u32);
471 let m = append_array!(m, i32);
472 let m = append_array!(m, f64);
473 let m = append_array!(m, String);
474 c.send(m).unwrap();
475 loop {
476 if let Some(m) = c.blocking_pop_message(std::time::Duration::from_millis(1000)).unwrap() {
477 if m.msg_type() != MessageType::MethodCall {
478 continue;
479 }
480 let mut i = m.iter_init();
481 let mut i2 = m.iter_init();
482
483 macro_rules! check_array {
484 ($t:ty) => {
485 let array: Variant<Box<dyn RefArg>> = i.read().unwrap();
486 assert_eq!(
487 cast::<Vec<$t>>(&(array.0)),
488 Some(&vec![Default::default()]),
489 "a variant containing an array of {0} should be castable to a Vec<{0}>",
490 std::any::type_name::<$t>()
491 );
492 let refarg = i2.get_refarg().unwrap();
493 println!("refarg {:?}", refarg);
494 let cloned = refarg.box_clone();
495 println!("cloned: {:?}", cloned);
496 let st_inner = refarg.as_static_inner(0).unwrap();
497 println!("st_inner {:?}", st_inner);
498 i2.next();
499 assert_eq!(cast::<Vec<$t>>(st_inner), Some(&vec![Default::default()]));
500 let cl_inner = refarg.as_static_inner(0).unwrap();
501 assert_eq!(cast::<Vec<$t>>(cl_inner), Some(&vec![Default::default()]));
502 };
503 }
504 check_array!(bool);
505 check_array!(u8);
506 check_array!(u16);
507 check_array!(i16);
508 check_array!(u32);
509 check_array!(i32);
510 check_array!(f64);
511 check_array!(String);
512 break;
513 }
514 }
515 }
516
517 #[test]
518 fn cast_dicts() {
519 let c = Channel::get_private(BusType::Session).unwrap();
520
521 let m = Message::new_method_call(
522 c.unique_name().unwrap(),
523 "/hello",
524 "com.example.hello",
525 "Hello",
526 )
527 .unwrap();
528 macro_rules! append_dict_variant {
529 ($m:expr, $k:ty, $v:ty) => {{
530 let mut map: HashMap<$k, Variant<Box<dyn RefArg>>> = HashMap::new();
531 map.insert(Default::default(), Variant(Box::new(<$v>::default())));
532 $m.append1(Variant(&map))
533 }};
534 }
535 let m = append_dict_variant!(m, bool, bool);
536 let m = append_dict_variant!(m, u8, u8);
537 let m = append_dict_variant!(m, u16, u16);
538 let m = append_dict_variant!(m, i16, i16);
539 let m = append_dict_variant!(m, u32, u32);
540 let m = append_dict_variant!(m, i32, i32);
541 let m = append_dict_variant!(m, u64, u64);
542 let m = append_dict_variant!(m, i64, i64);
543 let m = append_dict_variant!(m, u8, f64);
544 let m = append_dict_variant!(m, String, String);
545 c.send(m).unwrap();
546 loop {
547 if let Some(m) = c
548 .blocking_pop_message(std::time::Duration::from_millis(1000))
549 .unwrap()
550 {
551 if m.msg_type() != MessageType::MethodCall {
552 continue;
553 }
554 let mut i = m.iter_init();
555 let mut i2 = m.iter_init();
556
557 macro_rules! check_dict_variant {
558 ($k:ty, $v:ty) => {
559 let map: Variant<Box<dyn RefArg>> = i.read().unwrap();
560 let expected_key: $k = Default::default();
561 let expected_value: $v = Default::default();
562 let cast_map = cast::<HashMap<$k, Variant<Box<dyn RefArg>>>>(&map.0);
563 assert!(cast_map.is_some(),
564 "a variant containing a dict of {0} to Variant({1}) should be castable to a HashMap<{0}, Variant<Box<dyn RefArg>>>",
565 std::any::type_name::<$k>(),
566 std::any::type_name::<$v>()
567 );
568 let cast_map_value = cast_map.unwrap().get(&expected_key).unwrap();
569 assert_eq!(
570 cast::<$v>(&cast_map_value.0),
571 Some(&expected_value),
572 "a variant {0:?} containing a {1} should be castable to {1}",
573 cast_map_value,
574 std::any::type_name::<$v>()
575 );
576 let refarg = i2.get_refarg().unwrap();
577 println!("refarg {:?}", refarg);
578 let st_inner = refarg.as_static_inner(0).unwrap();
579 println!("st_inner {:?}", st_inner);
580 i2.next();
581 assert!(cast::<HashMap<$k, Variant<Box<dyn RefArg>>>>(st_inner).is_some());
582 };
583 }
584 check_dict_variant!(bool, bool);
585 check_dict_variant!(u8, u8);
586 check_dict_variant!(u16, u16);
587 check_dict_variant!(i16, i16);
588 check_dict_variant!(u32, u32);
589 check_dict_variant!(i32, i32);
590 check_dict_variant!(u64, u64);
591 check_dict_variant!(i64, i64);
592 check_dict_variant!(u8, f64);
593 check_dict_variant!(String, String);
594 break;
595 }
596 }
597 }
598}
599