[−][src]Macro byte_strings::c_str
Converts into a valid C string at compile time (no runtime cost)
This macro takes any number of comma-separated byte string literals, or string literals, and evaluates to (a static reference to) a C string made of all the bytes of the given literals concatenated left-to-right, with an appended null byte terminator.
Hence the macro evaluates to the type &'static ::std::ffi::CStr
.
Example
use ::byte_strings::c_str; assert_eq!( c_str!("Hello, ", "World!"), ::std::ffi::CStr::from_bytes_with_nul(b"Hello, World!\0").unwrap(), )
Compilation error
For the C string to be what should be expected, the arguments cannot contain any null byte. Else the compilation will fail.
Counter example
// error: input literals cannot contain null bytes let Hello_W = c_str!("Hello, ", "W\0rld!");
Macro expansion:
For those curious, c_str!(b"Hello, ", b"World!")
expands to:
{ union transmute { src: &'static [u8], dst: &'static ::std::ffi::CStr, } const transmute_is_sound_guard: [(); ::std::mem::size_of::<&'static [u8]>() ] = [(); ::std::mem::size_of::<&'static ::std::ffi::CStr>() ]; const __byte_strings__c_str: &'static ::std::ffi::CStr = unsafe { (transmute { src: b"Hello, World!\0" }).dst }; __byte_strings__c_str }
This trick is needed to circumvent the current restriction of procedural macros being able to expand to items only.
Since ::std::mem::transmute
is not a const fn
, union
transmutation
had to be used, although it allows using different sizes. To prevent
Undefined Behaviour, a size-check guard using arrays was added.