use std::ffi::c_char;
use std::slice;
use crate::utils::form_item::{FileSpec, FormItem};
#[derive(Clone, Debug)]
#[repr(C)]
pub(crate) struct CStringWrapper {
c_str: *const c_char,
len: u32,
}
impl From<&str> for CStringWrapper {
fn from(value: &str) -> Self {
let c_str = value.as_ptr() as *const c_char;
let len = value.len() as u32;
CStringWrapper { c_str, len }
}
}
impl From<&String> for CStringWrapper {
fn from(value: &String) -> Self {
Self::from(value.as_str())
}
}
impl ToString for CStringWrapper {
fn to_string(&self) -> String {
if self.c_str.is_null() || self.len == 0 {
#[cfg(feature = "oh")]
unsafe {
DeleteChar(self.c_str)
};
return String::new();
}
let bytes = unsafe { slice::from_raw_parts(self.c_str as *const u8, self.len as usize) };
let str = String::from_utf8(bytes.to_vec())
.unwrap_or_else(|_| String::from_utf8_lossy(bytes).into_owned());
#[cfg(feature = "oh")]
unsafe {
DeleteChar(self.c_str)
};
str
}
}
#[repr(C)]
pub(crate) struct CFileSpec {
pub(crate) name: CStringWrapper,
pub(crate) path: CStringWrapper,
pub(crate) file_name: CStringWrapper,
pub(crate) mime_type: CStringWrapper,
pub(crate) is_user_file: bool,
}
impl FileSpec {
pub(crate) fn to_c_struct(&self) -> CFileSpec {
CFileSpec {
name: CStringWrapper::from(&self.name),
path: CStringWrapper::from(&self.path),
file_name: CStringWrapper::from(&self.file_name),
mime_type: CStringWrapper::from(&self.mime_type),
is_user_file: self.is_user_file,
}
}
pub(crate) fn from_c_struct(c_struct: &CFileSpec) -> Self {
FileSpec {
name: c_struct.name.to_string(),
path: c_struct.path.to_string(),
file_name: c_struct.file_name.to_string(),
mime_type: c_struct.mime_type.to_string(),
is_user_file: c_struct.is_user_file,
fd: None,
}
}
}
#[repr(C)]
pub(crate) struct CFormItem {
pub(crate) name: CStringWrapper,
pub(crate) value: CStringWrapper,
}
impl FormItem {
pub(crate) fn to_c_struct(&self) -> CFormItem {
CFormItem {
name: CStringWrapper::from(&self.name),
value: CStringWrapper::from(&self.value),
}
}
pub(crate) fn from_c_struct(c_struct: &CFormItem) -> Self {
FormItem {
name: c_struct.name.to_string(),
value: c_struct.value.to_string(),
}
}
}
#[cfg(feature = "oh")]
extern "C" {
pub(crate) fn DeleteChar(ptr: *const c_char);
pub(crate) fn DeleteCFormItem(ptr: *const CFormItem);
pub(crate) fn DeleteCFileSpec(ptr: *const CFileSpec);
pub(crate) fn DeleteCStringPtr(ptr: *const CStringWrapper);
}