diff options
| author | Maybe Waffle <waffle.lapkin@gmail.com> | 2022-08-09 03:20:15 +0400 |
|---|---|---|
| committer | Maybe Waffle <waffle.lapkin@gmail.com> | 2022-09-12 16:29:12 +0400 |
| commit | cb02b647dc0441cfe152fa037ee14f4606c477cb (patch) | |
| tree | b6281270b85bd18f3c0364ef6c25a278d7aadcff /library/core/src | |
| parent | 9bbbf60b0442f1d56fc39f30274be77acc79164c (diff) | |
| download | rust-cb02b647dc0441cfe152fa037ee14f4606c477cb.tar.gz rust-cb02b647dc0441cfe152fa037ee14f4606c477cb.zip | |
constify `CStr` methods
Diffstat (limited to 'library/core/src')
| -rw-r--r-- | library/core/src/ffi/c_str.rs | 19 | ||||
| -rw-r--r-- | library/core/src/lib.rs | 1 | ||||
| -rw-r--r-- | library/core/src/slice/memchr.rs | 29 |
3 files changed, 37 insertions, 12 deletions
diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index 82e63a7fe1d..ec3cce2a234 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -121,10 +121,10 @@ enum FromBytesWithNulErrorKind { } impl FromBytesWithNulError { - fn interior_nul(pos: usize) -> FromBytesWithNulError { + const fn interior_nul(pos: usize) -> FromBytesWithNulError { FromBytesWithNulError { kind: FromBytesWithNulErrorKind::InteriorNul(pos) } } - fn not_nul_terminated() -> FromBytesWithNulError { + const fn not_nul_terminated() -> FromBytesWithNulError { FromBytesWithNulError { kind: FromBytesWithNulErrorKind::NotNulTerminated } } @@ -299,7 +299,8 @@ impl CStr { /// ``` /// #[unstable(feature = "cstr_from_bytes_until_nul", issue = "95027")] - pub fn from_bytes_until_nul(bytes: &[u8]) -> Result<&CStr, FromBytesUntilNulError> { + #[rustc_const_unstable(feature = "cstr_from_bytes_until_nul", issue = "95027")] + pub const fn from_bytes_until_nul(bytes: &[u8]) -> Result<&CStr, FromBytesUntilNulError> { let nul_pos = memchr::memchr(0, bytes); match nul_pos { Some(nul_pos) => { @@ -348,7 +349,8 @@ impl CStr { /// assert!(cstr.is_err()); /// ``` #[stable(feature = "cstr_from_bytes", since = "1.10.0")] - pub fn from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, FromBytesWithNulError> { + #[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")] + pub const fn from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, FromBytesWithNulError> { let nul_pos = memchr::memchr(0, bytes); match nul_pos { Some(nul_pos) if nul_pos + 1 == bytes.len() => { @@ -497,7 +499,8 @@ impl CStr { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] - pub fn to_bytes(&self) -> &[u8] { + #[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")] + pub const fn to_bytes(&self) -> &[u8] { let bytes = self.to_bytes_with_nul(); // SAFETY: to_bytes_with_nul returns slice with length at least 1 unsafe { bytes.get_unchecked(..bytes.len() - 1) } @@ -524,7 +527,8 @@ impl CStr { #[must_use = "this returns the result of the operation, \ without modifying the original"] #[stable(feature = "rust1", since = "1.0.0")] - pub fn to_bytes_with_nul(&self) -> &[u8] { + #[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")] + pub const fn to_bytes_with_nul(&self) -> &[u8] { // SAFETY: Transmuting a slice of `c_char`s to a slice of `u8`s // is safe on all supported targets. unsafe { &*(&self.inner as *const [c_char] as *const [u8]) } @@ -547,7 +551,8 @@ impl CStr { /// assert_eq!(cstr.to_str(), Ok("foo")); /// ``` #[stable(feature = "cstr_to_str", since = "1.4.0")] - pub fn to_str(&self) -> Result<&str, str::Utf8Error> { + #[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")] + pub const fn to_str(&self) -> Result<&str, str::Utf8Error> { // N.B., when `CStr` is changed to perform the length check in `.to_bytes()` // instead of in `from_ptr()`, it may be worth considering if this should // be rewritten to do the UTF-8 check inline with the length calculation diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 24742bb49b9..87ffc5abd2e 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -157,6 +157,7 @@ #![feature(const_slice_from_ref)] #![feature(const_slice_index)] #![feature(const_is_char_boundary)] +#![feature(const_cstr_methods)] // // Language features: #![feature(abi_unadjusted)] diff --git a/library/core/src/slice/memchr.rs b/library/core/src/slice/memchr.rs index dffeaf6a834..e0419f0ffdb 100644 --- a/library/core/src/slice/memchr.rs +++ b/library/core/src/slice/memchr.rs @@ -2,6 +2,7 @@ // Copyright 2015 Andrew Gallant, bluss and Nicolas Koch use crate::cmp; +use crate::intrinsics; use crate::mem; const LO_USIZE: usize = usize::repeat_u8(0x01); @@ -35,13 +36,31 @@ fn repeat_byte(b: u8) -> usize { /// Returns the first index matching the byte `x` in `text`. #[must_use] #[inline] -pub fn memchr(x: u8, text: &[u8]) -> Option<usize> { - // Fast path for small slices - if text.len() < 2 * USIZE_BYTES { - return text.iter().position(|elt| *elt == x); +pub const fn memchr(x: u8, text: &[u8]) -> Option<usize> { + #[inline] + fn rt_impl(x: u8, text: &[u8]) -> Option<usize> { + // Fast path for small slices + if text.len() < 2 * USIZE_BYTES { + return text.iter().position(|elt| *elt == x); + } + + memchr_general_case(x, text) + } + + const fn const_impl(x: u8, bytes: &[u8]) -> Option<usize> { + let mut i = 0; + while i < bytes.len() { + if bytes[i] == x { + return Some(i); + } + i += 1; + } + + None } - memchr_general_case(x, text) + // SAFETY: The const and runtime versions have identical behavior + unsafe { intrinsics::const_eval_select((x, text), const_impl, rt_impl) } } fn memchr_general_case(x: u8, text: &[u8]) -> Option<usize> { |
