ffi-std 0.1.0

FFI-safe versions of some std datastructures.
//! FFI-safe string slice (&str). Pointer first, then length.

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

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

#[repr(C)]
pub struct FFIStr<'a> {
	ptr: *mut u8,
	len: usize,
	_ph: PhantomData<&'a str>
}

copyclone!(FFIStr<'a;>);

rawparts!(FFIStr<'a;>; ptr: *mut u8, len: usize; _ph: PhantomData); debug!(FFIStr<'a;>);

from!(FFIStr<'a;> => &'a str; to_str);

impl<'a> FFIStr<'a> {
	pub fn new(x: &'a str) -> Frozen<Self> {
		Frozen::new(Self {
			ptr: x.as_ptr() as *mut _,
			len: x.len(),
			_ph: PhantomData
		})
	}

	pub fn new_mut(x: &'a mut str) -> Self {
		Self {
			ptr: x.as_mut_ptr(),
			len: x.len(),
			_ph: PhantomData
		}
	}

	pub fn to_str(self) -> &'a str {
		unsafe {
			std::str::from_utf8_unchecked(std::slice::from_raw_parts(self.ptr, self.len))
		}
	}

	pub fn to_str_mut(self) -> &'a mut str {
		unsafe {
			std::str::from_utf8_unchecked_mut(std::slice::from_raw_parts_mut(self.ptr, self.len))
		}
	}
}

impl<'a> Deref for FFIStr<'a> {
	type Target = str;

	fn deref(&self) -> &str {
		self.to_str()
	}
}

impl<'a> DerefMut for FFIStr<'a> {
	fn deref_mut(&mut self) -> &mut str {
		self.to_str_mut()
	}
}