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{}