astd/ffi.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
//! This module provides access to FFI utilities not present in the standard
//! library, but very helfpul for working with interoperating with C APIs.
use std::ffi::{c_char, CStr, CString};
/// Creates a compile-time [`CStr`] object from a string literal.
///
/// This will statically verify the invariant that the [`CStr`] does not contain
/// any embedded nul character, and will also append the trailing nul terminator.
///
/// # Examples
///
/// ```rust
/// # use astd::ffi::cstr;
///
/// let cstr = cstr!("Hello world!");
/// ```
///
/// [`CStr`]: core::ffi::CStr
#[macro_export]
#[doc(hidden)]
macro_rules! cstr {
($e:expr) => {{
use core::ffi::CStr;
const S: &'static str = concat!($e, "\0");
const _IS_VALID_C_STR: [(); $e.len()] = [(); $crate::_null_terminated_length(S)];
// SAFETY: `from_bytes_with_nul_unchecked` asserts at compile-time that there
// cannot be any embedded nuls. This guarantees that safety is upheld, despite
// being an unsafe API.
const RESULT: &'static CStr = unsafe { &CStr::from_bytes_with_nul_unchecked(S.as_bytes()) };
RESULT
}};
}
#[doc(inline)]
pub use super::cstr;
/// A module containing [`CStr`] utilities and functionality.
///
/// [`CStr`]: std::ffi::CStr
pub mod cstr {
use super::*;
/// Constructs a [`CStr`] reference from a [`c_char`] slice which contains a
/// nul-terminator.
///
/// # Parameters
///
/// * `slice` - a slice of [`c_char`] that ends with a nul-terminator.
///
/// # Safety
///
/// This function requires that `slice` be nul-terminated.
#[inline]
pub const unsafe fn from_char_slice_unchecked(slice: &[c_char]) -> &CStr {
// SAFETY: c_char (i8) and u8 are interconvertible
let s = unsafe { &*(slice as *const _ as *const [u8]) };
CStr::from_bytes_with_nul_unchecked(s)
}
}
/// A module containing [`CString`] utilities and functionality.
///
/// [`CString`]: std::ffi::CString
pub mod cstring {
use super::*;
/// Constructs a [`CString`] from a non null-terminated [`str`] reference.
///
/// # Parameters
///
/// * `string` - a standar rust string.
///
/// # Safety
///
/// `string` must not contain any interior nul bytes.
pub unsafe fn from_str(string: &str) -> CString {
let bytes = string.as_bytes().to_owned();
unsafe { CString::from_vec_unchecked(bytes) }
}
}