glib/
utils.rs

1// Copyright 2015-2016, The Gtk-rs Project Developers.
2// See the COPYRIGHT file at the top-level directory of this distribution.
3// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>
4
5use error::BoolError;
6use glib_sys;
7use gstring::GString;
8use std;
9use std::ffi::{OsStr, OsString};
10use std::path::{Path, PathBuf};
11use std::ptr;
12use translate::*;
13use Error;
14
15/// Same as [`get_prgname()`].
16///
17/// [`get_prgname()`]: fn.get_prgname.html
18pub fn get_program_name() -> Option<String> {
19    get_prgname()
20}
21
22pub fn get_prgname() -> Option<String> {
23    unsafe { from_glib_none(glib_sys::g_get_prgname()) }
24}
25
26/// Same as [`set_prgname()`].
27///
28/// [`set_prgname()`]: fn.set_prgname.html
29pub fn set_program_name(name: Option<&str>) {
30    set_prgname(name)
31}
32
33pub fn set_prgname(name: Option<&str>) {
34    unsafe { glib_sys::g_set_prgname(name.to_glib_none().0) }
35}
36
37pub fn getenv<K: AsRef<OsStr>>(variable_name: K) -> Option<OsString> {
38    #[cfg(not(windows))]
39    use glib_sys::g_getenv;
40    #[cfg(windows)]
41    use glib_sys::g_getenv_utf8 as g_getenv;
42
43    unsafe { from_glib_none(g_getenv(variable_name.as_ref().to_glib_none().0)) }
44}
45
46pub fn setenv<K: AsRef<OsStr>, V: AsRef<OsStr>>(
47    variable_name: K,
48    value: V,
49    overwrite: bool,
50) -> Result<(), BoolError> {
51    #[cfg(not(windows))]
52    use glib_sys::g_setenv;
53    #[cfg(windows)]
54    use glib_sys::g_setenv_utf8 as g_setenv;
55
56    unsafe {
57        glib_result_from_gboolean!(
58            g_setenv(
59                variable_name.as_ref().to_glib_none().0,
60                value.as_ref().to_glib_none().0,
61                overwrite.to_glib(),
62            ),
63            "Failed to set environment variable"
64        )
65    }
66}
67
68pub fn unsetenv<K: AsRef<OsStr>>(variable_name: K) {
69    #[cfg(not(windows))]
70    use glib_sys::g_unsetenv;
71    #[cfg(windows)]
72    use glib_sys::g_unsetenv_utf8 as g_unsetenv;
73
74    unsafe { g_unsetenv(variable_name.as_ref().to_glib_none().0) }
75}
76
77pub fn environ_getenv<K: AsRef<OsStr>>(envp: &[OsString], variable: K) -> Option<OsString> {
78    unsafe {
79        from_glib_none(glib_sys::g_environ_getenv(
80            envp.to_glib_none().0,
81            variable.as_ref().to_glib_none().0,
82        ))
83    }
84}
85
86pub fn get_user_name() -> Option<OsString> {
87    #[cfg(not(all(windows, target_arch = "x86")))]
88    use glib_sys::g_get_user_name;
89    #[cfg(all(windows, target_arch = "x86"))]
90    use glib_sys::g_get_user_name_utf8 as g_get_user_name;
91
92    unsafe { from_glib_none(g_get_user_name()) }
93}
94
95pub fn get_real_name() -> Option<OsString> {
96    #[cfg(not(all(windows, target_arch = "x86")))]
97    use glib_sys::g_get_real_name;
98    #[cfg(all(windows, target_arch = "x86"))]
99    use glib_sys::g_get_real_name_utf8 as g_get_real_name;
100
101    unsafe { from_glib_none(g_get_real_name()) }
102}
103
104pub fn get_current_dir() -> Option<PathBuf> {
105    #[cfg(not(windows))]
106    use glib_sys::g_get_current_dir;
107    #[cfg(windows)]
108    use glib_sys::g_get_current_dir_utf8 as g_get_current_dir;
109
110    unsafe { from_glib_full(g_get_current_dir()) }
111}
112
113pub fn filename_to_uri<P: AsRef<Path>>(
114    filename: P,
115    hostname: Option<&str>,
116) -> Result<GString, Error> {
117    #[cfg(not(windows))]
118    use glib_sys::g_filename_to_uri;
119    #[cfg(windows)]
120    use glib_sys::g_filename_to_uri_utf8 as g_filename_to_uri;
121
122    let hostname = hostname.to_glib_none();
123    unsafe {
124        let mut error = std::ptr::null_mut();
125        let ret = g_filename_to_uri(filename.as_ref().to_glib_none().0, hostname.0, &mut error);
126        if error.is_null() {
127            Ok(from_glib_full(ret))
128        } else {
129            Err(from_glib_full(error))
130        }
131    }
132}
133
134pub fn filename_from_uri(uri: &str) -> Result<(std::path::PathBuf, Option<GString>), Error> {
135    #[cfg(not(windows))]
136    use glib_sys::g_filename_from_uri;
137    #[cfg(windows)]
138    use glib_sys::g_filename_from_uri_utf8 as g_filename_from_uri;
139
140    unsafe {
141        let mut hostname = ptr::null_mut();
142        let mut error = ptr::null_mut();
143        let ret = g_filename_from_uri(uri.to_glib_none().0, &mut hostname, &mut error);
144        if error.is_null() {
145            Ok((from_glib_full(ret), from_glib_full(hostname)))
146        } else {
147            Err(from_glib_full(error))
148        }
149    }
150}
151
152pub fn find_program_in_path<P: AsRef<Path>>(program: P) -> Option<PathBuf> {
153    #[cfg(not(all(windows, target_arch = "x86")))]
154    use glib_sys::g_find_program_in_path;
155    #[cfg(all(windows, target_arch = "x86"))]
156    use glib_sys::g_find_program_in_path_utf8 as g_find_program_in_path;
157
158    unsafe { from_glib_full(g_find_program_in_path(program.as_ref().to_glib_none().0)) }
159}
160
161pub fn get_home_dir() -> Option<std::path::PathBuf> {
162    #[cfg(not(all(windows, target_arch = "x86")))]
163    use glib_sys::g_get_home_dir;
164    #[cfg(all(windows, target_arch = "x86"))]
165    use glib_sys::g_get_home_dir_utf8 as g_get_home_dir;
166
167    unsafe { from_glib_none(g_get_home_dir()) }
168}
169
170pub fn get_tmp_dir() -> Option<std::path::PathBuf> {
171    #[cfg(not(all(windows, target_arch = "x86")))]
172    use glib_sys::g_get_tmp_dir;
173    #[cfg(all(windows, target_arch = "x86"))]
174    use glib_sys::g_get_tmp_dir_utf8 as g_get_tmp_dir;
175
176    unsafe { from_glib_none(g_get_tmp_dir()) }
177}
178
179pub fn mkstemp<P: AsRef<std::path::Path>>(tmpl: P) -> i32 {
180    #[cfg(not(windows))]
181    use glib_sys::g_mkstemp;
182    #[cfg(windows)]
183    use glib_sys::g_mkstemp_utf8 as g_mkstemp;
184
185    unsafe { g_mkstemp(tmpl.as_ref().to_glib_none().0) }
186}
187
188#[cfg(test)]
189mod tests {
190    use std::env;
191    use std::sync::Mutex;
192
193    //Mutex to prevent run environment tests parallel
194    lazy_static! {
195        static ref LOCK: Mutex<()> = Mutex::new(());
196    }
197
198    const VAR_NAME: &str = "function_environment_test";
199
200    fn check_getenv(val: &str) {
201        let _data = LOCK.lock().unwrap();
202
203        env::set_var(VAR_NAME, val);
204        assert_eq!(env::var_os(VAR_NAME), Some(val.into()));
205        assert_eq!(::getenv(VAR_NAME), Some(val.into()));
206
207        let environ = ::get_environ();
208        assert_eq!(::environ_getenv(&environ, VAR_NAME), Some(val.into()));
209    }
210
211    fn check_setenv(val: &str) {
212        let _data = LOCK.lock().unwrap();
213
214        ::setenv(VAR_NAME, val, true).unwrap();
215        assert_eq!(env::var_os(VAR_NAME), Some(val.into()));
216    }
217
218    #[test]
219    fn getenv() {
220        check_getenv("Test");
221        check_getenv("Тест"); // "Test" in Russian
222    }
223
224    #[test]
225    fn setenv() {
226        check_setenv("Test");
227        check_setenv("Тест"); // "Test" in Russian
228    }
229
230    #[test]
231    fn test_filename_from_uri() {
232        use gstring::GString;
233        use std::path::PathBuf;
234        let uri: GString = "file:///foo/bar.txt".into();
235        if let Ok((filename, hostname)) = ::filename_from_uri(&uri) {
236            assert_eq!(filename, PathBuf::from(r"/foo/bar.txt"));
237            assert_eq!(hostname, None);
238        } else {
239            unreachable!();
240        }
241
242        let uri: GString = "file://host/foo/bar.txt".into();
243        if let Ok((filename, hostname)) = ::filename_from_uri(&uri) {
244            assert_eq!(filename, PathBuf::from(r"/foo/bar.txt"));
245            assert_eq!(hostname, Some(GString::from("host")));
246        } else {
247            unreachable!();
248        }
249    }
250}