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