1use crate::{bindings, util};
3use std::{collections::HashMap, ffi::CString};
4
5pub fn expand<S: AsRef<str>>(
28 shell_string: &str,
29 env_vars: HashMap<S, S>,
30) -> Result<String, String> {
31 let shell_string_ffi = CString::new(shell_string).unwrap();
32 let mut env_vec: Vec<CString> = vec![];
33
34 for (key, value) in env_vars {
35 let env_var_ffi =
36 CString::new(format!("{}={}", key.as_ref(), value.as_ref()).as_str()).unwrap();
37 env_vec.push(env_var_ffi);
38 }
39
40 let env_vec_ptrs: Vec<*mut libc::c_char> = env_vec
41 .iter()
42 .map(|string| string.as_ptr() as *mut libc::c_char)
43 .collect();
44 let resp = unsafe {
45 bindings::HuskShellExpand(
46 shell_string_ffi.as_ptr() as *mut libc::c_char,
47 env_vec_ptrs.as_ptr() as *mut *mut libc::c_char,
48 env_vec_ptrs.len().try_into().unwrap(),
49 )
50 };
51
52 let res = unsafe { CString::from_raw(resp.r0).into_string().unwrap() };
53 if resp.r1 == 0 {
54 Ok(res)
55 } else {
56 Err(res)
57 }
58}
59
60pub fn fields<S: AsRef<str>>(
69 shell_string: &str,
70 env_vars: HashMap<S, S>,
71) -> Result<Vec<String>, String> {
72 let shell_string_ffi = CString::new(shell_string).unwrap();
73
74 let mut env_vec: Vec<CString> = vec![];
75
76 for (key, value) in env_vars {
77 let env_var_ffi =
78 CString::new(format!("{}={}", key.as_ref(), value.as_ref()).as_str()).unwrap();
79 env_vec.push(env_var_ffi);
80 }
81
82 let env_vec_ptrs: Vec<*mut libc::c_char> = env_vec
83 .iter()
84 .map(|string| string.as_ptr() as *mut libc::c_char)
85 .collect();
86 let resp = unsafe {
87 bindings::HuskShellFields(
88 shell_string_ffi.as_ptr() as *mut libc::c_char,
89 env_vec_ptrs.as_ptr() as *mut *mut libc::c_char,
90 env_vec_ptrs.len().try_into().unwrap(),
91 )
92 };
93
94 if !resp.r1.is_null() {
95 Err(unsafe { CString::from_raw(resp.r1).into_string().unwrap() })
96 } else {
97 Ok(unsafe { util::go_to_rust_string_vec(resp.r0) })
98 }
99}