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    /// Asynchronously creates a new #GDBusObjectManagerClient object.
96    ///
97    /// This is an asynchronous failable constructor. When the result is
98    /// ready, @callback will be invoked in the thread-default main context
99    /// (see [`glib::MainContext::push_thread_default()`][crate::glib::MainContext::push_thread_default()])
100    /// of the thread you are calling this method from. You can then call
101    /// g_dbus_object_manager_client_new_finish() to get the result. See
102    /// g_dbus_object_manager_client_new_sync() for the synchronous version.
103    /// ## `connection`
104    /// A #GDBusConnection.
105    /// ## `flags`
106    /// Zero or more flags from the #GDBusObjectManagerClientFlags enumeration.
107    /// ## `name`
108    /// The owner of the control object (unique or well-known name).
109    /// ## `object_path`
110    /// The object path of the control object.
111    /// ## `get_proxy_type_func`
112    /// A #GDBusProxyTypeFunc function or [`None`] to always construct #GDBusProxy proxies.
113    /// ## `get_proxy_type_user_data`
114    /// User data to pass to @get_proxy_type_func.
115    /// ## `get_proxy_type_destroy_notify`
116    /// Free function for @get_proxy_type_user_data or [`None`].
117    /// ## `cancellable`
118    /// A #GCancellable or [`None`]
119    /// ## `callback`
120    /// A #GAsyncReadyCallback to call when the request is satisfied.
121    #[allow(clippy::new_ret_no_self)]
122    #[doc(alias = "g_dbus_object_manager_client_new")]
123    pub fn new<P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static>(
124        connection: &DBusConnection,
125        flags: DBusObjectManagerClientFlags,
126        name: &str,
127        object_path: &str,
128        cancellable: Option<&impl IsA<Cancellable>>,
129        callback: P,
130    ) {
131        Self::new_impl(
132            connection,
133            flags,
134            name,
135            object_path,
136            None,
137            cancellable,
138            callback,
139        )
140    }
141
142    #[allow(clippy::new_ret_no_self)]
143    #[doc(alias = "g_dbus_object_manager_client_new")]
144    pub fn new_with_fn<
145        P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
146        F: Fn(&DBusObjectManagerClient, &str, Option<&str>) -> glib::types::Type
147            + Send
148            + Sync
149            + 'static,
150    >(
151        connection: &DBusConnection,
152        flags: DBusObjectManagerClientFlags,
153        name: &str,
154        object_path: &str,
155        get_proxy_type_func: F,
156        cancellable: Option<&impl IsA<Cancellable>>,
157        callback: P,
158    ) {
159        Self::new_impl(
160            connection,
161            flags,
162            name,
163            object_path,
164            Some(Box::new(get_proxy_type_func)),
165            cancellable,
166            callback,
167        )
168    }
169
170    #[allow(clippy::new_ret_no_self)]
171    fn new_impl<P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static>(
172        connection: &DBusConnection,
173        flags: DBusObjectManagerClientFlags,
174        name: &str,
175        object_path: &str,
176        get_proxy_type_func: Option<DBusProxyTypeFn>,
177        cancellable: Option<&impl IsA<Cancellable>>,
178        callback: P,
179    ) {
180        let main_context = glib::MainContext::ref_thread_default();
181        let is_main_context_owner = main_context.is_owner();
182        let has_acquired_main_context = (!is_main_context_owner)
183            .then(|| main_context.acquire().ok())
184            .flatten();
185        assert!(
186            is_main_context_owner || has_acquired_main_context.is_some(),
187            "Async operations only allowed if the thread is owning the MainContext"
188        );
189
190        unsafe extern "C" fn get_proxy_type_func_func(
191            manager: *mut ffi::GDBusObjectManagerClient,
192            object_path: *const std::ffi::c_char,
193            interface_name: *const std::ffi::c_char,
194            data: glib::ffi::gpointer,
195        ) -> glib::ffi::GType {
196            let manager = from_glib_borrow(manager);
197            let object_path: Borrowed<glib::GString> = from_glib_borrow(object_path);
198            let interface_name: Borrowed<Option<glib::GString>> = from_glib_borrow(interface_name);
199            let callback = &*(data as *mut Option<DBusProxyTypeFn>);
200            if let Some(ref callback) = *callback {
201                callback(
202                    &manager,
203                    object_path.as_str(),
204                    (*interface_name).as_ref().map(|s| s.as_str()),
205                )
206            } else {
207                panic!("cannot get closure...")
208            }
209            .into_glib()
210        }
211
212        unsafe extern "C" fn get_proxy_type_destroy_notify_func(data: glib::ffi::gpointer) {
213            let _callback = Box::from_raw(data as *mut Option<DBusProxyTypeFn>);
214        }
215
216        unsafe extern "C" fn new_trampoline<
217            P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
218        >(
219            _source_object: *mut glib::gobject_ffi::GObject,
220            res: *mut crate::ffi::GAsyncResult,
221            user_data: glib::ffi::gpointer,
222        ) {
223            let mut error = std::ptr::null_mut();
224            let ret = ffi::g_dbus_object_manager_client_new_finish(res, &mut error);
225            let result = if error.is_null() {
226                Ok(from_glib_full(ret))
227            } else {
228                Err(from_glib_full(error))
229            };
230            let callback: Box<glib::thread_guard::ThreadGuard<P>> =
231                Box::from_raw(user_data as *mut _);
232            let callback: P = callback.into_inner();
233            callback(result);
234        }
235
236        let get_proxy_type_user_data = Box::new(get_proxy_type_func);
237        let get_proxy_type_func = if get_proxy_type_user_data.is_some() {
238            Some(get_proxy_type_func_func as _)
239        } else {
240            None
241        };
242        let get_proxy_type_destroy_notify = if get_proxy_type_user_data.is_some() {
243            Some(get_proxy_type_destroy_notify_func as _)
244        } else {
245            None
246        };
247
248        let user_data: Box<glib::thread_guard::ThreadGuard<P>> =
249            Box::new(glib::thread_guard::ThreadGuard::new(callback));
250        let callback = new_trampoline::<P>;
251
252        unsafe {
253            ffi::g_dbus_object_manager_client_new(
254                connection.to_glib_none().0,
255                flags.into_glib(),
256                name.to_glib_none().0,
257                object_path.to_glib_none().0,
258                get_proxy_type_func,
259                Box::into_raw(get_proxy_type_user_data) as *mut _,
260                get_proxy_type_destroy_notify,
261                cancellable.map(|p| p.as_ref()).to_glib_none().0,
262                Some(callback),
263                Box::into_raw(user_data) as *mut _,
264            );
265        }
266    }
267
268    pub fn new_future(
269        connection: &DBusConnection,
270        flags: DBusObjectManagerClientFlags,
271        name: &str,
272        object_path: &str,
273    ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
274        Self::new_future_impl(connection, flags, name, object_path, None)
275    }
276
277    pub fn new_future_with_fn<
278        F: Fn(&DBusObjectManagerClient, &str, Option<&str>) -> glib::types::Type
279            + Send
280            + Sync
281            + 'static,
282    >(
283        connection: &DBusConnection,
284        flags: DBusObjectManagerClientFlags,
285        name: &str,
286        object_path: &str,
287        get_proxy_type_func: F,
288    ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
289        Self::new_future_impl(
290            connection,
291            flags,
292            name,
293            object_path,
294            Some(Box::new(get_proxy_type_func)),
295        )
296    }
297
298    fn new_future_impl(
299        connection: &DBusConnection,
300        flags: DBusObjectManagerClientFlags,
301        name: &str,
302        object_path: &str,
303        get_proxy_type_func: Option<DBusProxyTypeFn>,
304    ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
305        let connection = connection.clone();
306        let name = String::from(name);
307        let object_path = String::from(object_path);
308        Box::pin(GioFuture::new(&(), move |_obj, cancellable, send| {
309            Self::new_impl(
310                &connection,
311                flags,
312                &name,
313                &object_path,
314                get_proxy_type_func,
315                Some(cancellable),
316                move |res| {
317                    send.resolve(res);
318                },
319            );
320        }))
321    }
322
323    /// Like g_dbus_object_manager_client_new() but takes a #GBusType instead of a
324    /// #GDBusConnection.
325    ///
326    /// This is an asynchronous failable constructor. When the result is
327    /// ready, @callback will be invoked in the thread-default main context
328    /// (see [`glib::MainContext::push_thread_default()`][crate::glib::MainContext::push_thread_default()])
329    /// of the thread you are calling this method from. You can
330    /// then call g_dbus_object_manager_client_new_for_bus_finish() to get the result. See
331    /// g_dbus_object_manager_client_new_for_bus_sync() for the synchronous version.
332    /// ## `bus_type`
333    /// A #GBusType.
334    /// ## `flags`
335    /// Zero or more flags from the #GDBusObjectManagerClientFlags enumeration.
336    /// ## `name`
337    /// The owner of the control object (unique or well-known name).
338    /// ## `object_path`
339    /// The object path of the control object.
340    /// ## `get_proxy_type_func`
341    /// A #GDBusProxyTypeFunc function or [`None`] to always construct #GDBusProxy proxies.
342    /// ## `get_proxy_type_user_data`
343    /// User data to pass to @get_proxy_type_func.
344    /// ## `get_proxy_type_destroy_notify`
345    /// Free function for @get_proxy_type_user_data or [`None`].
346    /// ## `cancellable`
347    /// A #GCancellable or [`None`]
348    /// ## `callback`
349    /// A #GAsyncReadyCallback to call when the request is satisfied.
350    #[doc(alias = "g_dbus_object_manager_client_new_for_bus")]
351    #[allow(clippy::new_ret_no_self)]
352    pub fn new_for_bus<
353        P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
354    >(
355        bus_type: BusType,
356        flags: DBusObjectManagerClientFlags,
357        name: &str,
358        object_path: &str,
359        cancellable: Option<&impl IsA<Cancellable>>,
360        callback: P,
361    ) {
362        Self::new_for_bus_impl(
363            bus_type,
364            flags,
365            name,
366            object_path,
367            None,
368            cancellable,
369            callback,
370        );
371    }
372
373    #[doc(alias = "g_dbus_object_manager_client_new_for_bus")]
374    #[allow(clippy::new_ret_no_self)]
375    pub fn new_for_bus_with_fn<
376        P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
377        F: Fn(&DBusObjectManagerClient, &str, Option<&str>) -> glib::types::Type
378            + Send
379            + Sync
380            + 'static,
381    >(
382        bus_type: BusType,
383        flags: DBusObjectManagerClientFlags,
384        name: &str,
385        object_path: &str,
386        get_proxy_type_func: F,
387        cancellable: Option<&impl IsA<Cancellable>>,
388        callback: P,
389    ) {
390        Self::new_for_bus_impl(
391            bus_type,
392            flags,
393            name,
394            object_path,
395            Some(Box::new(get_proxy_type_func)),
396            cancellable,
397            callback,
398        );
399    }
400
401    #[allow(clippy::new_ret_no_self)]
402    fn new_for_bus_impl<
403        P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
404    >(
405        bus_type: BusType,
406        flags: DBusObjectManagerClientFlags,
407        name: &str,
408        object_path: &str,
409        get_proxy_type_func: Option<DBusProxyTypeFn>,
410        cancellable: Option<&impl IsA<Cancellable>>,
411        callback: P,
412    ) {
413        let main_context = glib::MainContext::ref_thread_default();
414        let is_main_context_owner = main_context.is_owner();
415        let has_acquired_main_context = (!is_main_context_owner)
416            .then(|| main_context.acquire().ok())
417            .flatten();
418        assert!(
419            is_main_context_owner || has_acquired_main_context.is_some(),
420            "Async operations only allowed if the thread is owning the MainContext"
421        );
422
423        unsafe extern "C" fn get_proxy_type_func_func(
424            manager: *mut ffi::GDBusObjectManagerClient,
425            object_path: *const std::ffi::c_char,
426            interface_name: *const std::ffi::c_char,
427            data: glib::ffi::gpointer,
428        ) -> glib::ffi::GType {
429            let manager = from_glib_borrow(manager);
430            let object_path: Borrowed<glib::GString> = from_glib_borrow(object_path);
431            let interface_name: Borrowed<Option<glib::GString>> = from_glib_borrow(interface_name);
432            let callback = &*(data as *mut Option<DBusProxyTypeFn>);
433            if let Some(ref callback) = *callback {
434                callback(
435                    &manager,
436                    object_path.as_str(),
437                    (*interface_name).as_ref().map(|s| s.as_str()),
438                )
439            } else {
440                panic!("cannot get closure...")
441            }
442            .into_glib()
443        }
444
445        unsafe extern "C" fn get_proxy_type_destroy_notify_func(data: glib::ffi::gpointer) {
446            let _callback = Box::from_raw(data as *mut Option<DBusProxyTypeFn>);
447        }
448
449        unsafe extern "C" fn new_for_bus_trampoline<
450            P: FnOnce(Result<DBusObjectManagerClient, glib::Error>) + Send + Sync + 'static,
451        >(
452            _source_object: *mut glib::gobject_ffi::GObject,
453            res: *mut crate::ffi::GAsyncResult,
454            user_data: glib::ffi::gpointer,
455        ) {
456            let mut error = std::ptr::null_mut();
457            let ret = ffi::g_dbus_object_manager_client_new_finish(res, &mut error);
458            let result = if error.is_null() {
459                Ok(from_glib_full(ret))
460            } else {
461                Err(from_glib_full(error))
462            };
463            let callback: Box<glib::thread_guard::ThreadGuard<P>> =
464                Box::from_raw(user_data as *mut _);
465            let callback: P = callback.into_inner();
466            callback(result);
467        }
468
469        let get_proxy_type_user_data = Box::new(get_proxy_type_func);
470        let get_proxy_type_func = if get_proxy_type_user_data.is_some() {
471            Some(get_proxy_type_func_func as _)
472        } else {
473            None
474        };
475        let get_proxy_type_destroy_notify = if get_proxy_type_user_data.is_some() {
476            Some(get_proxy_type_destroy_notify_func as _)
477        } else {
478            None
479        };
480
481        let user_data: Box<glib::thread_guard::ThreadGuard<P>> =
482            Box::new(glib::thread_guard::ThreadGuard::new(callback));
483        let callback = new_for_bus_trampoline::<P>;
484
485        unsafe {
486            ffi::g_dbus_object_manager_client_new_for_bus(
487                bus_type.into_glib(),
488                flags.into_glib(),
489                name.to_glib_none().0,
490                object_path.to_glib_none().0,
491                get_proxy_type_func,
492                Box::into_raw(get_proxy_type_user_data) as *mut _,
493                get_proxy_type_destroy_notify,
494                cancellable.map(|p| p.as_ref()).to_glib_none().0,
495                Some(callback),
496                Box::into_raw(user_data) as *mut _,
497            );
498        }
499    }
500
501    pub fn new_for_bus_future(
502        bus_type: BusType,
503        flags: DBusObjectManagerClientFlags,
504        name: &str,
505        object_path: &str,
506    ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
507        Self::new_for_bus_future_impl(bus_type, flags, name, object_path, None)
508    }
509
510    pub fn new_for_bus_future_with_fn<
511        F: Fn(&DBusObjectManagerClient, &str, Option<&str>) -> glib::types::Type
512            + Send
513            + Sync
514            + 'static,
515    >(
516        bus_type: BusType,
517        flags: DBusObjectManagerClientFlags,
518        name: &str,
519        object_path: &str,
520        get_proxy_type_func: F,
521    ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
522        Self::new_for_bus_future_impl(
523            bus_type,
524            flags,
525            name,
526            object_path,
527            Some(Box::new(get_proxy_type_func)),
528        )
529    }
530
531    fn new_for_bus_future_impl(
532        bus_type: BusType,
533        flags: DBusObjectManagerClientFlags,
534        name: &str,
535        object_path: &str,
536        get_proxy_type_func: Option<DBusProxyTypeFn>,
537    ) -> Pin<Box<dyn Future<Output = Result<DBusObjectManagerClient, glib::Error>> + 'static>> {
538        let name = String::from(name);
539        let object_path = String::from(object_path);
540        Box::pin(GioFuture::new(&(), move |_obj, cancellable, send| {
541            Self::new_for_bus_impl(
542                bus_type,
543                flags,
544                &name,
545                &object_path,
546                get_proxy_type_func,
547                Some(cancellable),
548                move |res| {
549                    send.resolve(res);
550                },
551            );
552        }))
553    }
554}
555
556pub trait DBusObjectManagerClientExtManual: IsA<DBusObjectManagerClient> + 'static {
557    #[doc(alias = "interface-proxy-properties-changed")]
558    fn connect_interface_proxy_properties_changed<
559        F: Fn(&Self, &DBusObjectProxy, &DBusProxy, &glib::Variant, &StrVRef) + Send + Sync + 'static,
560    >(
561        &self,
562        f: F,
563    ) -> SignalHandlerId {
564        unsafe extern "C" fn interface_proxy_properties_changed_trampoline<
565            P: IsA<DBusObjectManagerClient>,
566            F: Fn(&P, &DBusObjectProxy, &DBusProxy, &glib::Variant, &StrVRef) + Send + Sync + 'static,
567        >(
568            this: *mut ffi::GDBusObjectManagerClient,
569            object_proxy: *mut ffi::GDBusObjectProxy,
570            interface_proxy: *mut ffi::GDBusProxy,
571            changed_properties: *mut glib::ffi::GVariant,
572            invalidated_properties: *const *const std::ffi::c_char,
573            f: glib::ffi::gpointer,
574        ) {
575            let f: &F = &*(f as *const F);
576            f(
577                DBusObjectManagerClient::from_glib_borrow(this).unsafe_cast_ref(),
578                &from_glib_borrow(object_proxy),
579                &from_glib_borrow(interface_proxy),
580                &from_glib_borrow(changed_properties),
581                StrVRef::from_glib_borrow(invalidated_properties),
582            )
583        }
584        unsafe {
585            let f: Box<F> = Box::new(f);
586            connect_raw(
587                self.as_ptr() as *mut _,
588                c"interface-proxy-properties-changed".as_ptr() as *const _,
589                Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
590                    interface_proxy_properties_changed_trampoline::<Self, F> as *const (),
591                )),
592                Box::into_raw(f),
593            )
594        }
595    }
596}
597
598impl<O: IsA<DBusObjectManagerClient>> DBusObjectManagerClientExtManual for O {}