use std::mem::MaybeUninit;
pub use crate::util::{ExternAlloc, ExternDrop};
opaque!(StdString);
impl StdString {
pub fn from_str(s: &str) -> ExternAlloc<StdString> {
unsafe {
let s = StdString_from_bytes(s.as_ptr(), s.len());
ExternAlloc::from_raw(s)
}
}
#[must_use]
pub fn from_utf8(&self) -> Result<&str, std::str::Utf8Error> {
let byte_slice = unsafe {
let mut len = MaybeUninit::uninit();
let data = StdString_get_data(self, len.as_mut_ptr());
std::slice::from_raw_parts(data, len.assume_init())
};
std::str::from_utf8(byte_slice)
}
pub fn clone(&self) -> ExternAlloc<StdString> {
unsafe {
let s = StdString_clone(self);
ExternAlloc::from_raw(s)
}
}
}
unsafe impl ExternDrop for StdString {
fn destroy(obj: ::core::ptr::NonNull<Self>) {
unsafe { StdString_delete(obj.as_ptr()) }
}
}
#[repr(C)]
pub struct StdVector<T: StdVectorItem + ?Sized> {
_data: (),
_gen: ::core::marker::PhantomData<(*mut T, ::core::marker::PhantomPinned)>,
}
unsafe impl<T> ExternDrop for StdVector<T> where T: StdVectorItem + ?Sized {
fn destroy(obj: std::ptr::NonNull<Self>) {
unsafe { T::destroy_vec(obj.as_ptr()) }
}
}
impl<T> StdVector<T> where T: StdVectorItem {
pub fn new() -> ExternAlloc<StdVector<T>> {
T::new()
}
pub fn push(&mut self, item: T) {
T::push(self, item)
}
pub fn len(&self) -> usize {
T::len(self)
}
pub fn clear(&mut self) {
T::clear(self)
}
pub fn extend(&mut self, items: &[T]) {
T::extend(self, items)
}
}
impl<T> ::core::ops::Deref for StdVector<T> where T: StdVectorItem {
type Target = [T];
fn deref(&self) -> &Self::Target {
unsafe { std::slice::from_raw_parts(T::data(self), T::len(self)) }
}
}
pub unsafe trait StdVectorItem: Sized {
fn new() -> ExternAlloc<StdVector<Self>>;
unsafe fn destroy_vec(vec: *mut StdVector<Self>);
fn data(vec: &StdVector<Self>) -> *const Self;
fn len(vec: &StdVector<Self>) -> usize;
fn clear(vec: &mut StdVector<Self>);
fn push(vec: &mut StdVector<Self>, item: Self);
fn extend(vec: &mut StdVector<Self>, items: &[Self]);
}
#[link(name = "reoxide")]
unsafe extern "C-unwind" {
fn StdString_from_bytes(s: *const u8, len: usize) -> *mut StdString;
fn StdString_get_data(this: *const StdString, len: *mut usize) -> *const u8;
fn StdString_delete(this: *mut StdString);
fn StdString_clone(this: *const StdString) -> *mut StdString;
}