22// Copyright 2015 Andrew Gallant, bluss and Nicolas Koch
33
44use crate :: cmp;
5- use crate :: intrinsics;
65use crate :: mem;
76
87const LO_USIZE : usize = usize:: repeat_u8 ( 0x01 ) ;
@@ -17,53 +16,51 @@ const USIZE_BYTES: usize = mem::size_of::<usize>();
1716/// bytes where the borrow propagated all the way to the most significant
1817/// bit."
1918#[ inline]
20- fn contains_zero_byte ( x : usize ) -> bool {
19+ const fn contains_zero_byte ( x : usize ) -> bool {
2120 x. wrapping_sub ( LO_USIZE ) & !x & HI_USIZE != 0
2221}
2322
2423#[ cfg( target_pointer_width = "16" ) ]
2524#[ inline]
26- fn repeat_byte ( b : u8 ) -> usize {
25+ const fn repeat_byte ( b : u8 ) -> usize {
2726 ( b as usize ) << 8 | b as usize
2827}
2928
3029#[ cfg( not( target_pointer_width = "16" ) ) ]
3130#[ inline]
32- fn repeat_byte ( b : u8 ) -> usize {
31+ const fn repeat_byte ( b : u8 ) -> usize {
3332 ( b as usize ) * ( usize:: MAX / 255 )
3433}
3534
3635/// Returns the first index matching the byte `x` in `text`.
3736#[ must_use]
3837#[ inline]
3938pub const fn memchr ( x : u8 , text : & [ u8 ] ) -> Option < usize > {
40- #[ inline]
41- fn rt_impl ( x : u8 , text : & [ u8 ] ) -> Option < usize > {
42- // Fast path for small slices
43- if text. len ( ) < 2 * USIZE_BYTES {
44- return text. iter ( ) . position ( |elt| * elt == x) ;
45- }
46-
47- memchr_general_case ( x, text)
39+ // Fast path for small slices.
40+ if text. len ( ) < 2 * USIZE_BYTES {
41+ return memchr_naive ( x, text) ;
4842 }
4943
50- const fn const_impl ( x : u8 , bytes : & [ u8 ] ) -> Option < usize > {
51- let mut i = 0 ;
52- while i < bytes. len ( ) {
53- if bytes[ i] == x {
54- return Some ( i) ;
55- }
56- i += 1 ;
44+ memchr_aligned ( x, text)
45+ }
46+
47+ #[ inline]
48+ const fn memchr_naive ( x : u8 , text : & [ u8 ] ) -> Option < usize > {
49+ let mut i = 0 ;
50+
51+ // FIXME(const-hack): Replace with `text.iter().pos(|c| *c == x)`.
52+ while i < text. len ( ) {
53+ if text[ i] == x {
54+ return Some ( i) ;
5755 }
5856
59- None
57+ i += 1 ;
6058 }
6159
62- // SAFETY: The const and runtime versions have identical behavior
63- unsafe { intrinsics:: const_eval_select ( ( x, text) , const_impl, rt_impl) }
60+ None
6461}
6562
66- fn memchr_general_case ( x : u8 , text : & [ u8 ] ) -> Option < usize > {
63+ const fn memchr_aligned ( x : u8 , text : & [ u8 ] ) -> Option < usize > {
6764 // Scan for a single byte value by reading two `usize` words at a time.
6865 //
6966 // Split `text` in three parts
@@ -78,7 +75,7 @@ fn memchr_general_case(x: u8, text: &[u8]) -> Option<usize> {
7875
7976 if offset > 0 {
8077 offset = cmp:: min ( offset, len) ;
81- if let Some ( index) = text[ ..offset] . iter ( ) . position ( |elt| * elt == x ) {
78+ if let Some ( index) = memchr_naive ( x , & text[ ..offset] ) {
8279 return Some ( index) ;
8380 }
8481 }
@@ -103,7 +100,8 @@ fn memchr_general_case(x: u8, text: &[u8]) -> Option<usize> {
103100 }
104101
105102 // Find the byte after the point the body loop stopped.
106- text[ offset..] . iter ( ) . position ( |elt| * elt == x) . map ( |i| offset + i)
103+ // FIXME(const-hack): Use `?` instead.
104+ if let Some ( i) = memchr_naive ( x, & text[ offset..] ) { Some ( offset + i) } else { None }
107105}
108106
109107/// Returns the last index matching the byte `x` in `text`.
0 commit comments