diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:11:38 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:12:43 +0000 |
commit | cf94bdc0742c13e2a0cac864c478b8626b266e1b (patch) | |
tree | 044670aa50cc5e2b4229aa0b6b3df6676730c0a6 /library/core/src/ffi/c_str.rs | |
parent | Adding debian version 1.65.0+dfsg1-2. (diff) | |
download | rustc-cf94bdc0742c13e2a0cac864c478b8626b266e1b.tar.xz rustc-cf94bdc0742c13e2a0cac864c478b8626b266e1b.zip |
Merging upstream version 1.66.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'library/core/src/ffi/c_str.rs')
-rw-r--r-- | library/core/src/ffi/c_str.rs | 76 |
1 files changed, 65 insertions, 11 deletions
diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index 21f80ec02..8923f548a 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -221,9 +221,7 @@ impl CStr { /// # Examples /// /// ```ignore (extern-declaration) - /// # fn main() { - /// use std::ffi::CStr; - /// use std::os::raw::c_char; + /// use std::ffi::{c_char, CStr}; /// /// extern "C" { /// fn my_string() -> *const c_char; @@ -233,14 +231,26 @@ impl CStr { /// let slice = CStr::from_ptr(my_string()); /// println!("string returned: {}", slice.to_str().unwrap()); /// } - /// # } + /// ``` + /// + /// ``` + /// #![feature(const_cstr_methods)] + /// + /// use std::ffi::{c_char, CStr}; + /// + /// const HELLO_PTR: *const c_char = { + /// const BYTES: &[u8] = b"Hello, world!\0"; + /// BYTES.as_ptr().cast() + /// }; + /// const HELLO: &CStr = unsafe { CStr::from_ptr(HELLO_PTR) }; /// ``` /// /// [valid]: core::ptr#safety #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] - pub unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr { + #[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")] + pub const unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr { // SAFETY: The caller has provided a pointer that points to a valid C // string with a NUL terminator of size less than `isize::MAX`, whose // content remain valid and doesn't change for the lifetime of the @@ -252,13 +262,29 @@ impl CStr { // // The cast from c_char to u8 is ok because a c_char is always one byte. unsafe { - extern "C" { - /// Provided by libc or compiler_builtins. - fn strlen(s: *const c_char) -> usize; + const fn strlen_ct(s: *const c_char) -> usize { + let mut len = 0; + + // SAFETY: Outer caller has provided a pointer to a valid C string. + while unsafe { *s.add(len) } != 0 { + len += 1; + } + + len } - let len = strlen(ptr); - let ptr = ptr as *const u8; - CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1)) + + fn strlen_rt(s: *const c_char) -> usize { + extern "C" { + /// Provided by libc or compiler_builtins. + fn strlen(s: *const c_char) -> usize; + } + + // SAFETY: Outer caller has provided a pointer to a valid C string. + unsafe { strlen(s) } + } + + let len = intrinsics::const_eval_select((ptr,), strlen_ct, strlen_rt); + Self::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr.cast(), len + 1)) } } @@ -474,6 +500,34 @@ impl CStr { self.inner.as_ptr() } + /// Returns `true` if `self.to_bytes()` has a length of 0. + /// + /// # Examples + /// + /// ``` + /// #![feature(cstr_is_empty)] + /// + /// use std::ffi::CStr; + /// # use std::ffi::FromBytesWithNulError; + /// + /// # fn main() { test().unwrap(); } + /// # fn test() -> Result<(), FromBytesWithNulError> { + /// let cstr = CStr::from_bytes_with_nul(b"foo\0")?; + /// assert!(!cstr.is_empty()); + /// + /// let empty_cstr = CStr::from_bytes_with_nul(b"\0")?; + /// assert!(empty_cstr.is_empty()); + /// # Ok(()) + /// # } + /// ``` + #[inline] + #[unstable(feature = "cstr_is_empty", issue = "102444")] + pub const fn is_empty(&self) -> bool { + // SAFETY: We know there is at least one byte; for empty strings it + // is the NUL terminator. + (unsafe { self.inner.get_unchecked(0) }) == &0 + } + /// Converts this C string to a byte slice. /// /// The returned slice will **not** contain the trailing nul terminator that this C |