#![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())
}
}