1 /// NOTE: No longer used - replaced with files in the "tree" directory.
2 
3 
4 #![allow(dead_code)]
5 
6 use {MessageItem, Message, MessageType, Connection, ConnectionItem, Error, ErrorName};
7 use {Signature, Member, Path};
8 use Interface as IfaceName;
9 use std::cell::RefCell;
10 use std::sync::{Arc, Mutex};
11 use std::collections::BTreeMap;
12 use std::marker::PhantomData;
13 use std::ffi::{CStr, CString};
14 use std::fmt;
15 use super::arg;
16 
17 type ArcMap<K, V> = BTreeMap<Arc<K>, Arc<V>>;
18 
19 #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
20 /// A D-Bus Argument.
21 pub struct Argument(Option<String>, Signature<'static>);
22 
23 impl Argument {
24     /// Create a new Argument.
new(name: Option<String>, sig: Signature<'static>) -> Argument25     pub fn new(name: Option<String>, sig: Signature<'static>) -> Argument { Argument(name, sig) }
26 
introspect(&self, indent: &str, dir: &str) -> String27     fn introspect(&self, indent: &str, dir: &str) -> String {
28         let n = self.0.as_ref().map(|n| format!("name=\"{}\" ", n)).unwrap_or("".into());
29         format!("{}<arg {}type=\"{}\"{}/>\n", indent, n, self.1, dir)
30     }
introspect_all(args: &[Argument], indent: &str, dir: &str) -> String31     fn introspect_all(args: &[Argument], indent: &str, dir: &str) -> String {
32         args.iter().fold("".to_string(), |aa, az| format!("{}{}", aa, az.introspect(indent, dir)))
33     }
34 }
35 
36 // Small helper struct to reduce memory somewhat for objects without annotations
37 #[derive(Clone, Debug, Default)]
38 struct Annotations(Option<BTreeMap<String, String>>);
39 
40 impl Annotations {
new() -> Annotations41     fn new() -> Annotations { Annotations(None) }
42 
insert<N: Into<String>, V: Into<String>>(&mut self, n: N, v: V)43     fn insert<N: Into<String>, V: Into<String>>(&mut self, n: N, v: V) {
44        if self.0.is_none() { self.0 = Some(BTreeMap::new()) }
45         self.0.as_mut().unwrap().insert(n.into(), v.into());
46     }
47 
introspect(&self, indent: &str) -> String48     fn introspect(&self, indent: &str) -> String {
49         self.0.as_ref().map(|s| s.iter().fold("".into(), |aa, (ak, av)| {
50             format!("{}{}<annotation name=\"{}\" value=\"{}\"/>\n", aa, indent, ak, av)
51         })).unwrap_or(String::new())
52     }
53 }
54 
55 // Doesn't work, conflicting impls
56 // impl<S: Into<Signature>> From<S> for Argument
57 
58 impl From<Signature<'static>> for Argument {
from(t: Signature<'static>) -> Argument59     fn from(t: Signature<'static>) -> Argument { Argument(None, t) }
60 }
61 
62 impl<'a> From<&'a str> for Argument {
from(t: &'a str) -> Argument63     fn from(t: &'a str) -> Argument { Argument(None, String::from(t).into()) }
64 }
65 
66 impl<N: Into<String>, S: Into<Signature<'static>>> From<(N, S)> for Argument {
from((n, s): (N, S)) -> Argument67     fn from((n, s): (N, S)) -> Argument { Argument(Some(n.into()), s.into()) }
68 }
69 
70 #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
71 /// A D-Bus Method Error.
72 pub struct MethodErr(ErrorName<'static>, String);
73 
74 impl MethodErr {
75     /// Create an Invalid Args MethodErr.
invalid_arg<T: fmt::Debug>(a: &T) -> MethodErr76     pub fn invalid_arg<T: fmt::Debug>(a: &T) -> MethodErr {
77         ("org.freedesktop.DBus.Error.InvalidArgs", format!("Invalid argument {:?}", a)).into()
78     }
79     /// Create a MethodErr that there are not enough arguments given.
no_arg() -> MethodErr80     pub fn no_arg() -> MethodErr {
81         ("org.freedesktop.DBus.Error.InvalidArgs", "Not enough arguments").into()
82     }
83     /// Create a MethodErr that the method failed in the way specified.
failed<T: fmt::Display>(a: &T) -> MethodErr84     pub fn failed<T: fmt::Display>(a: &T) -> MethodErr {
85         ("org.freedesktop.DBus.Error.Failed", a.to_string()).into()
86     }
87     /// Create a MethodErr that the Interface was unknown.
no_interface<T: fmt::Display>(a: &T) -> MethodErr88     pub fn no_interface<T: fmt::Display>(a: &T) -> MethodErr {
89         ("org.freedesktop.DBus.Error.UnknownInterface", format!("Unknown interface {}", a)).into()
90     }
91     /// Create a MethodErr that the Property was unknown.
no_property<T: fmt::Display>(a: &T) -> MethodErr92     pub fn no_property<T: fmt::Display>(a: &T) -> MethodErr {
93         ("org.freedesktop.DBus.Error.UnknownProperty", format!("Unknown property {}", a)).into()
94     }
95     /// Create a MethodErr that the Property was read-only.
ro_property<T: fmt::Display>(a: &T) -> MethodErr96     pub fn ro_property<T: fmt::Display>(a: &T) -> MethodErr {
97         ("org.freedesktop.DBus.Error.PropertyReadOnly", format!("Property {} is read only", a)).into()
98     }
99 }
100 
101 impl<T: Into<ErrorName<'static>>, M: Into<String>> From<(T, M)> for MethodErr {
from((t, m): (T, M)) -> MethodErr102     fn from((t, m): (T, M)) -> MethodErr { MethodErr(t.into(), m.into()) }
103 }
104 
105 /// Result containing the Messages returned from the Method, or a MethodErr.
106 pub type MethodResult = Result<Vec<Message>, MethodErr>;
107 
108 /// A MethodType that wraps an Fn function
109 pub struct MethodFn<'a>(Box<Fn(&Message, &ObjectPath<MethodFn<'a>>, &Tree<MethodFn<'a>>) -> MethodResult + 'a>);
110 /// A MethodType that wraps an FnMut function. Calling this recursively will cause a refcell panic.
111 pub struct MethodFnMut<'a>(Box<RefCell<FnMut(&Message, &ObjectPath<MethodFnMut<'a>>, &Tree<MethodFnMut<'a>>) -> MethodResult + 'a>>);
112 /// A MethodType that wraps an Fn+Send+Sync function, so it can be called from several threads in parallel.
113 pub struct MethodSync(Box<Fn(&Message, &ObjectPath<MethodSync>, &Tree<MethodSync>) -> MethodResult + Send + Sync + 'static>);
114 
115 impl<'a> fmt::Debug for MethodFn<'a> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result116     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "<Fn>") }
117 }
118 
119 impl<'a> fmt::Debug for MethodFnMut<'a> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result120     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "<FnMut>") }
121 }
122 
123 impl fmt::Debug for MethodSync {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result124     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "<Fn + Send + Sync>") }
125 }
126 
127 /// A helper trait used internally to make the tree generic over MethodFn, MethodFnMut and MethodSync.
128 pub trait MethodType: Sized {
call_method(&self, m: &Message, o: &ObjectPath<Self>, i: &Tree<Self>) -> MethodResult129     fn call_method(&self, m: &Message, o: &ObjectPath<Self>, i: &Tree<Self>) -> MethodResult;
box_method<H>(h: H) -> Self where H: Fn(&Message, &ObjectPath<Self>, &Tree<Self>) -> MethodResult + Send + Sync + 'static130     fn box_method<H>(h: H) -> Self
131     where H: Fn(&Message, &ObjectPath<Self>, &Tree<Self>) -> MethodResult + Send + Sync + 'static;
132 }
133 
134 impl<'a> MethodType for MethodFn<'a> {
call_method(&self, m: &Message, o: &ObjectPath<MethodFn<'a>>, i: &Tree<MethodFn<'a>>) -> MethodResult135     fn call_method(&self, m: &Message, o: &ObjectPath<MethodFn<'a>>, i: &Tree<MethodFn<'a>>) -> MethodResult { self.0(m, o, i) }
136 
box_method<H>(h: H) -> Self where H: Fn(&Message, &ObjectPath<MethodFn<'a>>, &Tree<MethodFn<'a>>) -> MethodResult + Send + Sync + 'static137     fn box_method<H>(h: H) -> Self
138     where H: Fn(&Message, &ObjectPath<MethodFn<'a>>, &Tree<MethodFn<'a>>) -> MethodResult + Send + Sync + 'static {
139         MethodFn(Box::new(h))
140     }
141 }
142 
143 impl MethodType for MethodSync {
call_method(&self, m: &Message, o: &ObjectPath<MethodSync>, i: &Tree<MethodSync>) -> MethodResult144     fn call_method(&self, m: &Message, o: &ObjectPath<MethodSync>, i: &Tree<MethodSync>) -> MethodResult { self.0(m, o, i) }
145 
box_method<H>(h: H) -> Self where H: Fn(&Message, &ObjectPath<MethodSync>, &Tree<MethodSync>) -> MethodResult + Send + Sync + 'static146     fn box_method<H>(h: H) -> Self
147     where H: Fn(&Message, &ObjectPath<MethodSync>, &Tree<MethodSync>) -> MethodResult + Send + Sync + 'static {
148         MethodSync(Box::new(h))
149     }
150 }
151 
152 impl<'a> MethodType for MethodFnMut<'a> {
call_method(&self, m: &Message, o: &ObjectPath<MethodFnMut<'a>>, i: &Tree<MethodFnMut<'a>>) -> MethodResult153     fn call_method(&self, m: &Message, o: &ObjectPath<MethodFnMut<'a>>, i: &Tree<MethodFnMut<'a>>) -> MethodResult {
154         let mut z = self.0.borrow_mut();
155         (&mut *z)(m, o, i)
156     }
157 
box_method<H>(h: H) -> Self where H: Fn(&Message, &ObjectPath<MethodFnMut<'a>>, &Tree<MethodFnMut<'a>>) -> MethodResult + Send + Sync + 'static158     fn box_method<H>(h: H) -> Self
159     where H: Fn(&Message, &ObjectPath<MethodFnMut<'a>>, &Tree<MethodFnMut<'a>>) -> MethodResult + Send + Sync + 'static {
160         MethodFnMut(Box::new(RefCell::new(h)))
161     }
162 }
163 
164 #[derive(Debug)]
165 /// A D-Bus Method.
166 pub struct Method<M> {
167     cb: M,
168     name: Arc<Member<'static>>,
169     i_args: Vec<Argument>,
170     o_args: Vec<Argument>,
171     anns: Annotations,
172 }
173 
174 impl<M> Method<M> {
175     /// Builder method that adds an "in" Argument to this Method.
in_arg<A: Into<Argument>>(mut self, a: A) -> Self176     pub fn in_arg<A: Into<Argument>>(mut self, a: A) -> Self { self.i_args.push(a.into()); self }
177     /// Builder method that adds an "in" Argument to this Method.
inarg<A: arg::Arg, S: Into<String>>(mut self, s: S) -> Self178     pub fn inarg<A: arg::Arg, S: Into<String>>(mut self, s: S) -> Self { self.i_args.push((s.into(), A::signature()).into()); self }
179     /// Builder method that adds multiple "in" Arguments to this Method.
in_args<Z: Into<Argument>, A: IntoIterator<Item=Z>>(mut self, a: A) -> Self180     pub fn in_args<Z: Into<Argument>, A: IntoIterator<Item=Z>>(mut self, a: A) -> Self {
181         self.i_args.extend(a.into_iter().map(|b| b.into())); self
182     }
183 
184     /// Builder method that adds an "out" Argument to this Method.
out_arg<A: Into<Argument>>(mut self, a: A) -> Self185     pub fn out_arg<A: Into<Argument>>(mut self, a: A) -> Self { self.o_args.push(a.into()); self }
186     /// Builder method that adds an "out" Argument to this Method.
outarg<A: arg::Arg, S: Into<String>>(mut self, s: S) -> Self187     pub fn outarg<A: arg::Arg, S: Into<String>>(mut self, s: S) -> Self { self.o_args.push((s.into(), A::signature()).into()); self }
188     /// Builder method that adds multiple "out" Arguments to this Method.
out_args<Z: Into<Argument>, A: IntoIterator<Item=Z>>(mut self, a: A) -> Self189     pub fn out_args<Z: Into<Argument>, A: IntoIterator<Item=Z>>(mut self, a: A) -> Self {
190         self.o_args.extend(a.into_iter().map(|b| b.into())); self
191     }
192 
193     /// Add an annotation to the method.
annotate<N: Into<String>, V: Into<String>>(mut self, name: N, value: V) -> Self194     pub fn annotate<N: Into<String>, V: Into<String>>(mut self, name: N, value: V) -> Self {
195         self.anns.insert(name, value); self
196     }
197     /// Add an annotation that this entity is deprecated.
deprecated(self) -> Self198     pub fn deprecated(self) -> Self { self.annotate("org.freedesktop.DBus.Deprecated", "true") }
199 }
200 
201 impl<M: MethodType> Method<M> {
202     /// Call the Method.
call(&self, m: &Message, o: &ObjectPath<M>, i: &Tree<M>) -> MethodResult203     pub fn call(&self, m: &Message, o: &ObjectPath<M>, i: &Tree<M>) -> MethodResult { self.cb.call_method(m, o, i) }
204 
new(n: Member<'static>, cb: M) -> Self205     fn new(n: Member<'static>, cb: M) -> Self { Method { name: Arc::new(n), i_args: vec!(),
206         o_args: vec!(), anns: Annotations::new(), cb: cb } }
207 }
208 
209 
210 #[derive(Debug)]
211 /// Represents a D-Bus interface.
212 pub struct Interface<M> {
213     name: Arc<IfaceName<'static>>,
214     methods: ArcMap<Member<'static>, Method<M>>,
215     signals: ArcMap<Member<'static>, Signal>,
216     properties: ArcMap<String, Property<M>>,
217     anns: Annotations,
218 }
219 
220 impl<M> Interface<M> {
221     /// Adds a method to the interface.
add_m(mut self, m: Method<M>) -> Self222     pub fn add_m(mut self, m: Method<M>) -> Self { self.methods.insert(m.name.clone(), Arc::new(m)); self }
223     /// Adds a signal to the interface.
add_s(mut self, s: Signal) -> Self224     pub fn add_s(mut self, s: Signal) -> Self { self.signals.insert(s.name.clone(), Arc::new(s)); self }
225     /// Adds a signal to the interface. Lets you keep another clone of the signal
226     /// (which you can use to emit the signal, once it belongs to an object path).
227     ///
228     /// Note: You are not allowed to add a signal to more than one interface.
add_s_arc(mut self, s: Arc<Signal>) -> Self229     pub fn add_s_arc(mut self, s: Arc<Signal>) -> Self { self.signals.insert(s.name.clone(), s); self }
230     /// Adds a signal to the interface. Returns a reference to the signal
231     /// (which you can use to emit the signal, once it belongs to an object path).
add_s_ref(&mut self, s: Signal) -> Arc<Signal>232     pub fn add_s_ref(&mut self, s: Signal) -> Arc<Signal> {
233         let s = Arc::new(s);
234         self.signals.insert(s.name.clone(), s.clone());
235         s
236     }
237 
238     /// Adds a property to the interface.
add_p(mut self, p: Property<M>) -> Self239     pub fn add_p(mut self, p: Property<M>) -> Self { self.properties.insert(p.name.clone(), Arc::new(p)); self }
240     /// Adds a property to the interface. Lets you keep another clone of the property
241     /// (which you can use to get and set the current value of the property).
242     ///
243     /// Note: You are not allowed to add a property to more than one interface. Later function calls might panic if you do so.
add_p_arc(mut self, p: Arc<Property<M>>) -> Self244     pub fn add_p_arc(mut self, p: Arc<Property<M>>) -> Self { self.properties.insert(p.name.clone(), p); self }
245     /// Adds a property to the interface. Returns a reference to the property
246     /// (which you can use to get and set the current value of the property).
add_p_ref(&mut self, p: Property<M>) -> Arc<Property<M>>247     pub fn add_p_ref(&mut self, p: Property<M>) -> Arc<Property<M>> {
248         let p = Arc::new(p);
249         self.properties.insert(p.name.clone(), p.clone());
250         p
251     }
252 
253     /// Add an annotation to this Inteface.
annotate<N: Into<String>, V: Into<String>>(mut self, name: N, value: V) -> Self254     pub fn annotate<N: Into<String>, V: Into<String>>(mut self, name: N, value: V) -> Self {
255         self.anns.insert(name, value); self
256     }
257     /// Add an annotation that this entity is deprecated.
deprecated(self) -> Self258     pub fn deprecated(self) -> Self { self.annotate("org.freedesktop.DBus.Deprecated", "true") }
259 
new(t: IfaceName<'static>) -> Interface<M>260     fn new(t: IfaceName<'static>) -> Interface<M> {
261         Interface { name: Arc::new(t), methods: BTreeMap::new(), signals: BTreeMap::new(),
262             properties: BTreeMap::new(), anns: Annotations::new()
263         }
264     }
265 
266 }
267 
268 #[derive(Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Debug)]
269 /// Enumerates the different signaling behaviors a Property can have
270 /// to being changed.
271 pub enum EmitsChangedSignal {
272     /// The Property emits a signal that includes the new value.
273     True,
274     /// The Property emits a signal that does not include the new value.
275     Invalidates,
276     /// The Property cannot be changed.
277     Const,
278     /// The Property does not emit a signal when changed.
279     False,
280 }
281 
282 #[derive(Copy, Clone, PartialEq, Eq, Ord, PartialOrd, Debug)]
283 /// The possible access characteristics a Property can have.
284 pub enum Access {
285     /// The Property can only be read (Get).
286     Read,
287     /// The Property can be read or written.
288     ReadWrite,
289     /// The Property can only be written (Set).
290     Write,
291 }
292 
293 impl Access {
introspect(&self) -> &'static str294     fn introspect(&self) -> &'static str {
295         match self {
296             &Access::Read => "read",
297             &Access::ReadWrite => "readwrite",
298             &Access::Write => "write",
299         }
300     }
301 }
302 
303 #[derive(Debug)]
304 /// A D-Bus Property.
305 pub struct Property<M> {
306     name: Arc<String>,
307     value: Mutex<MessageItem>,
308     emits: EmitsChangedSignal,
309     rw: Access,
310     set_cb: Option<M>,
311     owner: Mutex<Option<(Arc<Path<'static>>, Arc<IfaceName<'static>>)>>,
312     anns: Annotations,
313 }
314 
315 impl<M: MethodType> Property<M> {
316     /// Gets the value of the Property.
get_value(&self) -> MessageItem317     pub fn get_value(&self) -> MessageItem {
318         self.value.lock().unwrap().clone()
319     }
320 
321     /// Gets the signal (if any) associated with the Property.
get_signal(&self) -> Option<Message>322     pub fn get_signal(&self) -> Option<Message> {
323         self.owner.lock().unwrap().as_ref().map(|&(ref p, ref i)| {
324             Message::signal(&p, &"org.freedesktop.DBus.Properties".into(), &"PropertiesChanged".into())
325                 .append(String::from(&***i))
326         })
327     }
328 
329     /// Returns error if "emits" is "Const", and the property is in a
330     /// tree.  Returns messages to be sent over a connection, this
331     /// could be the PropertiesChanged signal.
set_value(&self, m: MessageItem) -> Result<Vec<Message>,()>332     pub fn set_value(&self, m: MessageItem) -> Result<Vec<Message>,()> {
333         let ss = match self.emits {
334             EmitsChangedSignal::False => None,
335             EmitsChangedSignal::Const => if self.get_signal().is_some() { return Err(()) } else { None },
336             EmitsChangedSignal::True => self.get_signal().map(|s|
337                 s.append2(arg::Dict::new(vec!((&**self.name, arg::Variant(m.clone())))), arg::Array::<&str, _>::new(vec!()))
338             ),
339             EmitsChangedSignal::Invalidates => self.get_signal().map(|s| {
340                 s.append2(arg::Dict::<&str, arg::Variant<MessageItem>, _>::new(vec!()), arg::Array::new(vec!(&**self.name)))
341             }),
342         };
343         *self.value.lock().unwrap() = m;
344         Ok(ss.map(|s| vec!(s)).unwrap_or(vec!()))
345     }
346 
347     /// Builder method that allows setting the Property's signal
348     /// behavior when changed.
emits_changed(mut self, e: EmitsChangedSignal) -> Self349     pub fn emits_changed(mut self, e: EmitsChangedSignal) -> Self {
350         self.emits = e;
351         assert!(self.rw == Access::Read || self.emits != EmitsChangedSignal::Const);
352         self
353     }
354 
355     /// Builder method that allows setting the Property as readable,
356     /// writable, or both.
access(mut self, e: Access) -> Self357     pub fn access(mut self, e: Access) -> Self {
358         self.rw = e;
359         assert!(self.rw == Access::Read || self.emits != EmitsChangedSignal::Const);
360         self
361     }
362 
363     /// Helper method to check accessibility before getting a value.
remote_get(&self, _: &Message) -> Result<MessageItem, MethodErr>364     pub fn remote_get(&self, _: &Message) -> Result<MessageItem, MethodErr> {
365         // TODO: We should be able to call a user-defined callback here instead...
366         if self.rw == Access::Write { return Err(MethodErr::failed(&format!("Property {} is write only", &self.name))) }
367         Ok(self.get_value())
368     }
369 
370     /// Helper method to verify and extract a MessageItem from a Set message
verify_remote_set(&self, m: &Message) -> Result<MessageItem, MethodErr>371     pub fn verify_remote_set(&self, m: &Message) -> Result<MessageItem, MethodErr> {
372         let items = m.get_items();
373         let s: &MessageItem = try!(items.get(2).ok_or_else(|| MethodErr::no_arg())
374             .and_then(|i| i.inner().map_err(|_| MethodErr::invalid_arg(&i))));
375 
376         if self.rw == Access::Read { Err(MethodErr::ro_property(&self.name)) }
377         else if s.type_sig() != self.value.lock().unwrap().type_sig() {
378             Err(MethodErr::failed(&format!("Property {} cannot change type to {}", &self.name, s.type_sig())))
379         }
380         else { Ok(s.clone()) }
381     }
382 
remote_set(&self, m: &Message, o: &ObjectPath<M>, t: &Tree<M>) -> Result<Vec<Message>, MethodErr>383     fn remote_set(&self, m: &Message, o: &ObjectPath<M>, t: &Tree<M>) -> Result<Vec<Message>, MethodErr> {
384         if let Some(ref cb) = self.set_cb {
385             cb.call_method(m, o, t)
386         }
387         else {
388             let s = try!(self.verify_remote_set(m));
389             self.set_value(s).map_err(|_| MethodErr::ro_property(&self.name))
390         }
391     }
392 
393     /// Add an annotation to this Property.
annotate<N: Into<String>, V: Into<String>>(mut self, name: N, value: V) -> Self394     pub fn annotate<N: Into<String>, V: Into<String>>(mut self, name: N, value: V) -> Self {
395         self.anns.insert(name, value); self
396     }
397 
398     /// Add an annotation that this entity is deprecated.
deprecated(self) -> Self399     pub fn deprecated(self) -> Self { self.annotate("org.freedesktop.DBus.Deprecated", "true") }
400 
new(s: String, i: MessageItem) -> Property<M>401     fn new(s: String, i: MessageItem) -> Property<M> {
402         Property { name: Arc::new(s), emits: EmitsChangedSignal::True, rw: Access::Read,
403             value: Mutex::new(i), owner: Mutex::new(None), anns: Annotations::new(), set_cb: None }
404     }
405 }
406 
407 impl Property<MethodSync> {
408     /// Sets a callback to be called when a "Set" call is coming in from the remote side.
409     /// Might change to something more ergonomic.
410     /// For multi-thread use.
on_set<H>(mut self, m: H) -> Self where H: Fn(&Message, &ObjectPath<MethodSync>, &Tree<MethodSync>) -> MethodResult + Send + Sync + 'static411     pub fn on_set<H>(mut self, m: H) -> Self
412     where H: Fn(&Message, &ObjectPath<MethodSync>, &Tree<MethodSync>) -> MethodResult + Send + Sync + 'static {
413         self.set_cb = Some(MethodSync::box_method(m));
414         self
415     }
416 }
417 
418 impl<'a> Property<MethodFn<'a>> {
419     /// Sets a callback to be called when a "Set" call is coming in from the remote side.
420     /// Might change to something more ergonomic.
421     /// For single-thread use.
on_set<H: 'a>(mut self, m: H) -> Self where H: Fn(&Message, &ObjectPath<MethodFn<'a>>, &Tree<MethodFn<'a>>) -> MethodResult422     pub fn on_set<H: 'a>(mut self, m: H) -> Self
423     where H: Fn(&Message, &ObjectPath<MethodFn<'a>>, &Tree<MethodFn<'a>>) -> MethodResult {
424         self.set_cb = Some(MethodFn(Box::new(m)));
425         self
426     }
427 }
428 
429 impl<'a> Property<MethodFnMut<'a>> {
430     /// Sets a callback to be called when a "Set" call is coming in from the remote side.
431     /// Might change to something more ergonomic.
432     /// For single-thread use.
on_set<H: 'a>(mut self, m: H) -> Self where H: FnMut(&Message, &ObjectPath<MethodFnMut<'a>>, &Tree<MethodFnMut<'a>>) -> MethodResult433     pub fn on_set<H: 'a>(mut self, m: H) -> Self
434     where H: FnMut(&Message, &ObjectPath<MethodFnMut<'a>>, &Tree<MethodFnMut<'a>>) -> MethodResult {
435         self.set_cb = Some(MethodFnMut(Box::new(RefCell::new(m))));
436         self
437     }
438 }
439 
440 
441 #[derive(Debug)]
442 /// A D-Bus Signal.
443 pub struct Signal {
444     name: Arc<Member<'static>>,
445     arguments: Vec<Argument>,
446     owner: Mutex<Option<(Arc<Path<'static>>, Arc<IfaceName<'static>>)>>,
447     anns: Annotations,
448 }
449 
450 impl Signal {
451     /// Returns a message which emits the signal when sent.
452     /// Panics if the signal is not inserted in an object path.
emit(&self, items: &[MessageItem]) -> Message453     pub fn emit(&self, items: &[MessageItem]) -> Message {
454         let mut m = {
455             let lock = self.owner.lock().unwrap();
456             let &(ref p, ref i) = lock.as_ref().unwrap();
457             Message::signal(p, i, &self.name)
458         };
459         m.append_items(items);
460         m
461     }
462 
463     /// Returns a message which emits the signal when sent.
464     /// Panics if the signal is not inserted in an object path.
465     ///
466     /// Same as "emit" but does not take a "MessageItem" argument.
msg(&self) -> Message467     pub fn msg(&self) -> Message { self.emit(&[]) }
468 
469     /// Builder method that adds an Argument to the Signal.
arg<A: Into<Argument>>(mut self, a: A) -> Self470     pub fn arg<A: Into<Argument>>(mut self, a: A) -> Self { self.arguments.push(a.into()); self }
471     /// Builder method that adds an Argument to the Signal.
sarg<A: arg::Arg, S: Into<String>>(mut self, s: S) -> Self472     pub fn sarg<A: arg::Arg, S: Into<String>>(mut self, s: S) -> Self { self.arguments.push((s.into(), A::signature()).into()); self }
473     /// Builder method that adds multiple "rguments to the Signel.
args<Z: Into<Argument>, A: IntoIterator<Item=Z>>(mut self, a: A) -> Self474     pub fn args<Z: Into<Argument>, A: IntoIterator<Item=Z>>(mut self, a: A) -> Self {
475         self.arguments.extend(a.into_iter().map(|b| b.into())); self
476     }
477 
478     /// Add an annotation to this Signal.
annotate<N: Into<String>, V: Into<String>>(mut self, name: N, value: V) -> Self479     pub fn annotate<N: Into<String>, V: Into<String>>(mut self, name: N, value: V) -> Self {
480         self.anns.insert(name, value); self
481     }
482     /// Add an annotation that this entity is deprecated.
deprecated(self) -> Self483     pub fn deprecated(self) -> Self { self.annotate("org.freedesktop.DBus.Deprecated", "true") }
484 }
485 
introspect_map<T, I: fmt::Display, C: Fn(&T) -> (String, String)> (h: &ArcMap<I, T>, name: &str, indent: &str, func: C) -> String486 fn introspect_map<T, I: fmt::Display, C: Fn(&T) -> (String, String)>
487     (h: &ArcMap<I, T>, name: &str, indent: &str, func: C) -> String {
488 
489     h.iter().fold("".into(), |a, (k, v)| {
490         let (params, contents) = func(v);
491         format!("{}{}<{} name=\"{}\"{}{}>\n",
492             a, indent, name, &**k, params, if contents.len() > 0 {
493                 format!(">\n{}{}</{}", contents, indent, name)
494             }
495             else { format!("/") }
496         )
497     })
498 }
499 
500 #[derive(Debug)]
501 /// A D-Bus Object Path.
502 pub struct ObjectPath<M> {
503     name: Arc<Path<'static>>,
504     ifaces: ArcMap<IfaceName<'static>, Interface<M>>,
505 }
506 
507 impl<M: MethodType> ObjectPath<M> {
new(p: Path<'static>) -> ObjectPath<M>508     fn new(p: Path<'static>) -> ObjectPath<M> {
509         ObjectPath { name: Arc::new(p), ifaces: BTreeMap::new() }
510     }
511 
get_iface<'a>(&'a self, i: Option<&'a CStr>) -> Result<&Arc<Interface<M>>, MethodErr>512     fn get_iface<'a>(&'a self, i: Option<&'a CStr>) -> Result<&Arc<Interface<M>>, MethodErr> {
513         let iface_name = try!(i.ok_or_else(|| MethodErr::invalid_arg(&0)));
514         let j = try!(IfaceName::from_slice(iface_name.to_bytes_with_nul()).map_err(|e| MethodErr::invalid_arg(&e)));
515         self.ifaces.get(&j).ok_or_else(|| MethodErr::no_interface(&j))
516     }
517 
prop_set(&self, m: &Message, o: &ObjectPath<M>, t: &Tree<M>) -> MethodResult518     fn prop_set(&self, m: &Message, o: &ObjectPath<M>, t: &Tree<M>) -> MethodResult {
519         let (iname, p) = m.get2();
520         let iface = try!(self.get_iface(iname));
521         let prop_name: &str = try!(p.ok_or_else(|| MethodErr::invalid_arg(&1)));
522         let prop: &Property<M> = try!(iface.properties.get(&String::from(prop_name))
523             .ok_or_else(|| MethodErr::no_property(&prop_name)));
524         let mut r = try!(prop.remote_set(m, o, t));
525         r.push(m.method_return());
526         Ok(r)
527     }
528 
prop_get(&self, m: &Message) -> MethodResult529     fn prop_get(&self, m: &Message) -> MethodResult {
530         let (iname, p) = m.get2();
531         let iface = try!(self.get_iface(iname));
532         let prop_name: &str = try!(p.ok_or_else(|| MethodErr::invalid_arg(&1)));
533         let prop: &Property<M> = try!(iface.properties.get(&String::from(prop_name))
534             .ok_or_else(|| MethodErr::no_property(&prop_name)));
535         let r = try!(prop.remote_get(m));
536         Ok(vec!(m.method_return().append1(arg::Variant(r))))
537     }
538 
prop_get_all(&self, m: &Message) -> MethodResult539     fn prop_get_all(&self, m: &Message) -> MethodResult {
540         let iface = try!(self.get_iface(m.get1()));
541         let mut q = vec!();
542         for v in iface.properties.values() {
543             q.push((&**v.name, arg::Variant(try!(v.remote_get(m)))));
544         }
545         Ok(vec!(m.method_return().append1(arg::Dict::new(q))))
546     }
547 
add_property_handler(&mut self)548     fn add_property_handler(&mut self) {
549         let ifname = IfaceName::from("org.freedesktop.DBus.Properties");
550         if self.ifaces.contains_key(&ifname) { return };
551         let f: Factory<M> = Factory(PhantomData);
552 
553         let i = Interface::<M>::new(ifname)
554             .add_m(f.method_sync("Get", |m,o,_| o.prop_get(m) )
555                 .inarg::<&str,_>("interface_name")
556                 .inarg::<&str,_>("property_name")
557                 .outarg::<arg::Variant<()>,_>("value"))
558             .add_m(f.method_sync("GetAll", |m,o,_| o.prop_get_all(m))
559                 .inarg::<&str,_>("interface_name")
560                 .outarg::<arg::Dict<&str, arg::Variant<()>, ()>,_>("props"))
561             .add_m(f.method_sync("Set", |m,o,t| o.prop_set(m, o, t))
562                 .inarg::<&str,_>("interface_name")
563                 .inarg::<&str,_>("property_name")
564                 .inarg::<arg::Variant<()>,_>("value"));
565         self.ifaces.insert(i.name.clone(), Arc::new(i));
566     }
567 
568     /// Add an Interface to this Object Path.
add(mut self, p: Interface<M>) -> Self569     pub fn add(mut self, p: Interface<M>) -> Self {
570         use std::mem;
571         for s in p.signals.values() {
572             let n = Some((self.name.clone(), p.name.clone()));
573             let o = mem::replace(&mut *s.owner.lock().unwrap(), n);
574             assert!(o.is_none(), "Signal {} already added to object path", s.name);
575         };
576         for s in p.properties.values() {
577             let n = Some((self.name.clone(), p.name.clone()));
578             let o = mem::replace(&mut *s.owner.lock().unwrap(), n);
579             assert!(o.is_none(), "Property {} already added to object path", s.name);
580         };
581         if !p.properties.is_empty() { self.add_property_handler(); }
582         self.ifaces.insert(p.name.clone(), Arc::new(p));
583         self
584     }
585 
586     /// Adds introspection support for this object path.
introspectable(self) -> Self587     pub fn introspectable(self) -> Self {
588         let ifname: IfaceName = "org.freedesktop.DBus.Introspectable".into();
589         if self.ifaces.contains_key(&ifname) { return self };
590         let f: Factory<M> = Factory(PhantomData);
591         self.add(Interface::<M>::new(ifname)
592             .add_m(f.method_sync("Introspect",
593                 |m,o,t| Ok(vec!(m.method_return().append(o.introspect(t)))))
594                 .out_arg(("xml_data", "s"))))
595     }
596 
handle(&self, m: &Message, t: &Tree<M>) -> MethodResult597     fn handle(&self, m: &Message, t: &Tree<M>) -> MethodResult {
598         let i = try!(m.interface().and_then(|i| self.ifaces.get(&i)).ok_or(
599             ("org.freedesktop.DBus.Error.UnknownInterface", "Unknown interface")));
600         let me = try!(m.member().and_then(|me| i.methods.get(&me)).ok_or(
601             ("org.freedesktop.DBus.Error.UnknownMethod", "Unknown method")));
602         me.call(m, &self, t)
603     }
604 
introspect(&self, tree: &Tree<M>) -> String605     fn introspect(&self, tree: &Tree<M>) -> String {
606         let ifacestr = introspect_map(&self.ifaces, "interface", "  ", |iv|
607             (format!(""), format!("{}{}{}{}",
608                 introspect_map(&iv.methods, "method", "    ", |m| (format!(""), format!("{}{}{}",
609                     Argument::introspect_all(&m.i_args, "      ", " direction=\"in\""),
610                     Argument::introspect_all(&m.o_args, "      ", " direction=\"out\""),
611                     m.anns.introspect("      ")
612                 ))),
613                 introspect_map(&iv.properties, "property", "    ", |p| (
614                     format!(" type=\"{}\" access=\"{}\"", p.get_value().type_sig(), p.rw.introspect()),
615                     p.anns.introspect("      ")
616                 )),
617                 introspect_map(&iv.signals, "signal", "    ", |s| (format!(""), format!("{}{}",
618                     Argument::introspect_all(&s.arguments, "      ", ""),
619                     s.anns.introspect("      ")
620                 ))),
621                 iv.anns.introspect("    ")
622             ))
623         );
624         let olen = self.name.len()+1;
625         let childstr = tree.children(&self, true).iter().fold("".to_string(), |na, n|
626             format!("{}  <node name=\"{}\"/>\n", na, &n.name[olen..])
627         );
628 
629         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">
630 <node name="{}">
631 {}{}</node>"##, self.name, ifacestr, childstr);
632         nodestr
633     }
634 
get_managed_objects(&self, t: &Tree<M>) -> MessageItem635     fn get_managed_objects(&self, t: &Tree<M>) -> MessageItem {
636         let mut paths = t.children(&self, false);
637         paths.push(&self);
638         MessageItem::Array(
639             paths.iter().map(|p| ((&*p.name).clone().into(), MessageItem::Array(
640                 p.ifaces.values().map(|i| ((&**i.name).into(), MessageItem::Array(
641                     i.properties.values().map(|pp| ((&**pp.name).into(), Box::new(pp.get_value()
642                     ).into()).into()).collect(), "{sv}".into()
643                 )).into()).collect(), "{sa{sv}}".into()
644             )).into()).collect(), "{oa{sa{sv}}}".into()
645         )
646     }
647 
648     /// Adds ObjectManager support for this object path.
649     ///
650     /// It is not possible to add/remove interfaces while the object path belongs to a tree,
651     /// hence no InterfacesAdded / InterfacesRemoved signals are sent.
object_manager(self) -> Self652     pub fn object_manager(self) -> Self {
653         let ifname: IfaceName = "org.freedesktop.DBus.ObjectManager".into();
654         if self.ifaces.contains_key(&ifname) { return self };
655         let f: Factory<M> = Factory(PhantomData);
656         self.add(Interface::<M>::new(ifname)
657             .add_m(f.method_sync("GetManagedObjects",
658                 |m,o,t| Ok(vec!(m.method_return().append(o.get_managed_objects(t)))))
659                 .out_arg("a{oa{sa{sv}}}")))
660     }
661 }
662 
663 /// An iterator adapter that handles incoming method calls.
664 ///
665 /// Method calls that match an object path in the tree are handled and consumed by this
666 /// iterator. Other messages are passed through.
667 pub struct TreeServer<'a, I, M: 'a> {
668     iter: I,
669     conn: &'a Connection,
670     tree: &'a Tree<M>,
671 }
672 
673 impl<'a, I: Iterator<Item=ConnectionItem>, M: 'a + MethodType> Iterator for TreeServer<'a, I, M> {
674     type Item = ConnectionItem;
675 
next(&mut self) -> Option<ConnectionItem>676     fn next(&mut self) -> Option<ConnectionItem> {
677         loop {
678             let n = self.iter.next();
679             if let &Some(ConnectionItem::MethodCall(ref msg)) = &n {
680                 if let Some(v) = self.tree.handle(&msg) {
681                     // Probably the wisest is to ignore any send errors here -
682                     // maybe the remote has disconnected during our processing.
683                     for m in v { let _ = self.conn.send(m); };
684                     continue;
685                 }
686             }
687             return n;
688         }
689     }
690 }
691 
692 /// A collection of object paths.
693 #[derive(Debug)]
694 pub struct Tree<M> {
695     paths: ArcMap<Path<'static>, ObjectPath<M>>
696 }
697 
698 impl<M: MethodType> Tree<M> {
699 
children(&self, o: &ObjectPath<M>, direct_only: bool) -> Vec<&ObjectPath<M>>700     fn children(&self, o: &ObjectPath<M>, direct_only: bool) -> Vec<&ObjectPath<M>> {
701         let parent: &str = &o.name;
702         let plen = parent.len()+1;
703         self.paths.values().filter_map(|v| {
704             let k: &str = &v.name;
705             if !k.starts_with(parent) || k.len() <= plen || &k[plen-1..plen] != "/" {None} else {
706                 let child = &k[plen..];
707                 if direct_only && child.contains("/") {None} else {Some(&**v)}
708             }
709         }).collect()
710     }
711 
712     /// Add an Object Path to this Tree.
713     ///
714     /// Note: This does not unregister a path with the connection, so if the tree is currently registered,
715     /// you might want to call Connection::register_object_path to add the path manually.
add(mut self, p: ObjectPath<M>) -> Self716     pub fn add(mut self, p: ObjectPath<M>) -> Self {
717         self.paths.insert(p.name.clone(), Arc::new(p));
718         self
719     }
720 
721     /// Adds an ObjectPath to this Tree. Returns a reference to the ObjectPath.
722     /// The note for add() also applies here.
add_o_ref(&mut self, p: ObjectPath<M>) -> Arc<ObjectPath<M>>723     pub fn add_o_ref(&mut self, p: ObjectPath<M>) -> Arc<ObjectPath<M>> {
724         let name = p.name.clone();
725         let o = Arc::new(p);
726         self.paths.insert(name, o.clone());
727         o
728     }
729 
730     /// Remove a object path from the Tree. Returns the object path removed, or None if not found.
731     ///
732     /// Note: This does not unregister a path with the connection, so if the tree is currently registered,
733     /// you might want to call Connection::unregister_object_path to remove the path manually.
remove(&mut self, p: &Path<'static>) -> Option<Arc<ObjectPath<M>>>734     pub fn remove(&mut self, p: &Path<'static>) -> Option<Arc<ObjectPath<M>>> {
735         // There is no real reason p needs to have a static lifetime; but
736         // the borrow checker doesn't agree. :-(
737         self.paths.remove(p)
738     }
739 
740     /// Registers or unregisters all object paths in the tree.
set_registered(&self, c: &Connection, b: bool) -> Result<(), Error>741     pub fn set_registered(&self, c: &Connection, b: bool) -> Result<(), Error> {
742         let mut regd_paths = Vec::new();
743         for p in self.paths.keys() {
744             if b {
745                 match c.register_object_path(p) {
746                     Ok(()) => regd_paths.push(p.clone()),
747                     Err(e) => {
748                         while let Some(rp) = regd_paths.pop() {
749                             c.unregister_object_path(&rp);
750                         }
751                         return Err(e)
752                     }
753                 }
754             } else {
755                 c.unregister_object_path(p);
756             }
757         }
758         Ok(())
759     }
760 
761     /// Handles a message. Will return None in case the object path was not
762     /// found, or otherwise a list of messages to be sent back.
handle(&self, m: &Message) -> Option<Vec<Message>>763     pub fn handle(&self, m: &Message) -> Option<Vec<Message>> {
764         if m.msg_type() != MessageType::MethodCall { None }
765         else { m.path().and_then(|p| self.paths.get(&p).map(|s| s.handle(m, &self)
766             .unwrap_or_else(|e| vec!(m.error(&e.0, &CString::new(e.1).unwrap()))))) }
767     }
768 
769     /// This method takes an `ConnectionItem` iterator (you get it from `Connection::iter()`)
770     /// 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>771     pub fn run<'a, I: Iterator<Item=ConnectionItem>>(&'a self, c: &'a Connection, i: I) -> TreeServer<'a, I, M> {
772         TreeServer { iter: i, tree: &self, conn: c }
773     }
774 }
775 
776 /// The factory is used to create object paths, interfaces, methods etc.
777 ///
778 /// There are three factories:
779 ///
780 ///  **Fn** - all methods are `Fn()`.
781 ///
782 ///  **FnMut** - all methods are `FnMut()`. This means they can mutate their environment,
783 ///  which has the side effect that if you call it recursively, it will RefCell panic.
784 ///
785 ///  **Sync** - all methods are `Fn() + Send + Sync + 'static`. This means that the methods
786 ///  can be called from different threads in parallel.
787 #[derive(Debug, Copy, Clone)]
788 pub struct Factory<M>(PhantomData<M>);
789 
790 impl<'a> Factory<MethodFn<'a>> {
791 
792     /// Creates a new factory for single-thread use.
new_fn() -> Self793     pub fn new_fn() -> Self { Factory(PhantomData) }
794 
795     /// Creates a new method for single-thread use.
method<'b, H: 'b, T>(&self, t: T, handler: H) -> Method<MethodFn<'b>> where H: Fn(&Message, &ObjectPath<MethodFn<'b>>, &Tree<MethodFn<'b>>) -> MethodResult, T: Into<Member<'static>>796     pub fn method<'b, H: 'b, T>(&self, t: T, handler: H) -> Method<MethodFn<'b>>
797     where H: Fn(&Message, &ObjectPath<MethodFn<'b>>, &Tree<MethodFn<'b>>) -> MethodResult, T: Into<Member<'static>> {
798         Method::new(t.into(), MethodFn(Box::new(handler)))
799     }
800 
801     /// Creates a new property for single-thread use.
property<'b, T: Into<String>, I: Into<MessageItem>>(&self, t: T, i: I) -> Property<MethodFn<'b>>802     pub fn property<'b, T: Into<String>, I: Into<MessageItem>>(&self, t: T, i: I) -> Property<MethodFn<'b>> {
803         Property::new(t.into(), i.into())
804     }
805 
806     /// Creates a new interface for single-thread use.
interface<'b, T: Into<IfaceName<'static>>>(&self, t: T) -> Interface<MethodFn<'b>>807     pub fn interface<'b, T: Into<IfaceName<'static>>>(&self, t: T) -> Interface<MethodFn<'b>> { Interface::new(t.into()) }
808 
809     /// Creates a new tree for single-thread use.
tree<'b>(&self) -> Tree<MethodFn<'b>>810     pub fn tree<'b>(&self) -> Tree<MethodFn<'b>> { Tree { paths: BTreeMap::new() }}
811 
812     /// Creates a new object path for single-thread use.
object_path<'b, T: Into<Path<'static>>>(&self, t: T) -> ObjectPath<MethodFn<'b>>813     pub fn object_path<'b, T: Into<Path<'static>>>(&self, t: T) -> ObjectPath<MethodFn<'b>> { ObjectPath::new(t.into()) }
814 }
815 
816 impl<'a> Factory<MethodFnMut<'a>> {
817 
818     /// Creates a new factory for single-thread + mutable fns use.
new_fnmut() -> Self819     pub fn new_fnmut() -> Self { Factory(PhantomData) }
820 
821     /// Creates a new method for single-thread use.
822     /// This method can mutate its environment, so it will panic in case
823     /// it is called recursively.
method<'b, H: 'b, T>(&self, t: T, handler: H) -> Method<MethodFnMut<'b>> where H: FnMut(&Message, &ObjectPath<MethodFnMut<'b>>, &Tree<MethodFnMut<'b>>) -> MethodResult, T: Into<Member<'static>>824     pub fn method<'b, H: 'b, T>(&self, t: T, handler: H) -> Method<MethodFnMut<'b>>
825     where H: FnMut(&Message, &ObjectPath<MethodFnMut<'b>>, &Tree<MethodFnMut<'b>>) -> MethodResult, T: Into<Member<'static>> {
826         Method::new(t.into(), MethodFnMut(Box::new(RefCell::new(handler))))
827     }
828 
829     /// Creates a new mutable property for single-thread use.
property<'b, T: Into<String>, I: Into<MessageItem>>(&self, t: T, i: I) -> Property<MethodFnMut<'b>>830     pub fn property<'b, T: Into<String>, I: Into<MessageItem>>(&self, t: T, i: I) -> Property<MethodFnMut<'b>> {
831         Property::new(t.into(), i.into())
832     }
833 
834     /// Creates a new mutable interface for single-thread use.
interface<'b, T: Into<IfaceName<'static>>>(&self, t: T) -> Interface<MethodFnMut<'b>>835     pub fn interface<'b, T: Into<IfaceName<'static>>>(&self, t: T) -> Interface<MethodFnMut<'b>> { Interface::new(t.into()) }
836 
837     /// Creates a new mutable tree for single-thread use.
tree<'b>(&self) -> Tree<MethodFnMut<'b>>838     pub fn tree<'b>(&self) -> Tree<MethodFnMut<'b>> { Tree { paths: BTreeMap::new() }}
839 
840     /// Creates a new mutable object path for single-thread use.
object_path<'b, T: Into<Path<'static>>>(&self, t: T) -> ObjectPath<MethodFnMut<'b>>841     pub fn object_path<'b, T: Into<Path<'static>>>(&self, t: T) -> ObjectPath<MethodFnMut<'b>> { ObjectPath::new(t.into()) }
842 }
843 
844 impl Factory<MethodSync> {
845 
846     /// Creates a new factory for multi-thread use.
847     /// Trees created will be able to Send and Sync, i e,
848     /// it can handle several messages in parallel.
new_sync() -> Self849     pub fn new_sync() -> Self { Factory(PhantomData) }
850 
851     /// Creates a new method for multi-thread use.
852     /// This puts bounds on the callback to enable it to be called from several threads
853     /// in parallel.
method<H, T>(&self, t: T, handler: H) -> Method<MethodSync> where H: Fn(&Message, &ObjectPath<MethodSync>, &Tree<MethodSync>) -> MethodResult + Send + Sync + 'static, T: Into<Member<'static>>854     pub fn method<H, T>(&self, t: T, handler: H) -> Method<MethodSync>
855     where H: Fn(&Message, &ObjectPath<MethodSync>, &Tree<MethodSync>) -> MethodResult + Send + Sync + 'static, T: Into<Member<'static>> {
856         Method::new(t.into(), MethodSync(Box::new(handler)))
857     }
858 
859     /// Creates a new property for multi-threaded use.
property<T: Into<String>, I: Into<MessageItem>>(&self, t: T, i: I) -> Property<MethodSync>860     pub fn property<T: Into<String>, I: Into<MessageItem>>(&self, t: T, i: I) -> Property<MethodSync> {
861         Property::new(t.into(), i.into())
862     }
863 
864     /// Creates a new interface for multi-threaded use.
interface<T: Into<IfaceName<'static>>>(&self, t: T) -> Interface<MethodSync>865     pub fn interface<T: Into<IfaceName<'static>>>(&self, t: T) -> Interface<MethodSync> { Interface::new(t.into()) }
866 
867     /// Creates a new tree for multi-threaded use.
tree(&self) -> Tree<MethodSync>868     pub fn tree(&self) -> Tree<MethodSync> { Tree { paths: BTreeMap::new() }}
869 
870     /// Creates a new object path for multi-threaded use.
object_path<T: Into<Path<'static>>>(&self, t: T) -> ObjectPath<MethodSync>871     pub fn object_path<T: Into<Path<'static>>>(&self, t: T) -> ObjectPath<MethodSync> { ObjectPath::new(t.into()) }
872 }
873 
874 impl<M> Factory<M> {
875     /// Create a Signal.
signal<T: Into<Member<'static>>>(&self, t: T) -> Signal876     pub fn signal<T: Into<Member<'static>>>(&self, t: T) -> Signal {
877         Signal { name: Arc::new(t.into()), arguments: vec!(), owner: Mutex::new(None), anns: Annotations::new() }
878     }
879 }
880 
881 impl<M: MethodType> Factory<M> {
882     /// Creates a new method with bounds enough to be used in all trees.
method_sync<H, T>(&self, t: T, handler: H) -> Method<M> where H: Fn(&Message, &ObjectPath<M>, &Tree<M>) -> MethodResult + Send + Sync + 'static, T: Into<Member<'static>>883     pub fn method_sync<H, T>(&self, t: T, handler: H) -> Method<M>
884     where H: Fn(&Message, &ObjectPath<M>, &Tree<M>) -> MethodResult + Send + Sync + 'static, T: Into<Member<'static>> {
885         Method::new(t.into(), M::box_method(handler))
886     }
887 }
888 
889 #[test]
factory_test()890 fn factory_test() {
891     let f = Factory::new_fn();
892     f.interface("com.example.hello").deprecated();
893     let b = 5i32;
894     f.method("GetSomething", |m,_,_| Ok(vec!({ let mut z = m.method_return(); z.append_items(&[b.into()]); z})));
895     let t = f.tree().add(f.object_path("/funghi").add(f.interface("a.b.c").deprecated()));
896     let t = t.add(f.object_path("/ab")).add(f.object_path("/a")).add(f.object_path("/a/b/c")).add(f.object_path("/a/b"));
897     assert_eq!(t.children(t.paths.get(&Path::from("/a")).unwrap(), true).len(), 1);
898 }
899 
900 #[test]
test_sync_prop()901 fn test_sync_prop() {
902     let f = Factory::new_sync();
903     let mut i = f.interface("com.example.echo");
904     let p = i.add_p_ref(f.property("EchoCount", 7i32));
905     let tree1 = Arc::new(f.tree().add(f.object_path("/echo").introspectable().add(i)));
906     let tree2 = tree1.clone();
907     println!("{:#?}", tree2);
908     ::std::thread::spawn(move || {
909         let r = p.set_value(9i32.into()).unwrap();
910         let signal = r.get(0).unwrap();
911         assert_eq!(signal.msg_type(), MessageType::Signal);
912         let mut msg = Message::new_method_call("com.example.echoserver", "/echo", "com.example", "dummy").unwrap();
913         super::message::message_set_serial(&mut msg, 3);
914         tree2.handle(&msg);
915     });
916 
917     let mut msg = Message::new_method_call("com.example.echoserver", "/echo", "org.freedesktop.DBus.Properties", "Get").unwrap()
918         .append("com.example.echo").append("EchoCount");
919     super::message::message_set_serial(&mut msg, 4);
920     let r = tree1.handle(&msg).unwrap();
921     let r1 = r.get(0).unwrap();
922     println!("{:?}", r1.get_items());
923     let vv: super::arg::Variant<i32> = r1.get1().unwrap();
924     assert!(vv.0 == 7 || vv.0 == 9);
925 }
926 
927 /* This test case no longer works, for unknown reason, see
928    https://github.com/diwic/dbus-rs/issues/27
929 
930 #[test]
931 fn prop_lifetime_simple() {
932     let count;
933     let f = Factory::new_fnmut();
934     count = Arc::new(f.property("changes", 0i32));
935     let mut i = f.interface("com.example.dbus.rs").add_p_arc(count.clone());
936 
937     let _setme = i.add_p_ref(f.property("setme", 0u8).access(Access::ReadWrite).on_set(|_,_,_| {
938         let v: i32 = count.get_value().inner().unwrap();
939         count.set_value((v + 1).into()).unwrap();
940         Ok(vec!())
941     }));
942 }
943 */
944 
945 #[test]
prop_server()946 fn prop_server() {
947     let setme: Arc<RefCell<Option<Arc<Property<_>>>>>; // Yikes!
948     setme = Arc::new(RefCell::new(None));
949     let f = Factory::new_fnmut();
950     let mut i = f.interface("com.example.dbus.rs");
951     let count = i.add_p_ref(f.property("changes", 0i32));
952     let count2 = count.clone();
953     let setme2 = setme.clone();
954     let setme3 = Arc::new(f.property("setme", 0u8).access(Access::ReadWrite).on_set(move |m,_,_| {
955         let ss2 = setme2.borrow();
956         let ss = ss2.as_ref().unwrap();
957         let s = try!(ss.verify_remote_set(m));
958         let r = try!(ss.set_value(s).map_err(|_| MethodErr::ro_property(&ss.name)));
959         let v: i32 = count2.get_value().inner().unwrap();
960         count2.set_value((v + 1).into()).unwrap();
961         Ok(r)
962     }));
963     *setme.borrow_mut() = Some(setme3.clone());
964     let i = i.add_p_arc(setme3);
965 
966     let tree = f.tree().add(f.object_path("/example").add(i));
967 
968     let mut msg = Message::new_method_call("com.example.dbus.rs", "/example", "org.freedesktop.DBus.Properties", "Get").unwrap()
969         .append("com.example.dbus.rs").append("changes");
970     super::message::message_set_serial(&mut msg, 10);
971     let r = tree.handle(&msg).unwrap();
972     let r1 = r.get(0).unwrap();
973     let ii = r1.get_items();
974     let vv: &MessageItem = ii.get(0).unwrap().inner().unwrap();
975     let v: i32 = vv.inner().unwrap();
976     assert_eq!(v, 0);
977 
978     // Read-only
979     let mut msg = Message::new_method_call("com.example.dbus.rs", "/example", "org.freedesktop.DBus.Properties", "Set").unwrap()
980         .append("com.example.dbus.rs").append("changes").append(5i32);
981     super::message::message_set_serial(&mut msg, 20);
982     let mut r = tree.handle(&msg).unwrap();
983     assert!(r.get_mut(0).unwrap().as_result().is_err());
984 
985     // Wrong type
986     let mut msg = Message::new_method_call("com.example.dbus.rs", "/example", "org.freedesktop.DBus.Properties", "Set").unwrap()
987         .append("com.example.dbus.rs").append("setme").append(8i32);
988     super::message::message_set_serial(&mut msg, 30);
989     let mut r = tree.handle(&msg).unwrap();
990     assert!(r.get_mut(0).unwrap().as_result().is_err());
991 
992     // Correct!
993     let mut msg = Message::new_method_call("com.example.dbus.rs", "/example", "org.freedesktop.DBus.Properties", "Set").unwrap()
994         .append("com.example.dbus.rs").append("setme").append(Box::new(9u8.into()));
995     super::message::message_set_serial(&mut msg, 30);
996     let mut r = tree.handle(&msg).unwrap();
997 
998     println!("{:?}", r[0].as_result());
999 
1000     let c: i32 = count.get_value().inner().unwrap();
1001     assert_eq!(c, 1);
1002 
1003 }
1004 
1005 
1006 #[test]
test_introspection()1007 fn test_introspection() {
1008     let f = Factory::new_sync();
1009     let t = f.object_path("/echo").introspectable()
1010         .add(f.interface("com.example.echo")
1011             .add_m(f.method("Echo", |_,_,_| unimplemented!()).in_arg(("request", "s")).out_arg(("reply", "s")))
1012             .add_p(f.property("EchoCount", 7i32))
1013             .add_s(f.signal("Echoed").arg(("data", "s")).deprecated())
1014     );
1015 
1016     let actual_result = t.introspect(&f.tree().add(f.object_path("/echo/subpath")));
1017     println!("\n=== Introspection XML start ===\n{}\n=== Introspection XML end ===", actual_result);
1018 
1019     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">
1020 <node name="/echo">
1021   <interface name="com.example.echo">
1022     <method name="Echo">
1023       <arg name="request" type="s" direction="in"/>
1024       <arg name="reply" type="s" direction="out"/>
1025     </method>
1026     <property name="EchoCount" type="i" access="read"/>
1027     <signal name="Echoed">
1028       <arg name="data" type="s"/>
1029       <annotation name="org.freedesktop.DBus.Deprecated" value="true"/>
1030     </signal>
1031   </interface>
1032   <interface name="org.freedesktop.DBus.Introspectable">
1033     <method name="Introspect">
1034       <arg name="xml_data" type="s" direction="out"/>
1035     </method>
1036   </interface>
1037   <interface name="org.freedesktop.DBus.Properties">
1038     <method name="Get">
1039       <arg name="interface_name" type="s" direction="in"/>
1040       <arg name="property_name" type="s" direction="in"/>
1041       <arg name="value" type="v" direction="out"/>
1042     </method>
1043     <method name="GetAll">
1044       <arg name="interface_name" type="s" direction="in"/>
1045       <arg name="props" type="a{sv}" direction="out"/>
1046     </method>
1047     <method name="Set">
1048       <arg name="interface_name" type="s" direction="in"/>
1049       <arg name="property_name" type="s" direction="in"/>
1050       <arg name="value" type="v" direction="in"/>
1051     </method>
1052   </interface>
1053   <node name="subpath"/>
1054 </node>"##;
1055 
1056     assert_eq!(expected_result, actual_result);
1057 }
1058 
1059