ffi-std 0.1.0

FFI-safe versions of some std datastructures.
//! FFI-safe Vec<T>. Pointer first, then length, then capacity.

use std::ops::{Deref, DerefMut};

use std::mem;
use std::mem::ManuallyDrop;
use std::marker::PhantomData;

use std::fmt;
use std::fmt::{Debug, Formatter};

use crate::{Frozen, from, rawparts};

#[repr(C)]
pub struct FFIVec<T> {
	ptr: *mut T,
	len: usize,
	cap: usize
}

rawparts!(FFIVec<;T>; ptr: *mut T, len: usize, cap: usize);

from!(FFIVec<;T> => Vec<T>; to_vec);

impl<T: Debug> Debug for FFIVec<T> {
	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
		Debug::fmt(&self.as_vec(), f)
	}
}

impl<T> FFIVec<T> {
	pub fn new(mut x: Vec<T>) -> Self {
		let s = Self {
			ptr: x.as_mut_ptr(),
			len: x.len(),
			cap: x.capacity()
		};
		mem::forget(x);
		s
	}
	pub fn to_vec(self) -> Vec<T> {
		unsafe {
			Vec::from_raw_parts(self.ptr, self.len, self.cap)
		}
	}

	pub fn as_vec<'a>(&'a self) -> Frozen<AsVec<'a, T>> {
		unsafe {
			Frozen::new(AsVec::new(Vec::from_raw_parts(self.ptr, self.len, self.cap)))
		}
	}

	pub fn as_vec_mut<'a>(&'a mut self) -> AsVec<'a, T> {
		unsafe {
			AsVec::new(Vec::from_raw_parts(self.ptr, self.len, self.cap))
		}
	}
}

impl<T> Drop for FFIVec<T> {
	fn drop(&mut self) {
		unsafe {
			Vec::from_raw_parts(self.ptr, self.len, self.cap);
		}
	}
}

pub struct AsVec<'a, T> {
	vec: ManuallyDrop<Vec<T>>,
	_ph: PhantomData<&'a FFIVec<T>>
}

impl<'a, T> Deref for AsVec<'a, T> {
	type Target = ManuallyDrop<Vec<T>>;

	fn deref(&self) -> &ManuallyDrop<Vec<T>> {
		&self.vec
	}
}

impl<'a, T> DerefMut for AsVec<'a, T> {
	fn deref_mut(&mut self) -> &mut ManuallyDrop<Vec<T>> {
		&mut self.vec
	}
}

impl<'a, T: Debug> Debug for AsVec<'a, T> {
	fn fmt(&self, f: &mut Formatter) -> fmt::Result {
		Debug::fmt(&*self.vec, f)
	}
}

impl<'a, T> AsVec<'a, T> {
	fn new(vec: Vec<T>) -> Self {
		Self { vec: ManuallyDrop::new(vec), _ph: PhantomData }
	}
}