1 | use crate::util::{ |
2 | prefilter::PrefilterI, |
3 | search::{MatchKind, Span}, |
4 | }; |
5 | |
6 | #[derive(Clone, Debug)] |
7 | pub(crate) struct Memchr(u8); |
8 | |
9 | impl Memchr { |
10 | pub(crate) fn new<B: AsRef<[u8]>>( |
11 | _kind: MatchKind, |
12 | needles: &[B], |
13 | ) -> Option<Memchr> { |
14 | #[cfg (not(feature = "perf-literal-substring" ))] |
15 | { |
16 | None |
17 | } |
18 | #[cfg (feature = "perf-literal-substring" )] |
19 | { |
20 | if needles.len() != 1 { |
21 | return None; |
22 | } |
23 | if needles[0].as_ref().len() != 1 { |
24 | return None; |
25 | } |
26 | Some(Memchr(needles[0].as_ref()[0])) |
27 | } |
28 | } |
29 | } |
30 | |
31 | impl PrefilterI for Memchr { |
32 | fn find(&self, haystack: &[u8], span: Span) -> Option<Span> { |
33 | #[cfg (not(feature = "perf-literal-substring" ))] |
34 | { |
35 | unreachable!() |
36 | } |
37 | #[cfg (feature = "perf-literal-substring" )] |
38 | { |
39 | memchr::memchr(self.0, &haystack[span]).map(|i| { |
40 | let start = span.start + i; |
41 | let end = start + 1; |
42 | Span { start, end } |
43 | }) |
44 | } |
45 | } |
46 | |
47 | fn prefix(&self, haystack: &[u8], span: Span) -> Option<Span> { |
48 | let b = *haystack.get(span.start)?; |
49 | if self.0 == b { |
50 | Some(Span { start: span.start, end: span.start + 1 }) |
51 | } else { |
52 | None |
53 | } |
54 | } |
55 | |
56 | fn memory_usage(&self) -> usize { |
57 | 0 |
58 | } |
59 | |
60 | fn is_fast(&self) -> bool { |
61 | true |
62 | } |
63 | } |
64 | |
65 | #[derive(Clone, Debug)] |
66 | pub(crate) struct Memchr2(u8, u8); |
67 | |
68 | impl Memchr2 { |
69 | pub(crate) fn new<B: AsRef<[u8]>>( |
70 | _kind: MatchKind, |
71 | needles: &[B], |
72 | ) -> Option<Memchr2> { |
73 | #[cfg (not(feature = "perf-literal-substring" ))] |
74 | { |
75 | None |
76 | } |
77 | #[cfg (feature = "perf-literal-substring" )] |
78 | { |
79 | if needles.len() != 2 { |
80 | return None; |
81 | } |
82 | if !needles.iter().all(|n| n.as_ref().len() == 1) { |
83 | return None; |
84 | } |
85 | let b1 = needles[0].as_ref()[0]; |
86 | let b2 = needles[1].as_ref()[0]; |
87 | Some(Memchr2(b1, b2)) |
88 | } |
89 | } |
90 | } |
91 | |
92 | impl PrefilterI for Memchr2 { |
93 | fn find(&self, haystack: &[u8], span: Span) -> Option<Span> { |
94 | #[cfg (not(feature = "perf-literal-substring" ))] |
95 | { |
96 | unreachable!() |
97 | } |
98 | #[cfg (feature = "perf-literal-substring" )] |
99 | { |
100 | memchr::memchr2(self.0, self.1, &haystack[span]).map(|i| { |
101 | let start = span.start + i; |
102 | let end = start + 1; |
103 | Span { start, end } |
104 | }) |
105 | } |
106 | } |
107 | |
108 | fn prefix(&self, haystack: &[u8], span: Span) -> Option<Span> { |
109 | let b = *haystack.get(span.start)?; |
110 | if self.0 == b || self.1 == b { |
111 | Some(Span { start: span.start, end: span.start + 1 }) |
112 | } else { |
113 | None |
114 | } |
115 | } |
116 | |
117 | fn memory_usage(&self) -> usize { |
118 | 0 |
119 | } |
120 | |
121 | fn is_fast(&self) -> bool { |
122 | true |
123 | } |
124 | } |
125 | |
126 | #[derive(Clone, Debug)] |
127 | pub(crate) struct Memchr3(u8, u8, u8); |
128 | |
129 | impl Memchr3 { |
130 | pub(crate) fn new<B: AsRef<[u8]>>( |
131 | _kind: MatchKind, |
132 | needles: &[B], |
133 | ) -> Option<Memchr3> { |
134 | #[cfg (not(feature = "perf-literal-substring" ))] |
135 | { |
136 | None |
137 | } |
138 | #[cfg (feature = "perf-literal-substring" )] |
139 | { |
140 | if needles.len() != 3 { |
141 | return None; |
142 | } |
143 | if !needles.iter().all(|n| n.as_ref().len() == 1) { |
144 | return None; |
145 | } |
146 | let b1 = needles[0].as_ref()[0]; |
147 | let b2 = needles[1].as_ref()[0]; |
148 | let b3 = needles[2].as_ref()[0]; |
149 | Some(Memchr3(b1, b2, b3)) |
150 | } |
151 | } |
152 | } |
153 | |
154 | impl PrefilterI for Memchr3 { |
155 | fn find(&self, haystack: &[u8], span: Span) -> Option<Span> { |
156 | #[cfg (not(feature = "perf-literal-substring" ))] |
157 | { |
158 | unreachable!() |
159 | } |
160 | #[cfg (feature = "perf-literal-substring" )] |
161 | { |
162 | memchr::memchr3(self.0, self.1, self.2, &haystack[span]).map(|i| { |
163 | let start = span.start + i; |
164 | let end = start + 1; |
165 | Span { start, end } |
166 | }) |
167 | } |
168 | } |
169 | |
170 | fn prefix(&self, haystack: &[u8], span: Span) -> Option<Span> { |
171 | let b = *haystack.get(span.start)?; |
172 | if self.0 == b || self.1 == b || self.2 == b { |
173 | Some(Span { start: span.start, end: span.start + 1 }) |
174 | } else { |
175 | None |
176 | } |
177 | } |
178 | |
179 | fn memory_usage(&self) -> usize { |
180 | 0 |
181 | } |
182 | |
183 | fn is_fast(&self) -> bool { |
184 | true |
185 | } |
186 | } |
187 | |