From: Markus Reiter Date: Fri, 9 Sep 2022 09:48:39 +0000 (+0200) Subject: Simplify `const` `memchr`. X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;ds=sidebyside;h=db29de7745047383031231857745c5ec9b0bb4e8;p=rust.git Simplify `const` `memchr`. --- diff --git a/library/core/src/slice/memchr.rs b/library/core/src/slice/memchr.rs index e0419f0ffdb..7de1f48e6c9 100644 --- a/library/core/src/slice/memchr.rs +++ b/library/core/src/slice/memchr.rs @@ -2,7 +2,6 @@ // 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); @@ -17,19 +16,19 @@ /// bytes where the borrow propagated all the way to the most significant /// bit." #[inline] -fn contains_zero_byte(x: usize) -> bool { +const fn contains_zero_byte(x: usize) -> bool { x.wrapping_sub(LO_USIZE) & !x & HI_USIZE != 0 } #[cfg(target_pointer_width = "16")] #[inline] -fn repeat_byte(b: u8) -> usize { +const fn repeat_byte(b: u8) -> usize { (b as usize) << 8 | b as usize } #[cfg(not(target_pointer_width = "16"))] #[inline] -fn repeat_byte(b: u8) -> usize { +const fn repeat_byte(b: u8) -> usize { (b as usize) * (usize::MAX / 255) } @@ -37,33 +36,31 @@ fn repeat_byte(b: u8) -> usize { #[must_use] #[inline] pub const fn memchr(x: u8, text: &[u8]) -> Option { - #[inline] - fn rt_impl(x: u8, text: &[u8]) -> Option { - // Fast path for small slices - if text.len() < 2 * USIZE_BYTES { - return text.iter().position(|elt| *elt == x); - } - - memchr_general_case(x, text) + // Fast path for small slices. + if text.len() < 2 * USIZE_BYTES { + return memchr_naive(x, text); } - const fn const_impl(x: u8, bytes: &[u8]) -> Option { - let mut i = 0; - while i < bytes.len() { - if bytes[i] == x { - return Some(i); - } - i += 1; + memchr_aligned(x, text) +} + +#[inline] +const fn memchr_naive(x: u8, text: &[u8]) -> Option { + let mut i = 0; + + // FIXME(const-hack): Replace with `text.iter().pos(|c| *c == x)`. + while i < text.len() { + if text[i] == x { + return Some(i); } - None + i += 1; } - // SAFETY: The const and runtime versions have identical behavior - unsafe { intrinsics::const_eval_select((x, text), const_impl, rt_impl) } + None } -fn memchr_general_case(x: u8, text: &[u8]) -> Option { +const fn memchr_aligned(x: u8, text: &[u8]) -> Option { // Scan for a single byte value by reading two `usize` words at a time. // // Split `text` in three parts @@ -78,7 +75,7 @@ fn memchr_general_case(x: u8, text: &[u8]) -> Option { if offset > 0 { offset = cmp::min(offset, len); - if let Some(index) = text[..offset].iter().position(|elt| *elt == x) { + if let Some(index) = memchr_naive(x, &text[..offset]) { return Some(index); } } @@ -103,7 +100,8 @@ fn memchr_general_case(x: u8, text: &[u8]) -> Option { } // Find the byte after the point the body loop stopped. - text[offset..].iter().position(|elt| *elt == x).map(|i| offset + i) + // FIXME(const-hack): Use `?` instead. + if let Some(i) = memchr_naive(x, &text[offset..]) { Some(offset + i) } else { None } } /// Returns the last index matching the byte `x` in `text`.