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:
parent
f688df1248
commit
c2d21fd0a8
|
@ -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);
|
||||
|
|
|
@ -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)]
|
||||
|
|
Reference in New Issue