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