1use crate::{prelude::*, Message, Session, WebsocketConnection};
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 let mut error = ptr::null_mut();
43 let ret = ffi::soup_session_websocket_connect_finish(
44 _source_object as *mut _,
45 res,
46 &mut error,
47 );
48 let result = if error.is_null() {
49 Ok(from_glib_full(ret))
50 } else {
51 Err(from_glib_full(error))
52 };
53 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
54 Box_::from_raw(user_data as *mut _);
55 let callback = callback.into_inner();
56 callback(result);
57 }
58 let callback = websocket_connect_async_trampoline::<P>;
59 unsafe {
60 ffi::soup_session_websocket_connect_async(
61 self.as_ref().to_glib_none().0,
62 msg.to_glib_none().0,
63 origin.to_glib_none().0,
64 protocols.to_glib_none().0,
65 io_priority.into_glib(),
66 cancellable.map(|p| p.as_ref()).to_glib_none().0,
67 Some(callback),
68 Box_::into_raw(user_data) as *mut _,
69 );
70 }
71 }
72
73 fn websocket_connect_async_future(
74 &self,
75 msg: &Message,
76 origin: Option<&str>,
77 protocols: &[&str],
78 io_priority: glib::Priority,
79 ) -> Pin<
80 Box_<dyn std::future::Future<Output = Result<WebsocketConnection, glib::Error>> + 'static>,
81 > {
82 let msg = msg.clone();
83 let origin = origin.map(ToOwned::to_owned);
84 let protocols = protocols
85 .iter()
86 .copied()
87 .map(String::from)
88 .collect::<Vec<_>>();
89 Box_::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
90 let protocols = protocols.iter().map(|s| s.as_str()).collect::<Vec<_>>();
91 obj.websocket_connect_async(
92 &msg,
93 origin.as_ref().map(::std::borrow::Borrow::borrow),
94 &protocols,
95 io_priority,
96 Some(cancellable),
97 move |res| {
98 send.resolve(res);
99 },
100 );
101 }))
102 }
103}
104
105impl<O: IsA<Session>> SessionExtManual for O {}