reoxide 0.7.0

Rust-bindings for the ReOxide decompiler extension framework
Documentation
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>>;

    /// Destroyes the allocated vector
    ///
    /// # Safety
    ///
    /// The caller must ensure that `vec` is a valid pointer to a C++
    /// vector. That means, `StdVectorItem::new()` for the **specific
    /// generic specialization** created this vector.
    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;
}