fix(types): Improve support for generic rust types

The support might be improved, but I still sort of want to remove
generic types, as the current implementation is just _bad_.
This commit is contained in:
Benedikt Peetz 2024-03-24 21:11:58 +01:00
parent 2ed6ed7f58
commit 648348bd38
Signed by: bpeetz
GPG Key ID: A5E94010C3A642AD
2 changed files with 52 additions and 20 deletions

View File

@ -129,12 +129,11 @@ pub extern "C" fn string_free(ptr: *const c_char) {
} }
impl<T: Convertible> Convertible for Option<T> { impl<T: Convertible> Convertible for Option<T> {
type Ptr = *const T; type Ptr = *const <T as Convertible>::Ptr;
fn into_ptr(self) -> Self::Ptr { fn into_ptr(self) -> Self::Ptr {
if let Some(inner) = self { if let Some(inner) = self {
let mut_ref = &mut inner.into_ptr(); &inner.into_ptr()
mut_ref as *mut _ as *const T
} else { } else {
ptr::null() ptr::null()
} }
@ -153,14 +152,11 @@ impl<T: Convertible> Convertible for Option<T> {
} }
impl<T: Convertible, E: Error> Convertible for Result<T, E> { impl<T: Convertible, E: Error> Convertible for Result<T, E> {
type Ptr = *const T; type Ptr = *const <T as Convertible>::Ptr;
fn into_ptr(self) -> Self::Ptr { fn into_ptr(self) -> Self::Ptr {
match self { match self {
Ok(ok) => { Ok(ok) => &ok.into_ptr(),
let mut_ref = &mut ok.into_ptr();
mut_ref as *mut _ as *const T
}
Err(err) => { Err(err) => {
errno::set(TypeConversionError::ResultWasErr { errno::set(TypeConversionError::ResultWasErr {
original_message: err.to_string(), original_message: err.to_string(),
@ -183,15 +179,16 @@ impl<T: Convertible, E: Error> Convertible for Result<T, E> {
} }
} }
impl<T> Convertible for Vec<T> { impl<T: Convertible> Convertible for Vec<T> {
type Ptr = crate::Vec<T>; type Ptr = crate::Vec<<T as Convertible>::Ptr>;
fn into_ptr(self) -> Self::Ptr { fn into_ptr(self) -> Self::Ptr {
let mut me = ManuallyDrop::new(self); let data_vec: Vec<_> = self.into_iter().map(|val| val.into_ptr()).collect();
let data_vec = ManuallyDrop::new(data_vec);
Self::Ptr { Self::Ptr {
data: me.as_mut_ptr() as *const T, data: data_vec.as_ptr(),
length: me.len(), length: data_vec.len(),
capacity: me.capacity(), capacity: data_vec.capacity(),
} }
} }
@ -203,18 +200,51 @@ impl<T> Convertible for Vec<T> {
// if !ptr.data.is_aligned() { // if !ptr.data.is_aligned() {
// return Err(TypeConversionError::NotAligned); // return Err(TypeConversionError::NotAligned);
// } // }
let vec = unsafe { let base_vec = unsafe {
// SAFETY: // SAFETY:
// We simply hope that c treated our vector as read-only and didn't modify it. // We simply hope that c treated our vector as read-only and didn't modify it.
// See the SAFETY section of the String implementation for more detail. // See the SAFETY section of the String implementation for more detail.
Vec::from_raw_parts(ptr.data as *mut T, ptr.length, ptr.capacity) Vec::from_raw_parts(
ptr.data as *mut <T as Convertible>::Ptr,
ptr.length,
ptr.capacity,
)
}; };
let vec: Vec<_> = base_vec
.into_iter()
.map(|val| <T as Convertible>::from_ptr(val))
.collect::<Result<Vec<_>, _>>()?;
Ok(vec) Ok(vec)
} }
} }
// FIXME(@soispha): Add the required generic support here <2024-02-18> macro_rules! make_vec_free {
($value:ident, $name:ident) => {
#[no_mangle] #[no_mangle]
pub extern "C" fn vec_free(ptr: crate::Vec<u8>) { pub extern "C" fn $name(ptr: crate::Vec<<$value as Convertible>::Ptr>) {
Vec::drop_ptr(ptr); Vec::<$value>::drop_ptr(ptr);
} }
};
}
// Unsigned
make_vec_free!(u8, vec_free_u8);
make_vec_free!(u16, vec_free_u16);
make_vec_free!(u32, vec_free_u32);
make_vec_free!(u64, vec_free_u64);
// Signed
make_vec_free!(i8, vec_free_i8);
make_vec_free!(i16, vec_free_i16);
make_vec_free!(i32, vec_free_i32);
make_vec_free!(i64, vec_free_i64);
// Float
make_vec_free!(f32, vec_free_f32);
make_vec_free!(f64, vec_free_f64);
// Other
make_vec_free!(String, vec_free_String);
// FIXME(@soispha): Find a way to support these <2024-02-27>
// make_vec_free!(Option<?>, vec_free_Option);
// make_vec_free!(Vec<?>, vec_free_Vec);
// make_vec_free!(Result<?, ?>, vec_free_Result);

View File

@ -22,6 +22,8 @@
// NOTE(@soispha): All types specified here *MUST* be include in the BASE_TYPES constant, otherwise // NOTE(@soispha): All types specified here *MUST* be include in the BASE_TYPES constant, otherwise
// they are not usable from Trixy code <2023-12-25> // they are not usable from Trixy code <2023-12-25>
// NOTE(@soispha): All types added here must also have an added free impl for the vector type (./traits/convert_trait.rs) <2024-02-27>
use std::ffi::c_char; use std::ffi::c_char;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]