@@ -221,9 +221,7 @@ impl CStr {
221221 /// # Examples
222222 ///
223223 /// ```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};
227225 ///
228226 /// extern "C" {
229227 /// fn my_string() -> *const c_char;
@@ -233,14 +231,26 @@ impl CStr {
233231 /// let slice = CStr::from_ptr(my_string());
234232 /// println!("string returned: {}", slice.to_str().unwrap());
235233 /// }
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) };
237246 /// ```
238247 ///
239248 /// [valid]: core::ptr#safety
240249 #[ inline]
241250 #[ must_use]
242251 #[ 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 {
244254 // SAFETY: The caller has provided a pointer that points to a valid C
245255 // string with a NUL terminator of size less than `isize::MAX`, whose
246256 // content remain valid and doesn't change for the lifetime of the
@@ -252,13 +262,29 @@ impl CStr {
252262 //
253263 // The cast from c_char to u8 is ok because a c_char is always one byte.
254264 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
258274 }
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 ) )
262288 }
263289 }
264290
0 commit comments