@@ -221,9 +221,7 @@ impl CStr {
221
221
/// # Examples
222
222
///
223
223
/// ```ignore (extern-declaration)
224
- /// # fn main() {
225
- /// use std::ffi::CStr;
226
- /// use std::os::raw::c_char;
224
+ /// use std::ffi::{c_char, CStr};
227
225
///
228
226
/// extern "C" {
229
227
/// fn my_string() -> *const c_char;
@@ -233,14 +231,26 @@ impl CStr {
233
231
/// let slice = CStr::from_ptr(my_string());
234
232
/// println!("string returned: {}", slice.to_str().unwrap());
235
233
/// }
236
- /// # }
234
+ /// ```
235
+ ///
236
+ /// ```
237
+ /// #![feature(const_cstr_methods)]
238
+ ///
239
+ /// use std::ffi::{c_char, CStr};
240
+ ///
241
+ /// const HELLO_PTR: *const c_char = {
242
+ /// const BYTES: &[u8] = b"Hello, world!\0";
243
+ /// BYTES.as_ptr().cast()
244
+ /// };
245
+ /// const HELLO: &CStr = unsafe { CStr::from_ptr(HELLO_PTR) };
237
246
/// ```
238
247
///
239
248
/// [valid]: core::ptr#safety
240
249
#[ inline]
241
250
#[ must_use]
242
251
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
243
- pub unsafe fn from_ptr < ' a > ( ptr : * const c_char ) -> & ' a CStr {
252
+ #[ rustc_const_unstable( feature = "const_cstr_methods" , issue = "101719" ) ]
253
+ pub const unsafe fn from_ptr < ' a > ( ptr : * const c_char ) -> & ' a CStr {
244
254
// SAFETY: The caller has provided a pointer that points to a valid C
245
255
// string with a NUL terminator of size less than `isize::MAX`, whose
246
256
// content remain valid and doesn't change for the lifetime of the
@@ -252,13 +262,29 @@ impl CStr {
252
262
//
253
263
// The cast from c_char to u8 is ok because a c_char is always one byte.
254
264
unsafe {
255
- extern "C" {
256
- /// Provided by libc or compiler_builtins.
257
- fn strlen ( s : * const c_char ) -> usize ;
265
+ const fn strlen_ct ( s : * const c_char ) -> usize {
266
+ let mut len = 0 ;
267
+
268
+ // SAFETY: Outer caller has provided a pointer to a valid C string.
269
+ while unsafe { * s. add ( len) } != 0 {
270
+ len += 1 ;
271
+ }
272
+
273
+ len
258
274
}
259
- let len = strlen ( ptr) ;
260
- let ptr = ptr as * const u8 ;
261
- CStr :: from_bytes_with_nul_unchecked ( slice:: from_raw_parts ( ptr, len as usize + 1 ) )
275
+
276
+ fn strlen_rt ( s : * const c_char ) -> usize {
277
+ extern "C" {
278
+ /// Provided by libc or compiler_builtins.
279
+ fn strlen ( s : * const c_char ) -> usize ;
280
+ }
281
+
282
+ // SAFETY: Outer caller has provided a pointer to a valid C string.
283
+ unsafe { strlen ( s) }
284
+ }
285
+
286
+ let len = intrinsics:: const_eval_select ( ( ptr, ) , strlen_ct, strlen_rt) ;
287
+ Self :: from_bytes_with_nul_unchecked ( slice:: from_raw_parts ( ptr. cast ( ) , len + 1 ) )
262
288
}
263
289
}
264
290
0 commit comments