//! Foreign function interface utilities. use crate::err::*; pub use std::{ffi::*, os::raw::*, ptr::{null, null_mut}}; /// Creates a C string from a literal. /// /// This is done by concatenating a null byte with the string and converting it /// to a pointer. /// /// # Examples /// /// ``` /// use maraiah::c_str; /// /// let st = c_str!("test"); /// /// assert!(!st.is_null()); /// /// unsafe { /// assert_eq!(std::slice::from_raw_parts(st, 5), &[116, 101, 115, 116, 0]); /// } /// ``` #[macro_export] macro_rules! c_str { ($s:expr) => { concat!($s, "\0").as_ptr() as $crate::ffi::NT }; } /// Returns [`null`] as a [`*const c_void`]. /// /// [`null`]: fn.null.html /// [`*const c_void`]: enum.c_void.html #[inline] pub const fn null_void() -> *const c_void {null()} /// Returns [`null_mut`] as a [`*mut c_void`]. /// /// [`null_mut`]: fn.null_mut.html /// [`*mut c_void`]: enum.c_void.html #[inline] pub const fn null_mut_void() -> *mut c_void {null_mut()} impl CStringVec { /// Creates a new `CStringVec` from an iterator. #[inline] pub fn new_from_iter<'a, I>(it: I) -> ResultS where I: Iterator { let mut v = Self::default(); for st in it { v.push(CString::new(st)?); } Ok(v) } /// Pushes a new `CString`. #[inline] pub fn push(&mut self, st: CString) { self.cv.insert(self.cv.len() - 1, st.as_ptr()); self.sv.push(st); } /// Returns the FFI pointer. #[inline] pub fn as_ptr(&self) -> *const NT {self.cv.as_ptr()} /// Returns the FFI pointer mutably. #[inline] pub fn as_mut_ptr(&mut self) -> *mut NT {self.cv.as_mut_ptr()} } impl Default for CStringVec { /// Creates a new empty CStringVec. #[inline] fn default() -> Self {Self{sv: Vec::new(), cv: vec![null()]}} } /// An owned null-terminated string vector. #[derive(Debug)] pub struct CStringVec { sv: Vec, cv: Vec, } /// A null-terminated byte string pointer. pub type NT = *const c_char; // EOF