use core::ffi::{c_char, c_void};
use core::marker::PhantomData;
use core::ops::Deref;
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct RawBytes {
pub data: *const u8,
pub size: usize,
pub owner: *mut c_void,
}
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct RawCString {
pub chars: *const c_char,
pub length: usize,
pub owner: *mut c_void,
}
extern "C" {
fn whiteout_Bytes_free(buf: RawBytes);
fn whiteout_CString_free(s: RawCString);
}
pub struct Bytes {
raw: RawBytes,
}
impl Bytes {
pub(crate) unsafe fn from_raw(raw: RawBytes) -> Option<Self> {
if raw.owner.is_null() {
None
} else {
Some(Bytes { raw })
}
}
pub(crate) fn empty() -> Self {
Bytes {
raw: RawBytes {
data: core::ptr::null(),
size: 0,
owner: core::ptr::null_mut(),
},
}
}
pub fn to_vec(&self) -> Vec<u8> {
self.as_ref().to_vec()
}
pub fn is_empty(&self) -> bool {
self.raw.size == 0
}
pub fn len(&self) -> usize {
self.raw.size
}
}
impl Deref for Bytes {
type Target = [u8];
fn deref(&self) -> &[u8] {
if self.raw.data.is_null() || self.raw.size == 0 {
return &[];
}
unsafe { core::slice::from_raw_parts(self.raw.data, self.raw.size) }
}
}
impl AsRef<[u8]> for Bytes {
fn as_ref(&self) -> &[u8] {
self
}
}
impl Drop for Bytes {
fn drop(&mut self) {
if self.raw.owner.is_null() {
return; }
unsafe { whiteout_Bytes_free(self.raw) }
}
}
impl core::fmt::Debug for Bytes {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Bytes").field("len", &self.len()).finish()
}
}
unsafe impl Send for Bytes {}
unsafe impl Sync for Bytes {}
pub(crate) unsafe fn take_string(raw: RawCString) -> String {
if raw.chars.is_null() {
unsafe { whiteout_CString_free(raw) };
return String::new();
}
let bytes = unsafe { core::slice::from_raw_parts(raw.chars as *const u8, raw.length) };
let out = String::from_utf8_lossy(bytes).into_owned();
unsafe { whiteout_CString_free(raw) };
out
}
pub(crate) unsafe fn take_string_opt(raw: RawCString) -> Option<String> {
if raw.owner.is_null() {
return None;
}
Some(unsafe { take_string(raw) })
}
pub struct BorrowedSlice<'a> {
ptr: *const u8,
len: usize,
_owner: PhantomData<&'a ()>,
}
impl<'a> BorrowedSlice<'a> {
pub(crate) unsafe fn new(ptr: *const u8, len: usize) -> Self {
BorrowedSlice {
ptr,
len,
_owner: PhantomData,
}
}
}
impl Deref for BorrowedSlice<'_> {
type Target = [u8];
fn deref(&self) -> &[u8] {
if self.ptr.is_null() || self.len == 0 {
return &[];
}
unsafe { core::slice::from_raw_parts(self.ptr, self.len) }
}
}
impl core::fmt::Debug for BorrowedSlice<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("BorrowedSlice")
.field("len", &self.len)
.finish()
}
}
pub struct Ref<'a, T> {
inner: core::mem::ManuallyDrop<T>,
_owner: PhantomData<&'a T>,
}
impl<'a, T> Ref<'a, T> {
pub(crate) unsafe fn new(value: T) -> Self {
Ref {
inner: core::mem::ManuallyDrop::new(value),
_owner: PhantomData,
}
}
}
impl<T> Deref for Ref<'_, T> {
type Target = T;
fn deref(&self) -> &T {
&self.inner
}
}
impl<T: core::fmt::Debug> core::fmt::Debug for Ref<'_, T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
(**self).fmt(f)
}
}
pub struct RefMut<'a, T> {
inner: core::mem::ManuallyDrop<T>,
_owner: PhantomData<&'a mut T>,
}
impl<'a, T> RefMut<'a, T> {
pub(crate) unsafe fn new(value: T) -> Self {
RefMut {
inner: core::mem::ManuallyDrop::new(value),
_owner: PhantomData,
}
}
}
impl<T> Deref for RefMut<'_, T> {
type Target = T;
fn deref(&self) -> &T {
&self.inner
}
}
impl<T> core::ops::DerefMut for RefMut<'_, T> {
fn deref_mut(&mut self) -> &mut T {
&mut self.inner
}
}
impl<T: core::fmt::Debug> core::fmt::Debug for RefMut<'_, T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
(**self).fmt(f)
}
}