sea-orm-ffi 0.1.3

Compatibility layer for Sea-ORM when crossing a Rust-to-Rust FFI boundary
Documentation
use crate::option;
use std::{
	fmt::{self, Debug, Display, Formatter},
	mem::ManuallyDrop,
	slice
};

/// A [`String`] pointer that is FFI-safe.
#[repr(C)]
pub(crate) struct StringPtr {
	ptr: *mut u8,
	len: usize,
	cap: usize
}

impl StringPtr {
	/// Create a new pointer.
	///
	/// This calls [`String::into_raw_parts()`] and stores the pointer, length and
	/// capacity in a C-ABI-compatible layout.
	pub(crate) fn new(s: String) -> Self {
		let (ptr, len, cap) = s.into_raw_parts();
		Self { ptr, len, cap }
	}

	/// Borrow the [`str`] pointed to by this pointer.
	///
	/// This calls [`slice::from_raw_parts`] and [`str::from_utf8_unchecked`].
	pub(crate) fn as_str(&self) -> &str {
		unsafe { str::from_utf8_unchecked(slice::from_raw_parts(self.ptr, self.len)) }
	}

	/// Return the [`String`] this pointer points to.
	///
	/// This calls [`String::from_raw_parts()`].
	pub(crate) fn into_string(self) -> String {
		let this = ManuallyDrop::new(self);
		unsafe { String::from_raw_parts(this.ptr, this.len, this.cap) }
	}
}

impl AsRef<str> for StringPtr {
	fn as_ref(&self) -> &str {
		self.as_str()
	}
}

impl Display for StringPtr {
	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
		Display::fmt(self.as_str(), f)
	}
}

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

impl Drop for StringPtr {
	fn drop(&mut self) {
		drop(unsafe { String::from_raw_parts(self.ptr, self.len, self.cap) });
	}
}

impl From<String> for StringPtr {
	fn from(value: String) -> Self {
		Self::new(value)
	}
}

impl From<StringPtr> for String {
	fn from(value: StringPtr) -> Self {
		value.into_string()
	}
}

unsafe impl Send for StringPtr {}

unsafe impl Sync for StringPtr {}

option!(StringPtr);