nm_rs/
remote_connection.rs

1use std::pin::Pin;
2
3use glib::object::IsA;
4use glib::translate::FromGlibPtrFull;
5use glib::translate::ToGlibPtr;
6use glib::translate::from_glib_full;
7
8use crate::RemoteConnection;
9use crate::ffi;
10
11pub trait RemoteConnectionExtManual:
12    IsA<RemoteConnection, GlibType = crate::ffi::NMRemoteConnection>
13{
14    #[doc(alias = "nm_remote_connection_get_secrets")]
15    #[doc(alias = "get_secrets")]
16    fn secrets(
17        &self,
18        setting_name: &str,
19        cancellable: Option<&impl IsA<gio::Cancellable>>,
20    ) -> Result<glib::Variant, glib::Error> {
21        unsafe {
22            let mut error = std::ptr::null_mut();
23            let res = ffi::nm_remote_connection_get_secrets(
24                self.to_glib_none().0,
25                setting_name.to_glib_none().0,
26                cancellable.map(|p| p.as_ref()).to_glib_none().0,
27                &mut error,
28            );
29
30            if error.is_null() {
31                Ok(glib::Variant::from_glib_full(res))
32            } else {
33                Err(glib::Error::from_glib_full(error))
34            }
35        }
36    }
37
38    #[doc(alias = "nm_remote_connection_get_secrets_async")]
39    #[doc(alias = "get_secrets_async")]
40    fn secrets_async<P: FnOnce(Result<glib::Variant, glib::Error>) + 'static>(
41        &self,
42        setting_name: &str,
43        cancellable: Option<&impl IsA<gio::Cancellable>>,
44        callback: P,
45    ) {
46        let main_context = glib::MainContext::ref_thread_default();
47        let is_main_context_owner = main_context.is_owner();
48        let has_acquired_main_context = (!is_main_context_owner)
49            .then(|| main_context.acquire().ok())
50            .flatten();
51        assert!(
52            is_main_context_owner || has_acquired_main_context.is_some(),
53            "Async operations only allowed if the thread is owning the MainContext"
54        );
55
56        let user_data: Box<glib::thread_guard::ThreadGuard<P>> =
57            Box::new(glib::thread_guard::ThreadGuard::new(callback));
58
59        unsafe extern "C" fn secrets_async_trampoline<
60            P: FnOnce(Result<glib::Variant, glib::Error>) + 'static,
61        >(
62            _connection: *mut glib::gobject_ffi::GObject,
63            res: *mut gio::ffi::GAsyncResult,
64            user_data: glib::ffi::gpointer,
65        ) {
66            let mut error = std::ptr::null_mut();
67            let ret = ffi::nm_remote_connection_get_secrets_finish(
68                _connection as *mut _,
69                res,
70                &mut error,
71            );
72            let result = if error.is_null() {
73                Ok(from_glib_full(ret))
74            } else {
75                Err(from_glib_full(error))
76            };
77            let callback: Box<glib::thread_guard::ThreadGuard<P>> =
78                Box::from_raw(user_data as *mut _);
79            let callback: P = callback.into_inner();
80            callback(result);
81        }
82        let callback = secrets_async_trampoline::<P>;
83        unsafe {
84            ffi::nm_remote_connection_get_secrets_async(
85                self.as_ref().to_glib_none().0,
86                setting_name.to_glib_none().0,
87                cancellable.map(|p| p.as_ref()).to_glib_none().0,
88                Some(callback),
89                Box::into_raw(user_data) as *mut _,
90            );
91        }
92    }
93
94    fn secrets_future(
95        &self,
96        setting_name: &str,
97    ) -> Pin<Box<dyn std::future::Future<Output = Result<glib::Variant, glib::Error>> + 'static>>
98    {
99        let setting_name = String::from(setting_name);
100        Box::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
101            obj.secrets_async(&setting_name, Some(cancellable), move |res| {
102                send.resolve(res);
103            });
104        }))
105    }
106}
107
108impl<T: IsA<RemoteConnection, GlibType = ffi::NMRemoteConnection>> RemoteConnectionExtManual for T {}