1 use std::mem::size_of;
2
3 use crate::ahocorasick::MatchKind;
4 use crate::automaton::Automaton;
5 use crate::classes::ByteClasses;
6 use crate::error::Result;
7 use crate::nfa::{PatternID, PatternLength, NFA};
8 use crate::prefilter::{Prefilter, PrefilterObj, PrefilterState};
9 use crate::state_id::{dead_id, fail_id, premultiply_overflow_error, StateID};
10 use crate::Match;
11
12 #[derive(Clone, Debug)]
13 pub enum DFA<S> {
14 Standard(Standard<S>),
15 ByteClass(ByteClass<S>),
16 Premultiplied(Premultiplied<S>),
17 PremultipliedByteClass(PremultipliedByteClass<S>),
18 }
19
20 impl<S: StateID> DFA<S> {
repr(&self) -> &Repr<S>21 fn repr(&self) -> &Repr<S> {
22 match *self {
23 DFA::Standard(ref dfa) => dfa.repr(),
24 DFA::ByteClass(ref dfa) => dfa.repr(),
25 DFA::Premultiplied(ref dfa) => dfa.repr(),
26 DFA::PremultipliedByteClass(ref dfa) => dfa.repr(),
27 }
28 }
29
match_kind(&self) -> &MatchKind30 pub fn match_kind(&self) -> &MatchKind {
31 &self.repr().match_kind
32 }
33
heap_bytes(&self) -> usize34 pub fn heap_bytes(&self) -> usize {
35 self.repr().heap_bytes
36 }
37
max_pattern_len(&self) -> usize38 pub fn max_pattern_len(&self) -> usize {
39 self.repr().max_pattern_len
40 }
41
pattern_count(&self) -> usize42 pub fn pattern_count(&self) -> usize {
43 self.repr().pattern_count
44 }
45
prefilter(&self) -> Option<&dyn Prefilter>46 pub fn prefilter(&self) -> Option<&dyn Prefilter> {
47 self.repr().prefilter.as_ref().map(|p| p.as_ref())
48 }
49
start_state(&self) -> S50 pub fn start_state(&self) -> S {
51 self.repr().start_id
52 }
53
54 #[inline(always)]
overlapping_find_at( &self, prestate: &mut PrefilterState, haystack: &[u8], at: usize, state_id: &mut S, match_index: &mut usize, ) -> Option<Match>55 pub fn overlapping_find_at(
56 &self,
57 prestate: &mut PrefilterState,
58 haystack: &[u8],
59 at: usize,
60 state_id: &mut S,
61 match_index: &mut usize,
62 ) -> Option<Match> {
63 match *self {
64 DFA::Standard(ref dfa) => dfa.overlapping_find_at(
65 prestate,
66 haystack,
67 at,
68 state_id,
69 match_index,
70 ),
71 DFA::ByteClass(ref dfa) => dfa.overlapping_find_at(
72 prestate,
73 haystack,
74 at,
75 state_id,
76 match_index,
77 ),
78 DFA::Premultiplied(ref dfa) => dfa.overlapping_find_at(
79 prestate,
80 haystack,
81 at,
82 state_id,
83 match_index,
84 ),
85 DFA::PremultipliedByteClass(ref dfa) => dfa.overlapping_find_at(
86 prestate,
87 haystack,
88 at,
89 state_id,
90 match_index,
91 ),
92 }
93 }
94
95 #[inline(always)]
earliest_find_at( &self, prestate: &mut PrefilterState, haystack: &[u8], at: usize, state_id: &mut S, ) -> Option<Match>96 pub fn earliest_find_at(
97 &self,
98 prestate: &mut PrefilterState,
99 haystack: &[u8],
100 at: usize,
101 state_id: &mut S,
102 ) -> Option<Match> {
103 match *self {
104 DFA::Standard(ref dfa) => {
105 dfa.earliest_find_at(prestate, haystack, at, state_id)
106 }
107 DFA::ByteClass(ref dfa) => {
108 dfa.earliest_find_at(prestate, haystack, at, state_id)
109 }
110 DFA::Premultiplied(ref dfa) => {
111 dfa.earliest_find_at(prestate, haystack, at, state_id)
112 }
113 DFA::PremultipliedByteClass(ref dfa) => {
114 dfa.earliest_find_at(prestate, haystack, at, state_id)
115 }
116 }
117 }
118
119 #[inline(always)]
find_at_no_state( &self, prestate: &mut PrefilterState, haystack: &[u8], at: usize, ) -> Option<Match>120 pub fn find_at_no_state(
121 &self,
122 prestate: &mut PrefilterState,
123 haystack: &[u8],
124 at: usize,
125 ) -> Option<Match> {
126 match *self {
127 DFA::Standard(ref dfa) => {
128 dfa.find_at_no_state(prestate, haystack, at)
129 }
130 DFA::ByteClass(ref dfa) => {
131 dfa.find_at_no_state(prestate, haystack, at)
132 }
133 DFA::Premultiplied(ref dfa) => {
134 dfa.find_at_no_state(prestate, haystack, at)
135 }
136 DFA::PremultipliedByteClass(ref dfa) => {
137 dfa.find_at_no_state(prestate, haystack, at)
138 }
139 }
140 }
141 }
142
143 #[derive(Clone, Debug)]
144 pub struct Standard<S>(Repr<S>);
145
146 impl<S: StateID> Standard<S> {
repr(&self) -> &Repr<S>147 fn repr(&self) -> &Repr<S> {
148 &self.0
149 }
150 }
151
152 impl<S: StateID> Automaton for Standard<S> {
153 type ID = S;
154
match_kind(&self) -> &MatchKind155 fn match_kind(&self) -> &MatchKind {
156 &self.repr().match_kind
157 }
158
anchored(&self) -> bool159 fn anchored(&self) -> bool {
160 self.repr().anchored
161 }
162
prefilter(&self) -> Option<&dyn Prefilter>163 fn prefilter(&self) -> Option<&dyn Prefilter> {
164 self.repr().prefilter.as_ref().map(|p| p.as_ref())
165 }
166
start_state(&self) -> S167 fn start_state(&self) -> S {
168 self.repr().start_id
169 }
170
is_valid(&self, id: S) -> bool171 fn is_valid(&self, id: S) -> bool {
172 id.to_usize() < self.repr().state_count
173 }
174
is_match_state(&self, id: S) -> bool175 fn is_match_state(&self, id: S) -> bool {
176 self.repr().is_match_state(id)
177 }
178
is_match_or_dead_state(&self, id: S) -> bool179 fn is_match_or_dead_state(&self, id: S) -> bool {
180 self.repr().is_match_or_dead_state(id)
181 }
182
get_match( &self, id: S, match_index: usize, end: usize, ) -> Option<Match>183 fn get_match(
184 &self,
185 id: S,
186 match_index: usize,
187 end: usize,
188 ) -> Option<Match> {
189 self.repr().get_match(id, match_index, end)
190 }
191
match_count(&self, id: S) -> usize192 fn match_count(&self, id: S) -> usize {
193 self.repr().match_count(id)
194 }
195
next_state(&self, current: S, input: u8) -> S196 fn next_state(&self, current: S, input: u8) -> S {
197 let o = current.to_usize() * 256 + input as usize;
198 self.repr().trans[o]
199 }
200 }
201
202 #[derive(Clone, Debug)]
203 pub struct ByteClass<S>(Repr<S>);
204
205 impl<S: StateID> ByteClass<S> {
repr(&self) -> &Repr<S>206 fn repr(&self) -> &Repr<S> {
207 &self.0
208 }
209 }
210
211 impl<S: StateID> Automaton for ByteClass<S> {
212 type ID = S;
213
match_kind(&self) -> &MatchKind214 fn match_kind(&self) -> &MatchKind {
215 &self.repr().match_kind
216 }
217
anchored(&self) -> bool218 fn anchored(&self) -> bool {
219 self.repr().anchored
220 }
221
prefilter(&self) -> Option<&dyn Prefilter>222 fn prefilter(&self) -> Option<&dyn Prefilter> {
223 self.repr().prefilter.as_ref().map(|p| p.as_ref())
224 }
225
start_state(&self) -> S226 fn start_state(&self) -> S {
227 self.repr().start_id
228 }
229
is_valid(&self, id: S) -> bool230 fn is_valid(&self, id: S) -> bool {
231 id.to_usize() < self.repr().state_count
232 }
233
is_match_state(&self, id: S) -> bool234 fn is_match_state(&self, id: S) -> bool {
235 self.repr().is_match_state(id)
236 }
237
is_match_or_dead_state(&self, id: S) -> bool238 fn is_match_or_dead_state(&self, id: S) -> bool {
239 self.repr().is_match_or_dead_state(id)
240 }
241
get_match( &self, id: S, match_index: usize, end: usize, ) -> Option<Match>242 fn get_match(
243 &self,
244 id: S,
245 match_index: usize,
246 end: usize,
247 ) -> Option<Match> {
248 self.repr().get_match(id, match_index, end)
249 }
250
match_count(&self, id: S) -> usize251 fn match_count(&self, id: S) -> usize {
252 self.repr().match_count(id)
253 }
254
next_state(&self, current: S, input: u8) -> S255 fn next_state(&self, current: S, input: u8) -> S {
256 let alphabet_len = self.repr().byte_classes.alphabet_len();
257 let input = self.repr().byte_classes.get(input);
258 let o = current.to_usize() * alphabet_len + input as usize;
259 self.repr().trans[o]
260 }
261 }
262
263 #[derive(Clone, Debug)]
264 pub struct Premultiplied<S>(Repr<S>);
265
266 impl<S: StateID> Premultiplied<S> {
repr(&self) -> &Repr<S>267 fn repr(&self) -> &Repr<S> {
268 &self.0
269 }
270 }
271
272 impl<S: StateID> Automaton for Premultiplied<S> {
273 type ID = S;
274
match_kind(&self) -> &MatchKind275 fn match_kind(&self) -> &MatchKind {
276 &self.repr().match_kind
277 }
278
anchored(&self) -> bool279 fn anchored(&self) -> bool {
280 self.repr().anchored
281 }
282
prefilter(&self) -> Option<&dyn Prefilter>283 fn prefilter(&self) -> Option<&dyn Prefilter> {
284 self.repr().prefilter.as_ref().map(|p| p.as_ref())
285 }
286
start_state(&self) -> S287 fn start_state(&self) -> S {
288 self.repr().start_id
289 }
290
is_valid(&self, id: S) -> bool291 fn is_valid(&self, id: S) -> bool {
292 (id.to_usize() / 256) < self.repr().state_count
293 }
294
is_match_state(&self, id: S) -> bool295 fn is_match_state(&self, id: S) -> bool {
296 self.repr().is_match_state(id)
297 }
298
is_match_or_dead_state(&self, id: S) -> bool299 fn is_match_or_dead_state(&self, id: S) -> bool {
300 self.repr().is_match_or_dead_state(id)
301 }
302
get_match( &self, id: S, match_index: usize, end: usize, ) -> Option<Match>303 fn get_match(
304 &self,
305 id: S,
306 match_index: usize,
307 end: usize,
308 ) -> Option<Match> {
309 if id > self.repr().max_match {
310 return None;
311 }
312 self.repr()
313 .matches
314 .get(id.to_usize() / 256)
315 .and_then(|m| m.get(match_index))
316 .map(|&(id, len)| Match { pattern: id, len, end })
317 }
318
match_count(&self, id: S) -> usize319 fn match_count(&self, id: S) -> usize {
320 let o = id.to_usize() / 256;
321 self.repr().matches[o].len()
322 }
323
next_state(&self, current: S, input: u8) -> S324 fn next_state(&self, current: S, input: u8) -> S {
325 let o = current.to_usize() + input as usize;
326 self.repr().trans[o]
327 }
328 }
329
330 #[derive(Clone, Debug)]
331 pub struct PremultipliedByteClass<S>(Repr<S>);
332
333 impl<S: StateID> PremultipliedByteClass<S> {
repr(&self) -> &Repr<S>334 fn repr(&self) -> &Repr<S> {
335 &self.0
336 }
337 }
338
339 impl<S: StateID> Automaton for PremultipliedByteClass<S> {
340 type ID = S;
341
match_kind(&self) -> &MatchKind342 fn match_kind(&self) -> &MatchKind {
343 &self.repr().match_kind
344 }
345
anchored(&self) -> bool346 fn anchored(&self) -> bool {
347 self.repr().anchored
348 }
349
prefilter(&self) -> Option<&dyn Prefilter>350 fn prefilter(&self) -> Option<&dyn Prefilter> {
351 self.repr().prefilter.as_ref().map(|p| p.as_ref())
352 }
353
start_state(&self) -> S354 fn start_state(&self) -> S {
355 self.repr().start_id
356 }
357
is_valid(&self, id: S) -> bool358 fn is_valid(&self, id: S) -> bool {
359 (id.to_usize() / self.repr().alphabet_len()) < self.repr().state_count
360 }
361
is_match_state(&self, id: S) -> bool362 fn is_match_state(&self, id: S) -> bool {
363 self.repr().is_match_state(id)
364 }
365
is_match_or_dead_state(&self, id: S) -> bool366 fn is_match_or_dead_state(&self, id: S) -> bool {
367 self.repr().is_match_or_dead_state(id)
368 }
369
get_match( &self, id: S, match_index: usize, end: usize, ) -> Option<Match>370 fn get_match(
371 &self,
372 id: S,
373 match_index: usize,
374 end: usize,
375 ) -> Option<Match> {
376 if id > self.repr().max_match {
377 return None;
378 }
379 self.repr()
380 .matches
381 .get(id.to_usize() / self.repr().alphabet_len())
382 .and_then(|m| m.get(match_index))
383 .map(|&(id, len)| Match { pattern: id, len, end })
384 }
385
match_count(&self, id: S) -> usize386 fn match_count(&self, id: S) -> usize {
387 let o = id.to_usize() / self.repr().alphabet_len();
388 self.repr().matches[o].len()
389 }
390
next_state(&self, current: S, input: u8) -> S391 fn next_state(&self, current: S, input: u8) -> S {
392 let input = self.repr().byte_classes.get(input);
393 let o = current.to_usize() + input as usize;
394 self.repr().trans[o]
395 }
396 }
397
398 #[derive(Clone, Debug)]
399 pub struct Repr<S> {
400 match_kind: MatchKind,
401 anchored: bool,
402 premultiplied: bool,
403 start_id: S,
404 /// The length, in bytes, of the longest pattern in this automaton. This
405 /// information is useful for keeping correct buffer sizes when searching
406 /// on streams.
407 max_pattern_len: usize,
408 /// The total number of patterns added to this automaton. This includes
409 /// patterns that may never match.
410 pattern_count: usize,
411 state_count: usize,
412 max_match: S,
413 /// The number of bytes of heap used by this NFA's transition table.
414 heap_bytes: usize,
415 /// A prefilter for quickly detecting candidate matchs, if pertinent.
416 prefilter: Option<PrefilterObj>,
417 byte_classes: ByteClasses,
418 trans: Vec<S>,
419 matches: Vec<Vec<(PatternID, PatternLength)>>,
420 }
421
422 impl<S: StateID> Repr<S> {
423 /// Returns the total alphabet size for this DFA.
424 ///
425 /// If byte classes are enabled, then this corresponds to the number of
426 /// equivalence classes. If they are disabled, then this is always 256.
alphabet_len(&self) -> usize427 fn alphabet_len(&self) -> usize {
428 self.byte_classes.alphabet_len()
429 }
430
431 /// Returns true only if the given state is a match state.
is_match_state(&self, id: S) -> bool432 fn is_match_state(&self, id: S) -> bool {
433 id <= self.max_match && id > dead_id()
434 }
435
436 /// Returns true only if the given state is either a dead state or a match
437 /// state.
is_match_or_dead_state(&self, id: S) -> bool438 fn is_match_or_dead_state(&self, id: S) -> bool {
439 id <= self.max_match
440 }
441
442 /// Get the ith match for the given state, where the end position of a
443 /// match was found at `end`.
444 ///
445 /// # Panics
446 ///
447 /// The caller must ensure that the given state identifier is valid,
448 /// otherwise this may panic. The `match_index` need not be valid. That is,
449 /// if the given state has no matches then this returns `None`.
get_match( &self, id: S, match_index: usize, end: usize, ) -> Option<Match>450 fn get_match(
451 &self,
452 id: S,
453 match_index: usize,
454 end: usize,
455 ) -> Option<Match> {
456 if id > self.max_match {
457 return None;
458 }
459 self.matches
460 .get(id.to_usize())
461 .and_then(|m| m.get(match_index))
462 .map(|&(id, len)| Match { pattern: id, len, end })
463 }
464
465 /// Return the total number of matches for the given state.
466 ///
467 /// # Panics
468 ///
469 /// The caller must ensure that the given identifier is valid, or else
470 /// this panics.
match_count(&self, id: S) -> usize471 fn match_count(&self, id: S) -> usize {
472 self.matches[id.to_usize()].len()
473 }
474
475 /// Get the next state given `from` as the current state and `byte` as the
476 /// current input byte.
next_state(&self, from: S, byte: u8) -> S477 fn next_state(&self, from: S, byte: u8) -> S {
478 let alphabet_len = self.alphabet_len();
479 let byte = self.byte_classes.get(byte);
480 self.trans[from.to_usize() * alphabet_len + byte as usize]
481 }
482
483 /// Set the `byte` transition for the `from` state to point to `to`.
set_next_state(&mut self, from: S, byte: u8, to: S)484 fn set_next_state(&mut self, from: S, byte: u8, to: S) {
485 let alphabet_len = self.alphabet_len();
486 let byte = self.byte_classes.get(byte);
487 self.trans[from.to_usize() * alphabet_len + byte as usize] = to;
488 }
489
490 /// Swap the given states in place.
swap_states(&mut self, id1: S, id2: S)491 fn swap_states(&mut self, id1: S, id2: S) {
492 assert!(!self.premultiplied, "can't swap states in premultiplied DFA");
493
494 let o1 = id1.to_usize() * self.alphabet_len();
495 let o2 = id2.to_usize() * self.alphabet_len();
496 for b in 0..self.alphabet_len() {
497 self.trans.swap(o1 + b, o2 + b);
498 }
499 self.matches.swap(id1.to_usize(), id2.to_usize());
500 }
501
502 /// This routine shuffles all match states in this DFA to the beginning
503 /// of the DFA such that every non-match state appears after every match
504 /// state. (With one exception: the special fail and dead states remain as
505 /// the first two states.)
506 ///
507 /// The purpose of doing this shuffling is to avoid an extra conditional
508 /// in the search loop, and in particular, detecting whether a state is a
509 /// match or not does not need to access any memory.
510 ///
511 /// This updates `self.max_match` to point to the last matching state as
512 /// well as `self.start` if the starting state was moved.
shuffle_match_states(&mut self)513 fn shuffle_match_states(&mut self) {
514 assert!(
515 !self.premultiplied,
516 "cannot shuffle match states of premultiplied DFA"
517 );
518
519 if self.state_count <= 1 {
520 return;
521 }
522
523 let mut first_non_match = self.start_id.to_usize();
524 while first_non_match < self.state_count
525 && self.matches[first_non_match].len() > 0
526 {
527 first_non_match += 1;
528 }
529
530 let mut swaps: Vec<S> = vec![fail_id(); self.state_count];
531 let mut cur = self.state_count - 1;
532 while cur > first_non_match {
533 if self.matches[cur].len() > 0 {
534 self.swap_states(
535 S::from_usize(cur),
536 S::from_usize(first_non_match),
537 );
538 swaps[cur] = S::from_usize(first_non_match);
539 swaps[first_non_match] = S::from_usize(cur);
540
541 first_non_match += 1;
542 while first_non_match < cur
543 && self.matches[first_non_match].len() > 0
544 {
545 first_non_match += 1;
546 }
547 }
548 cur -= 1;
549 }
550 for id in (0..self.state_count).map(S::from_usize) {
551 let alphabet_len = self.alphabet_len();
552 let offset = id.to_usize() * alphabet_len;
553 for next in &mut self.trans[offset..offset + alphabet_len] {
554 if swaps[next.to_usize()] != fail_id() {
555 *next = swaps[next.to_usize()];
556 }
557 }
558 }
559 if swaps[self.start_id.to_usize()] != fail_id() {
560 self.start_id = swaps[self.start_id.to_usize()];
561 }
562 self.max_match = S::from_usize(first_non_match - 1);
563 }
564
premultiply(&mut self) -> Result<()>565 fn premultiply(&mut self) -> Result<()> {
566 if self.premultiplied || self.state_count <= 1 {
567 return Ok(());
568 }
569
570 let alpha_len = self.alphabet_len();
571 premultiply_overflow_error(
572 S::from_usize(self.state_count - 1),
573 alpha_len,
574 )?;
575
576 for id in (2..self.state_count).map(S::from_usize) {
577 let offset = id.to_usize() * alpha_len;
578 for next in &mut self.trans[offset..offset + alpha_len] {
579 if *next == dead_id() {
580 continue;
581 }
582 *next = S::from_usize(next.to_usize() * alpha_len);
583 }
584 }
585 self.premultiplied = true;
586 self.start_id = S::from_usize(self.start_id.to_usize() * alpha_len);
587 self.max_match = S::from_usize(self.max_match.to_usize() * alpha_len);
588 Ok(())
589 }
590
591 /// Computes the total amount of heap used by this NFA in bytes.
calculate_size(&mut self)592 fn calculate_size(&mut self) {
593 let mut size = (self.trans.len() * size_of::<S>())
594 + (self.matches.len()
595 * size_of::<Vec<(PatternID, PatternLength)>>());
596 for state_matches in &self.matches {
597 size +=
598 state_matches.len() * size_of::<(PatternID, PatternLength)>();
599 }
600 size += self.prefilter.as_ref().map_or(0, |p| p.as_ref().heap_bytes());
601 self.heap_bytes = size;
602 }
603 }
604
605 /// A builder for configuring the determinization of an NFA into a DFA.
606 #[derive(Clone, Debug)]
607 pub struct Builder {
608 premultiply: bool,
609 byte_classes: bool,
610 }
611
612 impl Builder {
613 /// Create a new builder for a DFA.
new() -> Builder614 pub fn new() -> Builder {
615 Builder { premultiply: true, byte_classes: true }
616 }
617
618 /// Build a DFA from the given NFA.
619 ///
620 /// This returns an error if the state identifiers exceed their
621 /// representation size. This can only happen when state ids are
622 /// premultiplied (which is enabled by default).
build<S: StateID>(&self, nfa: &NFA<S>) -> Result<DFA<S>>623 pub fn build<S: StateID>(&self, nfa: &NFA<S>) -> Result<DFA<S>> {
624 let byte_classes = if self.byte_classes {
625 nfa.byte_classes().clone()
626 } else {
627 ByteClasses::singletons()
628 };
629 let alphabet_len = byte_classes.alphabet_len();
630 let trans = vec![fail_id(); alphabet_len * nfa.state_len()];
631 let matches = vec![vec![]; nfa.state_len()];
632 let mut repr = Repr {
633 match_kind: nfa.match_kind().clone(),
634 anchored: nfa.anchored(),
635 premultiplied: false,
636 start_id: nfa.start_state(),
637 max_pattern_len: nfa.max_pattern_len(),
638 pattern_count: nfa.pattern_count(),
639 state_count: nfa.state_len(),
640 max_match: fail_id(),
641 heap_bytes: 0,
642 prefilter: nfa.prefilter_obj().map(|p| p.clone()),
643 byte_classes: byte_classes.clone(),
644 trans,
645 matches,
646 };
647 for id in (0..nfa.state_len()).map(S::from_usize) {
648 repr.matches[id.to_usize()].extend_from_slice(nfa.matches(id));
649
650 let fail = nfa.failure_transition(id);
651 nfa.iter_all_transitions(&byte_classes, id, |b, mut next| {
652 if next == fail_id() {
653 next = nfa_next_state_memoized(nfa, &repr, id, fail, b);
654 }
655 repr.set_next_state(id, b, next);
656 });
657 }
658 repr.shuffle_match_states();
659 repr.calculate_size();
660 if self.premultiply {
661 repr.premultiply()?;
662 if byte_classes.is_singleton() {
663 Ok(DFA::Premultiplied(Premultiplied(repr)))
664 } else {
665 Ok(DFA::PremultipliedByteClass(PremultipliedByteClass(repr)))
666 }
667 } else {
668 if byte_classes.is_singleton() {
669 Ok(DFA::Standard(Standard(repr)))
670 } else {
671 Ok(DFA::ByteClass(ByteClass(repr)))
672 }
673 }
674 }
675
676 /// Whether to use byte classes or in the DFA.
byte_classes(&mut self, yes: bool) -> &mut Builder677 pub fn byte_classes(&mut self, yes: bool) -> &mut Builder {
678 self.byte_classes = yes;
679 self
680 }
681
682 /// Whether to premultiply state identifier in the DFA.
premultiply(&mut self, yes: bool) -> &mut Builder683 pub fn premultiply(&mut self, yes: bool) -> &mut Builder {
684 self.premultiply = yes;
685 self
686 }
687 }
688
689 /// This returns the next NFA transition (including resolving failure
690 /// transitions), except once it sees a state id less than the id of the DFA
691 /// state that is currently being populated, then we no longer need to follow
692 /// failure transitions and can instead query the pre-computed state id from
693 /// the DFA itself.
694 ///
695 /// In general, this should only be called when a failure transition is seen.
nfa_next_state_memoized<S: StateID>( nfa: &NFA<S>, dfa: &Repr<S>, populating: S, mut current: S, input: u8, ) -> S696 fn nfa_next_state_memoized<S: StateID>(
697 nfa: &NFA<S>,
698 dfa: &Repr<S>,
699 populating: S,
700 mut current: S,
701 input: u8,
702 ) -> S {
703 loop {
704 if current < populating {
705 return dfa.next_state(current, input);
706 }
707 let next = nfa.next_state(current, input);
708 if next != fail_id() {
709 return next;
710 }
711 current = nfa.failure_transition(current);
712 }
713 }
714