pattern_3/slices/
func.rs

1use needle::*;
2use haystack::Span;
3use std::ops::Range;
4
5pub struct ElemSearcher<F> {
6    predicate: F,
7}
8
9macro_rules! impl_needle {
10    (<[$($gen:tt)*]> $ty:ty) => {
11        impl<$($gen)*> Needle<$ty> for F
12        where
13            F: FnMut(&T) -> bool,
14        {
15            type Searcher = ElemSearcher<F>;
16            type Consumer = ElemSearcher<F>;
17
18            #[inline]
19            fn into_searcher(self) -> Self::Searcher {
20                ElemSearcher {
21                    predicate: self,
22                }
23            }
24
25            #[inline]
26            fn into_consumer(self) -> Self::Consumer {
27                ElemSearcher {
28                    predicate: self,
29                }
30            }
31        }
32    }
33}
34
35impl_needle!(<['h, T, F]> &'h [T]);
36impl_needle!(<['h, T, F]> &'h mut [T]);
37#[cfg(feature = "std")]
38impl_needle!(<[T, F]> Vec<T>);
39
40unsafe impl<T, F> Searcher<[T]> for ElemSearcher<F>
41where
42    F: FnMut(&T) -> bool,
43{
44    #[inline]
45    fn search(&mut self, span: Span<&[T]>) -> Option<Range<usize>> {
46        let (rest, range) = span.into_parts();
47        let start = range.start;
48        let pos = rest[range].iter().position(&mut self.predicate)?;
49        Some((pos + start)..(pos + start + 1))
50    }
51}
52
53unsafe impl<T, F> Consumer<[T]> for ElemSearcher<F>
54where
55    F: FnMut(&T) -> bool,
56{
57    #[inline]
58    fn consume(&mut self, span: Span<&[T]>) -> Option<usize> {
59        let (hay, range) = span.into_parts();
60        if range.end == range.start {
61            return None;
62        }
63        let x = unsafe { hay.get_unchecked(range.start) };
64        if (self.predicate)(x) {
65            Some(range.start + 1)
66        } else {
67            None
68        }
69    }
70
71    #[inline]
72    fn trim_start(&mut self, hay: &[T]) -> usize {
73        let mut it = hay.iter();
74        let len = hay.len();
75        if it.find(|x| !(self.predicate)(x)).is_some() {
76            len - it.as_slice().len() - 1
77        } else {
78            len
79        }
80    }
81}
82
83unsafe impl<T, F> ReverseSearcher<[T]> for ElemSearcher<F>
84where
85    F: FnMut(&T) -> bool,
86{
87    #[inline]
88    fn rsearch(&mut self, span: Span<&[T]>) -> Option<Range<usize>> {
89        let (rest, range) = span.into_parts();
90        let start = range.start;
91        let pos = rest[range].iter().rposition(&mut self.predicate)?;
92        Some((pos + start)..(pos + start + 1))
93    }
94}
95
96unsafe impl<T, F> ReverseConsumer<[T]> for ElemSearcher<F>
97where
98    F: FnMut(&T) -> bool,
99{
100    #[inline]
101    fn rconsume(&mut self, span: Span<&[T]>) -> Option<usize> {
102        let (hay, range) = span.into_parts();
103        if range.start == range.end {
104            return None;
105        }
106        let last = range.end - 1;
107        let x = unsafe { hay.get_unchecked(last) };
108        if (self.predicate)(x) {
109            Some(last)
110        } else {
111            None
112        }
113    }
114
115    #[inline]
116    fn trim_end(&mut self, hay: &[T]) -> usize {
117        hay.iter().rposition(|x| !(self.predicate)(x)).map_or(0, |p| p + 1)
118    }
119}
120
121unsafe impl<T, F> DoubleEndedSearcher<[T]> for ElemSearcher<F>
122where
123    F: FnMut(&T) -> bool,
124{}
125
126unsafe impl<T, F> DoubleEndedConsumer<[T]> for ElemSearcher<F>
127where
128    F: FnMut(&T) -> bool,
129{}