@@ -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