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) }
  }
}