Skip to main content

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};
13use std::ptr;
14
15// #[cfg(windows)]
16// #[cfg(feature = "v2_58")]
17// use std::os::windows::io::AsRawHandle;
18use crate::{ChecksumType, GStr, ffi, translate::*};
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        unsafe {
40            let callback: Box_<Option<Box_<dyn FnOnce() + 'static>>> =
41                Box_::from_raw(user_data as *mut _);
42            let callback = (*callback).expect("cannot get closure...");
43            callback()
44        }
45    }
46    let child_setup = if child_setup_data.is_some() {
47        Some(child_setup_func as _)
48    } else {
49        None
50    };
51    let super_callback0: Box_<Option<Box_<dyn FnOnce() + 'static>>> = child_setup_data;
52    let stdin_raw_fd = stdin_fd.map_or(-1, |fd| fd.as_fd().as_raw_fd());
53    let stdout_raw_fd = stdout_fd.map_or(-1, |fd| fd.as_fd().as_raw_fd());
54    let stderr_raw_fd = stderr_fd.map_or(-1, |fd| fd.as_fd().as_raw_fd());
55    unsafe {
56        let mut child_pid = mem::MaybeUninit::uninit();
57        let mut error = ptr::null_mut();
58        let _ = ffi::g_spawn_async_with_fds(
59            working_directory.as_ref().to_glib_none().0,
60            argv.to_glib_none().0,
61            envp.to_glib_none().0,
62            flags.into_glib(),
63            child_setup,
64            Box_::into_raw(super_callback0) as *mut _,
65            child_pid.as_mut_ptr(),
66            stdin_raw_fd,
67            stdout_raw_fd,
68            stderr_raw_fd,
69            &mut error,
70        );
71        let child_pid = from_glib(child_pid.assume_init());
72        if error.is_null() {
73            Ok(child_pid)
74        } else {
75            Err(from_glib_full(error))
76        }
77    }
78}
79
80// #[cfg(feature = "v2_58")]
81// #[cfg(windows)]
82// pub fn spawn_async_with_fds<
83//     P: AsRef<std::path::Path>,
84//     T: AsRawHandle,
85//     U: AsRawHandle,
86//     V: AsRawHandle,
87// >(
88//     working_directory: P,
89//     argv: &[&str],
90//     envp: &[&str],
91//     flags: SpawnFlags,
92//     child_setup: Option<Box_<dyn FnOnce() + 'static>>,
93//     stdin_fd: T,
94//     stdout_fd: U,
95//     stderr_fd: V,
96// ) -> Result<Pid, Error> {
97//     let child_setup_data: Box_<Option<Box_<dyn FnOnce() + 'static>>> = Box_::new(child_setup);
98//     unsafe extern "C" fn child_setup_func<P: AsRef<std::path::Path>>(
99//         user_data: ffi::gpointer,
100//     ) {
101//         let callback: Box_<Option<Box_<dyn FnOnce() + 'static>>> =
102//             Box_::from_raw(user_data as *mut _);
103//         let callback = (*callback).expect("cannot get closure...");
104//         callback()
105//     }
106//     let child_setup = if child_setup_data.is_some() {
107//         Some(child_setup_func::<P> as _)
108//     } else {
109//         None
110//     };
111//     let super_callback0: Box_<Option<Box_<dyn FnOnce() + 'static>>> = child_setup_data;
112//     unsafe {
113//         let mut child_pid = mem::MaybeUninit::uninit();
114//         let mut error = ptr::null_mut();
115//         let _ = ffi::g_spawn_async_with_fds(
116//             working_directory.as_ref().to_glib_none().0,
117//             argv.to_glib_none().0,
118//             envp.to_glib_none().0,
119//             flags.into_glib(),
120//             child_setup,
121//             Box_::into_raw(super_callback0) as *mut _,
122//             child_pid.as_mut_ptr(),
123//             stdin_fd.as_raw_handle() as usize as _,
124//             stdout_fd.as_raw_handle() as usize as _,
125//             stderr_fd.as_raw_handle() as usize as _,
126//             &mut error,
127//         );
128//         let child_pid = from_glib(child_pid.assume_init());
129//         if error.is_null() {
130//             Ok(child_pid)
131//         } else {
132//             Err(from_glib_full(error))
133//         }
134//     }
135// }
136
137#[cfg(not(windows))]
138#[cfg_attr(docsrs, doc(cfg(not(windows))))]
139#[doc(alias = "g_spawn_async_with_pipes")]
140pub fn spawn_async_with_pipes<
141    P: AsRef<std::path::Path>,
142    T: FromRawFd,
143    U: FromRawFd,
144    V: FromRawFd,
145>(
146    working_directory: P,
147    argv: &[&std::path::Path],
148    envp: &[&std::path::Path],
149    flags: SpawnFlags,
150    child_setup: Option<Box_<dyn FnOnce() + 'static>>,
151) -> Result<(Pid, T, U, V), Error> {
152    let child_setup_data: Box_<Option<Box_<dyn FnOnce() + 'static>>> = Box_::new(child_setup);
153    unsafe extern "C" fn child_setup_func(user_data: ffi::gpointer) {
154        unsafe {
155            let callback: Box_<Option<Box_<dyn FnOnce() + 'static>>> =
156                Box_::from_raw(user_data as *mut _);
157            let callback = (*callback).expect("cannot get closure...");
158            callback()
159        }
160    }
161    let child_setup = if child_setup_data.is_some() {
162        Some(child_setup_func as _)
163    } else {
164        None
165    };
166    let super_callback0: Box_<Option<Box_<dyn FnOnce() + 'static>>> = child_setup_data;
167    unsafe {
168        let mut child_pid = mem::MaybeUninit::uninit();
169        let mut standard_input = mem::MaybeUninit::uninit();
170        let mut standard_output = mem::MaybeUninit::uninit();
171        let mut standard_error = mem::MaybeUninit::uninit();
172        let mut error = ptr::null_mut();
173        let _ = ffi::g_spawn_async_with_pipes(
174            working_directory.as_ref().to_glib_none().0,
175            argv.to_glib_none().0,
176            envp.to_glib_none().0,
177            flags.into_glib(),
178            child_setup,
179            Box_::into_raw(super_callback0) as *mut _,
180            child_pid.as_mut_ptr(),
181            standard_input.as_mut_ptr(),
182            standard_output.as_mut_ptr(),
183            standard_error.as_mut_ptr(),
184            &mut error,
185        );
186        if error.is_null() {
187            let child_pid = from_glib(child_pid.assume_init());
188            let standard_input = standard_input.assume_init();
189            let standard_output = standard_output.assume_init();
190            let standard_error = standard_error.assume_init();
191            #[cfg(not(windows))]
192            {
193                Ok((
194                    child_pid,
195                    FromRawFd::from_raw_fd(standard_input),
196                    FromRawFd::from_raw_fd(standard_output),
197                    FromRawFd::from_raw_fd(standard_error),
198                ))
199            }
200        // #[cfg(windows)]
201        // {
202        //     use std::os::windows::io::{FromRawHandle, RawHandle};
203        //     Ok((
204        //         child_pid,
205        //         File::from_raw_handle(standard_input as usize as RawHandle),
206        //         File::from_raw_handle(standard_output as usize as RawHandle),
207        //         File::from_raw_handle(standard_error as usize as RawHandle),
208        //     ))
209        // }
210        } else {
211            Err(from_glib_full(error))
212        }
213    }
214}
215
216// rustdoc-stripper-ignore-next
217/// Obtain the character set for the current locale.
218///
219/// This returns whether the locale's encoding is UTF-8, and the current
220/// charset if available.
221#[doc(alias = "g_get_charset")]
222#[doc(alias = "get_charset")]
223pub fn charset() -> (bool, Option<&'static GStr>) {
224    unsafe {
225        let mut out_charset = ptr::null();
226        let is_utf8 = from_glib(ffi::g_get_charset(&mut out_charset));
227        let charset = from_glib_none(out_charset);
228        (is_utf8, charset)
229    }
230}
231
232/// Gets the current user's home directory.
233///
234/// As with most UNIX tools, this function will return the value of the
235/// `HOME` environment variable if it is set to an existing absolute path
236/// name, falling back to the `passwd` file in the case that it is unset.
237///
238/// If the path given in `HOME` is non-absolute, does not exist, or is
239/// not a directory, the result is undefined.
240///
241/// Before version 2.36 this function would ignore the `HOME` environment
242/// variable, taking the value from the `passwd` database instead. This was
243/// changed to increase the compatibility of GLib with other programs (and
244/// the XDG basedir specification) and to increase testability of programs
245/// based on GLib (by making it easier to run them from test frameworks).
246///
247/// If your program has a strong requirement for either the new or the
248/// old behaviour (and if you don't wish to increase your GLib
249/// dependency to ensure that the new behaviour is in effect) then you
250/// should either directly check the `HOME` environment variable yourself
251/// or unset it before calling any functions in GLib.
252///
253/// # Returns
254///
255/// the current user's home directory
256#[doc(alias = "g_get_home_dir")]
257#[doc(alias = "get_home_dir")]
258pub fn home_dir() -> &'static std::path::Path {
259    unsafe { c_to_path(ffi::g_get_home_dir()) }
260}
261
262/// Gets the directory to use for temporary files.
263///
264/// On UNIX, this is taken from the `TMPDIR` environment variable.
265/// If the variable is not set, `P_tmpdir` is
266/// used, as defined by the system C library. Failing that, a
267/// hard-coded default of "/tmp" is returned.
268///
269/// On Windows, the `TEMP` environment variable is used, with the
270/// root directory of the Windows installation (eg: "C:\") used
271/// as a default.
272///
273/// The encoding of the returned string is system-defined. On Windows,
274/// it is always UTF-8. The return value is never [`None`] or the empty
275/// string.
276///
277/// # Returns
278///
279/// the directory to use for temporary files.
280#[doc(alias = "g_get_tmp_dir")]
281#[doc(alias = "get_tmp_dir")]
282pub fn tmp_dir() -> &'static std::path::Path {
283    unsafe { c_to_path(ffi::g_get_tmp_dir()) }
284}
285
286/// Gets the user name of the current user. The encoding of the returned
287/// string is system-defined. On UNIX, it might be the preferred file name
288/// encoding, or something else, and there is no guarantee that it is even
289/// consistent on a machine. On Windows, it is always UTF-8.
290///
291/// # Returns
292///
293/// the user name of the current user.
294#[doc(alias = "g_get_user_name")]
295#[doc(alias = "get_user_name")]
296pub fn user_name() -> &'static std::ffi::OsStr {
297    unsafe { c_to_path(ffi::g_get_user_name()).as_os_str() }
298}
299
300/// Gets the real name of the user. This usually comes from the user's
301/// entry in the `passwd` file. The encoding of the returned string is
302/// system-defined. (On Windows, it is, however, always UTF-8.) If the
303/// real user name cannot be determined, the string "Unknown" is
304/// returned.
305///
306/// # Returns
307///
308/// the user's real name.
309#[doc(alias = "g_get_real_name")]
310#[doc(alias = "get_real_name")]
311pub fn real_name() -> &'static std::ffi::OsStr {
312    unsafe { c_to_path(ffi::g_get_real_name()).as_os_str() }
313}
314
315/// Return a name for the machine.
316///
317/// The returned name is not necessarily a fully-qualified domain name,
318/// or even present in DNS or some other name service at all. It need
319/// not even be unique on your local network or site, but usually it
320/// is. Callers should not rely on the return value having any specific
321/// properties like uniqueness for security purposes. Even if the name
322/// of the machine is changed while an application is running, the
323/// return value from this function does not change. The returned
324/// string is owned by GLib and should not be modified or freed. If no
325/// name can be determined, a default fixed string "localhost" is
326/// returned.
327///
328/// The encoding of the returned string is UTF-8.
329///
330/// # Returns
331///
332/// the host name of the machine.
333#[doc(alias = "g_get_host_name")]
334#[doc(alias = "get_host_name")]
335pub fn host_name() -> &'static GStr {
336    unsafe { GStr::from_ptr(ffi::g_get_host_name()) }
337}
338
339/// Returns a base directory in which to store non-essential, cached
340/// data specific to particular user.
341///
342/// On UNIX platforms this is determined using the mechanisms described
343/// in the
344/// [XDG Base Directory Specification](http://www.freedesktop.org/Standards/basedir-spec).
345/// In this case the directory retrieved will be `XDG_CACHE_HOME`.
346///
347/// On Windows it follows XDG Base Directory Specification if `XDG_CACHE_HOME` is defined.
348/// If `XDG_CACHE_HOME` is undefined, the directory that serves as a common
349/// repository for temporary Internet files is used instead. A typical path is
350/// `C:\Documents and Settings\username\Local Settings\Temporary Internet Files`.
351/// See the [documentation for `FOLDERID_InternetCache`](https://docs.microsoft.com/en-us/windows/win32/shell/knownfolderid).
352///
353/// The return value is cached and modifying it at runtime is not supported, as
354/// it’s not thread-safe to modify environment variables at runtime.
355///
356/// # Returns
357///
358/// a string owned by GLib that
359///   must not be modified or freed.
360#[doc(alias = "g_get_user_cache_dir")]
361#[doc(alias = "get_user_cache_dir")]
362pub fn user_cache_dir() -> &'static std::path::Path {
363    unsafe { c_to_path(ffi::g_get_user_cache_dir()) }
364}
365
366/// Returns a base directory in which to store user-specific application
367/// configuration information such as user preferences and settings.
368///
369/// On UNIX platforms this is determined using the mechanisms described
370/// in the
371/// [XDG Base Directory Specification](http://www.freedesktop.org/Standards/basedir-spec).
372/// In this case the directory retrieved will be `XDG_CONFIG_HOME`.
373///
374/// On Windows it follows XDG Base Directory Specification if `XDG_CONFIG_HOME` is defined.
375/// If `XDG_CONFIG_HOME` is undefined, the folder to use for local (as opposed
376/// to roaming) application data is used instead. See the
377/// [documentation for `FOLDERID_LocalAppData`](https://docs.microsoft.com/en-us/windows/win32/shell/knownfolderid).
378/// Note that in this case on Windows it will be  the same
379/// as what g_get_user_data_dir() returns.
380///
381/// The return value is cached and modifying it at runtime is not supported, as
382/// it’s not thread-safe to modify environment variables at runtime.
383///
384/// # Returns
385///
386/// a string owned by GLib that
387///   must not be modified or freed.
388#[doc(alias = "g_get_user_config_dir")]
389#[doc(alias = "get_user_config_dir")]
390pub fn user_config_dir() -> &'static std::path::Path {
391    unsafe { c_to_path(ffi::g_get_user_config_dir()) }
392}
393
394/// Returns a base directory in which to access application data such
395/// as icons that is customized for a particular user.
396///
397/// On UNIX platforms this is determined using the mechanisms described
398/// in the
399/// [XDG Base Directory Specification](http://www.freedesktop.org/Standards/basedir-spec).
400/// In this case the directory retrieved will be `XDG_DATA_HOME`.
401///
402/// On Windows it follows XDG Base Directory Specification if `XDG_DATA_HOME`
403/// is defined. If `XDG_DATA_HOME` is undefined, the folder to use for local (as
404/// opposed to roaming) application data is used instead. See the
405/// [documentation for `FOLDERID_LocalAppData`](https://docs.microsoft.com/en-us/windows/win32/shell/knownfolderid).
406/// Note that in this case on Windows it will be the same
407/// as what g_get_user_config_dir() returns.
408///
409/// The return value is cached and modifying it at runtime is not supported, as
410/// it’s not thread-safe to modify environment variables at runtime.
411///
412/// # Returns
413///
414/// a string owned by GLib that must
415///   not be modified or freed.
416#[doc(alias = "g_get_user_data_dir")]
417#[doc(alias = "get_user_data_dir")]
418pub fn user_data_dir() -> &'static std::path::Path {
419    unsafe { c_to_path(ffi::g_get_user_data_dir()) }
420}
421
422/// Returns a directory that is unique to the current user on the local
423/// system.
424///
425/// This is determined using the mechanisms described
426/// in the
427/// [XDG Base Directory Specification](http://www.freedesktop.org/Standards/basedir-spec).
428/// This is the directory
429/// specified in the `XDG_RUNTIME_DIR` environment variable.
430/// In the case that this variable is not set, we return the value of
431/// g_get_user_cache_dir(), after verifying that it exists.
432///
433/// The return value is cached and modifying it at runtime is not supported, as
434/// it’s not thread-safe to modify environment variables at runtime.
435///
436/// # Returns
437///
438/// a string owned by GLib that must not be
439///     modified or freed.
440#[doc(alias = "g_get_user_runtime_dir")]
441#[doc(alias = "get_user_runtime_dir")]
442pub fn user_runtime_dir() -> &'static std::path::Path {
443    unsafe { c_to_path(ffi::g_get_user_runtime_dir()) }
444}
445
446/// Returns a base directory in which to store state files specific to
447/// particular user.
448///
449/// On UNIX platforms this is determined using the mechanisms described
450/// in the
451/// [XDG Base Directory Specification](http://www.freedesktop.org/Standards/basedir-spec).
452/// In this case the directory retrieved will be `XDG_STATE_HOME`.
453///
454/// On Windows it follows XDG Base Directory Specification if `XDG_STATE_HOME` is defined.
455/// If `XDG_STATE_HOME` is undefined, the folder to use for local (as opposed
456/// to roaming) application data is used instead. See the
457/// [documentation for `FOLDERID_LocalAppData`](https://docs.microsoft.com/en-us/windows/win32/shell/knownfolderid).
458/// Note that in this case on Windows it will be the same
459/// as what g_get_user_data_dir() returns.
460///
461/// The return value is cached and modifying it at runtime is not supported, as
462/// it’s not thread-safe to modify environment variables at runtime.
463///
464/// # Returns
465///
466/// a string owned by GLib that
467///   must not be modified or freed.
468#[cfg(feature = "v2_72")]
469#[cfg_attr(docsrs, doc(cfg(feature = "v2_72")))]
470#[doc(alias = "g_get_user_state_dir")]
471#[doc(alias = "get_user_state_dir")]
472pub fn user_state_dir() -> &'static std::path::Path {
473    unsafe { c_to_path(ffi::g_get_user_state_dir()) }
474}
475
476/// Returns an ordered list of base directories in which to access
477/// system-wide application data.
478///
479/// On UNIX platforms this is determined using the mechanisms described
480/// in the
481/// [XDG Base Directory Specification](http://www.freedesktop.org/Standards/basedir-spec)
482/// In this case the list of directories retrieved will be `XDG_DATA_DIRS`.
483///
484/// On Windows it follows XDG Base Directory Specification if `XDG_DATA_DIRS` is defined.
485/// If `XDG_DATA_DIRS` is undefined,
486/// the first elements in the list are the Application Data
487/// and Documents folders for All Users. (These can be determined only
488/// on Windows 2000 or later and are not present in the list on other
489/// Windows versions.) See documentation for FOLDERID_ProgramData and
490/// FOLDERID_PublicDocuments.
491///
492/// Then follows the "share" subfolder in the installation folder for
493/// the package containing the DLL that calls this function, if it can
494/// be determined.
495///
496/// Finally the list contains the "share" subfolder in the installation
497/// folder for GLib, and in the installation folder for the package the
498/// application's .exe file belongs to.
499///
500/// The installation folders above are determined by looking up the
501/// folder where the module (DLL or EXE) in question is located. If the
502/// folder's name is "bin", its parent is used, otherwise the folder
503/// itself.
504///
505/// Note that on Windows the returned list can vary depending on where
506/// this function is called.
507///
508/// The return value is cached and modifying it at runtime is not supported, as
509/// it’s not thread-safe to modify environment variables at runtime.
510///
511/// # Returns
512///
513///
514///     a [`None`]-terminated array of strings owned by GLib that must not be
515///     modified or freed.
516#[doc(alias = "g_get_system_data_dirs")]
517#[doc(alias = "get_system_data_dirs")]
518pub fn system_data_dirs() -> &'static [&'static std::path::Path] {
519    static DIRS: std::sync::LazyLock<Vec<&'static std::path::Path>> =
520        std::sync::LazyLock::new(|| unsafe { strv_to_static_paths(ffi::g_get_system_data_dirs()) });
521
522    std::sync::LazyLock::force(&DIRS).as_slice()
523}
524
525/// Returns an ordered list of base directories in which to access
526/// system-wide configuration information.
527///
528/// On UNIX platforms this is determined using the mechanisms described
529/// in the
530/// [XDG Base Directory Specification](http://www.freedesktop.org/Standards/basedir-spec).
531/// In this case the list of directories retrieved will be `XDG_CONFIG_DIRS`.
532///
533/// On Windows it follows XDG Base Directory Specification if `XDG_CONFIG_DIRS` is defined.
534/// If `XDG_CONFIG_DIRS` is undefined, the directory that contains application
535/// data for all users is used instead. A typical path is
536/// `C:\Documents and Settings\All Users\Application Data`.
537/// This folder is used for application data
538/// that is not user specific. For example, an application can store
539/// a spell-check dictionary, a database of clip art, or a log file in the
540/// FOLDERID_ProgramData folder. This information will not roam and is available
541/// to anyone using the computer.
542///
543/// The return value is cached and modifying it at runtime is not supported, as
544/// it’s not thread-safe to modify environment variables at runtime.
545///
546/// # Returns
547///
548///
549///     a [`None`]-terminated array of strings owned by GLib that must not be
550///     modified or freed.
551#[doc(alias = "g_get_system_config_dirs")]
552#[doc(alias = "get_system_config_dirs")]
553pub fn system_config_dirs() -> &'static [&'static std::path::Path] {
554    static DIRS: std::sync::LazyLock<Vec<&'static std::path::Path>> =
555        std::sync::LazyLock::new(|| unsafe {
556            strv_to_static_paths(ffi::g_get_system_config_dirs())
557        });
558
559    std::sync::LazyLock::force(&DIRS).as_slice()
560}
561
562/// Computes a list of applicable locale names, which can be used to
563/// e.g. construct locale-dependent filenames or search paths. The returned
564/// list is sorted from most desirable to least desirable and always contains
565/// the default locale "C".
566///
567/// For example, if LANGUAGE=de:en_US, then the returned list is
568/// "de", "en_US", "en", "C".
569///
570/// This function consults the environment variables `LANGUAGE`, `LC_ALL`,
571/// `LC_MESSAGES` and `LANG` to find the list of locales specified by the
572/// user.
573///
574/// # Returns
575///
576/// a [`None`]-terminated array of strings owned by GLib
577///    that must not be modified or freed.
578#[doc(alias = "g_get_language_names")]
579#[doc(alias = "get_language_names")]
580pub fn language_names() -> &'static [crate::GStringPtr] {
581    unsafe { crate::StrV::from_glib_borrow(ffi::g_get_language_names()) }
582}
583
584unsafe fn strv_to_static_paths(
585    mut ptr: *const *const libc::c_char,
586) -> Vec<&'static std::path::Path> {
587    let mut paths = Vec::new();
588
589    unsafe {
590        while !(*ptr).is_null() {
591            paths.push(c_to_path(*ptr));
592            ptr = ptr.add(1);
593        }
594    }
595
596    paths
597}
598
599#[doc(alias = "g_compute_checksum_for_string")]
600pub fn compute_checksum_for_string(
601    checksum_type: ChecksumType,
602    str: impl IntoGStr,
603) -> Option<crate::GString> {
604    str.run_with_gstr(|str| unsafe {
605        from_glib_full(ffi::g_compute_checksum_for_string(
606            checksum_type.into_glib(),
607            str.as_ptr(),
608            str.len() as _,
609        ))
610    })
611}
612
613/// Opens a file for writing in the preferred directory for temporary
614/// files (as returned by g_get_tmp_dir()).
615///
616/// @tmpl should be a string in the GLib file name encoding containing
617/// a sequence of six 'X' characters, as the parameter to g_mkstemp().
618/// However, unlike these functions, the template should only be a
619/// basename, no directory components are allowed. If template is
620/// [`None`], a default template is used.
621///
622/// Note that in contrast to g_mkstemp() (and mkstemp()) @tmpl is not
623/// modified, and might thus be a read-only literal string.
624///
625/// Upon success, and if @name_used is non-[`None`], the actual name used
626/// is returned in @name_used. This string should be freed with g_free()
627/// when not needed any longer. The returned name is in the GLib file
628/// name encoding.
629/// ## `tmpl`
630/// Template for file name, as in
631///   g_mkstemp(), basename only, or [`None`] for a default template
632///
633/// # Returns
634///
635/// A file handle (as from open()) to the file opened for
636///   reading and writing. The file is opened in binary mode on platforms
637///   where there is a difference. The file handle should be closed with
638///   close(). In case of errors, -1 is returned and @error will be set.
639///
640/// ## `name_used`
641/// location to store actual name used,
642///   or [`None`]
643#[cfg(unix)]
644#[doc(alias = "g_file_open_tmp")]
645pub fn file_open_tmp(
646    tmpl: Option<impl AsRef<std::path::Path>>,
647) -> Result<(OwnedFd, std::path::PathBuf), crate::Error> {
648    unsafe {
649        let mut name_used = ptr::null_mut();
650        let mut error = ptr::null_mut();
651        let ret = ffi::g_file_open_tmp(
652            tmpl.as_ref().map(|p| p.as_ref()).to_glib_none().0,
653            &mut name_used,
654            &mut error,
655        );
656        if error.is_null() {
657            Ok((OwnedFd::from_raw_fd(ret), from_glib_full(name_used)))
658        } else {
659            Err(from_glib_full(error))
660        }
661    }
662}
663
664// rustdoc-stripper-ignore-next
665/// Spawn a new infallible `Future` on the thread-default main context.
666///
667/// This can be called from any thread and will execute the future from the thread
668/// where main context is running, e.g. via a `MainLoop`.
669#[cfg(feature = "futures")]
670pub fn spawn_future<R: Send + 'static, F: std::future::Future<Output = R> + Send + 'static>(
671    f: F,
672) -> crate::JoinHandle<R> {
673    let ctx = crate::MainContext::ref_thread_default();
674    ctx.spawn(f)
675}
676
677// rustdoc-stripper-ignore-next
678/// Spawn a new infallible `Future` on the thread-default main context.
679///
680/// The given `Future` does not have to be `Send`.
681///
682/// This can be called only from the thread where the main context is running, e.g.
683/// from any other `Future` that is executed on this main context, or after calling
684/// `with_thread_default` or `acquire` on the main context.
685#[cfg(feature = "futures")]
686pub fn spawn_future_local<R: 'static, F: std::future::Future<Output = R> + 'static>(
687    f: F,
688) -> crate::JoinHandle<R> {
689    let ctx = crate::MainContext::ref_thread_default();
690    ctx.spawn_local(f)
691}