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 f688df1248
commit c2d21fd0a8
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> {
type Ptr = *const T;
type Ptr = *const <T as Convertible>::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<T: Convertible> Convertible for Option<T> {
}
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 {
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<T: Convertible, E: Error> Convertible for Result<T, E> {
}
}
impl<T> Convertible for Vec<T> {
type Ptr = crate::Vec<T>;
impl<T: Convertible> Convertible for Vec<T> {
type Ptr = crate::Vec<<T as Convertible>::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<T> Convertible for Vec<T> {
// 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 <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)
}
}
// FIXME(@soispha): Add the required generic support here <2024-02-18>
macro_rules! make_vec_free {
($value:ident, $name:ident) => {
#[no_mangle]
pub extern "C" fn vec_free(ptr: crate::Vec<u8>) {
Vec::drop_ptr(ptr);
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);

View File

@ -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)]