c_str_macro/
c_str.rs

1// Copyright 2017 Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
2// See the COPYRIGHT file at the top-level directory of this source tree.
3//
4// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7// option. This file may not be copied, modified, or distributed
8// except according to those terms.
9
10#![warn(clippy::all)]
11
12//! A macro to produce C-compatible string data from literals.
13//!
14//! In Rust code using FFI bindings, it is often necessary to pass in a static
15//! constant string that must follow the C string format, i.e. be terminated
16//! with a 0 byte. Rust string literals, unlike in C or C++, do not
17//! translate to implicitly null-terminated string data, so the terminating
18//! `"\0"` has to be explicitly present to make the string safe to pass
19//! to a C API. This is kludgy and can easily be forgotten.
20//!
21//! To alleviate this issue, this crate provides the `c_str!` macro that
22//! takes a Rust string literal, appends a terminating 0 byte, and casts
23//! the output value to a `std::ffi::CStr` reference.
24
25
26/// Produce a `CStr` reference out of a static string literal.
27///
28/// This macro provides a convenient way to use string literals in
29/// expressions where a `std::ffi::CStr` reference is accepted.
30/// The macro parameter does not need to end with `"\0"`, as the 0 byte is
31/// appended by the macro.
32///
33/// The lifetime of the output reference is inferred from the expansion
34/// site. This is always safe because the string is static and immutable.
35///
36/// # Example
37///
38/// ```rust
39/// use c_str_macro::c_str;
40///
41/// fn main() {
42///     let s = c_str!("Hello, world!");
43///     unsafe { libc::puts(s.as_ptr()) };
44/// }
45/// ```
46#[macro_export]
47macro_rules! c_str {
48    ($lit:expr) => {
49        // Currently, there is no working way to concatenate a byte string
50        // literal out of bytestring or string literals. Otherwise, we could
51        // use from_static_bytes and accept byte strings as well.
52        // See https://github.com/rust-lang/rfcs/pull/566
53        unsafe {
54            std::ffi::CStr::from_ptr(concat!($lit, "\0").as_ptr()
55                                     as *const std::os::raw::c_char)
56        }
57    }
58}