• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use core::any::Any;
2 
3 use dbus_macros::{dbus_propmap, generate_dbus_arg};
4 
5 use dbus::arg::{Arg, ArgType, IterAppend, RefArg};
6 use dbus::Signature;
7 
8 generate_dbus_arg!();
9 
10 #[derive(Debug, Default, Clone, PartialEq)]
11 struct OtherStruct {
12     address: String,
13 }
14 
15 #[dbus_propmap(OtherStruct)]
16 struct OtherStructDBus {
17     address: String,
18 }
19 
20 #[derive(Debug, Default, Clone, PartialEq)]
21 struct SomeStruct {
22     name: String,
23     number: i32,
24     other_struct: OtherStruct,
25     bytes: Vec<u8>,
26     nested: Vec<Vec<String>>,
27     recursive: Vec<SomeStruct>,
28 }
29 
30 #[dbus_propmap(SomeStruct)]
31 struct SomeStructDBus {
32     name: String,
33     number: i32,
34     other_struct: OtherStruct,
35     bytes: Vec<u8>,
36     nested: Vec<Vec<String>>,
37     recursive: Vec<SomeStruct>,
38 }
39 
40 // Pretends to be a D-Bus dictionary.
41 #[derive(Debug)]
42 struct FakeDictionary {
43     items: Vec<(String, Box<dyn RefArg>)>,
44 }
45 
46 impl RefArg for FakeDictionary {
arg_type(&self) -> ArgType47     fn arg_type(&self) -> ArgType {
48         todo!()
49     }
signature(&self) -> dbus::Signature<'static>50     fn signature(&self) -> dbus::Signature<'static> {
51         todo!()
52     }
append(&self, _: &mut IterAppend<'_>)53     fn append(&self, _: &mut IterAppend<'_>) {
54         todo!()
55     }
as_any(&self) -> &(dyn Any + 'static)56     fn as_any(&self) -> &(dyn Any + 'static) {
57         todo!()
58     }
as_any_mut(&mut self) -> &mut (dyn Any + 'static)59     fn as_any_mut(&mut self) -> &mut (dyn Any + 'static) {
60         todo!()
61     }
box_clone(&self) -> Box<dyn RefArg + 'static>62     fn box_clone(&self) -> Box<dyn RefArg + 'static> {
63         Box::new(FakeDictionary {
64             items: self.items.iter().map(|(k, v)| (k.clone(), v.box_clone())).collect(),
65         })
66     }
67 
as_iter<'b>(&'b self) -> Option<Box<dyn Iterator<Item = &'b dyn RefArg> + 'b>>68     fn as_iter<'b>(&'b self) -> Option<Box<dyn Iterator<Item = &'b dyn RefArg> + 'b>> {
69         Some(Box::new(
70             self.items
71                 .iter()
72                 .flat_map(|(k, v)| vec![k as &dyn RefArg, v as &dyn RefArg].into_iter()),
73         ))
74     }
75 }
76 
77 impl Arg for FakeDictionary {
78     const ARG_TYPE: ArgType = ArgType::Array;
signature() -> dbus::Signature<'static>79     fn signature() -> dbus::Signature<'static> {
80         Signature::from("a{sv}")
81     }
82 }
83 
84 #[cfg(test)]
85 mod tests {
86     use super::*;
87 
88     #[test]
test_dbus_propmap_error()89     fn test_dbus_propmap_error() {
90         let data_dbus = String::from("some data");
91         let result = <dbus::arg::PropMap as RefArgToRust>::ref_arg_to_rust(
92             &data_dbus,
93             String::from("Some Variable"),
94         );
95         assert!(result.is_err());
96         assert_eq!("Some Variable is not iterable", result.unwrap_err().to_string());
97     }
98 
99     #[test]
test_dbus_propmap_success()100     fn test_dbus_propmap_success() {
101         let data_dbus = FakeDictionary {
102             items: vec![
103                 (String::from("name"), Box::new(String::from("foo"))),
104                 (String::from("number"), Box::new(100)),
105                 (
106                     String::from("other_struct"),
107                     Box::new(FakeDictionary {
108                         items: vec![(
109                             String::from("address"),
110                             Box::new(String::from("aa:bb:cc:dd:ee:ff")),
111                         )],
112                     }),
113                 ),
114                 (String::from("bytes"), Box::new(vec![1 as u8, 2, 3])),
115                 (
116                     String::from("nested"),
117                     Box::new(vec![
118                         vec![
119                             String::from("string a"),
120                             String::from("string b"),
121                             String::from("string c"),
122                         ],
123                         vec![String::from("string 1"), String::from("string 2")],
124                     ]),
125                 ),
126                 (
127                     String::from("recursive"),
128                     Box::new(vec![FakeDictionary {
129                         items: vec![
130                             (String::from("name"), Box::new(String::from("bar"))),
131                             (String::from("number"), Box::new(200)),
132                             (
133                                 String::from("other_struct"),
134                                 Box::new(FakeDictionary {
135                                     items: vec![(
136                                         String::from("address"),
137                                         Box::new(String::from("xx")),
138                                     )],
139                                 }),
140                             ),
141                             (String::from("bytes"), Box::new(Vec::<u8>::new())),
142                             (String::from("nested"), Box::new(Vec::<Vec<u8>>::new())),
143                             (String::from("recursive"), Box::new(Vec::<FakeDictionary>::new())),
144                         ],
145                     }]),
146                 ),
147             ],
148         };
149         let result = <dbus::arg::PropMap as RefArgToRust>::ref_arg_to_rust(
150             &data_dbus,
151             String::from("Some Variable"),
152         );
153         assert!(result.is_ok());
154         let result = result.unwrap();
155         let result_struct = <SomeStruct as DBusArg>::from_dbus(result, None, None, None).unwrap();
156         let expected_struct = SomeStruct {
157             name: String::from("foo"),
158             number: 100,
159             other_struct: OtherStruct { address: String::from("aa:bb:cc:dd:ee:ff") },
160             bytes: vec![1, 2, 3],
161             nested: vec![
162                 vec![String::from("string a"), String::from("string b"), String::from("string c")],
163                 vec![String::from("string 1"), String::from("string 2")],
164             ],
165             recursive: vec![SomeStruct {
166                 name: String::from("bar"),
167                 number: 200,
168                 other_struct: OtherStruct { address: String::from("xx") },
169                 bytes: vec![],
170                 nested: vec![],
171                 recursive: vec![],
172             }],
173         };
174         assert_eq!(expected_struct, result_struct);
175     }
176 }
177