use std::{
cell::RefCell,
ffi::{CStr, CString},
os::raw::c_char,
ptr,
};
use crate::api::propagate_panic;
type FreeDartNativeStringFunction = extern "C" fn(ptr::NonNull<c_char>);
thread_local! {
static FREE_DART_NATIVE_STRING: RefCell<
Option<FreeDartNativeStringFunction>
> = RefCell::default();
}
#[must_use]
pub unsafe fn c_str_into_string(string: ptr::NonNull<c_char>) -> String {
unsafe { CStr::from_ptr(string.as_ptr()) }.to_str().unwrap().to_owned()
}
#[must_use]
pub fn string_into_c_str(string: String) -> ptr::NonNull<c_char> {
ptr::NonNull::new(CString::new(string).unwrap().into_raw()).unwrap()
}
#[must_use]
pub unsafe fn dart_string_into_rust(
dart_string: ptr::NonNull<c_char>,
) -> String {
let rust_string = unsafe { c_str_into_string(dart_string) };
unsafe {
free_dart_native_string(dart_string);
}
rust_string
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn String_free(s: ptr::NonNull<c_char>) {
propagate_panic(move || {
drop(unsafe { CString::from_raw(s.as_ptr()) });
});
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn register_free_dart_native_string(
f: FreeDartNativeStringFunction,
) {
FREE_DART_NATIVE_STRING.set(Some(f));
}
pub unsafe fn free_dart_native_string(s: ptr::NonNull<c_char>) {
FREE_DART_NATIVE_STRING.with_borrow(|f| f.unwrap()(s));
}