| 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 | |