ezffi 0.1.1

Generate C-FFI bindings from Rust types/functions via a single proc-macro attribute
use ezffi_macros::{export, export_extern_type, wrap_methods};

use crate::{CRefIntoRust, RustRefIntoC};

export_extern_type!(String);

#[doc(hidden)]
#[repr(C)]
#[derive(Clone, Copy)]
pub struct EzffiStr {
    len: usize,
    ptr: *mut u8,
}

impl RustRefIntoC<()> for str {
    type C = EzffiStr;

    unsafe fn ref_into_c(&self) -> EzffiStr {
        EzffiStr {
            ptr: self.as_ptr() as *mut u8,
            len: self.len(),
        }
    }
}

impl CRefIntoRust<str> for EzffiStr {
    unsafe fn into_rust(&self) -> &str {
        let slice = unsafe { core::slice::from_raw_parts(self.ptr, self.len) };
        unsafe { core::str::from_utf8_unchecked(slice) }
    }

    unsafe fn into_rust_mut(&mut self) -> &mut str {
        let slice = unsafe { core::slice::from_raw_parts_mut(self.ptr, self.len) };
        unsafe { core::str::from_utf8_unchecked_mut(slice) }
    }
}

wrap_methods!(String {
    fn new() -> String;
    fn with_capacity(capacity: usize) -> String;
    fn from(s: &str) -> String;
    fn len(&self) -> usize;
    fn is_empty(&self) -> bool;
    fn capacity(&self) -> usize;
    fn clear(&mut self);
    fn reserve(&mut self, additional: usize);
    fn truncate(&mut self, new_len: usize);
    fn shrink_to_fit(&mut self);
    fn push_str(&mut self, s: &str);
    fn insert_str(&mut self, idx: usize, s: &str);
});

#[doc(hidden)]
#[export]
pub fn string_eq_str(s: &String, other: &str) -> bool {
    s == other
}