use std::{mem::ManuallyDrop, ops::Deref};
use super::traits::{FFIFromRust, FFIToRust};
#[repr(C)]
#[derive(Debug)]
pub struct FFISeq<T> {
data: *mut T,
size: usize,
capacity: usize,
}
impl<T> FFISeq<T> {
pub fn as_slice(&self) -> &[T] {
self
}
pub const fn len(&self) -> usize {
self.size
}
pub const fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl<T> FFIToRust for FFISeq<T>
where
T: FFIToRust,
{
type Target = Vec<T::Target>;
unsafe fn to_rust(&self) -> Self::Target {
self.iter().map(|v| unsafe { v.to_rust() }).collect()
}
}
macro_rules! impl_traits_to_primitive {
($type: ty) => {
impl FFIToRust for FFISeq<$type> {
type Target = Vec<$type>;
unsafe fn to_rust(&self) -> Self::Target {
self.iter().cloned().collect()
}
}
};
}
impl_traits_to_primitive!(i8);
impl_traits_to_primitive!(i16);
impl_traits_to_primitive!(i32);
impl_traits_to_primitive!(i64);
impl_traits_to_primitive!(u8);
impl_traits_to_primitive!(u16);
impl_traits_to_primitive!(u32);
impl_traits_to_primitive!(u64);
impl_traits_to_primitive!(f32);
impl_traits_to_primitive!(f64);
impl_traits_to_primitive!(bool);
impl<T> Deref for FFISeq<T> {
type Target = [T];
fn deref(&self) -> &[T] {
unsafe { std::slice::from_raw_parts(self.data, self.len()) }
}
}
impl<T> AsRef<[T]> for FFISeq<T> {
fn as_ref(&self) -> &[T] {
self
}
}
#[repr(C)]
#[derive(Debug)]
pub struct OwnedFFISeq<T> {
data: *mut T,
size: usize,
capacity: usize,
}
impl<T> OwnedFFISeq<T> {
pub fn as_slice(&self) -> &[T] {
unsafe { std::slice::from_raw_parts(self.data, self.len()) }
}
pub const fn len(&self) -> usize {
self.size
}
pub const fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl<T> FFIFromRust for OwnedFFISeq<T>
where
T: FFIFromRust,
{
type From = Vec<T::From>;
unsafe fn from_rust(vec: &Self::From) -> Self {
if vec.is_empty() {
Self {
data: std::ptr::null_mut(),
size: 0,
capacity: 0,
}
} else {
let mut new_vec = vec
.iter()
.map(|v| unsafe { FFIFromRust::from_rust(v) })
.collect::<Vec<_>>();
new_vec.shrink_to_fit();
assert_eq!(new_vec.len(), new_vec.capacity());
let mut new_vec = ManuallyDrop::new(new_vec);
Self {
data: new_vec.as_mut_ptr(),
size: new_vec.len(),
capacity: new_vec.len(),
}
}
}
}
impl<T> Drop for OwnedFFISeq<T> {
fn drop(&mut self) {
unsafe { Vec::from_raw_parts(self.data, self.size, self.capacity) };
}
}
#[repr(C)]
#[derive(Debug)]
pub struct RefFFISeq<T> {
data: *mut T,
size: usize,
capacity: usize,
}
impl<T> RefFFISeq<T> {
pub fn as_slice(&self) -> &[T] {
unsafe { std::slice::from_raw_parts(self.data, self.len()) }
}
pub const fn len(&self) -> usize {
self.size
}
pub const fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl<T> FFIFromRust for RefFFISeq<T> {
type From = Vec<T>;
unsafe fn from_rust(vec: &Self::From) -> Self {
if vec.is_empty() {
Self {
data: std::ptr::null_mut(),
size: 0,
capacity: 0,
}
} else {
Self {
data: vec.as_ptr() as *mut _,
size: vec.len(),
capacity: vec.len(),
}
}
}
}