@@ -123,13 +123,14 @@ impl FromBytesWithNulError {
123
123
const fn interior_nul ( pos : usize ) -> FromBytesWithNulError {
124
124
FromBytesWithNulError { kind : FromBytesWithNulErrorKind :: InteriorNul ( pos) }
125
125
}
126
+
126
127
const fn not_nul_terminated ( ) -> FromBytesWithNulError {
127
128
FromBytesWithNulError { kind : FromBytesWithNulErrorKind :: NotNulTerminated }
128
129
}
129
130
130
131
#[ doc( hidden) ]
131
132
#[ unstable( feature = "cstr_internals" , issue = "none" ) ]
132
- pub fn __description ( & self ) -> & str {
133
+ pub const fn __description ( & self ) -> & str {
133
134
match self . kind {
134
135
FromBytesWithNulErrorKind :: InteriorNul ( ..) => {
135
136
"data provided contains an interior nul byte"
@@ -139,6 +140,18 @@ impl FromBytesWithNulError {
139
140
}
140
141
}
141
142
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
+
142
155
/// An error indicating that no nul byte was present.
143
156
///
144
157
/// A slice used to create a [`CStr`] must contain a nul byte somewhere
@@ -164,24 +177,45 @@ impl fmt::Debug for CStr {
164
177
}
165
178
}
166
179
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( ) )
173
202
}
174
203
}
175
204
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 ! ( )
185
219
}
186
220
}
187
221
0 commit comments