use std::{ffi::c_void, mem::ManuallyDrop, path::PathBuf, ptr};
use smol_str::SmolStr;
#[derive(Debug)]
#[repr(C)]
pub struct CVec<T> {
ptr: *mut T,
length: usize,
capacity: usize,
}
impl<T> CVec<T> {
pub fn into_vec(self) -> Vec<T> {
let vec = ManuallyDrop::new(self);
let CVec {
ptr,
length,
capacity,
} = *vec;
unsafe { Vec::from_raw_parts(ptr, length, capacity) }
}
pub fn from_vec(vec: Vec<T>) -> CVec<T> {
let mut vec = ManuallyDrop::new(vec);
let ptr = vec.as_mut_ptr();
let length = vec.len();
let capacity = vec.capacity();
Self {
ptr,
length,
capacity,
}
}
}
impl<T> From<Vec<T>> for CVec<T> {
fn from(vec: Vec<T>) -> Self {
CVec::from_vec(vec)
}
}
impl<T> Drop for CVec<T> {
fn drop(&mut self) {
let CVec {
ptr,
length,
capacity,
} = *self;
let _ = unsafe { Vec::from_raw_parts(ptr, length, capacity) };
}
}
#[derive(Debug)]
#[repr(C)]
pub struct Utf8String {
ptr: *mut u8,
length: usize,
capacity: usize,
}
impl From<String> for Utf8String {
fn from(mut value: String) -> Self {
let ptr = value.as_mut_ptr();
let length = value.len();
let capacity = value.capacity();
Self {
ptr,
length,
capacity,
}
}
}
impl From<SmolStr> for Utf8String {
fn from(value: SmolStr) -> Self {
let mut value = ManuallyDrop::new(value.to_string());
let ptr = value.as_mut_ptr();
let length = value.len();
let capacity = value.capacity();
Self {
ptr,
length,
capacity,
}
}
}
impl Drop for Utf8String {
fn drop(&mut self) {
let Self {
ptr,
length,
capacity,
} = self;
let _ = unsafe { String::from_raw_parts(*ptr, *length, *capacity) };
}
}
#[derive(Debug)]
#[repr(C)]
pub struct CPathBuf {
ptr: *mut u8,
length: usize,
capacity: usize,
}
impl From<PathBuf> for CPathBuf {
fn from(value: PathBuf) -> Self {
let mut value = ManuallyDrop::new(value.into_os_string().into_encoded_bytes());
let ptr = value.as_mut_ptr();
let length = value.len();
let capacity = value.capacity();
Self {
ptr,
length,
capacity,
}
}
}
impl Drop for CPathBuf {
fn drop(&mut self) {
let Self {
ptr,
length,
capacity,
} = self;
let _ = unsafe { Vec::from_raw_parts(*ptr, *length, *capacity) };
}
}
#[derive(Debug)]
#[repr(C)]
pub struct COption<T>(*const T);
impl<I, O> From<Option<I>> for COption<O>
where
O: From<I>,
{
fn from(value: Option<I>) -> Self {
match value {
Some(value) => COption(&O::from(value) as *const O),
None => COption(ptr::null()),
}
}
}
impl<T> Drop for COption<T> {
fn drop(&mut self) {
let Self(ptr) = self;
if !ptr.is_null() {
let _ = unsafe { &**ptr as &T };
}
}
}
#[derive(Debug)]
#[repr(C)]
pub struct Pair<A, B>(pub A, pub B);
impl<A, B> From<(A, B)> for Pair<A, B> {
fn from((a, b): (A, B)) -> Self {
Self(a, b)
}
}
pub fn into_ptr<T>(value: T) -> *mut T {
debug_assert_eq!(size_of::<*mut T>(), size_of::<*mut c_void>());
let boxed = Box::new(value);
Box::into_raw(boxed)
}
pub unsafe fn from_ptr<T>(ptr: *mut T) -> T {
debug_assert!(!ptr.is_null());
debug_assert_eq!(size_of::<*mut T>(), size_of::<*mut c_void>());
*unsafe { Box::from_raw(ptr) }
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn cvec() {
let vec_in: Vec<usize> = vec![2, 5];
let c_vec = CVec::from(vec_in.clone());
let vec_out = c_vec.into_vec();
assert_eq!(vec_in, vec_out);
}
}