gio/
dbus_object_manager_client.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use crate::{
4    ffi, BusType, Cancellable, DBusConnection, DBusObjectManagerClient,
5    DBusObjectManagerClientFlags, DBusObjectProxy, DBusProxy, GioFuture,
6};
7use glib::object::{Cast as _, IsA};
8use glib::signal::connect_raw;
9use glib::translate::{
10    from_glib_borrow, from_glib_full, Borrowed, FromGlibPtrBorrow as _, IntoGlib as _,
11    ToGlibPtr as _,
12};
13use glib::{SignalHandlerId, StrVRef};
14use std::future::Future;
15use std::pin::Pin;
16
17type DBusProxyTypeFn = Box<
18    dyn Fn(&DBusObjectManagerClient, &str, Option<&str>) -> glib::types::Type
19        + Send
20        + Sync
21        + 'static,
22>;
23
24impl DBusObjectManagerClient {
25    #[doc(alias = "g_dbus_object_manager_client_new_sync")]
26    pub fn new_sync(
27        connection: &DBusConnection,
28        flags: DBusObjectManagerClientFlags,
29        name: Option<&str>,
30        object_path: &str,
31        cancellable: Option<&impl IsA<Cancellable>>,
32    ) -> Result<DBusObjectManagerClient, glib::Error> {
33        Self::new_sync_impl(connection, flags, name, object_path, None, cancellable)
34    }
35
36    #[doc(alias = "g_dbus_object_manager_client_new_sync")]
37    pub fn new_sync_with_fn<
38        F: Fn(&DBusObjectManagerClient, &str, Option<&str>) -> glib::types::Type
39            + Send
40            + Sync
41            + 'static,
42    >(
43        connection: &DBusConnection,
44        flags: DBusObjectManagerClientFlags,
45        name: Option<&str>,
46        object_path: &str,
47        get_proxy_type_func: F,
48        cancellable: Option<&impl IsA<Cancellable>>,
49    ) -> Result<DBusObjectManagerClient, glib::Error> {
50        Self::new_sync_impl(
51            connection,
52            flags,
53            name,
54            object_path,
55            Some(Box::new(get_proxy_type_func)),
56            cancellable,
57        )
58    }
59
60    #[doc(alias = "g_dbus_object_manager_client_new_for_bus_sync")]
61    pub fn for_bus_sync(
62        bus_type: BusType,
63        flags: DBusObjectManagerClientFlags,
64        name: &str,
65        object_path: &str,
66        cancellable: Option<&impl IsA<Cancellable>>,
67    ) -> Result<DBusObjectManagerClient, glib::Error> {
68        Self::for_bus_sync_impl(bus_type, flags, name, object_path, None, cancellable)
69    }
70
71    #[doc(alias = "g_dbus_object_manager_client_new_for_bus_sync")]
72    pub fn for_bus_sync_with_fn<
73        F: Fn(&DBusObjectManagerClient, &str, Option<&str>) -> glib::types::Type
74            + Send
75            + Sync
76            + 'static,
77    >(
78        bus_type: BusType,
79        flags: DBusObjectManagerClientFlags,
80        name: &str,
81        object_path: &str,
82        get_proxy_type_func: F,
83        cancellable: Option<&impl IsA<Cancellable>>,
84    ) -> Result<DBusObjectManagerClient, glib::Error> {
85        Self::for_bus_sync_impl(
86            bus_type,
87            flags,
88            name,
89            object_path,
90            Some(Box::new(get_proxy_type_func)),
91            cancellable,
92        )
93    }
94
95    #[allow(clippy::new_ret_no_self)]
96    #[doc(alias = "g_dbus_object_manager_client_new")]
97    pub fn new<P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static>(
98        connection: &DBusConnection,
99        flags: DBusObjectManagerClientFlags,
100        name: &str,
101        object_path: &str,
102        cancellable: Option<&impl IsA<Cancellable>>,
103        callback: P,
104    ) {
105        Self::new_impl(
106            connection,
107            flags,
108            name,
109            object_path,
110            None,
111            cancellable,
112            callback,
113        )
114    }
115
116    #[allow(clippy::new_ret_no_self)]
117    #[doc(alias = "g_dbus_object_manager_client_new")]
118    pub fn new_with_fn<
119        P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
120        F: Fn(&DBusObjectManagerClient, &str, Option<&str>) -> glib::types::Type
121            + Send
122            + Sync
123            + 'static,
124    >(
125        connection: &DBusConnection,
126        flags: DBusObjectManagerClientFlags,
127        name: &str,
128        object_path: &str,
129        get_proxy_type_func: F,
130        cancellable: Option<&impl IsA<Cancellable>>,
131        callback: P,
132    ) {
133        Self::new_impl(
134            connection,
135            flags,
136            name,
137            object_path,
138            Some(Box::new(get_proxy_type_func)),
139            cancellable,
140            callback,
141        )
142    }
143
144    #[allow(clippy::new_ret_no_self)]
145    fn new_impl<P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static>(
146        connection: &DBusConnection,
147        flags: DBusObjectManagerClientFlags,
148        name: &str,
149        object_path: &str,
150        get_proxy_type_func: Option<DBusProxyTypeFn>,
151        cancellable: Option<&impl IsA<Cancellable>>,
152        callback: P,
153    ) {
154        let main_context = glib::MainContext::ref_thread_default();
155        let is_main_context_owner = main_context.is_owner();
156        let has_acquired_main_context = (!is_main_context_owner)
157            .then(|| main_context.acquire().ok())
158            .flatten();
159        assert!(
160            is_main_context_owner || has_acquired_main_context.is_some(),
161            "Async operations only allowed if the thread is owning the MainContext"
162        );
163
164        unsafe extern "C" fn get_proxy_type_func_func(
165            manager: *mut ffi::GDBusObjectManagerClient,
166            object_path: *const std::ffi::c_char,
167            interface_name: *const std::ffi::c_char,
168            data: glib::ffi::gpointer,
169        ) -> glib::ffi::GType {
170            let manager = from_glib_borrow(manager);
171            let object_path: Borrowed<glib::GString> = from_glib_borrow(object_path);
172            let interface_name: Borrowed<Option<glib::GString>> = from_glib_borrow(interface_name);
173            let callback = &*(data as *mut Option<DBusProxyTypeFn>);
174            if let Some(ref callback) = *callback {
175                callback(
176                    &manager,
177                    object_path.as_str(),
178                    (*interface_name).as_ref().map(|s| s.as_str()),
179                )
180            } else {
181                panic!("cannot get closure...")
182            }
183            .into_glib()
184        }
185
186        unsafe extern "C" fn get_proxy_type_destroy_notify_func(data: glib::ffi::gpointer) {
187            let _callback = Box::from_raw(data as *mut Option<DBusProxyTypeFn>);
188        }
189
190        unsafe extern "C" fn new_trampoline<
191            P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
192        >(
193            _source_object: *mut glib::gobject_ffi::GObject,
194            res: *mut crate::ffi::GAsyncResult,
195            user_data: glib::ffi::gpointer,
196        ) {
197            let mut error = std::ptr::null_mut();
198            let ret = ffi::g_dbus_object_manager_client_new_finish(res, &mut error);
199            let result = if error.is_null() {
200                Ok(from_glib_full(ret))
201            } else {
202                Err(from_glib_full(error))
203            };
204            let callback: Box<glib::thread_guard::ThreadGuard<P>> =
205                Box::from_raw(user_data as *mut _);
206            let callback: P = callback.into_inner();
207            callback(result);
208        }
209
210        let get_proxy_type_user_data = Box::new(get_proxy_type_func);
211        let get_proxy_type_func = if get_proxy_type_user_data.is_some() {
212            Some(get_proxy_type_func_func as _)
213        } else {
214            None
215        };
216        let get_proxy_type_destroy_notify = if get_proxy_type_user_data.is_some() {
217            Some(get_proxy_type_destroy_notify_func as _)
218        } else {
219            None
220        };
221
222        let user_data: Box<glib::thread_guard::ThreadGuard<P>> =
223            Box::new(glib::thread_guard::ThreadGuard::new(callback));
224        let callback = new_trampoline::<P>;
225
226        unsafe {
227            ffi::g_dbus_object_manager_client_new(
228                connection.to_glib_none().0,
229                flags.into_glib(),
230                name.to_glib_none().0,
231                object_path.to_glib_none().0,
232                get_proxy_type_func,
233                Box::into_raw(get_proxy_type_user_data) as *mut _,
234                get_proxy_type_destroy_notify,
235                cancellable.map(|p| p.as_ref()).to_glib_none().0,
236                Some(callback),
237                Box::into_raw(user_data) as *mut _,
238            );
239        }
240    }
241
242    pub fn new_future(
243        connection: &DBusConnection,
244        flags: DBusObjectManagerClientFlags,
245        name: &str,
246        object_path: &str,
247    ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
248        Self::new_future_impl(connection, flags, name, object_path, None)
249    }
250
251    pub fn new_future_with_fn<
252        F: Fn(&DBusObjectManagerClient, &str, Option<&str>) -> glib::types::Type
253            + Send
254            + Sync
255            + 'static,
256    >(
257        connection: &DBusConnection,
258        flags: DBusObjectManagerClientFlags,
259        name: &str,
260        object_path: &str,
261        get_proxy_type_func: F,
262    ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
263        Self::new_future_impl(
264            connection,
265            flags,
266            name,
267            object_path,
268            Some(Box::new(get_proxy_type_func)),
269        )
270    }
271
272    fn new_future_impl(
273        connection: &DBusConnection,
274        flags: DBusObjectManagerClientFlags,
275        name: &str,
276        object_path: &str,
277        get_proxy_type_func: Option<DBusProxyTypeFn>,
278    ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
279        let connection = connection.clone();
280        let name = String::from(name);
281        let object_path = String::from(object_path);
282        Box::pin(GioFuture::new(&(), move |_obj, cancellable, send| {
283            Self::new_impl(
284                &connection,
285                flags,
286                &name,
287                &object_path,
288                get_proxy_type_func,
289                Some(cancellable),
290                move |res| {
291                    send.resolve(res);
292                },
293            );
294        }))
295    }
296
297    #[doc(alias = "g_dbus_object_manager_client_new_for_bus")]
298    #[allow(clippy::new_ret_no_self)]
299    pub fn new_for_bus<
300        P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
301    >(
302        bus_type: BusType,
303        flags: DBusObjectManagerClientFlags,
304        name: &str,
305        object_path: &str,
306        cancellable: Option<&impl IsA<Cancellable>>,
307        callback: P,
308    ) {
309        Self::new_for_bus_impl(
310            bus_type,
311            flags,
312            name,
313            object_path,
314            None,
315            cancellable,
316            callback,
317        );
318    }
319
320    #[doc(alias = "g_dbus_object_manager_client_new_for_bus")]
321    #[allow(clippy::new_ret_no_self)]
322    pub fn new_for_bus_with_fn<
323        P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
324        F: Fn(&DBusObjectManagerClient, &str, Option<&str>) -> glib::types::Type
325            + Send
326            + Sync
327            + 'static,
328    >(
329        bus_type: BusType,
330        flags: DBusObjectManagerClientFlags,
331        name: &str,
332        object_path: &str,
333        get_proxy_type_func: F,
334        cancellable: Option<&impl IsA<Cancellable>>,
335        callback: P,
336    ) {
337        Self::new_for_bus_impl(
338            bus_type,
339            flags,
340            name,
341            object_path,
342            Some(Box::new(get_proxy_type_func)),
343            cancellable,
344            callback,
345        );
346    }
347
348    #[allow(clippy::new_ret_no_self)]
349    fn new_for_bus_impl<
350        P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
351    >(
352        bus_type: BusType,
353        flags: DBusObjectManagerClientFlags,
354        name: &str,
355        object_path: &str,
356        get_proxy_type_func: Option<DBusProxyTypeFn>,
357        cancellable: Option<&impl IsA<Cancellable>>,
358        callback: P,
359    ) {
360        let main_context = glib::MainContext::ref_thread_default();
361        let is_main_context_owner = main_context.is_owner();
362        let has_acquired_main_context = (!is_main_context_owner)
363            .then(|| main_context.acquire().ok())
364            .flatten();
365        assert!(
366            is_main_context_owner || has_acquired_main_context.is_some(),
367            "Async operations only allowed if the thread is owning the MainContext"
368        );
369
370        unsafe extern "C" fn get_proxy_type_func_func(
371            manager: *mut ffi::GDBusObjectManagerClient,
372            object_path: *const std::ffi::c_char,
373            interface_name: *const std::ffi::c_char,
374            data: glib::ffi::gpointer,
375        ) -> glib::ffi::GType {
376            let manager = from_glib_borrow(manager);
377            let object_path: Borrowed<glib::GString> = from_glib_borrow(object_path);
378            let interface_name: Borrowed<Option<glib::GString>> = from_glib_borrow(interface_name);
379            let callback = &*(data as *mut Option<DBusProxyTypeFn>);
380            if let Some(ref callback) = *callback {
381                callback(
382                    &manager,
383                    object_path.as_str(),
384                    (*interface_name).as_ref().map(|s| s.as_str()),
385                )
386            } else {
387                panic!("cannot get closure...")
388            }
389            .into_glib()
390        }
391
392        unsafe extern "C" fn get_proxy_type_destroy_notify_func(data: glib::ffi::gpointer) {
393            let _callback = Box::from_raw(data as *mut Option<DBusProxyTypeFn>);
394        }
395
396        unsafe extern "C" fn new_for_bus_trampoline<
397            P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
398        >(
399            _source_object: *mut glib::gobject_ffi::GObject,
400            res: *mut crate::ffi::GAsyncResult,
401            user_data: glib::ffi::gpointer,
402        ) {
403            let mut error = std::ptr::null_mut();
404            let ret = ffi::g_dbus_object_manager_client_new_finish(res, &mut error);
405            let result = if error.is_null() {
406                Ok(from_glib_full(ret))
407            } else {
408                Err(from_glib_full(error))
409            };
410            let callback: Box<glib::thread_guard::ThreadGuard<P>> =
411                Box::from_raw(user_data as *mut _);
412            let callback: P = callback.into_inner();
413            callback(result);
414        }
415
416        let get_proxy_type_user_data = Box::new(get_proxy_type_func);
417        let get_proxy_type_func = if get_proxy_type_user_data.is_some() {
418            Some(get_proxy_type_func_func as _)
419        } else {
420            None
421        };
422        let get_proxy_type_destroy_notify = if get_proxy_type_user_data.is_some() {
423            Some(get_proxy_type_destroy_notify_func as _)
424        } else {
425            None
426        };
427
428        let user_data: Box<glib::thread_guard::ThreadGuard<P>> =
429            Box::new(glib::thread_guard::ThreadGuard::new(callback));
430        let callback = new_for_bus_trampoline::<P>;
431
432        unsafe {
433            ffi::g_dbus_object_manager_client_new_for_bus(
434                bus_type.into_glib(),
435                flags.into_glib(),
436                name.to_glib_none().0,
437                object_path.to_glib_none().0,
438                get_proxy_type_func,
439                Box::into_raw(get_proxy_type_user_data) as *mut _,
440                get_proxy_type_destroy_notify,
441                cancellable.map(|p| p.as_ref()).to_glib_none().0,
442                Some(callback),
443                Box::into_raw(user_data) as *mut _,
444            );
445        }
446    }
447
448    pub fn new_for_bus_future(
449        bus_type: BusType,
450        flags: DBusObjectManagerClientFlags,
451        name: &str,
452        object_path: &str,
453    ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
454        Self::new_for_bus_future_impl(bus_type, flags, name, object_path, None)
455    }
456
457    pub fn new_for_bus_future_with_fn<
458        F: Fn(&DBusObjectManagerClient, &str, Option<&str>) -> glib::types::Type
459            + Send
460            + Sync
461            + 'static,
462    >(
463        bus_type: BusType,
464        flags: DBusObjectManagerClientFlags,
465        name: &str,
466        object_path: &str,
467        get_proxy_type_func: F,
468    ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
469        Self::new_for_bus_future_impl(
470            bus_type,
471            flags,
472            name,
473            object_path,
474            Some(Box::new(get_proxy_type_func)),
475        )
476    }
477
478    fn new_for_bus_future_impl(
479        bus_type: BusType,
480        flags: DBusObjectManagerClientFlags,
481        name: &str,
482        object_path: &str,
483        get_proxy_type_func: Option<DBusProxyTypeFn>,
484    ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
485        let name = String::from(name);
486        let object_path = String::from(object_path);
487        Box::pin(GioFuture::new(&(), move |_obj, cancellable, send| {
488            Self::new_for_bus_impl(
489                bus_type,
490                flags,
491                &name,
492                &object_path,
493                get_proxy_type_func,
494                Some(cancellable),
495                move |res| {
496                    send.resolve(res);
497                },
498            );
499        }))
500    }
501}
502
503pub trait DBusObjectManagerClientExtManual: IsA<DBusObjectManagerClient> + 'static {
504    #[doc(alias = "interface-proxy-properties-changed")]
505    fn connect_interface_proxy_properties_changed<
506        F: Fn(&Self, &DBusObjectProxy, &DBusProxy, &glib::Variant, &StrVRef) + Send + Sync + 'static,
507    >(
508        &self,
509        f: F,
510    ) -> SignalHandlerId {
511        unsafe extern "C" fn interface_proxy_properties_changed_trampoline<
512            P: IsA<DBusObjectManagerClient>,
513            F: Fn(&P, &DBusObjectProxy, &DBusProxy, &glib::Variant, &StrVRef) + Send + Sync + 'static,
514        >(
515            this: *mut ffi::GDBusObjectManagerClient,
516            object_proxy: *mut ffi::GDBusObjectProxy,
517            interface_proxy: *mut ffi::GDBusProxy,
518            changed_properties: *mut glib::ffi::GVariant,
519            invalidated_properties: *const *const std::ffi::c_char,
520            f: glib::ffi::gpointer,
521        ) {
522            let f: &F = &*(f as *const F);
523            f(
524                DBusObjectManagerClient::from_glib_borrow(this).unsafe_cast_ref(),
525                &from_glib_borrow(object_proxy),
526                &from_glib_borrow(interface_proxy),
527                &from_glib_borrow(changed_properties),
528                StrVRef::from_glib_borrow(invalidated_properties),
529            )
530        }
531        unsafe {
532            let f: Box<F> = Box::new(f);
533            connect_raw(
534                self.as_ptr() as *mut _,
535                c"interface-proxy-properties-changed".as_ptr() as *const _,
536                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
537                    interface_proxy_properties_changed_trampoline::<Self, F> as *const (),
538                )),
539                Box::into_raw(f),
540            )
541        }
542    }
543}
544
545impl<O: IsA<DBusObjectManagerClient>> DBusObjectManagerClientExtManual for O {}