1use std::ffi::{CStr, CString};
2use std::os::raw::*;
3use std::{slice, str};
4
5pub fn ptr_to_string(ptr: *const c_char) -> String {
6 let strs = if ptr.is_null() {
7 ""
8 } else {
9 let cstr = unsafe { CStr::from_ptr(ptr) };
10 if let Ok(s) = str::from_utf8(cstr.to_bytes()) {
11 s
12 } else {
13 ""
14 }
15 };
16 strs.to_string()
17}
18
19pub fn ptr_to_vec_string(ptr: *const *const c_char, size: usize) -> Vec<String> {
20 let slice = unsafe { slice::from_raw_parts(ptr, size) };
21 slice
22 .iter()
23 .map(|raw_str| ptr_to_string(*raw_str))
24 .collect()
25}
26
27pub fn str_to_heap_ptr<T: Into<Vec<u8>>>(input: T) -> *mut c_char {
28 CString::new(input).unwrap().into_raw()
29}
30
31#[cfg(test)]
32mod tests {
33 use super::*;
34
35 #[test]
36 fn test_ptr_to_vec_string() {
37 let vec_string = vec![String::from("string1"), String::from("string2")];
38 let vec_cstring = vec_string
39 .iter()
40 .map(|arg| CString::new(arg.as_str()).unwrap())
41 .collect::<Vec<CString>>();
42 let mut vec_ptr = vec_cstring
43 .iter()
44 .map(|arg| arg.as_ptr())
45 .collect::<Vec<*const c_char>>();
46 vec_ptr.push(std::ptr::null());
47 let ptr: *const *const c_char = vec_ptr.as_ptr();
48 let result = ptr_to_vec_string(ptr, vec_string.len());
49 assert_eq!(vec_string, result);
50 }
51
52 #[test]
53 fn test_str_to_heap_ptr_and_ptr_to_string() {
54 let string = "string";
55 let ptr = str_to_heap_ptr(string);
56 let result = ptr_to_string(ptr);
57 assert_eq!(string, result);
58 unsafe {
59 CString::from_raw(ptr);
60 }
61 }
62}