From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- third_party/rust/dbus/src/tree/factory.rs | 137 ++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 third_party/rust/dbus/src/tree/factory.rs (limited to 'third_party/rust/dbus/src/tree/factory.rs') 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, D: DataType=()>(Arc>); + +impl, D: DataType> From>> for Factory { + fn from(f: Arc>) -> Self { Factory(f) } +} + +impl Factory, ()> { + /// Creates a new factory for single-thread use. + pub fn new_fn() -> Factory, D> { Factory(IfaceCache::new()) } + + /// Creates a new factory for single-thread use, where callbacks can mutate their environment. + pub fn new_fnmut() -> Factory, D> { Factory(IfaceCache::new()) } + + /// Creates a new factory for multi-thread use. + pub fn new_sync() -> Factory, D> { Factory(IfaceCache::new()) } + +} + +impl Factory, D> { + /// Creates a new method for single-thread use. + pub fn method(&self, t: T, data: D::Method, handler: H) -> Method, D> + where H: 'static + Fn(&MethodInfo, D>) -> MethodResult, T: Into> { + super::leaves::new_method(t.into(), data, Box::new(handler) as Box<_>) + } +} + +impl Factory, D> { + /// Creates a new method for single-thread use. + pub fn method(&self, t: T, data: D::Method, handler: H) -> Method, D> + where H: 'static + FnMut(&MethodInfo, D>) -> MethodResult, T: Into> { + super::leaves::new_method(t.into(), data, Box::new(RefCell::new(handler)) as Box<_>) + } +} + +impl Factory, D> { + /// Creates a new method for multi-thread use. + pub fn method(&self, t: T, data: D::Method, handler: H) -> Method, D> + where H: Fn(&MethodInfo, D>) -> MethodResult + Send + Sync + 'static, T: Into> { + super::leaves::new_method(t.into(), data, Box::new(handler) as Box<_>) + } +} + + +impl, D: DataType> Factory { + + /// Creates a new property. + /// + /// `A` is used to calculate the type signature of the property. + pub fn property>(&self, name: T, data: D::Property) -> Property { + let sig = A::signature(); + super::leaves::new_property(name.into(), sig, data) + } + + /// Creates a new signal. + pub fn signal>>(&self, name: T, data: D::Signal) -> Signal { + super::leaves::new_signal(name.into(), data) + } + + /// Creates a new interface. + pub fn interface>>(&self, name: T, data: D::Interface) -> Interface { + super::objectpath::new_interface(name.into(), data) + } + + /// Creates a new object path. + pub fn object_path>>(&self, name: T, data: D::ObjectPath) -> ObjectPath { + super::objectpath::new_objectpath(name.into(), data, self.0.clone()) + } + + /// Creates a new tree. + pub fn tree(&self, data: D::Tree) -> Tree { + 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(&self, t: T, data: D::Method, handler: H) -> Method + where H: Fn(&MethodInfo) -> MethodResult + Send + Sync + 'static, T: Into> { + 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; + type Interface = (); + type Property = (); + type Method = i32; + type Signal = (); + } + + let f = Factory::new_fn::(); + + 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); +} -- cgit v1.2.3