On Sat May 24, 2025 at 10:33 PM CEST, Tamir Duberstein wrote:
-/// Creates a new [`CStr`] from a string literal. +/// Creates a static C string wrapper at compile time. /// -/// The string literal should not contain any `NUL` bytes. +/// Rust supports C string literals since Rust 1.77, and they should be used instead of this macro +/// where possible. This macro exists to allow static *non-literal* C strings to be created at +/// compile time. This is most often used in other macros. +/// +/// # Panics +/// +/// This macro panics if the operand contains an interior `NUL` byte. /// /// # Examples /// /// ``` -/// # use kernel::c_str; +/// # use kernel::c_str_avoid_literals; /// # use kernel::str::CStr; -/// const MY_CSTR: &CStr = c_str!("My awesome CStr!"); +/// const MY_CSTR: &CStr = c_str_avoid_literals!(concat!(file!(), ":", line!(), ": My CStr!")); /// ``` #[macro_export] -macro_rules! c_str { +macro_rules! c_str_avoid_literals {
I don't like this name, how about `concat_to_c_str` or `concat_with_nul`?
This macro also is useful from macros that have a normal string literal, but can't turn it into a `c""` one.
- // NB: we could write `($str:lit) => compile_error!("use a C string literal instead");` here but
- // that would trigger when the literal is at the top of several macro expansions. That would be
- // too limiting to macro authors, so we rely on the name as a hint instead. ($str:expr) => {{
const S: &str = concat!($str, "\0");
const C: &$crate::str::CStr = match $crate::str::CStr::from_bytes_with_nul(S.as_bytes()) {
Ok(v) => v,
Err(_) => panic!("string contains interior NUL"),
};
const S: &'static str = concat!($str, "\0");
const C: &'static $crate::str::CStr =
match $crate::str::CStr::from_bytes_with_nul(S.as_bytes()) {
Why is this still our CStr?
Ok(v) => v,
Err(err) => {
let _: core::ffi::FromBytesWithNulError = err;
Is this really necessary?
--- Cheers, Benno
panic!("string contains interior NUL")
}
}};}; C
}