Skip to content

Commit 328f817

Browse files
committed
Make CStr::from_ptr const.
1 parent e6ce562 commit 328f817

File tree

1 file changed

+25
-7
lines changed

1 file changed

+25
-7
lines changed

library/core/src/ffi/c_str.rs

+25-7
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,9 @@ impl CStr {
240240
#[inline]
241241
#[must_use]
242242
#[stable(feature = "rust1", since = "1.0.0")]
243-
pub unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr {
243+
#[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")]
244+
#[rustc_allow_const_fn_unstable(const_eval_select)]
245+
pub const unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr {
244246
// SAFETY: The caller has provided a pointer that points to a valid C
245247
// string with a NUL terminator of size less than `isize::MAX`, whose
246248
// content remain valid and doesn't change for the lifetime of the
@@ -252,13 +254,29 @@ impl CStr {
252254
//
253255
// The cast from c_char to u8 is ok because a c_char is always one byte.
254256
unsafe {
255-
extern "C" {
256-
/// Provided by libc or compiler_builtins.
257-
fn strlen(s: *const c_char) -> usize;
257+
const fn strlen_ct(s: *const c_char) -> usize {
258+
let mut len = 0;
259+
260+
// SAFETY: Outer caller has provided a pointer to a valid C string.
261+
while unsafe { *s.add(len) } != 0 {
262+
len += 1;
263+
}
264+
265+
len
258266
}
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))
267+
268+
fn strlen_rt(s: *const c_char) -> usize {
269+
extern "C" {
270+
/// Provided by libc or compiler_builtins.
271+
fn strlen(s: *const c_char) -> usize;
272+
}
273+
274+
// SAFETY: Outer caller has provided a pointer to a valid C string.
275+
unsafe { strlen(s) }
276+
}
277+
278+
let len = intrinsics::const_eval_select((ptr,), strlen_ct, strlen_rt);
279+
Self::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr.cast(), len + 1))
262280
}
263281
}
264282

0 commit comments

Comments
 (0)