use std::cell::RefCell;
use std::ffi::CStr;
use std::mem;
use std::os::raw::c_char;
pub const CHAR_ARRAY_SIZE: usize = 256;
pub const EMPTY_CHAR_ARRAY: [c_char; CHAR_ARRAY_SIZE] = ['\0' as c_char; CHAR_ARRAY_SIZE];
#[repr(C)]
pub struct CharArrays {
array: *mut [c_char; CHAR_ARRAY_SIZE],
length: u32,
capacity: u32,
}
impl From<&[String]> for CharArrays {
fn from(strings: &[String]) -> Self {
let mut vector: Vec<[c_char; CHAR_ARRAY_SIZE]> = strings.iter().map(|string| str_to_char_array(string)).collect();
let char_arrays = CharArrays {
array: vector.as_mut_ptr(),
length: vector.len() as u32,
capacity: vector.capacity() as u32,
};
mem::forget(vector);
char_arrays
}
}
impl From<&[Vec<u8>]> for CharArrays {
fn from(bytes: &[Vec<u8>]) -> Self {
let mut vector: Vec<[c_char; CHAR_ARRAY_SIZE]> = bytes.iter().map(|bytes| bytes_to_char_array(bytes)).collect();
let char_arrays = Self {
array: vector.as_mut_ptr(),
length: vector.len() as u32,
capacity: vector.capacity() as u32,
};
mem::forget(vector);
char_arrays
}
}
#[no_mangle]
pub extern "C" fn XIMU3_char_arrays_free(char_arrays: CharArrays) {
if char_arrays.array.is_null() {
return;
}
unsafe {
let _ = Vec::from_raw_parts(char_arrays.array, char_arrays.length as usize, char_arrays.capacity as usize);
}
}
thread_local! {
static CHAR_ARRAY: RefCell<[c_char; CHAR_ARRAY_SIZE]> = RefCell::new(EMPTY_CHAR_ARRAY);
}
pub fn str_to_char_ptr(string: &str) -> *const c_char {
CHAR_ARRAY.with(|char_array| {
let mut array = char_array.borrow_mut();
*array = str_to_char_array(string);
array.as_ptr()
}) }
pub fn bytes_to_char_array(bytes: &[u8]) -> [c_char; CHAR_ARRAY_SIZE] {
let mut char_array = EMPTY_CHAR_ARRAY;
let bytes = &bytes[..(char_array.len() - 1).min(bytes.len())];
bytes.iter().enumerate().for_each(|(index, &byte)| {
char_array[index] = byte as c_char;
});
char_array
}
pub fn str_to_char_array(string: &str) -> [c_char; CHAR_ARRAY_SIZE] {
bytes_to_char_array(string.as_bytes())
}
pub unsafe fn char_ptr_to_string(char_ptr: *const c_char) -> String {
let c_str = unsafe { CStr::from_ptr(char_ptr) };
String::from_utf8_lossy(c_str.to_bytes()).to_string()
}
pub unsafe fn char_ptr_to_bytes(char_ptr: *const c_char) -> Vec<u8> {
let c_str = unsafe { CStr::from_ptr(char_ptr) };
c_str.to_bytes().to_vec()
}
pub unsafe fn char_array_to_string(char_array: &[c_char]) -> String {
unsafe { char_ptr_to_string(char_array.as_ptr()) }
}
pub unsafe fn char_ptr_array_to_vec_string(char_ptr_array: *const *const c_char, length: u32) -> Vec<String> {
let mut vec_string = Vec::new();
for index in 0..length {
let char_ptr = unsafe { *char_ptr_array.offset(index as isize) };
vec_string.push(char_ptr_to_string(char_ptr));
}
vec_string
}
pub unsafe fn char_ptr_array_to_vec_bytes(char_ptr_array: *const *const c_char, length: u32) -> Vec<Vec<u8>> {
let mut vec_bytes = Vec::new();
for index in 0..length {
let char_ptr = unsafe { *char_ptr_array.offset(index as isize) };
vec_bytes.push(char_ptr_to_bytes(char_ptr));
}
vec_bytes
}