Skip to main content

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    BusType, Cancellable, DBusConnection, DBusObjectManagerClient, DBusObjectManagerClientFlags,
5    DBusObjectProxy, DBusProxy, GioFuture, ffi,
6};
7use glib::object::{Cast as _, IsA};
8use glib::signal::connect_raw;
9use glib::translate::{
10    Borrowed, FromGlibPtrBorrow as _, IntoGlib as _, ToGlibPtr as _, from_glib_borrow,
11    from_glib_full,
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            unsafe {
171                let manager = from_glib_borrow(manager);
172                let object_path: Borrowed<glib::GString> = from_glib_borrow(object_path);
173                let interface_name: Borrowed<Option<glib::GString>> =
174                    from_glib_borrow(interface_name);
175                let callback = &*(data as *mut Option<DBusProxyTypeFn>);
176                if let Some(ref callback) = *callback {
177                    callback(
178                        &manager,
179                        object_path.as_str(),
180                        (*interface_name).as_ref().map(|s| s.as_str()),
181                    )
182                } else {
183                    panic!("cannot get closure...")
184                }
185                .into_glib()
186            }
187        }
188
189        unsafe extern "C" fn get_proxy_type_destroy_notify_func(data: glib::ffi::gpointer) {
190            unsafe {
191                let _callback = Box::from_raw(data as *mut Option<DBusProxyTypeFn>);
192            }
193        }
194
195        unsafe extern "C" fn new_trampoline<
196            P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
197        >(
198            _source_object: *mut glib::gobject_ffi::GObject,
199            res: *mut crate::ffi::GAsyncResult,
200            user_data: glib::ffi::gpointer,
201        ) {
202            unsafe {
203                let mut error = std::ptr::null_mut();
204                let ret = ffi::g_dbus_object_manager_client_new_finish(res, &mut error);
205                let result = if error.is_null() {
206                    Ok(from_glib_full(ret))
207                } else {
208                    Err(from_glib_full(error))
209                };
210                let callback: Box<glib::thread_guard::ThreadGuard<P>> =
211                    Box::from_raw(user_data as *mut _);
212                let callback: P = callback.into_inner();
213                callback(result);
214            }
215        }
216
217        let get_proxy_type_user_data = Box::new(get_proxy_type_func);
218        let get_proxy_type_func = if get_proxy_type_user_data.is_some() {
219            Some(get_proxy_type_func_func as _)
220        } else {
221            None
222        };
223        let get_proxy_type_destroy_notify = if get_proxy_type_user_data.is_some() {
224            Some(get_proxy_type_destroy_notify_func as _)
225        } else {
226            None
227        };
228
229        let user_data: Box<glib::thread_guard::ThreadGuard<P>> =
230            Box::new(glib::thread_guard::ThreadGuard::new(callback));
231        let callback = new_trampoline::<P>;
232
233        unsafe {
234            ffi::g_dbus_object_manager_client_new(
235                connection.to_glib_none().0,
236                flags.into_glib(),
237                name.to_glib_none().0,
238                object_path.to_glib_none().0,
239                get_proxy_type_func,
240                Box::into_raw(get_proxy_type_user_data) as *mut _,
241                get_proxy_type_destroy_notify,
242                cancellable.map(|p| p.as_ref()).to_glib_none().0,
243                Some(callback),
244                Box::into_raw(user_data) as *mut _,
245            );
246        }
247    }
248
249    pub fn new_future(
250        connection: &DBusConnection,
251        flags: DBusObjectManagerClientFlags,
252        name: &str,
253        object_path: &str,
254    ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
255        Self::new_future_impl(connection, flags, name, object_path, None)
256    }
257
258    pub fn new_future_with_fn<
259        F: Fn(&DBusObjectManagerClient, &str, Option<&str>) -> glib::types::Type
260            + Send
261            + Sync
262            + 'static,
263    >(
264        connection: &DBusConnection,
265        flags: DBusObjectManagerClientFlags,
266        name: &str,
267        object_path: &str,
268        get_proxy_type_func: F,
269    ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
270        Self::new_future_impl(
271            connection,
272            flags,
273            name,
274            object_path,
275            Some(Box::new(get_proxy_type_func)),
276        )
277    }
278
279    fn new_future_impl(
280        connection: &DBusConnection,
281        flags: DBusObjectManagerClientFlags,
282        name: &str,
283        object_path: &str,
284        get_proxy_type_func: Option<DBusProxyTypeFn>,
285    ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
286        let connection = connection.clone();
287        let name = String::from(name);
288        let object_path = String::from(object_path);
289        Box::pin(GioFuture::new(&(), move |_obj, cancellable, send| {
290            Self::new_impl(
291                &connection,
292                flags,
293                &name,
294                &object_path,
295                get_proxy_type_func,
296                Some(cancellable),
297                move |res| {
298                    send.resolve(res);
299                },
300            );
301        }))
302    }
303
304    #[doc(alias = "g_dbus_object_manager_client_new_for_bus")]
305    #[allow(clippy::new_ret_no_self)]
306    pub fn new_for_bus<
307        P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
308    >(
309        bus_type: BusType,
310        flags: DBusObjectManagerClientFlags,
311        name: &str,
312        object_path: &str,
313        cancellable: Option<&impl IsA<Cancellable>>,
314        callback: P,
315    ) {
316        Self::new_for_bus_impl(
317            bus_type,
318            flags,
319            name,
320            object_path,
321            None,
322            cancellable,
323            callback,
324        );
325    }
326
327    #[doc(alias = "g_dbus_object_manager_client_new_for_bus")]
328    #[allow(clippy::new_ret_no_self)]
329    pub fn new_for_bus_with_fn<
330        P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
331        F: Fn(&DBusObjectManagerClient, &str, Option<&str>) -> glib::types::Type
332            + Send
333            + Sync
334            + 'static,
335    >(
336        bus_type: BusType,
337        flags: DBusObjectManagerClientFlags,
338        name: &str,
339        object_path: &str,
340        get_proxy_type_func: F,
341        cancellable: Option<&impl IsA<Cancellable>>,
342        callback: P,
343    ) {
344        Self::new_for_bus_impl(
345            bus_type,
346            flags,
347            name,
348            object_path,
349            Some(Box::new(get_proxy_type_func)),
350            cancellable,
351            callback,
352        );
353    }
354
355    #[allow(clippy::new_ret_no_self)]
356    fn new_for_bus_impl<
357        P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
358    >(
359        bus_type: BusType,
360        flags: DBusObjectManagerClientFlags,
361        name: &str,
362        object_path: &str,
363        get_proxy_type_func: Option<DBusProxyTypeFn>,
364        cancellable: Option<&impl IsA<Cancellable>>,
365        callback: P,
366    ) {
367        let main_context = glib::MainContext::ref_thread_default();
368        let is_main_context_owner = main_context.is_owner();
369        let has_acquired_main_context = (!is_main_context_owner)
370            .then(|| main_context.acquire().ok())
371            .flatten();
372        assert!(
373            is_main_context_owner || has_acquired_main_context.is_some(),
374            "Async operations only allowed if the thread is owning the MainContext"
375        );
376
377        unsafe extern "C" fn get_proxy_type_func_func(
378            manager: *mut ffi::GDBusObjectManagerClient,
379            object_path: *const std::ffi::c_char,
380            interface_name: *const std::ffi::c_char,
381            data: glib::ffi::gpointer,
382        ) -> glib::ffi::GType {
383            unsafe {
384                let manager = from_glib_borrow(manager);
385                let object_path: Borrowed<glib::GString> = from_glib_borrow(object_path);
386                let interface_name: Borrowed<Option<glib::GString>> =
387                    from_glib_borrow(interface_name);
388                let callback = &*(data as *mut Option<DBusProxyTypeFn>);
389                if let Some(ref callback) = *callback {
390                    callback(
391                        &manager,
392                        object_path.as_str(),
393                        (*interface_name).as_ref().map(|s| s.as_str()),
394                    )
395                } else {
396                    panic!("cannot get closure...")
397                }
398                .into_glib()
399            }
400        }
401
402        unsafe extern "C" fn get_proxy_type_destroy_notify_func(data: glib::ffi::gpointer) {
403            unsafe {
404                let _callback = Box::from_raw(data as *mut Option<DBusProxyTypeFn>);
405            }
406        }
407
408        unsafe extern "C" fn new_for_bus_trampoline<
409            P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
410        >(
411            _source_object: *mut glib::gobject_ffi::GObject,
412            res: *mut crate::ffi::GAsyncResult,
413            user_data: glib::ffi::gpointer,
414        ) {
415            unsafe {
416                let mut error = std::ptr::null_mut();
417                let ret = ffi::g_dbus_object_manager_client_new_finish(res, &mut error);
418                let result = if error.is_null() {
419                    Ok(from_glib_full(ret))
420                } else {
421                    Err(from_glib_full(error))
422                };
423                let callback: Box<glib::thread_guard::ThreadGuard<P>> =
424                    Box::from_raw(user_data as *mut _);
425                let callback: P = callback.into_inner();
426                callback(result);
427            }
428        }
429
430        let get_proxy_type_user_data = Box::new(get_proxy_type_func);
431        let get_proxy_type_func = if get_proxy_type_user_data.is_some() {
432            Some(get_proxy_type_func_func as _)
433        } else {
434            None
435        };
436        let get_proxy_type_destroy_notify = if get_proxy_type_user_data.is_some() {
437            Some(get_proxy_type_destroy_notify_func as _)
438        } else {
439            None
440        };
441
442        let user_data: Box<glib::thread_guard::ThreadGuard<P>> =
443            Box::new(glib::thread_guard::ThreadGuard::new(callback));
444        let callback = new_for_bus_trampoline::<P>;
445
446        unsafe {
447            ffi::g_dbus_object_manager_client_new_for_bus(
448                bus_type.into_glib(),
449                flags.into_glib(),
450                name.to_glib_none().0,
451                object_path.to_glib_none().0,
452                get_proxy_type_func,
453                Box::into_raw(get_proxy_type_user_data) as *mut _,
454                get_proxy_type_destroy_notify,
455                cancellable.map(|p| p.as_ref()).to_glib_none().0,
456                Some(callback),
457                Box::into_raw(user_data) as *mut _,
458            );
459        }
460    }
461
462    pub fn new_for_bus_future(
463        bus_type: BusType,
464        flags: DBusObjectManagerClientFlags,
465        name: &str,
466        object_path: &str,
467    ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
468        Self::new_for_bus_future_impl(bus_type, flags, name, object_path, None)
469    }
470
471    pub fn new_for_bus_future_with_fn<
472        F: Fn(&DBusObjectManagerClient, &str, Option<&str>) -> glib::types::Type
473            + Send
474            + Sync
475            + 'static,
476    >(
477        bus_type: BusType,
478        flags: DBusObjectManagerClientFlags,
479        name: &str,
480        object_path: &str,
481        get_proxy_type_func: F,
482    ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
483        Self::new_for_bus_future_impl(
484            bus_type,
485            flags,
486            name,
487            object_path,
488            Some(Box::new(get_proxy_type_func)),
489        )
490    }
491
492    fn new_for_bus_future_impl(
493        bus_type: BusType,
494        flags: DBusObjectManagerClientFlags,
495        name: &str,
496        object_path: &str,
497        get_proxy_type_func: Option<DBusProxyTypeFn>,
498    ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
499        let name = String::from(name);
500        let object_path = String::from(object_path);
501        Box::pin(GioFuture::new(&(), move |_obj, cancellable, send| {
502            Self::new_for_bus_impl(
503                bus_type,
504                flags,
505                &name,
506                &object_path,
507                get_proxy_type_func,
508                Some(cancellable),
509                move |res| {
510                    send.resolve(res);
511                },
512            );
513        }))
514    }
515}
516
517pub trait DBusObjectManagerClientExtManual: IsA<DBusObjectManagerClient> + 'static {
518    #[doc(alias = "interface-proxy-properties-changed")]
519    fn connect_interface_proxy_properties_changed<
520        F: Fn(&Self, &DBusObjectProxy, &DBusProxy, &glib::Variant, &StrVRef) + Send + Sync + 'static,
521    >(
522        &self,
523        f: F,
524    ) -> SignalHandlerId {
525        unsafe extern "C" fn interface_proxy_properties_changed_trampoline<
526            P: IsA<DBusObjectManagerClient>,
527            F: Fn(&P, &DBusObjectProxy, &DBusProxy, &glib::Variant, &StrVRef) + Send + Sync + 'static,
528        >(
529            this: *mut ffi::GDBusObjectManagerClient,
530            object_proxy: *mut ffi::GDBusObjectProxy,
531            interface_proxy: *mut ffi::GDBusProxy,
532            changed_properties: *mut glib::ffi::GVariant,
533            invalidated_properties: *const *const std::ffi::c_char,
534            f: glib::ffi::gpointer,
535        ) {
536            unsafe {
537                let f: &F = &*(f as *const F);
538                f(
539                    DBusObjectManagerClient::from_glib_borrow(this).unsafe_cast_ref(),
540                    &from_glib_borrow(object_proxy),
541                    &from_glib_borrow(interface_proxy),
542                    &from_glib_borrow(changed_properties),
543                    StrVRef::from_glib_borrow(invalidated_properties),
544                )
545            }
546        }
547        unsafe {
548            let f: Box<F> = Box::new(f);
549            connect_raw(
550                self.as_ptr() as *mut _,
551                c"interface-proxy-properties-changed".as_ptr() as *const _,
552                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
553                    interface_proxy_properties_changed_trampoline::<Self, F> as *const (),
554                )),
555                Box::into_raw(f),
556            )
557        }
558    }
559}
560
561impl<O: IsA<DBusObjectManagerClient>> DBusObjectManagerClientExtManual for O {}