glib/
functions.rs

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