summaryrefslogtreecommitdiffstats
path: root/third_party/rust/dbus/src/tree/factory.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/dbus/src/tree/factory.rs')
-rw-r--r--third_party/rust/dbus/src/tree/factory.rs137
1 files changed, 137 insertions, 0 deletions
diff --git a/third_party/rust/dbus/src/tree/factory.rs b/third_party/rust/dbus/src/tree/factory.rs
new file mode 100644
index 0000000000..2157fc4110
--- /dev/null
+++ b/third_party/rust/dbus/src/tree/factory.rs
@@ -0,0 +1,137 @@
+use super::{MethodType, DataType, MTFn, MTFnMut, MTSync, MethodResult, MethodInfo};
+use super::{Tree, ObjectPath, Interface, Property, Signal, Method};
+use super::objectpath::IfaceCache;
+use std::sync::Arc;
+use Interface as IfaceName;
+use {Member, Path, arg};
+use std::cell::RefCell;
+
+/// The factory is used to create object paths, interfaces, methods etc.
+///
+/// There are three factories:
+///
+/// **MTFn** - all methods are `Fn()`.
+///
+/// **MTFnMut** - all methods are `FnMut()`. This means they can mutate their environment,
+/// which has the side effect that if you call it recursively, it will RefCell panic.
+///
+/// **MTSync** - all methods are `Fn() + Send + Sync + 'static`. This means that the methods
+/// can be called from different threads in parallel.
+///
+#[derive(Debug, Clone)]
+pub struct Factory<M: MethodType<D>, D: DataType=()>(Arc<IfaceCache<M, D>>);
+
+impl<M: MethodType<D>, D: DataType> From<Arc<IfaceCache<M, D>>> for Factory<M, D> {
+ fn from(f: Arc<IfaceCache<M, D>>) -> Self { Factory(f) }
+}
+
+impl Factory<MTFn<()>, ()> {
+ /// Creates a new factory for single-thread use.
+ pub fn new_fn<D: DataType>() -> Factory<MTFn<D>, D> { Factory(IfaceCache::new()) }
+
+ /// Creates a new factory for single-thread use, where callbacks can mutate their environment.
+ pub fn new_fnmut<D: DataType>() -> Factory<MTFnMut<D>, D> { Factory(IfaceCache::new()) }
+
+ /// Creates a new factory for multi-thread use.
+ pub fn new_sync<D: DataType>() -> Factory<MTSync<D>, D> { Factory(IfaceCache::new()) }
+
+}
+
+impl<D: DataType> Factory<MTFn<D>, D> {
+ /// Creates a new method for single-thread use.
+ pub fn method<H, T>(&self, t: T, data: D::Method, handler: H) -> Method<MTFn<D>, D>
+ where H: 'static + Fn(&MethodInfo<MTFn<D>, D>) -> MethodResult, T: Into<Member<'static>> {
+ super::leaves::new_method(t.into(), data, Box::new(handler) as Box<_>)
+ }
+}
+
+impl<D: DataType> Factory<MTFnMut<D>, D> {
+ /// Creates a new method for single-thread use.
+ pub fn method<H, T>(&self, t: T, data: D::Method, handler: H) -> Method<MTFnMut<D>, D>
+ where H: 'static + FnMut(&MethodInfo<MTFnMut<D>, D>) -> MethodResult, T: Into<Member<'static>> {
+ super::leaves::new_method(t.into(), data, Box::new(RefCell::new(handler)) as Box<_>)
+ }
+}
+
+impl<D: DataType> Factory<MTSync<D>, D> {
+ /// Creates a new method for multi-thread use.
+ pub fn method<H, T>(&self, t: T, data: D::Method, handler: H) -> Method<MTSync<D>, D>
+ where H: Fn(&MethodInfo<MTSync<D>, D>) -> MethodResult + Send + Sync + 'static, T: Into<Member<'static>> {
+ super::leaves::new_method(t.into(), data, Box::new(handler) as Box<_>)
+ }
+}
+
+
+impl<M: MethodType<D>, D: DataType> Factory<M, D> {
+
+ /// Creates a new property.
+ ///
+ /// `A` is used to calculate the type signature of the property.
+ pub fn property<A: arg::Arg, T: Into<String>>(&self, name: T, data: D::Property) -> Property<M, D> {
+ let sig = A::signature();
+ super::leaves::new_property(name.into(), sig, data)
+ }
+
+ /// Creates a new signal.
+ pub fn signal<T: Into<Member<'static>>>(&self, name: T, data: D::Signal) -> Signal<D> {
+ super::leaves::new_signal(name.into(), data)
+ }
+
+ /// Creates a new interface.
+ pub fn interface<T: Into<IfaceName<'static>>>(&self, name: T, data: D::Interface) -> Interface<M, D> {
+ super::objectpath::new_interface(name.into(), data)
+ }
+
+ /// Creates a new object path.
+ pub fn object_path<T: Into<Path<'static>>>(&self, name: T, data: D::ObjectPath) -> ObjectPath<M, D> {
+ super::objectpath::new_objectpath(name.into(), data, self.0.clone())
+ }
+
+ /// Creates a new tree.
+ pub fn tree(&self, data: D::Tree) -> Tree<M, D> {
+ super::objectpath::new_tree(data)
+ }
+
+ /// Creates a new method - usually you'll use "method" instead.
+ ///
+ /// This is useful for being able to create methods in code which is generic over methodtype.
+ pub fn method_sync<H, T>(&self, t: T, data: D::Method, handler: H) -> Method<M, D>
+ where H: Fn(&MethodInfo<M, D>) -> MethodResult + Send + Sync + 'static, T: Into<Member<'static>> {
+ super::leaves::new_method(t.into(), data, M::make_method(handler))
+ }
+}
+
+
+#[test]
+fn create_fnmut() {
+ let f = Factory::new_fnmut::<()>();
+ let mut move_me = 5u32;
+ let m = f.method("test", (), move |m| {
+ move_me += 1;
+ Ok(vec!(m.msg.method_return().append1(&move_me)))
+ });
+ assert_eq!(&**m.get_name(), "test");
+}
+
+
+#[test]
+fn fn_customdata() {
+ #[derive(Default)]
+ struct Custom;
+ impl DataType for Custom {
+ type Tree = ();
+ type ObjectPath = Arc<u8>;
+ type Interface = ();
+ type Property = ();
+ type Method = i32;
+ type Signal = ();
+ }
+
+ let f = Factory::new_fn::<Custom>();
+
+ let m = f.method("test", 789, |_| unimplemented!());
+ assert_eq!(*m.get_data(), 789);
+
+ let o = f.object_path("/test/test", Arc::new(7));
+ assert_eq!(**o.get_data(), 7);
+}