@@ -177,11 +177,7 @@ impl fmt::Debug for CStr {
177
177
}
178
178
}
179
179
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`.
185
181
///
186
182
/// # Examples
187
183
///
@@ -193,18 +189,60 @@ impl fmt::Debug for CStr {
193
189
/// const HELLO: &CStr = cstr!("Hello, world!");
194
190
/// assert_eq!(HELLO.to_bytes_with_nul(), b"Hello, world!\0");
195
191
/// ```
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
+ /// ```
196
203
#[ macro_export]
197
204
#[ unstable( feature = "cstr_macro" , issue = "101607" ) ]
198
205
#[ rustc_diagnostic_item = "core_cstr_macro" ]
199
206
macro_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 ;
202
238
}
239
+
240
+ bytes_with_nul
203
241
}
204
242
205
243
#[ unstable( feature = "cstr_macro" , issue = "101607" ) ]
206
244
#[ 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 {
208
246
match CStr :: from_bytes_with_nul ( bytes) {
209
247
Ok ( cstr) => cstr,
210
248
Err ( err) => panic ! ( "{}" , err. __description( ) ) ,
0 commit comments