::byte_strings::c_str! => zero-cost C string literals for safe FFI

#1

Since there was currently no way in stable Rust to have C string literals, I have released the following crate.

It features

  • concat_bytes!, which already existed in the ecosystem although I don’t think it did in stable Rust;
  • c_str!(...), which is like
    unsafe {
      use ::std::ffi::CStr;
      CStr::from_bytes_with_nul_unchecked(
        concat_bytes!(..., b"\0")
      )
    }
    
    but in a safe (it does check that the input literals do not contain null bytes) and const manner.

byte-strings-rs

Rust zero-cost byte strings manipulation, for a better and safer FFI

Repository
Latest version
Documentation
License

Example

Featuring the c_str! macro to create valid C string literals with literally no
runtime cost!

/// Some lib
mod safe {
    use ::std::{
        ffi::CStr,
        os::raw::{c_char, c_int},
    };

    /// private unsafe C FFI
    mod ffi { use super::*; extern "C" {
        pub fn puts (_: *const c_char) -> c_int;
    }}

    /// lib API: safe Rust wrapper => uses `CStr`
    pub fn puts (message: &'_ CStr) -> i32
    {
        unsafe {
            ffi::puts(message.as_ptr()) as i32
        }
    }
}

fn main ()
{
    use ::byte_strings::c_str;

    dbg!(safe::puts(
        c_str!(
            "Hello, ",
            "World!",
        ) // No runtime error, no runtime cost
    ));
}

Note:

the crate uses procedural macros under the hood, and those are not as smooth/ergonomic to use as macros by example (macro_rules!) are.

For instance, ::byte_strings::as_bytes!(stringify!(...)) does not currently work.

If you have an idea to fix this that does not involve coding stringify! logic all over again, I’m all ears!
3 Likes