From c2d21fd0a83ea3fc84414d51139ecacd4bc90844 Mon Sep 17 00:00:00 2001 From: Soispha Date: Sun, 24 Mar 2024 21:11:58 +0100 Subject: [PATCH] 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_. --- trixy-types/src/traits/convert_trait.rs | 70 ++++++++++++++++++------- trixy-types/src/types_list.rs | 2 + 2 files changed, 52 insertions(+), 20 deletions(-) diff --git a/trixy-types/src/traits/convert_trait.rs b/trixy-types/src/traits/convert_trait.rs index 8971e18..1521911 100644 --- a/trixy-types/src/traits/convert_trait.rs +++ b/trixy-types/src/traits/convert_trait.rs @@ -129,12 +129,11 @@ pub extern "C" fn string_free(ptr: *const c_char) { } impl Convertible for Option { - type Ptr = *const T; + type Ptr = *const ::Ptr; fn into_ptr(self) -> Self::Ptr { if let Some(inner) = self { - let mut_ref = &mut inner.into_ptr(); - mut_ref as *mut _ as *const T + &inner.into_ptr() } else { ptr::null() } @@ -153,14 +152,11 @@ impl Convertible for Option { } impl Convertible for Result { - type Ptr = *const T; + type Ptr = *const ::Ptr; fn into_ptr(self) -> Self::Ptr { match self { - Ok(ok) => { - let mut_ref = &mut ok.into_ptr(); - mut_ref as *mut _ as *const T - } + Ok(ok) => &ok.into_ptr(), Err(err) => { errno::set(TypeConversionError::ResultWasErr { original_message: err.to_string(), @@ -183,15 +179,16 @@ impl Convertible for Result { } } -impl Convertible for Vec { - type Ptr = crate::Vec; +impl Convertible for Vec { + type Ptr = crate::Vec<::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 { - data: me.as_mut_ptr() as *const T, - length: me.len(), - capacity: me.capacity(), + data: data_vec.as_ptr(), + length: data_vec.len(), + capacity: data_vec.capacity(), } } @@ -203,18 +200,51 @@ impl Convertible for Vec { // if !ptr.data.is_aligned() { // return Err(TypeConversionError::NotAligned); // } - let vec = unsafe { + let base_vec = unsafe { // SAFETY: // 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. - Vec::from_raw_parts(ptr.data as *mut T, ptr.length, ptr.capacity) + Vec::from_raw_parts( + ptr.data as *mut ::Ptr, + ptr.length, + ptr.capacity, + ) }; + + let vec: Vec<_> = base_vec + .into_iter() + .map(|val| ::from_ptr(val)) + .collect::, _>>()?; Ok(vec) } } -// FIXME(@soispha): Add the required generic support here <2024-02-18> -#[no_mangle] -pub extern "C" fn vec_free(ptr: crate::Vec) { - Vec::drop_ptr(ptr); +macro_rules! make_vec_free { + ($value:ident, $name:ident) => { + #[no_mangle] + pub extern "C" fn $name(ptr: crate::Vec<<$value as Convertible>::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); diff --git a/trixy-types/src/types_list.rs b/trixy-types/src/types_list.rs index e4695d2..bdbd680 100644 --- a/trixy-types/src/types_list.rs +++ b/trixy-types/src/types_list.rs @@ -22,6 +22,8 @@ // 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> +// 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; #[derive(Debug, Clone)]