1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | |
3 | pub use crate::auto::functions::*; |
4 | #[cfg (not(windows))] |
5 | use std::boxed::Box as Box_; |
6 | #[cfg (not(windows))] |
7 | use std::mem; |
8 | #[cfg (not(windows))] |
9 | #[cfg (feature = "v2_58" )] |
10 | use std::os::unix::io::AsRawFd; |
11 | #[cfg (not(windows))] |
12 | use std::os::unix::io::{FromRawFd, IntoRawFd, RawFd}; |
13 | use std::ptr; |
14 | |
15 | // #[cfg(windows)] |
16 | // #[cfg(feature = "v2_58")] |
17 | // use std::os::windows::io::AsRawHandle; |
18 | use crate::{ffi, translate::*, ChecksumType, GStr}; |
19 | #[cfg (not(windows))] |
20 | use crate::{Error, Pid, SpawnFlags}; |
21 | |
22 | #[cfg (feature = "v2_58" )] |
23 | #[cfg (not(windows))] |
24 | #[cfg_attr (docsrs, doc(cfg(all(feature = "v2_58" , not(windows)))))] |
25 | #[allow (clippy::too_many_arguments)] |
26 | #[doc (alias = "g_spawn_async_with_fds" )] |
27 | pub fn spawn_async_with_fds<P: AsRef<std::path::Path>, T: AsRawFd, U: AsRawFd, V: AsRawFd>( |
28 | working_directory: P, |
29 | argv: &[&str], |
30 | envp: &[&str], |
31 | flags: SpawnFlags, |
32 | child_setup: Option<Box_<dyn FnOnce() + 'static>>, |
33 | stdin_fd: T, |
34 | stdout_fd: U, |
35 | stderr_fd: V, |
36 | ) -> Result<Pid, Error> { |
37 | let child_setup_data: Box_<Option<Box_<dyn FnOnce() + 'static>>> = Box_::new(child_setup); |
38 | unsafe extern "C" fn child_setup_func(user_data: ffi::gpointer) { |
39 | let callback: Box_<Option<Box_<dyn FnOnce() + 'static>>> = |
40 | Box_::from_raw(user_data as *mut _); |
41 | let callback = (*callback).expect("cannot get closure..." ); |
42 | callback() |
43 | } |
44 | let child_setup = if child_setup_data.is_some() { |
45 | Some(child_setup_func as _) |
46 | } else { |
47 | None |
48 | }; |
49 | let super_callback0: Box_<Option<Box_<dyn FnOnce() + 'static>>> = child_setup_data; |
50 | unsafe { |
51 | let mut child_pid = mem::MaybeUninit::uninit(); |
52 | let mut error = ptr::null_mut(); |
53 | let _ = ffi::g_spawn_async_with_fds( |
54 | working_directory.as_ref().to_glib_none().0, |
55 | argv.to_glib_none().0, |
56 | envp.to_glib_none().0, |
57 | flags.into_glib(), |
58 | child_setup, |
59 | Box_::into_raw(super_callback0) as *mut _, |
60 | child_pid.as_mut_ptr(), |
61 | stdin_fd.as_raw_fd(), |
62 | stdout_fd.as_raw_fd(), |
63 | stderr_fd.as_raw_fd(), |
64 | &mut error, |
65 | ); |
66 | let child_pid = from_glib(child_pid.assume_init()); |
67 | if error.is_null() { |
68 | Ok(child_pid) |
69 | } else { |
70 | Err(from_glib_full(error)) |
71 | } |
72 | } |
73 | } |
74 | |
75 | // #[cfg(feature = "v2_58")] |
76 | // #[cfg(windows)] |
77 | // pub fn spawn_async_with_fds< |
78 | // P: AsRef<std::path::Path>, |
79 | // T: AsRawHandle, |
80 | // U: AsRawHandle, |
81 | // V: AsRawHandle, |
82 | // >( |
83 | // working_directory: P, |
84 | // argv: &[&str], |
85 | // envp: &[&str], |
86 | // flags: SpawnFlags, |
87 | // child_setup: Option<Box_<dyn FnOnce() + 'static>>, |
88 | // stdin_fd: T, |
89 | // stdout_fd: U, |
90 | // stderr_fd: V, |
91 | // ) -> Result<Pid, Error> { |
92 | // let child_setup_data: Box_<Option<Box_<dyn FnOnce() + 'static>>> = Box_::new(child_setup); |
93 | // unsafe extern "C" fn child_setup_func<P: AsRef<std::path::Path>>( |
94 | // user_data: ffi::gpointer, |
95 | // ) { |
96 | // let callback: Box_<Option<Box_<dyn FnOnce() + 'static>>> = |
97 | // Box_::from_raw(user_data as *mut _); |
98 | // let callback = (*callback).expect("cannot get closure..."); |
99 | // callback() |
100 | // } |
101 | // let child_setup = if child_setup_data.is_some() { |
102 | // Some(child_setup_func::<P> as _) |
103 | // } else { |
104 | // None |
105 | // }; |
106 | // let super_callback0: Box_<Option<Box_<dyn FnOnce() + 'static>>> = child_setup_data; |
107 | // unsafe { |
108 | // let mut child_pid = mem::MaybeUninit::uninit(); |
109 | // let mut error = ptr::null_mut(); |
110 | // let _ = ffi::g_spawn_async_with_fds( |
111 | // working_directory.as_ref().to_glib_none().0, |
112 | // argv.to_glib_none().0, |
113 | // envp.to_glib_none().0, |
114 | // flags.into_glib(), |
115 | // child_setup, |
116 | // Box_::into_raw(super_callback0) as *mut _, |
117 | // child_pid.as_mut_ptr(), |
118 | // stdin_fd.as_raw_handle() as usize as _, |
119 | // stdout_fd.as_raw_handle() as usize as _, |
120 | // stderr_fd.as_raw_handle() as usize as _, |
121 | // &mut error, |
122 | // ); |
123 | // let child_pid = from_glib(child_pid.assume_init()); |
124 | // if error.is_null() { |
125 | // Ok(child_pid) |
126 | // } else { |
127 | // Err(from_glib_full(error)) |
128 | // } |
129 | // } |
130 | // } |
131 | |
132 | #[cfg (not(windows))] |
133 | #[cfg_attr (docsrs, doc(cfg(not(windows))))] |
134 | #[doc (alias = "g_spawn_async_with_pipes" )] |
135 | pub fn spawn_async_with_pipes< |
136 | P: AsRef<std::path::Path>, |
137 | T: FromRawFd, |
138 | U: FromRawFd, |
139 | V: FromRawFd, |
140 | >( |
141 | working_directory: P, |
142 | argv: &[&std::path::Path], |
143 | envp: &[&std::path::Path], |
144 | flags: SpawnFlags, |
145 | child_setup: Option<Box_<dyn FnOnce() + 'static>>, |
146 | ) -> Result<(Pid, T, U, V), Error> { |
147 | let child_setup_data: Box_<Option<Box_<dyn FnOnce() + 'static>>> = Box_::new(child_setup); |
148 | unsafe extern "C" fn child_setup_func(user_data: ffi::gpointer) { |
149 | let callback: Box_<Option<Box_<dyn FnOnce() + 'static>>> = |
150 | Box_::from_raw(user_data as *mut _); |
151 | let callback = (*callback).expect("cannot get closure..." ); |
152 | callback() |
153 | } |
154 | let child_setup = if child_setup_data.is_some() { |
155 | Some(child_setup_func as _) |
156 | } else { |
157 | None |
158 | }; |
159 | let super_callback0: Box_<Option<Box_<dyn FnOnce() + 'static>>> = child_setup_data; |
160 | unsafe { |
161 | let mut child_pid = mem::MaybeUninit::uninit(); |
162 | let mut standard_input = mem::MaybeUninit::uninit(); |
163 | let mut standard_output = mem::MaybeUninit::uninit(); |
164 | let mut standard_error = mem::MaybeUninit::uninit(); |
165 | let mut error = ptr::null_mut(); |
166 | let _ = ffi::g_spawn_async_with_pipes( |
167 | working_directory.as_ref().to_glib_none().0, |
168 | argv.to_glib_none().0, |
169 | envp.to_glib_none().0, |
170 | flags.into_glib(), |
171 | child_setup, |
172 | Box_::into_raw(super_callback0) as *mut _, |
173 | child_pid.as_mut_ptr(), |
174 | standard_input.as_mut_ptr(), |
175 | standard_output.as_mut_ptr(), |
176 | standard_error.as_mut_ptr(), |
177 | &mut error, |
178 | ); |
179 | let child_pid = from_glib(child_pid.assume_init()); |
180 | let standard_input = standard_input.assume_init(); |
181 | let standard_output = standard_output.assume_init(); |
182 | let standard_error = standard_error.assume_init(); |
183 | if error.is_null() { |
184 | #[cfg (not(windows))] |
185 | { |
186 | Ok(( |
187 | child_pid, |
188 | FromRawFd::from_raw_fd(standard_input), |
189 | FromRawFd::from_raw_fd(standard_output), |
190 | FromRawFd::from_raw_fd(standard_error), |
191 | )) |
192 | } |
193 | // #[cfg(windows)] |
194 | // { |
195 | // use std::os::windows::io::{FromRawHandle, RawHandle}; |
196 | // Ok(( |
197 | // child_pid, |
198 | // File::from_raw_handle(standard_input as usize as RawHandle), |
199 | // File::from_raw_handle(standard_output as usize as RawHandle), |
200 | // File::from_raw_handle(standard_error as usize as RawHandle), |
201 | // )) |
202 | // } |
203 | } else { |
204 | Err(from_glib_full(error)) |
205 | } |
206 | } |
207 | } |
208 | |
209 | // rustdoc-stripper-ignore-next |
210 | /// Obtain the character set for the current locale. |
211 | /// |
212 | /// This returns whether the locale's encoding is UTF-8, and the current |
213 | /// charset if available. |
214 | #[doc (alias = "g_get_charset" )] |
215 | #[doc (alias = "get_charset" )] |
216 | pub fn charset() -> (bool, Option<&'static GStr>) { |
217 | unsafe { |
218 | let mut out_charset: *const {unknown} = ptr::null(); |
219 | let is_utf8: bool = from_glib(val:ffi::g_get_charset(&mut out_charset)); |
220 | let charset: Option<&'static GStr> = from_glib_none(ptr:out_charset); |
221 | (is_utf8, charset) |
222 | } |
223 | } |
224 | |
225 | #[doc (alias = "g_compute_checksum_for_string" )] |
226 | pub fn compute_checksum_for_string( |
227 | checksum_type: ChecksumType, |
228 | str: impl IntoGStr, |
229 | ) -> Option<crate::GString> { |
230 | str.run_with_gstr(|str: &GStr| unsafe { |
231 | from_glib_full(ptr:ffi::g_compute_checksum_for_string( |
232 | checksum_type.into_glib(), |
233 | str.as_ptr(), |
234 | length:str.len() as _, |
235 | )) |
236 | }) |
237 | } |
238 | |
239 | #[cfg (unix)] |
240 | #[doc (alias = "g_unix_open_pipe" )] |
241 | pub fn unix_open_pipe(flags: i32) -> Result<(RawFd, RawFd), Error> { |
242 | unsafe { |
243 | let mut fds: [i32; 2] = [0, 2]; |
244 | let mut error: *mut GError = ptr::null_mut(); |
245 | let _ = ffi::g_unix_open_pipe(&mut fds, flags, &mut error); |
246 | if error.is_null() { |
247 | Ok(( |
248 | FromRawFd::from_raw_fd(fds[0]), |
249 | FromRawFd::from_raw_fd(fds[1]), |
250 | )) |
251 | } else { |
252 | Err(from_glib_full(ptr:error)) |
253 | } |
254 | } |
255 | } |
256 | |
257 | #[cfg (unix)] |
258 | #[doc (alias = "g_file_open_tmp" )] |
259 | pub fn file_open_tmp( |
260 | tmpl: Option<impl AsRef<std::path::Path>>, |
261 | ) -> Result<(RawFd, std::path::PathBuf), crate::Error> { |
262 | unsafe { |
263 | let mut name_used: *mut i8 = ptr::null_mut(); |
264 | let mut error: *mut GError = ptr::null_mut(); |
265 | let ret = ffi::g_file_open_tmp( |
266 | tmpl.as_ref().map(|p: &impl AsRef| p.as_ref()).to_glib_none().0, |
267 | &mut name_used, |
268 | &mut error, |
269 | ); |
270 | if error.is_null() { |
271 | Ok((ret.into_raw_fd(), from_glib_full(ptr:name_used))) |
272 | } else { |
273 | Err(from_glib_full(ptr:error)) |
274 | } |
275 | } |
276 | } |
277 | |
278 | // rustdoc-stripper-ignore-next |
279 | /// Spawn a new infallible `Future` on the thread-default main context. |
280 | /// |
281 | /// This can be called from any thread and will execute the future from the thread |
282 | /// where main context is running, e.g. via a `MainLoop`. |
283 | pub fn spawn_future<R: Send + 'static, F: std::future::Future<Output = R> + Send + 'static>( |
284 | f: F, |
285 | ) -> crate::JoinHandle<R> { |
286 | let ctx: MainContext = crate::MainContext::ref_thread_default(); |
287 | ctx.spawn(f) |
288 | } |
289 | |
290 | // rustdoc-stripper-ignore-next |
291 | /// Spawn a new infallible `Future` on the thread-default main context. |
292 | /// |
293 | /// The given `Future` does not have to be `Send`. |
294 | /// |
295 | /// This can be called only from the thread where the main context is running, e.g. |
296 | /// from any other `Future` that is executed on this main context, or after calling |
297 | /// `with_thread_default` or `acquire` on the main context. |
298 | pub fn spawn_future_local<R: 'static, F: std::future::Future<Output = R> + 'static>( |
299 | f: F, |
300 | ) -> crate::JoinHandle<R> { |
301 | let ctx: MainContext = crate::MainContext::ref_thread_default(); |
302 | ctx.spawn_local(f) |
303 | } |
304 | |