@@ -177,11 +177,7 @@ impl fmt::Debug for CStr {
177177 }
178178}
179179
180- /// Converts a string literal to a `&'static Cstr`.
181- ///
182- /// # Panics
183- ///
184- /// `cstr!` panics if the input contains any interior nul bytes.
180+ /// Converts a string or byte literal to a `&'static Cstr`.
185181///
186182/// # Examples
187183///
@@ -193,18 +189,60 @@ impl fmt::Debug for CStr {
193189/// const HELLO: &CStr = cstr!("Hello, world!");
194190/// assert_eq!(HELLO.to_bytes_with_nul(), b"Hello, world!\0");
195191/// ```
192+ ///
193+ /// If the given expression contains any interior nul bytes this will
194+ /// result in a compilation error:
195+ ///
196+ /// ```compile_fail
197+ /// #![feature(const_cstr_from_bytes)]
198+ ///
199+ /// use core::ffi::CStr;
200+ ///
201+ /// const HELLO: &CStr = cstr!("Hello, world!\0"); // compile fail!
202+ /// ```
196203#[ macro_export]
197204#[ unstable( feature = "cstr_macro" , issue = "101607" ) ]
198205#[ rustc_diagnostic_item = "core_cstr_macro" ]
199206macro_rules! cstr {
200- ( $( $s: expr) ,* ) => {
201- $crate:: ffi:: __cstr_macro_impl( concat!( $( $s, ) * "\0 " ) . as_bytes( ) )
207+ ( ) => {
208+ cstr!( "" )
209+ } ;
210+ ( $s: literal) => { {
211+ const BYTES : & [ u8 ] = $crate:: ffi:: __cstr_macro_impl_as_bytes( $s) ;
212+ const BYTES_WITH_NUL : [ u8 ; { BYTES . len( ) + 1 } ] =
213+ $crate:: ffi:: __cstr_macro_impl_to_bytes_with_nul( BYTES ) ;
214+ const CSTR : & $crate:: ffi:: CStr =
215+ $crate:: ffi:: __cstr_macro_impl_from_bytes_with_nul( & BYTES_WITH_NUL ) ;
216+ CSTR
217+ } } ;
218+ }
219+
220+ #[ unstable( feature = "cstr_macro" , issue = "101607" ) ]
221+ #[ doc( hidden) ]
222+ pub const fn __cstr_macro_impl_as_bytes < T > ( v : & T ) -> & [ u8 ]
223+ where
224+ T : ?Sized + ~const AsRef < [ u8 ] > + ~const crate :: marker:: Destruct ,
225+ {
226+ v. as_ref ( )
227+ }
228+
229+ #[ unstable( feature = "cstr_macro" , issue = "101607" ) ]
230+ #[ doc( hidden) ]
231+ pub const fn __cstr_macro_impl_to_bytes_with_nul < const N : usize > ( bytes : & [ u8 ] ) -> [ u8 ; N ] {
232+ let mut bytes_with_nul = [ 0 ; N ] ;
233+
234+ let mut i = 0 ;
235+ while i < bytes. len ( ) {
236+ bytes_with_nul[ i] = bytes[ i] ;
237+ i += 1 ;
202238 }
239+
240+ bytes_with_nul
203241}
204242
205243#[ unstable( feature = "cstr_macro" , issue = "101607" ) ]
206244#[ doc( hidden) ]
207- pub const fn __cstr_macro_impl ( bytes : & [ u8 ] ) -> & CStr {
245+ pub const fn __cstr_macro_impl_from_bytes_with_nul ( bytes : & [ u8 ] ) -> & CStr {
208246 match CStr :: from_bytes_with_nul ( bytes) {
209247 Ok ( cstr) => cstr,
210248 Err ( err) => panic ! ( "{}" , err. __description( ) ) ,
0 commit comments