1 // Copyright (C) 2023 Huawei Device Co., Ltd. 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 use std::ffi::c_char; 15 use std::slice; 16 17 use crate::utils::form_item::{FileSpec, FormItem}; 18 19 #[derive(Clone, Debug)] 20 #[repr(C)] 21 pub(crate) struct CStringWrapper { 22 c_str: *const c_char, 23 len: u32, 24 } 25 26 impl From<&str> for CStringWrapper { from(value: &str) -> Self27 fn from(value: &str) -> Self { 28 let c_str = value.as_ptr() as *const c_char; 29 let len = value.len() as u32; 30 CStringWrapper { c_str, len } 31 } 32 } 33 34 impl From<&String> for CStringWrapper { from(value: &String) -> Self35 fn from(value: &String) -> Self { 36 Self::from(value.as_str()) 37 } 38 } 39 40 impl ToString for CStringWrapper { to_string(&self) -> String41 fn to_string(&self) -> String { 42 if self.c_str.is_null() || self.len == 0 { 43 #[cfg(feature = "oh")] 44 unsafe { 45 DeleteChar(self.c_str) 46 }; 47 return String::new(); 48 } 49 let bytes = unsafe { slice::from_raw_parts(self.c_str as *const u8, self.len as usize) }; 50 let str = unsafe { String::from_utf8_unchecked(bytes.to_vec()) }; 51 #[cfg(feature = "oh")] 52 unsafe { 53 DeleteChar(self.c_str) 54 }; 55 str 56 } 57 } 58 59 #[repr(C)] 60 pub(crate) struct CFileSpec { 61 pub(crate) name: CStringWrapper, 62 pub(crate) path: CStringWrapper, 63 pub(crate) file_name: CStringWrapper, 64 pub(crate) mime_type: CStringWrapper, 65 pub(crate) is_user_file: bool, 66 } 67 68 impl FileSpec { to_c_struct(&self) -> CFileSpec69 pub(crate) fn to_c_struct(&self) -> CFileSpec { 70 CFileSpec { 71 name: CStringWrapper::from(&self.name), 72 path: CStringWrapper::from(&self.path), 73 file_name: CStringWrapper::from(&self.file_name), 74 mime_type: CStringWrapper::from(&self.mime_type), 75 is_user_file: self.is_user_file, 76 } 77 } 78 from_c_struct(c_struct: &CFileSpec) -> Self79 pub(crate) fn from_c_struct(c_struct: &CFileSpec) -> Self { 80 FileSpec { 81 name: c_struct.name.to_string(), 82 path: c_struct.path.to_string(), 83 file_name: c_struct.file_name.to_string(), 84 mime_type: c_struct.mime_type.to_string(), 85 is_user_file: c_struct.is_user_file, 86 fd: None, 87 } 88 } 89 } 90 91 #[repr(C)] 92 pub(crate) struct CFormItem { 93 pub(crate) name: CStringWrapper, 94 pub(crate) value: CStringWrapper, 95 } 96 97 impl FormItem { to_c_struct(&self) -> CFormItem98 pub(crate) fn to_c_struct(&self) -> CFormItem { 99 CFormItem { 100 name: CStringWrapper::from(&self.name), 101 value: CStringWrapper::from(&self.value), 102 } 103 } 104 from_c_struct(c_struct: &CFormItem) -> Self105 pub(crate) fn from_c_struct(c_struct: &CFormItem) -> Self { 106 FormItem { 107 name: c_struct.name.to_string(), 108 value: c_struct.value.to_string(), 109 } 110 } 111 } 112 113 #[cfg(feature = "oh")] 114 extern "C" { DeleteChar(ptr: *const c_char)115 pub(crate) fn DeleteChar(ptr: *const c_char); DeleteCFormItem(ptr: *const CFormItem)116 pub(crate) fn DeleteCFormItem(ptr: *const CFormItem); DeleteCFileSpec(ptr: *const CFileSpec)117 pub(crate) fn DeleteCFileSpec(ptr: *const CFileSpec); DeleteCStringPtr(ptr: *const CStringWrapper)118 pub(crate) fn DeleteCStringPtr(ptr: *const CStringWrapper); 119 } 120