Skip to main content

soup/
session.rs

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