@@ -123,13 +123,14 @@ impl FromBytesWithNulError {
123123 const fn interior_nul ( pos : usize ) -> FromBytesWithNulError {
124124 FromBytesWithNulError { kind : FromBytesWithNulErrorKind :: InteriorNul ( pos) }
125125 }
126+
126127 const fn not_nul_terminated ( ) -> FromBytesWithNulError {
127128 FromBytesWithNulError { kind : FromBytesWithNulErrorKind :: NotNulTerminated }
128129 }
129130
130131 #[ doc( hidden) ]
131132 #[ unstable( feature = "cstr_internals" , issue = "none" ) ]
132- pub fn __description ( & self ) -> & str {
133+ pub const fn __description ( & self ) -> & str {
133134 match self . kind {
134135 FromBytesWithNulErrorKind :: InteriorNul ( ..) => {
135136 "data provided contains an interior nul byte"
@@ -139,6 +140,18 @@ impl FromBytesWithNulError {
139140 }
140141}
141142
143+ #[ stable( feature = "frombyteswithnulerror_impls" , since = "1.17.0" ) ]
144+ impl fmt:: Display for FromBytesWithNulError {
145+ #[ allow( deprecated, deprecated_in_future) ]
146+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
147+ f. write_str ( self . __description ( ) ) ?;
148+ if let FromBytesWithNulErrorKind :: InteriorNul ( pos) = self . kind {
149+ write ! ( f, " at byte pos {pos}" ) ?;
150+ }
151+ Ok ( ( ) )
152+ }
153+ }
154+
142155/// An error indicating that no nul byte was present.
143156///
144157/// A slice used to create a [`CStr`] must contain a nul byte somewhere
@@ -164,24 +177,45 @@ impl fmt::Debug for CStr {
164177 }
165178}
166179
167- #[ stable( feature = "cstr_default" , since = "1.10.0" ) ]
168- impl Default for & CStr {
169- fn default ( ) -> Self {
170- const SLICE : & [ c_char ] = & [ 0 ] ;
171- // SAFETY: `SLICE` is indeed pointing to a valid nul-terminated string.
172- unsafe { CStr :: from_ptr ( SLICE . as_ptr ( ) ) }
180+ /// Converts a string literal to a `&'static Cstr`.
181+ ///
182+ /// # Panics
183+ ///
184+ /// `cstr!` panics if the input contains any interior nul bytes.
185+ ///
186+ /// # Examples
187+ ///
188+ /// ```
189+ /// #![feature(cstr_macro)]
190+ ///
191+ /// use core::ffi::CStr;
192+ ///
193+ /// const HELLO: &CStr = cstr!("Hello, world!");
194+ /// assert_eq!(HELLO.to_bytes_with_nul(), b"Hello, world!\0");
195+ /// ```
196+ #[ macro_export]
197+ #[ unstable( feature = "cstr_macro" , issue = "101607" ) ]
198+ #[ rustc_diagnostic_item = "core_cstr_macro" ]
199+ macro_rules! cstr {
200+ ( $( $s: expr) ,* ) => {
201+ $crate:: ffi:: __cstr_macro_impl( concat!( $( $s, ) * "\0 " ) . as_bytes( ) )
173202 }
174203}
175204
176- #[ stable( feature = "frombyteswithnulerror_impls" , since = "1.17.0" ) ]
177- impl fmt:: Display for FromBytesWithNulError {
178- #[ allow( deprecated, deprecated_in_future) ]
179- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
180- f. write_str ( self . __description ( ) ) ?;
181- if let FromBytesWithNulErrorKind :: InteriorNul ( pos) = self . kind {
182- write ! ( f, " at byte pos {pos}" ) ?;
183- }
184- Ok ( ( ) )
205+ #[ unstable( feature = "cstr_macro" , issue = "101607" ) ]
206+ #[ doc( hidden) ]
207+ pub const fn __cstr_macro_impl ( bytes : & [ u8 ] ) -> & CStr {
208+ match CStr :: from_bytes_with_nul ( bytes) {
209+ Ok ( cstr) => cstr,
210+ Err ( err) => panic ! ( "{}" , err. __description( ) ) ,
211+ }
212+ }
213+
214+ #[ stable( feature = "cstr_default" , since = "1.10.0" ) ]
215+ #[ rustc_const_unstable( feature = "const_default_impls" , issue = "87864" ) ]
216+ impl const Default for & CStr {
217+ fn default ( ) -> Self {
218+ cstr ! ( )
185219 }
186220}
187221
0 commit comments