> +#[macro_export] > +/// Given a string constant _without_ embedded or trailing NULs, return > +/// a CStr. > +/// > +/// Needed for compatibility with Rust <1.77. > +macro_rules! c_str { > + ($str:expr) => {{ > + const STRING: &str = concat!($str, "\0"); > + const BYTES: &[u8] = STRING.as_bytes(); > + > + // "for" is not allowed in const context... oh well, > + // everybody loves some lisp. This could be turned into > + // a procedural macro if this is a problem; alternatively > + // Rust 1.72 makes CStr::from_bytes_with_nul a const function. > + const fn f(b: &[u8], i: usize) { > + if i == b.len() - 1 { > + } else if b[i] == 0 { > + panic!("c_str argument contains NUL") > + } else { > + f(b, i + 1) > + } > + } > + f(BYTES, 0); > + > + // SAFETY: absence of NULs apart from the final byte was checked > above > + unsafe { std::ffi::CStr::from_bytes_with_nul_unchecked(BYTES) } > + }}; > +} > +
It's not worth introducing the const_for crate for the loop, and I can't come up with a better solution. The current implementation is simple and effective, so for now, it's the best option for me. Reviewed-by: Zhao Liu <zhao1....@intel.com>