tesseract_swift_utils/
string.rs1use crate::panic::PanicContext;
2use crate::traits::AsCRef;
3
4use super::error::CError;
5use super::response::CMoveResponse;
6use super::result::Result;
7use super::traits::TryAsRef;
8use std::ffi::{CStr as FCStr, CString as FCString};
9use std::mem::ManuallyDrop;
10use std::os::raw::c_char;
11use std::borrow::Borrow;
12
13pub type CStringRef = *const c_char;
14
15#[repr(C)]
16#[derive(Debug)]
17pub struct CString(*const c_char);
18
19unsafe impl Sync for CString {}
20unsafe impl Send for CString {}
21
22impl Drop for CString {
23 fn drop(&mut self) {
24 let _ = unsafe { FCString::from_raw(self.0 as *mut c_char) };
25 }
26}
27
28impl Clone for CString {
29 fn clone(&self) -> Self {
30 self.try_as_ref().unwrap().into()
31 }
32}
33
34impl PartialEq for CString {
35 fn eq(&self, other: &Self) -> bool {
36 unsafe { FCStr::from_ptr(self.0).eq(FCStr::from_ptr(other.0)) }
37 }
38}
39
40impl TryAsRef<str> for CStringRef {
41 type Error = CError;
42
43 fn try_as_ref(&self) -> Result<&str> {
44 unsafe { FCStr::from_ptr(*self).to_str().map_err(|err| err.into()) }
45 }
46}
47
48impl std::fmt::Display for CString {
49 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50 let string = self.try_as_ref().map_err(|_| std::fmt::Error)?;
51 write!(f, "{}", string)
52 }
53}
54
55impl TryAsRef<str> for CString {
56 type Error = CError;
57
58 fn try_as_ref(&self) -> Result<&str> {
59 self.0.try_as_ref()
60 }
61}
62
63impl AsCRef<CStringRef> for CString {
64 fn as_cref(&self) -> CStringRef {
65 self.0
66 }
67}
68
69impl<'a> TryFrom<&'a CString> for &'a str {
70 type Error = CError;
71
72 fn try_from(value: &'a CString) -> Result<Self> {
73 value.0.try_as_ref()
74 }
75}
76
77impl TryFrom<CString> for String {
78 type Error = CError;
79
80 fn try_from(value: CString) -> Result<Self> {
81 if value.0.is_null() {
82 Err(CError::null::<CString>())
83 } else {
84 let value = ManuallyDrop::new(value); unsafe {
86 FCString::from_raw(value.0 as *mut c_char)
87 .into_string()
88 .map_err(|err| err.into())
89 }
90 }
91 }
92}
93
94impl<T: Borrow<str>> From<T> for CString {
95 fn from(value: T) -> Self {
96 Self(FCString::new(value.borrow()).unwrap().into_raw())
97 }
98}
99
100#[no_mangle]
101pub unsafe extern "C" fn tesseract_utils_cstring_new(
102 cstr: CStringRef,
103 res: &mut ManuallyDrop<CString>,
104 err: &mut ManuallyDrop<CError>,
105) -> bool {
106 CError::panic_context(|| cstr.try_as_ref()).response(res, err)
107}
108
109#[no_mangle]
110pub unsafe extern "C" fn tesseract_utils_cstring_free(cstr: ManuallyDrop<CString>) {
111 let _ = ManuallyDrop::into_inner(cstr);
112}