1 use super::utils::{ArcMap, Iter, IterE, Annotations, Introspect};
2 use super::{Factory, MethodType, MethodInfo, MethodResult, MethodErr, DataType, Property, Method, Signal, methodtype};
3 use std::sync::{Arc, Mutex};
4 use {Member, Message, Path, Signature, MessageType, Connection, ConnectionItem, Error, arg, MsgHandler, MsgHandlerType, MsgHandlerResult};
5 use Interface as IfaceName;
6 use std::fmt;
7 use std::ffi::CStr;
8 use super::leaves::prop_append_dict;
9 
introspect_map<I: fmt::Display, T: Introspect> (h: &ArcMap<I, T>, indent: &str) -> String10 fn introspect_map<I: fmt::Display, T: Introspect>
11     (h: &ArcMap<I, T>, indent: &str) -> String {
12 
13     h.iter().fold("".into(), |a, (k, v)| {
14         let (name, params, contents) = (v.xml_name(), v.xml_params(), v.xml_contents());
15         format!("{}{}<{} name=\"{}\"{}{}>\n",
16             a, indent, name, &*k, params, if contents.len() > 0 {
17                 format!(">\n{}{}</{}", contents, indent, name)
18             }
19             else { format!("/") }
20         )
21     })
22 }
23 
24 #[derive(Debug)]
25 /// Represents a D-Bus interface.
26 pub struct Interface<M: MethodType<D>, D: DataType> {
27     name: Arc<IfaceName<'static>>,
28     methods: ArcMap<Member<'static>, Method<M, D>>,
29     signals: ArcMap<Member<'static>, Signal<D>>,
30     properties: ArcMap<String, Property<M, D>>,
31     anns: Annotations,
32     data: D::Interface,
33 }
34 
35 impl<M: MethodType<D>, D: DataType> Interface<M, D> {
36     /// Builder function that adds a method to the interface.
add_m<I: Into<Arc<Method<M, D>>>>(mut self, m: I) -> Self37     pub fn add_m<I: Into<Arc<Method<M, D>>>>(mut self, m: I) -> Self {
38         let m = m.into();
39         self.methods.insert(m.get_name().clone(), m);
40         self
41     }
42 
43     /// Builder function that adds a signal to the interface.
add_s<I: Into<Arc<Signal<D>>>>(mut self, s: I) -> Self44     pub fn add_s<I: Into<Arc<Signal<D>>>>(mut self, s: I) -> Self {
45         let m = s.into();
46         self.signals.insert(m.get_name().clone(), m);
47         self
48     }
49 
50     /// Builder function that adds a property to the interface.
add_p<I: Into<Arc<Property<M, D>>>>(mut self, p: I) -> Self51     pub fn add_p<I: Into<Arc<Property<M, D>>>>(mut self, p: I) -> Self {
52         let m = p.into();
53         self.properties.insert(m.get_name().to_owned(), m);
54         self
55     }
56 
57     /// Builder function that adds an annotation to this interface.
annotate<N: Into<String>, V: Into<String>>(mut self, name: N, value: V) -> Self58     pub fn annotate<N: Into<String>, V: Into<String>>(mut self, name: N, value: V) -> Self {
59         self.anns.insert(name, value); self
60     }
61 
62     /// Builder function that adds an annotation that this entity is deprecated.
deprecated(self) -> Self63     pub fn deprecated(self) -> Self { self.annotate("org.freedesktop.DBus.Deprecated", "true") }
64 
65     /// Get interface name
get_name(&self) -> &IfaceName<'static>66     pub fn get_name(&self) -> &IfaceName<'static> { &self.name }
67 
68     /// Get associated data
get_data(&self) -> &D::Interface69     pub fn get_data(&self) -> &D::Interface { &self.data }
70 
71     /// Iterates over methods implemented by this interface.
iter_m<'a>(&'a self) -> Iter<'a, Method<M, D>>72     pub fn iter_m<'a>(&'a self) -> Iter<'a, Method<M, D>> { IterE::Member(self.methods.values()).into() }
73 
74     /// Iterates over signals implemented by this interface.
iter_s<'a>(&'a self) -> Iter<'a, Signal<D>>75     pub fn iter_s<'a>(&'a self) -> Iter<'a, Signal<D>> { IterE::Member(self.signals.values()).into() }
76 
77     /// Iterates over properties implemented by this interface.
iter_p<'a>(&'a self) -> Iter<'a, Property<M, D>>78     pub fn iter_p<'a>(&'a self) -> Iter<'a, Property<M, D>> { IterE::String(self.properties.values()).into() }
79 }
80 
81 impl<M: MethodType<D>, D: DataType> Introspect for Interface<M, D> {
xml_name(&self) -> &'static str82     fn xml_name(&self) -> &'static str { "interface" }
xml_params(&self) -> String83     fn xml_params(&self) -> String { String::new() }
xml_contents(&self) -> String84     fn xml_contents(&self) -> String {
85         format!("{}{}{}{}",
86             introspect_map(&self.methods, "    "),
87             introspect_map(&self.properties, "    "),
88             introspect_map(&self.signals, "    "),
89             self.anns.introspect("    "))
90     }
91 }
92 
93 
new_interface<M: MethodType<D>, D: DataType>(t: IfaceName<'static>, d: D::Interface) -> Interface<M, D>94 pub fn new_interface<M: MethodType<D>, D: DataType>(t: IfaceName<'static>, d: D::Interface) -> Interface<M, D> {
95     Interface { name: Arc::new(t), methods: ArcMap::new(), signals: ArcMap::new(),
96         properties: ArcMap::new(), anns: Annotations::new(), data: d
97     }
98 }
99 
100 
101 #[derive(Debug)]
102 /// Cache of built-in interfaces, in order to save memory when many object paths implement the same interface(s).
103 pub struct IfaceCache<M: MethodType<D>, D: DataType>(Mutex<ArcMap<IfaceName<'static>, Interface<M, D>>>);
104 
105 impl<M: MethodType<D>, D: DataType> IfaceCache<M, D>
106 where D::Interface: Default {
get<S: Into<IfaceName<'static>> + Clone, F>(&self, s: S, f: F) -> Arc<Interface<M, D>> where F: FnOnce(Interface<M, D>) -> Interface<M, D>107     pub fn get<S: Into<IfaceName<'static>> + Clone, F>(&self, s: S, f: F) -> Arc<Interface<M, D>>
108         where F: FnOnce(Interface<M, D>) -> Interface<M, D> {
109         let s2 = s.clone().into();
110         let mut m = self.0.lock().unwrap();
111         m.entry(s2).or_insert_with(|| {
112             let i = new_interface(s.into(), Default::default());
113             Arc::new(f(i))
114         }).clone()
115     }
116 }
117 
118 impl<M: MethodType<D>, D: DataType> IfaceCache<M, D> {
get_factory<S: Into<IfaceName<'static>> + Clone, F>(&self, s: S, f: F) -> Arc<Interface<M, D>> where F: FnOnce() -> Interface<M, D>119     pub fn get_factory<S: Into<IfaceName<'static>> + Clone, F>(&self, s: S, f: F) -> Arc<Interface<M, D>>
120         where F: FnOnce() -> Interface<M, D> {
121         let s2 = s.clone().into();
122         let mut m = self.0.lock().unwrap();
123         m.entry(s2).or_insert_with(|| {
124             Arc::new(f())
125         }).clone()
126     }
127 
128 
new() -> Arc<Self>129     pub fn new() -> Arc<Self> { Arc::new(IfaceCache(Mutex::new(ArcMap::new()))) }
130 }
131 
132 #[derive(Debug)]
133 /// A D-Bus Object Path.
134 pub struct ObjectPath<M: MethodType<D>, D: DataType> {
135     name: Arc<Path<'static>>,
136     ifaces: ArcMap<Arc<IfaceName<'static>>, Interface<M, D>>,
137     ifacecache: Arc<IfaceCache<M, D>>,
138     data: D::ObjectPath,
139 }
140 
141 impl<M: MethodType<D>, D: DataType> ObjectPath<M, D> {
142 
143     /// Get property name
get_name(&self) -> &Path<'static>144     pub fn get_name(&self) -> &Path<'static> { &self.name }
145 
146     /// Get associated data
get_data(&self) -> &D::ObjectPath147     pub fn get_data(&self) -> &D::ObjectPath { &self.data }
148 
149     /// Iterates over interfaces implemented by this object path.
iter<'a>(&'a self) -> Iter<'a, Interface<M, D>>150     pub fn iter<'a>(&'a self) -> Iter<'a, Interface<M, D>> { IterE::Iface(self.ifaces.values()).into() }
151 
introspect(&self, tree: &Tree<M, D>) -> String152     pub(super) fn introspect(&self, tree: &Tree<M, D>) -> String {
153         let ifacestr = introspect_map(&self.ifaces, "  ");
154         let olen = self.name.len()+1;
155         let childstr = tree.children(self, true).iter().fold("".to_string(), |na, n|
156             format!("{}  <node name=\"{}\"/>\n", na, &n.name[olen..])
157         );
158 
159         let nodestr = format!(r##"<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
160 <node name="{}">
161 {}{}</node>"##, self.name, ifacestr, childstr);
162         nodestr
163     }
164 
get_iface<'a>(&'a self, iface_name: &'a CStr) -> Result<&Arc<Interface<M, D>>, MethodErr>165     fn get_iface<'a>(&'a self, iface_name: &'a CStr) -> Result<&Arc<Interface<M, D>>, MethodErr> {
166         let j = try!(IfaceName::from_slice(iface_name.to_bytes_with_nul()).map_err(|e| MethodErr::invalid_arg(&e)));
167         self.ifaces.get(&j).ok_or_else(|| MethodErr::no_interface(&j))
168     }
169 
prop_get(&self, m: &MethodInfo<M, D>) -> MethodResult170     fn prop_get(&self, m: &MethodInfo<M, D>) -> MethodResult {
171         let (iname, prop_name): (&CStr, &str) = try!(m.msg.read2());
172         let iface = try!(self.get_iface(iname));
173         let prop: &Property<M, D> = try!(iface.properties.get(&String::from(prop_name))
174             .ok_or_else(|| MethodErr::no_property(&prop_name)));
175         try!(prop.can_get());
176         let mut mret = m.msg.method_return();
177         {
178             let mut iter = arg::IterAppend::new(&mut mret);
179             let pinfo = m.to_prop_info(iface, prop);
180             try!(prop.get_as_variant(&mut iter, &pinfo));
181         }
182         Ok(vec!(mret))
183     }
184 
prop_get_all(&self, m: &MethodInfo<M, D>) -> MethodResult185     fn prop_get_all(&self, m: &MethodInfo<M, D>) -> MethodResult {
186         let iface = try!(self.get_iface(try!(m.msg.read1())));
187         let mut mret = m.msg.method_return();
188         try!(prop_append_dict(&mut arg::IterAppend::new(&mut mret),
189             iface.properties.values().map(|v| &**v), m));
190         Ok(vec!(mret))
191     }
192 
193 
prop_set(&self, m: &MethodInfo<M, D>) -> MethodResult194     fn prop_set(&self, m: &MethodInfo<M, D>) -> MethodResult {
195         let (iname, prop_name): (&CStr, &str) = try!(m.msg.read2());
196         let iface = try!(self.get_iface(iname));
197         let prop: &Property<M, D> = try!(iface.properties.get(&String::from(prop_name))
198             .ok_or_else(|| MethodErr::no_property(&prop_name)));
199 
200         let mut iter = arg::Iter::new(m.msg);
201         iter.next(); iter.next();
202         let mut iter2 = iter;
203         try!(prop.can_set(Some(iter)));
204 
205         let pinfo = m.to_prop_info(iface, prop);
206         let mut r: Vec<Message> = try!(prop.set_as_variant(&mut iter2, &pinfo)).into_iter().collect();
207         r.push(m.msg.method_return());
208         Ok(r)
209 
210     }
211 
get_managed_objects(&self, m: &MethodInfo<M, D>) -> MethodResult212     fn get_managed_objects(&self, m: &MethodInfo<M, D>) -> MethodResult {
213         use arg::{Dict, Variant};
214         let mut paths = m.tree.children(&self, false);
215         paths.push(&self);
216         let mut result = Ok(());
217         let mut r = m.msg.method_return();
218         {
219             let mut i = arg::IterAppend::new(&mut r);
220             i.append_dict(&Signature::make::<Path>(), &Signature::make::<Dict<&str,Dict<&str,Variant<()>,()>,()>>(), |ii| {
221                 for p in paths {
222                     ii.append_dict_entry(|pi| {
223                         pi.append(&*p.name);
224                         pi.append_dict(&Signature::make::<&str>(), &Signature::make::<Dict<&str,Variant<()>,()>>(), |pii| {
225                             for ifaces in p.ifaces.values() {
226                                 let m2 = MethodInfo { msg: m.msg, path: p, iface: ifaces, tree: m.tree, method: m.method };
227                                 pii.append_dict_entry(|ppii| {
228                                     ppii.append(&**ifaces.name);
229                                     result = prop_append_dict(ppii, ifaces.properties.values().map(|v| &**v), &m2);
230                                 });
231                                 if result.is_err() { break; }
232                             }
233                         });
234                     });
235                     if result.is_err() { break; }
236                 }
237             });
238         }
239         try!(result);
240         Ok(vec!(r))
241     }
242 
handle(&self, m: &Message, t: &Tree<M, D>) -> MethodResult243     fn handle(&self, m: &Message, t: &Tree<M, D>) -> MethodResult {
244         let i = try!(m.interface().and_then(|i| self.ifaces.get(&i)).ok_or_else(|| MethodErr::no_interface(&"")));
245         let me = try!(m.member().and_then(|me| i.methods.get(&me)).ok_or_else(|| MethodErr::no_method(&"")));
246         let minfo = MethodInfo { msg: m, tree: t, path: self, iface: i, method: me };
247         me.call(&minfo)
248     }
249 
250 }
251 
252 impl<M: MethodType<D>, D: DataType> ObjectPath<M, D>
253 where <D as DataType>::Interface: Default, <D as DataType>::Method: Default
254 {
255     /// Adds introspection support for this object path.
introspectable(self) -> Self256     pub fn introspectable(self) -> Self {
257         let z = self.ifacecache.get_factory("org.freedesktop.DBus.Introspectable", || {
258             let f = Factory::from(self.ifacecache.clone());
259             methodtype::org_freedesktop_dbus_introspectable_server(&f, Default::default())
260         });
261         self.add(z)
262     }
263 
264     /// Builder function that adds a interface to the object path.
add<I: Into<Arc<Interface<M, D>>>>(mut self, s: I) -> Self265     pub fn add<I: Into<Arc<Interface<M, D>>>>(mut self, s: I) -> Self {
266         let m = s.into();
267         if !m.properties.is_empty() { self.add_property_handler(); }
268         self.ifaces.insert(m.name.clone(), m);
269         self
270     }
271 
272     /// Adds ObjectManager support for this object path.
273     ///
274     /// It is not possible to add/remove interfaces while the object path belongs to a tree,
275     /// hence no InterfacesAdded / InterfacesRemoved signals are sent.
object_manager(mut self) -> Self276     pub fn object_manager(mut self) -> Self {
277         use arg::{Variant, Dict};
278         let ifname = IfaceName::from("org.freedesktop.DBus.ObjectManager");
279         if self.ifaces.contains_key(&ifname) { return self };
280         let z = self.ifacecache.get(ifname, |i| {
281             i.add_m(super::leaves::new_method("GetManagedObjects".into(), Default::default(),
282                 M::make_method(|m| m.path.get_managed_objects(m)))
283                 .outarg::<Dict<Path,Dict<&str,Dict<&str,Variant<()>,()>,()>,()>,_>("objpath_interfaces_and_properties"))
284         });
285         self.ifaces.insert(z.name.clone(), z);
286         self
287     }
288 
add_property_handler(&mut self)289     fn add_property_handler(&mut self) {
290         use arg::{Variant, Dict};
291         let ifname = IfaceName::from("org.freedesktop.DBus.Properties");
292         if self.ifaces.contains_key(&ifname) { return };
293         let z = self.ifacecache.get(ifname, |i| {
294             i.add_m(super::leaves::new_method("Get".into(), Default::default(),
295                 M::make_method(|m| m.path.prop_get(m)))
296                 .inarg::<&str,_>("interface_name")
297                 .inarg::<&str,_>("property_name")
298                 .outarg::<Variant<()>,_>("value"))
299             .add_m(super::leaves::new_method("GetAll".into(), Default::default(),
300                 M::make_method(|m| m.path.prop_get_all(m)))
301                 .inarg::<&str,_>("interface_name")
302                 .outarg::<Dict<&str, Variant<()>, ()>,_>("props"))
303             .add_m(super::leaves::new_method("Set".into(), Default::default(),
304                 M::make_method(|m| m.path.prop_set(m)))
305                 .inarg::<&str,_>("interface_name")
306                 .inarg::<&str,_>("property_name")
307                 .inarg::<Variant<bool>,_>("value"))
308         });
309         self.ifaces.insert(z.name.clone(), z);
310     }
311 }
312 
new_objectpath<M: MethodType<D>, D: DataType>(n: Path<'static>, d: D::ObjectPath, cache: Arc<IfaceCache<M, D>>) -> ObjectPath<M, D>313 pub fn new_objectpath<M: MethodType<D>, D: DataType>(n: Path<'static>, d: D::ObjectPath, cache: Arc<IfaceCache<M, D>>)
314     -> ObjectPath<M, D> {
315     ObjectPath { name: Arc::new(n), data: d, ifaces: ArcMap::new(), ifacecache: cache }
316 }
317 
318 
319 /// A collection of object paths.
320 #[derive(Debug, Default)]
321 pub struct Tree<M: MethodType<D>, D: DataType> {
322     paths: ArcMap<Arc<Path<'static>>, ObjectPath<M, D>>,
323     data: D::Tree,
324 }
325 
326 impl<M: MethodType<D>, D: DataType> Tree<M, D> {
327     /// Builder function that adds an object path to this tree.
328     ///
329     /// Note: This does not register a path with the connection, so if the tree is currently registered,
330     /// you might want to call Connection::register_object_path to add the path manually.
add<I: Into<Arc<ObjectPath<M, D>>>>(mut self, s: I) -> Self331     pub fn add<I: Into<Arc<ObjectPath<M, D>>>>(mut self, s: I) -> Self {
332         self.insert(s);
333         self
334     }
335 
336     /// Get a reference to an object path from the tree.
get(&self, p: &Path<'static>) -> Option<&Arc<ObjectPath<M, D>>>337     pub fn get(&self, p: &Path<'static>) -> Option<&Arc<ObjectPath<M, D>>> {
338         self.paths.get(p)
339     }
340 
341     /// Iterates over object paths in this tree.
iter<'a>(&'a self) -> Iter<'a, ObjectPath<M, D>>342     pub fn iter<'a>(&'a self) -> Iter<'a, ObjectPath<M, D>> { IterE::Path(self.paths.values()).into() }
343 
344     /// Non-builder function that adds an object path to this tree.
345     ///
346     /// Note: This does not register a path with the connection, so if the tree is currently registered,
347     /// you might want to call Connection::register_object_path to add the path manually.
insert<I: Into<Arc<ObjectPath<M, D>>>>(&mut self, s: I)348     pub fn insert<I: Into<Arc<ObjectPath<M, D>>>>(&mut self, s: I) {
349         let m = s.into();
350         self.paths.insert(m.name.clone(), m);
351     }
352 
353 
354     /// Remove a object path from the Tree. Returns the object path removed, or None if not found.
355     ///
356     /// Note: This does not unregister a path with the connection, so if the tree is currently registered,
357     /// you might want to call Connection::unregister_object_path to remove the path manually.
remove(&mut self, p: &Path<'static>) -> Option<Arc<ObjectPath<M, D>>>358     pub fn remove(&mut self, p: &Path<'static>) -> Option<Arc<ObjectPath<M, D>>> {
359         // There is no real reason p needs to have a static lifetime; but
360         // the borrow checker doesn't agree. :-(
361         self.paths.remove(p)
362     }
363 
364     /// Registers or unregisters all object paths in the tree.
set_registered(&self, c: &Connection, b: bool) -> Result<(), Error>365     pub fn set_registered(&self, c: &Connection, b: bool) -> Result<(), Error> {
366         let mut regd_paths = Vec::new();
367         for p in self.paths.keys() {
368             if b {
369                 match c.register_object_path(p) {
370                     Ok(()) => regd_paths.push(p.clone()),
371                     Err(e) => {
372                         while let Some(rp) = regd_paths.pop() {
373                             c.unregister_object_path(&rp);
374                         }
375                         return Err(e)
376                     }
377                 }
378             } else {
379                 c.unregister_object_path(p);
380             }
381         }
382         Ok(())
383     }
384 
385     /// This method takes an `ConnectionItem` iterator (you get it from `Connection::iter()`)
386     /// and handles all matching items. Non-matching items (e g signals) are passed through.
run<'a, I: Iterator<Item=ConnectionItem>>(&'a self, c: &'a Connection, i: I) -> TreeServer<'a, I, M, D>387     pub fn run<'a, I: Iterator<Item=ConnectionItem>>(&'a self, c: &'a Connection, i: I) -> TreeServer<'a, I, M, D> {
388         TreeServer { iter: i, tree: &self, conn: c }
389     }
390 
391     /// Handles a message.
392     ///
393     /// Will return None in case the object path was not
394     /// found in this tree, or otherwise a list of messages to be sent back.
handle(&self, m: &Message) -> Option<Vec<Message>>395     pub fn handle(&self, m: &Message) -> Option<Vec<Message>> {
396         if m.msg_type() != MessageType::MethodCall { None }
397         else { m.path().and_then(|p| self.paths.get(&p).map(|s| s.handle(m, &self)
398             .unwrap_or_else(|e| vec!(e.to_message(m))))) }
399     }
400 
401 
children(&self, o: &ObjectPath<M, D>, direct_only: bool) -> Vec<&ObjectPath<M, D>>402     fn children(&self, o: &ObjectPath<M, D>, direct_only: bool) -> Vec<&ObjectPath<M, D>> {
403         let parent: &str = &o.name;
404         let plen = parent.len()+1;
405         self.paths.values().filter_map(|v| {
406             let k: &str = &v.name;
407             if !k.starts_with(parent) || k.len() <= plen || &k[plen-1..plen] != "/" {None} else {
408                 let child = &k[plen..];
409                 if direct_only && child.contains("/") {None} else {Some(&**v)}
410             }
411         }).collect()
412     }
413 
414     /// Get associated data
get_data(&self) -> &D::Tree415     pub fn get_data(&self) -> &D::Tree { &self.data }
416 
417 }
418 
new_tree<M: MethodType<D>, D: DataType>(d: D::Tree) -> Tree<M, D>419 pub fn new_tree<M: MethodType<D>, D: DataType>(d: D::Tree) -> Tree<M, D> {
420     Tree { paths: ArcMap::new(), data: d }
421 }
422 
423 impl<M: MethodType<D>, D: DataType> MsgHandler for Tree<M, D> {
handle_msg(&mut self, msg: &Message) -> Option<MsgHandlerResult>424     fn handle_msg(&mut self, msg: &Message) -> Option<MsgHandlerResult> {
425         self.handle(msg).map(|v| MsgHandlerResult { handled: true, done: false, reply: v })
426     }
handler_type(&self) -> MsgHandlerType427     fn handler_type(&self) -> MsgHandlerType { MsgHandlerType::MsgType(MessageType::MethodCall) }
428 }
429 
430 impl<M: MethodType<D>, D: DataType> MsgHandler for Arc<Tree<M, D>> {
handle_msg(&mut self, msg: &Message) -> Option<MsgHandlerResult>431     fn handle_msg(&mut self, msg: &Message) -> Option<MsgHandlerResult> {
432         self.handle(msg).map(|v| MsgHandlerResult { handled: true, done: false, reply: v })
433     }
handler_type(&self) -> MsgHandlerType434     fn handler_type(&self) -> MsgHandlerType { MsgHandlerType::MsgType(MessageType::MethodCall) }
435 }
436 
437 /// An iterator adapter that handles incoming method calls.
438 ///
439 /// Method calls that match an object path in the tree are handled and consumed by this
440 /// iterator. Other messages are passed through.
441 pub struct TreeServer<'a, I, M: MethodType<D> + 'a, D: DataType + 'a> {
442     iter: I,
443     conn: &'a Connection,
444     tree: &'a Tree<M, D>,
445 }
446 
447 impl<'a, I: Iterator<Item=ConnectionItem>, M: 'a + MethodType<D>, D: DataType + 'a> Iterator for TreeServer<'a, I, M, D> {
448     type Item = ConnectionItem;
449 
next(&mut self) -> Option<ConnectionItem>450     fn next(&mut self) -> Option<ConnectionItem> {
451         loop {
452             let n = self.iter.next();
453             if let &Some(ConnectionItem::MethodCall(ref msg)) = &n {
454                 if let Some(v) = self.tree.handle(&msg) {
455                     // Probably the wisest is to ignore any send errors here -
456                     // maybe the remote has disconnected during our processing.
457                     for m in v { let _ = self.conn.send(m); };
458                     continue;
459                 }
460             }
461             return n;
462         }
463     }
464 }
465 
466 
467 #[test]
test_iter()468 fn test_iter() {
469     let f = super::Factory::new_fn::<()>();
470     let t = f.tree(())
471     .add(f.object_path("/echo", ()).introspectable()
472         .add(f.interface("com.example.echo", ())
473             .add_m(f.method("Echo", (), |_| unimplemented!()).in_arg(("request", "s")).out_arg(("reply", "s")))
474             .add_p(f.property::<i32,_>("EchoCount", ()))
475             .add_s(f.signal("Echoed", ()).arg(("data", "s")).deprecated()
476         )
477     )).add(f.object_path("/echo/subpath", ()));
478 
479     let paths: Vec<_> = t.iter().collect();
480     assert_eq!(paths.len(), 2);
481 }
482 
483 
484 #[test]
test_introspection()485 fn test_introspection() {
486     let f = super::Factory::new_fn::<()>();
487     let t = f.object_path("/echo", ()).introspectable()
488         .add(f.interface("com.example.echo", ())
489             .add_m(f.method("Echo", (), |_| unimplemented!()).in_arg(("request", "s")).out_arg(("reply", "s")))
490             .add_p(f.property::<i32,_>("EchoCount", ()))
491             .add_s(f.signal("Echoed", ()).arg(("data", "s")).deprecated())
492     );
493 
494     let actual_result = t.introspect(&f.tree(()).add(f.object_path("/echo/subpath", ())));
495     println!("\n=== Introspection XML start ===\n{}\n=== Introspection XML end ===", actual_result);
496 
497     let expected_result = r##"<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
498 <node name="/echo">
499   <interface name="com.example.echo">
500     <method name="Echo">
501       <arg name="request" type="s" direction="in"/>
502       <arg name="reply" type="s" direction="out"/>
503     </method>
504     <property name="EchoCount" type="i" access="read"/>
505     <signal name="Echoed">
506       <arg name="data" type="s"/>
507       <annotation name="org.freedesktop.DBus.Deprecated" value="true"/>
508     </signal>
509   </interface>
510   <interface name="org.freedesktop.DBus.Introspectable">
511     <method name="Introspect">
512       <arg name="xml_data" type="s" direction="out"/>
513     </method>
514   </interface>
515   <interface name="org.freedesktop.DBus.Properties">
516     <method name="Get">
517       <arg name="interface_name" type="s" direction="in"/>
518       <arg name="property_name" type="s" direction="in"/>
519       <arg name="value" type="v" direction="out"/>
520     </method>
521     <method name="GetAll">
522       <arg name="interface_name" type="s" direction="in"/>
523       <arg name="props" type="a{sv}" direction="out"/>
524     </method>
525     <method name="Set">
526       <arg name="interface_name" type="s" direction="in"/>
527       <arg name="property_name" type="s" direction="in"/>
528       <arg name="value" type="v" direction="in"/>
529     </method>
530   </interface>
531   <node name="subpath"/>
532 </node>"##;
533 
534     assert_eq!(expected_result, actual_result);
535 }
536 
537