1use nstd_collections::vec::*;
2use std::{
3 env,
4 ffi::{CStr, CString},
5 os::raw::{c_char, c_int, c_void},
6 ptr,
7};
8#[cfg(feature = "deps")]
9pub mod deps {
10 pub use nstd_collections;
11}
12
13#[allow(non_camel_case_types)]
14type byte = u8;
15
16macro_rules! nstd_path_fns {
18 ($fn_name: ident, $env_fn: ident) => {
19 #[cfg_attr(feature = "clib", no_mangle)]
20 pub unsafe extern "C" fn $fn_name(errc: *mut c_int) -> *mut c_char {
21 match env::$env_fn() {
22 Ok(path) => {
23 *errc = 0;
24 let mut path = path.to_string_lossy().to_string();
25 path.push('\0');
26 CString::from_vec_unchecked(path.into_bytes()).into_raw()
27 }
28 _ => {
29 *errc = 1;
30 ptr::null_mut()
31 }
32 }
33 }
34 };
35}
36nstd_path_fns!(nstd_env_path_to_exe, current_exe);
37nstd_path_fns!(nstd_env_current_dir, current_dir);
38
39#[inline]
43#[cfg_attr(feature = "clib", no_mangle)]
44pub unsafe extern "C" fn nstd_env_temp_dir() -> *mut c_char {
45 match env::temp_dir().into_os_string().into_string() {
46 Ok(path) => CString::from_vec_unchecked(path.into_bytes()).into_raw(),
47 _ => ptr::null_mut(),
48 }
49}
50
51#[inline]
56#[cfg_attr(feature = "clib", no_mangle)]
57pub unsafe extern "C" fn nstd_env_free_path(path: *mut *mut c_char) {
58 static_nstd_free_cstring(path);
59}
60
61#[cfg_attr(feature = "clib", no_mangle)]
66pub unsafe extern "C" fn nstd_env_set_current_dir(path: *const c_char) -> c_int {
67 match CStr::from_ptr(path).to_str() {
68 Ok(path) => match env::set_current_dir(path) {
69 Ok(_) => 0,
70 _ => 1,
71 },
72 _ => 1,
73 }
74}
75
76#[cfg_attr(feature = "clib", no_mangle)]
79pub unsafe extern "C" fn nstd_env_args() -> NSTDVec {
80 const ELEMENT_SIZE: usize = std::mem::size_of::<*mut c_char>();
81 let args_iter = env::args().collect::<Vec<String>>();
82 let mut args = nstd_collections_vec_new_with_capacity(ELEMENT_SIZE, args_iter.len());
83 if !args.data.is_null() {
84 for arg in args_iter {
85 let mut bytes = arg.into_bytes();
86 bytes.push(0);
87 let cstr = CString::from_vec_unchecked(bytes).into_raw();
88 let cstrptr = &cstr as *const *mut c_char as *const c_void;
89 nstd_collections_vec_push(&mut args, cstrptr);
90 }
91 }
92 args
93}
94
95#[inline]
100#[cfg_attr(feature = "clib", no_mangle)]
101pub unsafe extern "C" fn nstd_env_free_args(args: &mut NSTDVec) -> c_int {
102 for i in 0..args.size {
103 let cstrptr = nstd_collections_vec_get(args, i) as *const *mut c_char;
104 if !cstrptr.is_null() {
105 drop(CString::from_raw(*cstrptr));
106 }
107 }
108 nstd_collections_vec_free(args)
109}
110
111#[cfg_attr(feature = "clib", no_mangle)]
116pub unsafe extern "C" fn nstd_env_set_var(k: *const c_char, v: *const c_char) {
117 if let Ok(k) = CStr::from_ptr(k).to_str() {
118 if let Ok(v) = CStr::from_ptr(v).to_str() {
119 env::set_var(k, v);
120 }
121 }
122}
123
124#[cfg_attr(feature = "clib", no_mangle)]
129pub unsafe extern "C" fn nstd_env_get_var(k: *const c_char) -> *mut c_char {
130 if let Ok(k) = CStr::from_ptr(k).to_str() {
131 if let Ok(v) = env::var(k) {
132 return CString::from_vec_unchecked(v.into_bytes()).into_raw();
133 }
134 }
135 ptr::null_mut()
136}
137
138#[inline]
143#[cfg_attr(feature = "clib", no_mangle)]
144pub unsafe extern "C" fn nstd_env_remove_var(k: *const c_char) {
145 if let Ok(k) = CStr::from_ptr(k).to_str() {
146 env::remove_var(k);
147 }
148}
149
150#[inline]
154#[cfg_attr(feature = "clib", no_mangle)]
155pub unsafe extern "C" fn nstd_env_free_var(k: *mut *mut c_char) {
156 static_nstd_free_cstring(k);
157}
158
159#[cfg_attr(feature = "clib", no_mangle)]
164pub unsafe extern "C" fn nstd_env_vars(size: *mut usize) -> *mut c_char {
165 let vars = env::vars().collect::<Vec<(String, String)>>();
166 let mut bytes = Vec::<byte>::new();
167 *size = vars.len();
168 for var in vars {
169 bytes.extend(var.0.into_bytes());
170 bytes.push(0);
171 }
172 Box::<[byte]>::into_raw(bytes.into_boxed_slice()) as *mut c_char
173}
174
175#[inline]
179#[cfg_attr(feature = "clib", no_mangle)]
180pub unsafe extern "C" fn nstd_env_free_vars(vars: *mut *mut c_char) {
181 static_nstd_free_cstring(vars);
182}
183
184#[inline]
188unsafe fn static_nstd_free_cstring(cstr: *mut *mut c_char) {
189 Box::from_raw(*cstr as *mut byte);
190 *cstr = ptr::null_mut();
191}