cmajor 0.7.0

Rust bindings for the Cmajor JIT engine.
Documentation
use std::{
    borrow::Cow,
    ffi::{c_char, c_int},
    ptr::null_mut,
};

#[repr(C)]
struct CmajorStringVTable {
    add_ref: unsafe extern "system" fn(*mut CmajorString) -> c_int,
    release: unsafe extern "system" fn(*mut CmajorString) -> c_int,
    ref_count: unsafe extern "system" fn(*const CmajorString) -> c_int,
    begin: unsafe extern "system" fn(*const CmajorString) -> *const c_char,
    end: unsafe extern "system" fn(*const CmajorString) -> *const c_char,
}

#[repr(C)]
pub struct CmajorString {
    vtable: *const CmajorStringVTable,
}

pub struct CmajorStringPtr {
    string: *mut CmajorString,
}

impl Drop for CmajorStringPtr {
    fn drop(&mut self) {
        unsafe { ((*(*self.string).vtable).release)(self.string) };
    }
}

impl CmajorStringPtr {
    pub unsafe fn new(string: *mut CmajorString) -> Self {
        assert_ne!(string, null_mut());
        Self { string }
    }

    pub fn to_string(&self) -> Cow<'_, str> {
        let begin = unsafe { ((*(*self.string).vtable).begin)(self.string) };
        let end = unsafe { ((*(*self.string).vtable).end)(self.string) };

        let len = unsafe { end.offset_from(begin) };
        assert!(len >= 0);

        let slice = unsafe { std::slice::from_raw_parts(begin.cast(), len as usize) };

        String::from_utf8_lossy(slice)
    }
}