use nstd_collections::vec::*;
use std::{
env,
ffi::{CStr, CString},
os::raw::{c_char, c_int, c_void},
ptr,
};
#[cfg(feature = "deps")]
pub mod deps {
pub use nstd_collections;
}
#[allow(non_camel_case_types)]
type byte = u8;
macro_rules! nstd_path_fns {
($fn_name: ident, $env_fn: ident) => {
#[cfg_attr(feature = "clib", no_mangle)]
pub unsafe extern "C" fn $fn_name(errc: *mut c_int) -> *mut c_char {
match env::$env_fn() {
Ok(path) => {
*errc = 0;
let mut path = path.to_string_lossy().to_string();
path.push('\0');
CString::from_vec_unchecked(path.into_bytes()).into_raw()
}
_ => {
*errc = 1;
ptr::null_mut()
}
}
}
};
}
nstd_path_fns!(nstd_env_path_to_exe, current_exe);
nstd_path_fns!(nstd_env_current_dir, current_dir);
#[inline]
#[cfg_attr(feature = "clib", no_mangle)]
pub unsafe extern "C" fn nstd_env_temp_dir() -> *mut c_char {
match env::temp_dir().into_os_string().into_string() {
Ok(path) => CString::from_vec_unchecked(path.into_bytes()).into_raw(),
_ => ptr::null_mut(),
}
}
#[inline]
#[cfg_attr(feature = "clib", no_mangle)]
pub unsafe extern "C" fn nstd_env_free_path(path: *mut *mut c_char) {
static_nstd_free_cstring(path);
}
#[cfg_attr(feature = "clib", no_mangle)]
pub unsafe extern "C" fn nstd_env_set_current_dir(path: *const c_char) -> c_int {
match CStr::from_ptr(path).to_str() {
Ok(path) => match env::set_current_dir(path) {
Ok(_) => 0,
_ => 1,
},
_ => 1,
}
}
#[cfg_attr(feature = "clib", no_mangle)]
pub unsafe extern "C" fn nstd_env_args() -> NSTDVec {
const ELEMENT_SIZE: usize = std::mem::size_of::<*mut c_char>();
let args_iter = env::args().collect::<Vec<String>>();
let mut args = nstd_collections_vec_new_with_capacity(ELEMENT_SIZE, args_iter.len());
if !args.data.is_null() {
for arg in args_iter {
let mut bytes = arg.into_bytes();
bytes.push(0);
let cstr = CString::from_vec_unchecked(bytes).into_raw();
let cstrptr = &cstr as *const *mut c_char as *const c_void;
nstd_collections_vec_push(&mut args, cstrptr);
}
}
args
}
#[inline]
#[cfg_attr(feature = "clib", no_mangle)]
pub unsafe extern "C" fn nstd_env_free_args(args: &mut NSTDVec) -> c_int {
for i in 0..args.size {
let cstrptr = nstd_collections_vec_get(args, i) as *const *mut c_char;
if !cstrptr.is_null() {
drop(CString::from_raw(*cstrptr));
}
}
nstd_collections_vec_free(args)
}
#[cfg_attr(feature = "clib", no_mangle)]
pub unsafe extern "C" fn nstd_env_set_var(k: *const c_char, v: *const c_char) {
if let Ok(k) = CStr::from_ptr(k).to_str() {
if let Ok(v) = CStr::from_ptr(v).to_str() {
env::set_var(k, v);
}
}
}
#[cfg_attr(feature = "clib", no_mangle)]
pub unsafe extern "C" fn nstd_env_get_var(k: *const c_char) -> *mut c_char {
if let Ok(k) = CStr::from_ptr(k).to_str() {
if let Ok(v) = env::var(k) {
return CString::from_vec_unchecked(v.into_bytes()).into_raw();
}
}
ptr::null_mut()
}
#[inline]
#[cfg_attr(feature = "clib", no_mangle)]
pub unsafe extern "C" fn nstd_env_remove_var(k: *const c_char) {
if let Ok(k) = CStr::from_ptr(k).to_str() {
env::remove_var(k);
}
}
#[inline]
#[cfg_attr(feature = "clib", no_mangle)]
pub unsafe extern "C" fn nstd_env_free_var(k: *mut *mut c_char) {
static_nstd_free_cstring(k);
}
#[cfg_attr(feature = "clib", no_mangle)]
pub unsafe extern "C" fn nstd_env_vars(size: *mut usize) -> *mut c_char {
let vars = env::vars().collect::<Vec<(String, String)>>();
let mut bytes = Vec::<byte>::new();
*size = vars.len();
for var in vars {
bytes.extend(var.0.into_bytes());
bytes.push(0);
}
Box::<[byte]>::into_raw(bytes.into_boxed_slice()) as *mut c_char
}
#[inline]
#[cfg_attr(feature = "clib", no_mangle)]
pub unsafe extern "C" fn nstd_env_free_vars(vars: *mut *mut c_char) {
static_nstd_free_cstring(vars);
}
#[inline]
unsafe fn static_nstd_free_cstring(cstr: *mut *mut c_char) {
Box::from_raw(*cstr as *mut byte);
*cstr = ptr::null_mut();
}