#![feature(str_from_raw_parts)]
#![warn(missing_docs)]
use std::{fmt::{self, Display, Formatter}, ops::Deref};
#[derive(Copy, Clone)]
#[repr(C)]
pub struct FFIStr<'a> {
	ptr: &'a u8,
	len: u32,
}
impl<'a> FFIStr<'a> {
	pub fn new(from: &'a str) -> Self {
		unsafe {
			Self {
				ptr: &*from.as_ptr(),
				len: from.len() as u32,
			}
		}
	}
	pub fn as_str(&self) -> &'a str {
		unsafe {
			core::str::from_raw_parts(self.ptr, self.len as usize)
		}
	}
}
impl Deref for FFIStr<'_> {
	type Target = str;
	fn deref(&self) -> &Self::Target {
		self.as_str()
	}
}
impl fmt::Debug for FFIStr<'_> {
	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
		write!(f, "\"{}\"", self.as_str())
	}
}
impl Display for FFIStr<'_> {
	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
		write!(f, "{}", self.as_str())
	}
}
impl<'a> From<&'a str> for FFIStr<'a> {
	fn from(value: &'a str) -> Self {
		Self::new(value)
	}
}
impl<'a> AsRef<str> for FFIStr<'a> {
	fn as_ref(&self) -> &str {
		self.as_str()
	}
}
impl Into<String> for FFIStr<'_> {
	fn into(self) -> String {
		self.to_string()
	}
}
#[repr(C)]
pub struct FFIString {
	ptr: *mut u8,
	len: u32,
	cap: u32,
}
impl FFIString {
	pub fn new(from: impl Into<String>) -> Self {
		let mut from = from.into();
		let output = Self {
			ptr: from.as_mut_ptr(),
			len: from.len() as u32,
			cap: from.capacity() as u32,
		};
		std::mem::forget(from);
		output
	}
	pub fn into_string(self) -> String {
		unsafe {
			let output = String::from_raw_parts(self.ptr, self.len as usize, self.cap as usize);
			std::mem::forget(self);
			output
		}
	}
	pub fn as_str(&self) -> &str {
		unsafe {
			core::str::from_raw_parts(self.ptr, self.len as usize)
		}
	}
}
impl Drop for FFIString {
	fn drop(&mut self) {
		unsafe {
			String::from_raw_parts(self.ptr, self.len as usize, self.cap as usize);
		}
	}
}
impl Deref for FFIString {
	type Target = str;
	fn deref(&self) -> &Self::Target {
		self.as_str()
	}
}
impl fmt::Debug for FFIString {
	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
		write!(f, "\"{}\"", self.as_str())
	}
}
impl Display for FFIString {
	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
		write!(f, "{}", self.as_str())
	}
}
impl From<String> for FFIString {
	fn from(value: String) -> Self {
		Self::new(value)
	}
}
impl AsRef<str> for FFIString {
	fn as_ref(&self) -> &str {
		self.as_str()
	}
}
impl Into<String> for FFIString {
	fn into(self) -> String {
		self.to_string()
	}
}
impl Clone for FFIString {
	fn clone(&self) -> Self {
		Self::new(self.to_string())
	}
}