Coverage Report

Created: 2026-11-12 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/regex-1.5.6/src/dfa.rs
Line
Count
Source
1
/*!
2
The DFA matching engine.
3
4
A DFA provides faster matching because the engine is in exactly one state at
5
any point in time. In the NFA, there may be multiple active states, and
6
considerable CPU cycles are spent shuffling them around. In finite automata
7
speak, the DFA follows epsilon transitions in the regex far less than the NFA.
8
9
A DFA is a classic trade off between time and space. The NFA is slower, but
10
its memory requirements are typically small and predictable. The DFA is faster,
11
but given the right regex and the right input, the number of states in the
12
DFA can grow exponentially. To mitigate this space problem, we do two things:
13
14
1. We implement an *online* DFA. That is, the DFA is constructed from the NFA
15
   during a search. When a new state is computed, it is stored in a cache so
16
   that it may be reused. An important consequence of this implementation
17
   is that states that are never reached for a particular input are never
18
   computed. (This is impossible in an "offline" DFA which needs to compute
19
   all possible states up front.)
20
2. If the cache gets too big, we wipe it and continue matching.
21
22
In pathological cases, a new state can be created for every byte of input.
23
(e.g., The regex `(a|b)*a(a|b){20}` on a long sequence of a's and b's.)
24
In this case, performance regresses to slightly slower than the full NFA
25
simulation, in large part because the cache becomes useless. If the cache
26
is wiped too frequently, the DFA quits and control falls back to one of the
27
NFA simulations.
28
29
Because of the "lazy" nature of this DFA, the inner matching loop is
30
considerably more complex than one might expect out of a DFA. A number of
31
tricks are employed to make it fast. Tread carefully.
32
33
N.B. While this implementation is heavily commented, Russ Cox's series of
34
articles on regexes is strongly recommended: https://swtch.com/~rsc/regexp/
35
(As is the DFA implementation in RE2, which heavily influenced this
36
implementation.)
37
*/
38
39
use std::collections::HashMap;
40
use std::fmt;
41
use std::iter::repeat;
42
use std::mem;
43
use std::sync::Arc;
44
45
use crate::exec::ProgramCache;
46
use crate::prog::{Inst, Program};
47
use crate::sparse::SparseSet;
48
49
/// Return true if and only if the given program can be executed by a DFA.
50
///
51
/// Generally, a DFA is always possible. A pathological case where it is not
52
/// possible is if the number of NFA states exceeds `u32::MAX`, in which case,
53
/// this function will return false.
54
///
55
/// This function will also return false if the given program has any Unicode
56
/// instructions (Char or Ranges) since the DFA operates on bytes only.
57
21
pub fn can_exec(insts: &Program) -> bool {
58
    use crate::prog::Inst::*;
59
    // If for some reason we manage to allocate a regex program with more
60
    // than i32::MAX instructions, then we can't execute the DFA because we
61
    // use 32 bit instruction pointer deltas for memory savings.
62
    // If i32::MAX is the largest positive delta,
63
    // then -i32::MAX == i32::MIN + 1 is the largest negative delta,
64
    // and we are OK to use 32 bits.
65
21
    if insts.dfa_size_limit == 0 || insts.len() > ::std::i32::MAX as usize {
66
0
        return false;
67
21
    }
68
1.91k
    for inst in insts {
69
1.89k
        match *inst {
70
0
            Char(_) | Ranges(_) => return false,
71
1.89k
            EmptyLook(_) | Match(_) | Save(_) | Split(_) | Bytes(_) => {}
72
        }
73
    }
74
21
    true
75
21
}
regex::dfa::can_exec
Line
Count
Source
57
9
pub fn can_exec(insts: &Program) -> bool {
58
    use crate::prog::Inst::*;
59
    // If for some reason we manage to allocate a regex program with more
60
    // than i32::MAX instructions, then we can't execute the DFA because we
61
    // use 32 bit instruction pointer deltas for memory savings.
62
    // If i32::MAX is the largest positive delta,
63
    // then -i32::MAX == i32::MIN + 1 is the largest negative delta,
64
    // and we are OK to use 32 bits.
65
9
    if insts.dfa_size_limit == 0 || insts.len() > ::std::i32::MAX as usize {
66
0
        return false;
67
9
    }
68
819
    for inst in insts {
69
810
        match *inst {
70
0
            Char(_) | Ranges(_) => return false,
71
810
            EmptyLook(_) | Match(_) | Save(_) | Split(_) | Bytes(_) => {}
72
        }
73
    }
74
9
    true
75
9
}
regex::dfa::can_exec
Line
Count
Source
57
12
pub fn can_exec(insts: &Program) -> bool {
58
    use crate::prog::Inst::*;
59
    // If for some reason we manage to allocate a regex program with more
60
    // than i32::MAX instructions, then we can't execute the DFA because we
61
    // use 32 bit instruction pointer deltas for memory savings.
62
    // If i32::MAX is the largest positive delta,
63
    // then -i32::MAX == i32::MIN + 1 is the largest negative delta,
64
    // and we are OK to use 32 bits.
65
12
    if insts.dfa_size_limit == 0 || insts.len() > ::std::i32::MAX as usize {
66
0
        return false;
67
12
    }
68
1.09k
    for inst in insts {
69
1.08k
        match *inst {
70
0
            Char(_) | Ranges(_) => return false,
71
1.08k
            EmptyLook(_) | Match(_) | Save(_) | Split(_) | Bytes(_) => {}
72
        }
73
    }
74
12
    true
75
12
}
76
77
/// A reusable cache of DFA states.
78
///
79
/// This cache is reused between multiple invocations of the same regex
80
/// program. (It is not shared simultaneously between threads. If there is
81
/// contention, then new caches are created.)
82
#[derive(Debug)]
83
pub struct Cache {
84
    /// Group persistent DFA related cache state together. The sparse sets
85
    /// listed below are used as scratch space while computing uncached states.
86
    inner: CacheInner,
87
    /// qcur and qnext are ordered sets with constant time
88
    /// addition/membership/clearing-whole-set and linear time iteration. They
89
    /// are used to manage the sets of NFA states in DFA states when computing
90
    /// cached DFA states. In particular, the order of the NFA states matters
91
    /// for leftmost-first style matching. Namely, when computing a cached
92
    /// state, the set of NFA states stops growing as soon as the first Match
93
    /// instruction is observed.
94
    qcur: SparseSet,
95
    qnext: SparseSet,
96
}
97
98
/// `CacheInner` is logically just a part of Cache, but groups together fields
99
/// that aren't passed as function parameters throughout search. (This split
100
/// is mostly an artifact of the borrow checker. It is happily paid.)
101
#[derive(Debug)]
102
struct CacheInner {
103
    /// A cache of pre-compiled DFA states, keyed by the set of NFA states
104
    /// and the set of empty-width flags set at the byte in the input when the
105
    /// state was observed.
106
    ///
107
    /// A StatePtr is effectively a `*State`, but to avoid various inconvenient
108
    /// things, we just pass indexes around manually. The performance impact of
109
    /// this is probably an instruction or two in the inner loop. However, on
110
    /// 64 bit, each StatePtr is half the size of a *State.
111
    compiled: StateMap,
112
    /// The transition table.
113
    ///
114
    /// The transition table is laid out in row-major order, where states are
115
    /// rows and the transitions for each state are columns. At a high level,
116
    /// given state `s` and byte `b`, the next state can be found at index
117
    /// `s * 256 + b`.
118
    ///
119
    /// This is, of course, a lie. A StatePtr is actually a pointer to the
120
    /// *start* of a row in this table. When indexing in the DFA's inner loop,
121
    /// this removes the need to multiply the StatePtr by the stride. Yes, it
122
    /// matters. This reduces the number of states we can store, but: the
123
    /// stride is rarely 256 since we define transitions in terms of
124
    /// *equivalence classes* of bytes. Each class corresponds to a set of
125
    /// bytes that never discriminate a distinct path through the DFA from each
126
    /// other.
127
    trans: Transitions,
128
    /// A set of cached start states, which are limited to the number of
129
    /// permutations of flags set just before the initial byte of input. (The
130
    /// index into this vec is a `EmptyFlags`.)
131
    ///
132
    /// N.B. A start state can be "dead" (i.e., no possible match), so we
133
    /// represent it with a StatePtr.
134
    start_states: Vec<StatePtr>,
135
    /// Stack scratch space used to follow epsilon transitions in the NFA.
136
    /// (This permits us to avoid recursion.)
137
    ///
138
    /// The maximum stack size is the number of NFA states.
139
    stack: Vec<InstPtr>,
140
    /// The total number of times this cache has been flushed by the DFA
141
    /// because of space constraints.
142
    flush_count: u64,
143
    /// The total heap size of the DFA's cache. We use this to determine when
144
    /// we should flush the cache.
145
    size: usize,
146
    /// Scratch space used when building instruction pointer lists for new
147
    /// states. This helps amortize allocation.
148
    insts_scratch_space: Vec<u8>,
149
}
150
151
/// The transition table.
152
///
153
/// It is laid out in row-major order, with states as rows and byte class
154
/// transitions as columns.
155
///
156
/// The transition table is responsible for producing valid `StatePtrs`. A
157
/// `StatePtr` points to the start of a particular row in this table. When
158
/// indexing to find the next state this allows us to avoid a multiplication
159
/// when computing an index into the table.
160
#[derive(Clone)]
161
struct Transitions {
162
    /// The table.
163
    table: Vec<StatePtr>,
164
    /// The stride.
165
    num_byte_classes: usize,
166
}
167
168
/// Fsm encapsulates the actual execution of the DFA.
169
#[derive(Debug)]
170
pub struct Fsm<'a> {
171
    /// prog contains the NFA instruction opcodes. DFA execution uses either
172
    /// the `dfa` instructions or the `dfa_reverse` instructions from
173
    /// `exec::ExecReadOnly`. (It never uses `ExecReadOnly.nfa`, which may have
174
    /// Unicode opcodes that cannot be executed by the DFA.)
175
    prog: &'a Program,
176
    /// The start state. We record it here because the pointer may change
177
    /// when the cache is wiped.
178
    start: StatePtr,
179
    /// The current position in the input.
180
    at: usize,
181
    /// Should we quit after seeing the first match? e.g., When the caller
182
    /// uses `is_match` or `shortest_match`.
183
    quit_after_match: bool,
184
    /// The last state that matched.
185
    ///
186
    /// When no match has occurred, this is set to STATE_UNKNOWN.
187
    ///
188
    /// This is only useful when matching regex sets. The last match state
189
    /// is useful because it contains all of the match instructions seen,
190
    /// thereby allowing us to enumerate which regexes in the set matched.
191
    last_match_si: StatePtr,
192
    /// The input position of the last cache flush. We use this to determine
193
    /// if we're thrashing in the cache too often. If so, the DFA quits so
194
    /// that we can fall back to the NFA algorithm.
195
    last_cache_flush: usize,
196
    /// All cached DFA information that is persisted between searches.
197
    cache: &'a mut CacheInner,
198
}
199
200
/// The result of running the DFA.
201
///
202
/// Generally, the result is either a match or not a match, but sometimes the
203
/// DFA runs too slowly because the cache size is too small. In that case, it
204
/// gives up with the intent of falling back to the NFA algorithm.
205
///
206
/// The DFA can also give up if it runs out of room to create new states, or if
207
/// it sees non-ASCII bytes in the presence of a Unicode word boundary.
208
#[derive(Clone, Debug)]
209
pub enum Result<T> {
210
    Match(T),
211
    NoMatch(usize),
212
    Quit,
213
}
214
215
impl<T> Result<T> {
216
    /// Returns true if this result corresponds to a match.
217
0
    pub fn is_match(&self) -> bool {
218
0
        match *self {
219
0
            Result::Match(_) => true,
220
0
            Result::NoMatch(_) | Result::Quit => false,
221
        }
222
0
    }
Unexecuted instantiation: <regex::dfa::Result<usize>>::is_match
Unexecuted instantiation: <regex::dfa::Result<usize>>::is_match
223
224
    /// Maps the given function onto T and returns the result.
225
    ///
226
    /// If this isn't a match, then this is a no-op.
227
    #[cfg(feature = "perf-literal")]
228
0
    pub fn map<U, F: FnMut(T) -> U>(self, mut f: F) -> Result<U> {
229
0
        match self {
230
0
            Result::Match(t) => Result::Match(f(t)),
231
0
            Result::NoMatch(x) => Result::NoMatch(x),
232
0
            Result::Quit => Result::Quit,
233
        }
234
0
    }
Unexecuted instantiation: <regex::dfa::Result<(usize, usize)>>::map::<usize, <regex::exec::ExecNoSync>::shortest_dfa_reverse_suffix::{closure#0}>
Unexecuted instantiation: <regex::dfa::Result<(usize, usize)>>::map::<usize, <regex::exec::ExecNoSync>::shortest_dfa_reverse_suffix::{closure#0}>
235
236
    /// Sets the non-match position.
237
    ///
238
    /// If this isn't a non-match, then this is a no-op.
239
0
    fn set_non_match(self, at: usize) -> Result<T> {
240
0
        match self {
241
0
            Result::NoMatch(_) => Result::NoMatch(at),
242
0
            r => r,
243
        }
244
0
    }
Unexecuted instantiation: <regex::dfa::Result<usize>>::set_non_match
Unexecuted instantiation: <regex::dfa::Result<usize>>::set_non_match
245
}
246
247
/// `State` is a DFA state. It contains an ordered set of NFA states (not
248
/// necessarily complete) and a smattering of flags.
249
///
250
/// The flags are packed into the first byte of data.
251
///
252
/// States don't carry their transitions. Instead, transitions are stored in
253
/// a single row-major table.
254
///
255
/// Delta encoding is used to store the instruction pointers.
256
/// The first instruction pointer is stored directly starting
257
/// at data[1], and each following pointer is stored as an offset
258
/// to the previous one. If a delta is in the range -127..127,
259
/// it is packed into a single byte; Otherwise the byte 128 (-128 as an i8)
260
/// is coded as a flag, followed by 4 bytes encoding the delta.
261
#[derive(Clone, Eq, Hash, PartialEq)]
262
struct State {
263
    data: Arc<[u8]>,
264
}
265
266
/// `InstPtr` is a 32 bit pointer into a sequence of opcodes (i.e., it indexes
267
/// an NFA state).
268
///
269
/// Throughout this library, this is usually set to `usize`, but we force a
270
/// `u32` here for the DFA to save on space.
271
type InstPtr = u32;
272
273
/// Adds ip to data using delta encoding with respect to prev.
274
///
275
/// After completion, `data` will contain `ip` and `prev` will be set to `ip`.
276
0
fn push_inst_ptr(data: &mut Vec<u8>, prev: &mut InstPtr, ip: InstPtr) {
277
0
    let delta = (ip as i32) - (*prev as i32);
278
0
    write_vari32(data, delta);
279
0
    *prev = ip;
280
0
}
Unexecuted instantiation: regex::dfa::push_inst_ptr
Unexecuted instantiation: regex::dfa::push_inst_ptr
281
282
struct InstPtrs<'a> {
283
    base: usize,
284
    data: &'a [u8],
285
}
286
287
impl<'a> Iterator for InstPtrs<'a> {
288
    type Item = usize;
289
290
0
    fn next(&mut self) -> Option<usize> {
291
0
        if self.data.is_empty() {
292
0
            return None;
293
0
        }
294
0
        let (delta, nread) = read_vari32(self.data);
295
0
        let base = self.base as i32 + delta;
296
0
        debug_assert!(base >= 0);
297
0
        debug_assert!(nread > 0);
298
0
        self.data = &self.data[nread..];
299
0
        self.base = base as usize;
300
0
        Some(self.base)
301
0
    }
Unexecuted instantiation: <regex::dfa::InstPtrs as core::iter::traits::iterator::Iterator>::next
Unexecuted instantiation: <regex::dfa::InstPtrs as core::iter::traits::iterator::Iterator>::next
302
}
303
304
impl State {
305
0
    fn flags(&self) -> StateFlags {
306
0
        StateFlags(self.data[0])
307
0
    }
Unexecuted instantiation: <regex::dfa::State>::flags
Unexecuted instantiation: <regex::dfa::State>::flags
308
309
0
    fn inst_ptrs(&self) -> InstPtrs<'_> {
310
0
        InstPtrs { base: 0, data: &self.data[1..] }
311
0
    }
Unexecuted instantiation: <regex::dfa::State>::inst_ptrs
Unexecuted instantiation: <regex::dfa::State>::inst_ptrs
312
}
313
314
/// `StatePtr` is a 32 bit pointer to the start of a row in the transition
315
/// table.
316
///
317
/// It has many special values. There are two types of special values:
318
/// sentinels and flags.
319
///
320
/// Sentinels corresponds to special states that carry some kind of
321
/// significance. There are three such states: unknown, dead and quit states.
322
///
323
/// Unknown states are states that haven't been computed yet. They indicate
324
/// that a transition should be filled in that points to either an existing
325
/// cached state or a new state altogether. In general, an unknown state means
326
/// "follow the NFA's epsilon transitions."
327
///
328
/// Dead states are states that can never lead to a match, no matter what
329
/// subsequent input is observed. This means that the DFA should quit
330
/// immediately and return the longest match it has found thus far.
331
///
332
/// Quit states are states that imply the DFA is not capable of matching the
333
/// regex correctly. Currently, this is only used when a Unicode word boundary
334
/// exists in the regex *and* a non-ASCII byte is observed.
335
///
336
/// The other type of state pointer is a state pointer with special flag bits.
337
/// There are two flags: a start flag and a match flag. The lower bits of both
338
/// kinds always contain a "valid" `StatePtr` (indicated by the `STATE_MAX`
339
/// mask).
340
///
341
/// The start flag means that the state is a start state, and therefore may be
342
/// subject to special prefix scanning optimizations.
343
///
344
/// The match flag means that the state is a match state, and therefore the
345
/// current position in the input (while searching) should be recorded.
346
///
347
/// The above exists mostly in the service of making the inner loop fast.
348
/// In particular, the inner *inner* loop looks something like this:
349
///
350
/// ```ignore
351
/// while state <= STATE_MAX and i < len(text):
352
///     state = state.next[i]
353
/// ```
354
///
355
/// This is nice because it lets us execute a lazy DFA as if it were an
356
/// entirely offline DFA (i.e., with very few instructions). The loop will
357
/// quit only when we need to examine a case that needs special attention.
358
type StatePtr = u32;
359
360
/// An unknown state means that the state has not been computed yet, and that
361
/// the only way to progress is to compute it.
362
const STATE_UNKNOWN: StatePtr = 1 << 31;
363
364
/// A dead state means that the state has been computed and it is known that
365
/// once it is entered, no future match can ever occur.
366
const STATE_DEAD: StatePtr = STATE_UNKNOWN + 1;
367
368
/// A quit state means that the DFA came across some input that it doesn't
369
/// know how to process correctly. The DFA should quit and another matching
370
/// engine should be run in its place.
371
const STATE_QUIT: StatePtr = STATE_DEAD + 1;
372
373
/// A start state is a state that the DFA can start in.
374
///
375
/// Note that start states have their lower bits set to a state pointer.
376
const STATE_START: StatePtr = 1 << 30;
377
378
/// A match state means that the regex has successfully matched.
379
///
380
/// Note that match states have their lower bits set to a state pointer.
381
const STATE_MATCH: StatePtr = 1 << 29;
382
383
/// The maximum state pointer. This is useful to mask out the "valid" state
384
/// pointer from a state with the "start" or "match" bits set.
385
///
386
/// It doesn't make sense to use this with unknown, dead or quit state
387
/// pointers, since those pointers are sentinels and never have their lower
388
/// bits set to anything meaningful.
389
const STATE_MAX: StatePtr = STATE_MATCH - 1;
390
391
/// Byte is a u8 in spirit, but a u16 in practice so that we can represent the
392
/// special EOF sentinel value.
393
#[derive(Copy, Clone, Debug)]
394
struct Byte(u16);
395
396
/// A set of flags for zero-width assertions.
397
#[derive(Clone, Copy, Eq, Debug, Default, Hash, PartialEq)]
398
struct EmptyFlags {
399
    start: bool,
400
    end: bool,
401
    start_line: bool,
402
    end_line: bool,
403
    word_boundary: bool,
404
    not_word_boundary: bool,
405
}
406
407
/// A set of flags describing various configurations of a DFA state. This is
408
/// represented by a `u8` so that it is compact.
409
#[derive(Clone, Copy, Eq, Default, Hash, PartialEq)]
410
struct StateFlags(u8);
411
412
impl Cache {
413
    /// Create new empty cache for the DFA engine.
414
42
    pub fn new(prog: &Program) -> Self {
415
        // We add 1 to account for the special EOF byte.
416
42
        let num_byte_classes = (prog.byte_classes[255] as usize + 1) + 1;
417
42
        let starts = vec![STATE_UNKNOWN; 256];
418
42
        let mut cache = Cache {
419
42
            inner: CacheInner {
420
42
                compiled: StateMap::new(num_byte_classes),
421
42
                trans: Transitions::new(num_byte_classes),
422
42
                start_states: starts,
423
42
                stack: vec![],
424
42
                flush_count: 0,
425
42
                size: 0,
426
42
                insts_scratch_space: vec![],
427
42
            },
428
42
            qcur: SparseSet::new(prog.insts.len()),
429
42
            qnext: SparseSet::new(prog.insts.len()),
430
42
        };
431
42
        cache.inner.reset_size();
432
42
        cache
433
42
    }
<regex::dfa::Cache>::new
Line
Count
Source
414
18
    pub fn new(prog: &Program) -> Self {
415
        // We add 1 to account for the special EOF byte.
416
18
        let num_byte_classes = (prog.byte_classes[255] as usize + 1) + 1;
417
18
        let starts = vec![STATE_UNKNOWN; 256];
418
18
        let mut cache = Cache {
419
18
            inner: CacheInner {
420
18
                compiled: StateMap::new(num_byte_classes),
421
18
                trans: Transitions::new(num_byte_classes),
422
18
                start_states: starts,
423
18
                stack: vec![],
424
18
                flush_count: 0,
425
18
                size: 0,
426
18
                insts_scratch_space: vec![],
427
18
            },
428
18
            qcur: SparseSet::new(prog.insts.len()),
429
18
            qnext: SparseSet::new(prog.insts.len()),
430
18
        };
431
18
        cache.inner.reset_size();
432
18
        cache
433
18
    }
<regex::dfa::Cache>::new
Line
Count
Source
414
24
    pub fn new(prog: &Program) -> Self {
415
        // We add 1 to account for the special EOF byte.
416
24
        let num_byte_classes = (prog.byte_classes[255] as usize + 1) + 1;
417
24
        let starts = vec![STATE_UNKNOWN; 256];
418
24
        let mut cache = Cache {
419
24
            inner: CacheInner {
420
24
                compiled: StateMap::new(num_byte_classes),
421
24
                trans: Transitions::new(num_byte_classes),
422
24
                start_states: starts,
423
24
                stack: vec![],
424
24
                flush_count: 0,
425
24
                size: 0,
426
24
                insts_scratch_space: vec![],
427
24
            },
428
24
            qcur: SparseSet::new(prog.insts.len()),
429
24
            qnext: SparseSet::new(prog.insts.len()),
430
24
        };
431
24
        cache.inner.reset_size();
432
24
        cache
433
24
    }
434
}
435
436
impl CacheInner {
437
    /// Resets the cache size to account for fixed costs, such as the program
438
    /// and stack sizes.
439
42
    fn reset_size(&mut self) {
440
42
        self.size = (self.start_states.len() * mem::size_of::<StatePtr>())
441
42
            + (self.stack.len() * mem::size_of::<InstPtr>());
442
42
    }
<regex::dfa::CacheInner>::reset_size
Line
Count
Source
439
18
    fn reset_size(&mut self) {
440
18
        self.size = (self.start_states.len() * mem::size_of::<StatePtr>())
441
18
            + (self.stack.len() * mem::size_of::<InstPtr>());
442
18
    }
<regex::dfa::CacheInner>::reset_size
Line
Count
Source
439
24
    fn reset_size(&mut self) {
440
24
        self.size = (self.start_states.len() * mem::size_of::<StatePtr>())
441
24
            + (self.stack.len() * mem::size_of::<InstPtr>());
442
24
    }
443
}
444
445
impl<'a> Fsm<'a> {
446
    #[cfg_attr(feature = "perf-inline", inline(always))]
447
0
    pub fn forward(
448
0
        prog: &'a Program,
449
0
        cache: &ProgramCache,
450
0
        quit_after_match: bool,
451
0
        text: &[u8],
452
0
        at: usize,
453
0
    ) -> Result<usize> {
454
0
        let mut cache = cache.borrow_mut();
455
0
        let cache = &mut cache.dfa;
456
0
        let mut dfa = Fsm {
457
0
            prog: prog,
458
0
            start: 0, // filled in below
459
0
            at: at,
460
0
            quit_after_match: quit_after_match,
461
0
            last_match_si: STATE_UNKNOWN,
462
0
            last_cache_flush: at,
463
0
            cache: &mut cache.inner,
464
0
        };
465
0
        let (empty_flags, state_flags) = dfa.start_flags(text, at);
466
        dfa.start =
467
0
            match dfa.start_state(&mut cache.qcur, empty_flags, state_flags) {
468
0
                None => return Result::Quit,
469
0
                Some(STATE_DEAD) => return Result::NoMatch(at),
470
0
                Some(si) => si,
471
            };
472
0
        debug_assert!(dfa.start != STATE_UNKNOWN);
473
0
        dfa.exec_at(&mut cache.qcur, &mut cache.qnext, text)
474
0
    }
Unexecuted instantiation: <regex::dfa::Fsm>::forward
Unexecuted instantiation: <regex::dfa::Fsm>::forward
475
476
    #[cfg_attr(feature = "perf-inline", inline(always))]
477
0
    pub fn reverse(
478
0
        prog: &'a Program,
479
0
        cache: &ProgramCache,
480
0
        quit_after_match: bool,
481
0
        text: &[u8],
482
0
        at: usize,
483
0
    ) -> Result<usize> {
484
0
        let mut cache = cache.borrow_mut();
485
0
        let cache = &mut cache.dfa_reverse;
486
0
        let mut dfa = Fsm {
487
0
            prog: prog,
488
0
            start: 0, // filled in below
489
0
            at: at,
490
0
            quit_after_match: quit_after_match,
491
0
            last_match_si: STATE_UNKNOWN,
492
0
            last_cache_flush: at,
493
0
            cache: &mut cache.inner,
494
0
        };
495
0
        let (empty_flags, state_flags) = dfa.start_flags_reverse(text, at);
496
        dfa.start =
497
0
            match dfa.start_state(&mut cache.qcur, empty_flags, state_flags) {
498
0
                None => return Result::Quit,
499
0
                Some(STATE_DEAD) => return Result::NoMatch(at),
500
0
                Some(si) => si,
501
            };
502
0
        debug_assert!(dfa.start != STATE_UNKNOWN);
503
0
        dfa.exec_at_reverse(&mut cache.qcur, &mut cache.qnext, text)
504
0
    }
Unexecuted instantiation: <regex::dfa::Fsm>::reverse
Unexecuted instantiation: <regex::dfa::Fsm>::reverse
505
506
    #[cfg_attr(feature = "perf-inline", inline(always))]
507
0
    pub fn forward_many(
508
0
        prog: &'a Program,
509
0
        cache: &ProgramCache,
510
0
        matches: &mut [bool],
511
0
        text: &[u8],
512
0
        at: usize,
513
0
    ) -> Result<usize> {
514
0
        debug_assert!(matches.len() == prog.matches.len());
515
0
        let mut cache = cache.borrow_mut();
516
0
        let cache = &mut cache.dfa;
517
0
        let mut dfa = Fsm {
518
0
            prog: prog,
519
0
            start: 0, // filled in below
520
0
            at: at,
521
0
            quit_after_match: false,
522
0
            last_match_si: STATE_UNKNOWN,
523
0
            last_cache_flush: at,
524
0
            cache: &mut cache.inner,
525
0
        };
526
0
        let (empty_flags, state_flags) = dfa.start_flags(text, at);
527
        dfa.start =
528
0
            match dfa.start_state(&mut cache.qcur, empty_flags, state_flags) {
529
0
                None => return Result::Quit,
530
0
                Some(STATE_DEAD) => return Result::NoMatch(at),
531
0
                Some(si) => si,
532
            };
533
0
        debug_assert!(dfa.start != STATE_UNKNOWN);
534
0
        let result = dfa.exec_at(&mut cache.qcur, &mut cache.qnext, text);
535
0
        if result.is_match() {
536
0
            if matches.len() == 1 {
537
0
                matches[0] = true;
538
0
            } else {
539
0
                debug_assert!(dfa.last_match_si != STATE_UNKNOWN);
540
0
                debug_assert!(dfa.last_match_si != STATE_DEAD);
541
0
                for ip in dfa.state(dfa.last_match_si).inst_ptrs() {
542
0
                    if let Inst::Match(slot) = dfa.prog[ip] {
543
0
                        matches[slot] = true;
544
0
                    }
545
                }
546
            }
547
0
        }
548
0
        result
549
0
    }
Unexecuted instantiation: <regex::dfa::Fsm>::forward_many
Unexecuted instantiation: <regex::dfa::Fsm>::forward_many
550
551
    /// Executes the DFA on a forward NFA.
552
    ///
553
    /// {qcur,qnext} are scratch ordered sets which may be non-empty.
554
    #[cfg_attr(feature = "perf-inline", inline(always))]
555
0
    fn exec_at(
556
0
        &mut self,
557
0
        qcur: &mut SparseSet,
558
0
        qnext: &mut SparseSet,
559
0
        text: &[u8],
560
0
    ) -> Result<usize> {
561
        // For the most part, the DFA is basically:
562
        //
563
        //   last_match = null
564
        //   while current_byte != EOF:
565
        //     si = current_state.next[current_byte]
566
        //     if si is match
567
        //       last_match = si
568
        //   return last_match
569
        //
570
        // However, we need to deal with a few things:
571
        //
572
        //   1. This is an *online* DFA, so the current state's next list
573
        //      may not point to anywhere yet, so we must go out and compute
574
        //      them. (They are then cached into the current state's next list
575
        //      to avoid re-computation.)
576
        //   2. If we come across a state that is known to be dead (i.e., never
577
        //      leads to a match), then we can quit early.
578
        //   3. If the caller just wants to know if a match occurs, then we
579
        //      can quit as soon as we know we have a match. (Full leftmost
580
        //      first semantics require continuing on.)
581
        //   4. If we're in the start state, then we can use a pre-computed set
582
        //      of prefix literals to skip quickly along the input.
583
        //   5. After the input is exhausted, we run the DFA on one symbol
584
        //      that stands for EOF. This is useful for handling empty width
585
        //      assertions.
586
        //   6. We can't actually do state.next[byte]. Instead, we have to do
587
        //      state.next[byte_classes[byte]], which permits us to keep the
588
        //      'next' list very small.
589
        //
590
        // Since there's a bunch of extra stuff we need to consider, we do some
591
        // pretty hairy tricks to get the inner loop to run as fast as
592
        // possible.
593
0
        debug_assert!(!self.prog.is_reverse);
594
595
        // The last match is the currently known ending match position. It is
596
        // reported as an index to the most recent byte that resulted in a
597
        // transition to a match state and is always stored in capture slot `1`
598
        // when searching forwards. Its maximum value is `text.len()`.
599
0
        let mut result = Result::NoMatch(self.at);
600
0
        let (mut prev_si, mut next_si) = (self.start, self.start);
601
0
        let mut at = self.at;
602
0
        while at < text.len() {
603
            // This is the real inner loop. We take advantage of special bits
604
            // set in the state pointer to determine whether a state is in the
605
            // "common" case or not. Specifically, the common case is a
606
            // non-match non-start non-dead state that has already been
607
            // computed. So long as we remain in the common case, this inner
608
            // loop will chew through the input.
609
            //
610
            // We also unroll the loop 4 times to amortize the cost of checking
611
            // whether we've consumed the entire input. We are also careful
612
            // to make sure that `prev_si` always represents the previous state
613
            // and `next_si` always represents the next state after the loop
614
            // exits, even if it isn't always true inside the loop.
615
0
            while next_si <= STATE_MAX && at < text.len() {
616
                // Argument for safety is in the definition of next_si.
617
0
                prev_si = unsafe { self.next_si(next_si, text, at) };
618
0
                at += 1;
619
0
                if prev_si > STATE_MAX || at + 2 >= text.len() {
620
0
                    mem::swap(&mut prev_si, &mut next_si);
621
0
                    break;
622
0
                }
623
0
                next_si = unsafe { self.next_si(prev_si, text, at) };
624
0
                at += 1;
625
0
                if next_si > STATE_MAX {
626
0
                    break;
627
0
                }
628
0
                prev_si = unsafe { self.next_si(next_si, text, at) };
629
0
                at += 1;
630
0
                if prev_si > STATE_MAX {
631
0
                    mem::swap(&mut prev_si, &mut next_si);
632
0
                    break;
633
0
                }
634
0
                next_si = unsafe { self.next_si(prev_si, text, at) };
635
0
                at += 1;
636
            }
637
0
            if next_si & STATE_MATCH > 0 {
638
                // A match state is outside of the common case because it needs
639
                // special case analysis. In particular, we need to record the
640
                // last position as having matched and possibly quit the DFA if
641
                // we don't need to keep matching.
642
0
                next_si &= !STATE_MATCH;
643
0
                result = Result::Match(at - 1);
644
0
                if self.quit_after_match {
645
0
                    return result;
646
0
                }
647
0
                self.last_match_si = next_si;
648
0
                prev_si = next_si;
649
650
                // This permits short-circuiting when matching a regex set.
651
                // In particular, if this DFA state contains only match states,
652
                // then it's impossible to extend the set of matches since
653
                // match states are final. Therefore, we can quit.
654
0
                if self.prog.matches.len() > 1 {
655
0
                    let state = self.state(next_si);
656
0
                    let just_matches =
657
0
                        state.inst_ptrs().all(|ip| self.prog[ip].is_match());
Unexecuted instantiation: <regex::dfa::Fsm>::exec_at::{closure#0}
Unexecuted instantiation: <regex::dfa::Fsm>::exec_at::{closure#0}
658
0
                    if just_matches {
659
0
                        return result;
660
0
                    }
661
0
                }
662
663
                // Another inner loop! If the DFA stays in this particular
664
                // match state, then we can rip through all of the input
665
                // very quickly, and only recording the match location once
666
                // we've left this particular state.
667
0
                let cur = at;
668
0
                while (next_si & !STATE_MATCH) == prev_si
669
0
                    && at + 2 < text.len()
670
0
                {
671
0
                    // Argument for safety is in the definition of next_si.
672
0
                    next_si = unsafe {
673
0
                        self.next_si(next_si & !STATE_MATCH, text, at)
674
0
                    };
675
0
                    at += 1;
676
0
                }
677
0
                if at > cur {
678
0
                    result = Result::Match(at - 2);
679
0
                }
680
0
            } else if next_si & STATE_START > 0 {
681
                // A start state isn't in the common case because we may
682
                // want to do quick prefix scanning. If the program doesn't
683
                // have a detected prefix, then start states are actually
684
                // considered common and this case is never reached.
685
0
                debug_assert!(self.has_prefix());
686
0
                next_si &= !STATE_START;
687
0
                prev_si = next_si;
688
0
                at = match self.prefix_at(text, at) {
689
0
                    None => return Result::NoMatch(text.len()),
690
0
                    Some(i) => i,
691
                };
692
0
            } else if next_si >= STATE_UNKNOWN {
693
0
                if next_si == STATE_QUIT {
694
0
                    return Result::Quit;
695
0
                }
696
                // Finally, this corresponds to the case where the transition
697
                // entered a state that can never lead to a match or a state
698
                // that hasn't been computed yet. The latter being the "slow"
699
                // path.
700
0
                let byte = Byte::byte(text[at - 1]);
701
                // We no longer care about the special bits in the state
702
                // pointer.
703
0
                prev_si &= STATE_MAX;
704
                // Record where we are. This is used to track progress for
705
                // determining whether we should quit if we've flushed the
706
                // cache too much.
707
0
                self.at = at;
708
0
                next_si = match self.next_state(qcur, qnext, prev_si, byte) {
709
0
                    None => return Result::Quit,
710
0
                    Some(STATE_DEAD) => return result.set_non_match(at),
711
0
                    Some(si) => si,
712
                };
713
0
                debug_assert!(next_si != STATE_UNKNOWN);
714
0
                if next_si & STATE_MATCH > 0 {
715
0
                    next_si &= !STATE_MATCH;
716
0
                    result = Result::Match(at - 1);
717
0
                    if self.quit_after_match {
718
0
                        return result;
719
0
                    }
720
0
                    self.last_match_si = next_si;
721
0
                }
722
0
                prev_si = next_si;
723
0
            } else {
724
0
                prev_si = next_si;
725
0
            }
726
        }
727
728
        // Run the DFA once more on the special EOF sentinel value.
729
        // We don't care about the special bits in the state pointer any more,
730
        // so get rid of them.
731
0
        prev_si &= STATE_MAX;
732
0
        prev_si = match self.next_state(qcur, qnext, prev_si, Byte::eof()) {
733
0
            None => return Result::Quit,
734
0
            Some(STATE_DEAD) => return result.set_non_match(text.len()),
735
0
            Some(si) => si & !STATE_START,
736
        };
737
0
        debug_assert!(prev_si != STATE_UNKNOWN);
738
0
        if prev_si & STATE_MATCH > 0 {
739
0
            prev_si &= !STATE_MATCH;
740
0
            self.last_match_si = prev_si;
741
0
            result = Result::Match(text.len());
742
0
        }
743
0
        result
744
0
    }
Unexecuted instantiation: <regex::dfa::Fsm>::exec_at
Unexecuted instantiation: <regex::dfa::Fsm>::exec_at
745
746
    /// Executes the DFA on a reverse NFA.
747
    #[cfg_attr(feature = "perf-inline", inline(always))]
748
0
    fn exec_at_reverse(
749
0
        &mut self,
750
0
        qcur: &mut SparseSet,
751
0
        qnext: &mut SparseSet,
752
0
        text: &[u8],
753
0
    ) -> Result<usize> {
754
        // The comments in `exec_at` above mostly apply here too. The main
755
        // difference is that we move backwards over the input and we look for
756
        // the longest possible match instead of the leftmost-first match.
757
        //
758
        // N.B. The code duplication here is regrettable. Efforts to improve
759
        // it without sacrificing performance are welcome. ---AG
760
0
        debug_assert!(self.prog.is_reverse);
761
0
        let mut result = Result::NoMatch(self.at);
762
0
        let (mut prev_si, mut next_si) = (self.start, self.start);
763
0
        let mut at = self.at;
764
0
        while at > 0 {
765
0
            while next_si <= STATE_MAX && at > 0 {
766
                // Argument for safety is in the definition of next_si.
767
0
                at -= 1;
768
0
                prev_si = unsafe { self.next_si(next_si, text, at) };
769
0
                if prev_si > STATE_MAX || at <= 4 {
770
0
                    mem::swap(&mut prev_si, &mut next_si);
771
0
                    break;
772
0
                }
773
0
                at -= 1;
774
0
                next_si = unsafe { self.next_si(prev_si, text, at) };
775
0
                if next_si > STATE_MAX {
776
0
                    break;
777
0
                }
778
0
                at -= 1;
779
0
                prev_si = unsafe { self.next_si(next_si, text, at) };
780
0
                if prev_si > STATE_MAX {
781
0
                    mem::swap(&mut prev_si, &mut next_si);
782
0
                    break;
783
0
                }
784
0
                at -= 1;
785
0
                next_si = unsafe { self.next_si(prev_si, text, at) };
786
            }
787
0
            if next_si & STATE_MATCH > 0 {
788
0
                next_si &= !STATE_MATCH;
789
0
                result = Result::Match(at + 1);
790
0
                if self.quit_after_match {
791
0
                    return result;
792
0
                }
793
0
                self.last_match_si = next_si;
794
0
                prev_si = next_si;
795
0
                let cur = at;
796
0
                while (next_si & !STATE_MATCH) == prev_si && at >= 2 {
797
0
                    // Argument for safety is in the definition of next_si.
798
0
                    at -= 1;
799
0
                    next_si = unsafe {
800
0
                        self.next_si(next_si & !STATE_MATCH, text, at)
801
0
                    };
802
0
                }
803
0
                if at < cur {
804
0
                    result = Result::Match(at + 2);
805
0
                }
806
0
            } else if next_si >= STATE_UNKNOWN {
807
0
                if next_si == STATE_QUIT {
808
0
                    return Result::Quit;
809
0
                }
810
0
                let byte = Byte::byte(text[at]);
811
0
                prev_si &= STATE_MAX;
812
0
                self.at = at;
813
0
                next_si = match self.next_state(qcur, qnext, prev_si, byte) {
814
0
                    None => return Result::Quit,
815
0
                    Some(STATE_DEAD) => return result.set_non_match(at),
816
0
                    Some(si) => si,
817
                };
818
0
                debug_assert!(next_si != STATE_UNKNOWN);
819
0
                if next_si & STATE_MATCH > 0 {
820
0
                    next_si &= !STATE_MATCH;
821
0
                    result = Result::Match(at + 1);
822
0
                    if self.quit_after_match {
823
0
                        return result;
824
0
                    }
825
0
                    self.last_match_si = next_si;
826
0
                }
827
0
                prev_si = next_si;
828
0
            } else {
829
0
                prev_si = next_si;
830
0
            }
831
        }
832
833
        // Run the DFA once more on the special EOF sentinel value.
834
0
        prev_si = match self.next_state(qcur, qnext, prev_si, Byte::eof()) {
835
0
            None => return Result::Quit,
836
0
            Some(STATE_DEAD) => return result.set_non_match(0),
837
0
            Some(si) => si,
838
        };
839
0
        debug_assert!(prev_si != STATE_UNKNOWN);
840
0
        if prev_si & STATE_MATCH > 0 {
841
0
            prev_si &= !STATE_MATCH;
842
0
            self.last_match_si = prev_si;
843
0
            result = Result::Match(0);
844
0
        }
845
0
        result
846
0
    }
Unexecuted instantiation: <regex::dfa::Fsm>::exec_at_reverse
Unexecuted instantiation: <regex::dfa::Fsm>::exec_at_reverse
847
848
    /// next_si transitions to the next state, where the transition input
849
    /// corresponds to text[i].
850
    ///
851
    /// This elides bounds checks, and is therefore not safe.
852
    #[cfg_attr(feature = "perf-inline", inline(always))]
853
0
    unsafe fn next_si(&self, si: StatePtr, text: &[u8], i: usize) -> StatePtr {
854
        // What is the argument for safety here?
855
        // We have three unchecked accesses that could possibly violate safety:
856
        //
857
        //   1. The given byte of input (`text[i]`).
858
        //   2. The class of the byte of input (`classes[text[i]]`).
859
        //   3. The transition for the class (`trans[si + cls]`).
860
        //
861
        // (1) is only safe when calling next_si is guarded by
862
        // `i < text.len()`.
863
        //
864
        // (2) is the easiest case to guarantee since `text[i]` is always a
865
        // `u8` and `self.prog.byte_classes` always has length `u8::MAX`.
866
        // (See `ByteClassSet.byte_classes` in `compile.rs`.)
867
        //
868
        // (3) is only safe if (1)+(2) are safe. Namely, the transitions
869
        // of every state are defined to have length equal to the number of
870
        // byte classes in the program. Therefore, a valid class leads to a
871
        // valid transition. (All possible transitions are valid lookups, even
872
        // if it points to a state that hasn't been computed yet.) (3) also
873
        // relies on `si` being correct, but StatePtrs should only ever be
874
        // retrieved from the transition table, which ensures they are correct.
875
0
        debug_assert!(i < text.len());
876
0
        let b = *text.get_unchecked(i);
877
0
        debug_assert!((b as usize) < self.prog.byte_classes.len());
878
0
        let cls = *self.prog.byte_classes.get_unchecked(b as usize);
879
0
        self.cache.trans.next_unchecked(si, cls as usize)
880
0
    }
Unexecuted instantiation: <regex::dfa::Fsm>::next_si
Unexecuted instantiation: <regex::dfa::Fsm>::next_si
881
882
    /// Computes the next state given the current state and the current input
883
    /// byte (which may be EOF).
884
    ///
885
    /// If STATE_DEAD is returned, then there is no valid state transition.
886
    /// This implies that no permutation of future input can lead to a match
887
    /// state.
888
    ///
889
    /// STATE_UNKNOWN can never be returned.
890
0
    fn exec_byte(
891
0
        &mut self,
892
0
        qcur: &mut SparseSet,
893
0
        qnext: &mut SparseSet,
894
0
        mut si: StatePtr,
895
0
        b: Byte,
896
0
    ) -> Option<StatePtr> {
897
        use crate::prog::Inst::*;
898
899
        // Initialize a queue with the current DFA state's NFA states.
900
0
        qcur.clear();
901
0
        for ip in self.state(si).inst_ptrs() {
902
0
            qcur.insert(ip);
903
0
        }
904
905
        // Before inspecting the current byte, we may need to also inspect
906
        // whether the position immediately preceding the current byte
907
        // satisfies the empty assertions found in the current state.
908
        //
909
        // We only need to do this step if there are any empty assertions in
910
        // the current state.
911
0
        let is_word_last = self.state(si).flags().is_word();
912
0
        let is_word = b.is_ascii_word();
913
0
        if self.state(si).flags().has_empty() {
914
            // Compute the flags immediately preceding the current byte.
915
            // This means we only care about the "end" or "end line" flags.
916
            // (The "start" flags are computed immediately following the
917
            // current byte and are handled below.)
918
0
            let mut flags = EmptyFlags::default();
919
0
            if b.is_eof() {
920
0
                flags.end = true;
921
0
                flags.end_line = true;
922
0
            } else if b.as_byte().map_or(false, |b| b == b'\n') {
Unexecuted instantiation: <regex::dfa::Fsm>::exec_byte::{closure#0}
Unexecuted instantiation: <regex::dfa::Fsm>::exec_byte::{closure#0}
923
0
                flags.end_line = true;
924
0
            }
925
0
            if is_word_last == is_word {
926
0
                flags.not_word_boundary = true;
927
0
            } else {
928
0
                flags.word_boundary = true;
929
0
            }
930
            // Now follow epsilon transitions from every NFA state, but make
931
            // sure we only follow transitions that satisfy our flags.
932
0
            qnext.clear();
933
0
            for &ip in &*qcur {
934
0
                self.follow_epsilons(usize_to_u32(ip), qnext, flags);
935
0
            }
936
0
            mem::swap(qcur, qnext);
937
0
        }
938
939
        // Now we set flags for immediately after the current byte. Since start
940
        // states are processed separately, and are the only states that can
941
        // have the StartText flag set, we therefore only need to worry about
942
        // the StartLine flag here.
943
        //
944
        // We do also keep track of whether this DFA state contains a NFA state
945
        // that is a matching state. This is precisely how we delay the DFA
946
        // matching by one byte in order to process the special EOF sentinel
947
        // byte. Namely, if this DFA state containing a matching NFA state,
948
        // then it is the *next* DFA state that is marked as a match.
949
0
        let mut empty_flags = EmptyFlags::default();
950
0
        let mut state_flags = StateFlags::default();
951
0
        empty_flags.start_line = b.as_byte().map_or(false, |b| b == b'\n');
Unexecuted instantiation: <regex::dfa::Fsm>::exec_byte::{closure#1}
Unexecuted instantiation: <regex::dfa::Fsm>::exec_byte::{closure#1}
952
0
        if b.is_ascii_word() {
953
0
            state_flags.set_word();
954
0
        }
955
        // Now follow all epsilon transitions again, but only after consuming
956
        // the current byte.
957
0
        qnext.clear();
958
0
        for &ip in &*qcur {
959
0
            match self.prog[ip as usize] {
960
                // These states never happen in a byte-based program.
961
0
                Char(_) | Ranges(_) => unreachable!(),
962
                // These states are handled when following epsilon transitions.
963
0
                Save(_) | Split(_) | EmptyLook(_) => {}
964
                Match(_) => {
965
0
                    state_flags.set_match();
966
0
                    if !self.continue_past_first_match() {
967
0
                        break;
968
0
                    } else if self.prog.matches.len() > 1
969
0
                        && !qnext.contains(ip as usize)
970
0
                    {
971
0
                        // If we are continuing on to find other matches,
972
0
                        // then keep a record of the match states we've seen.
973
0
                        qnext.insert(ip);
974
0
                    }
975
                }
976
0
                Bytes(ref inst) => {
977
0
                    if b.as_byte().map_or(false, |b| inst.matches(b)) {
Unexecuted instantiation: <regex::dfa::Fsm>::exec_byte::{closure#2}
Unexecuted instantiation: <regex::dfa::Fsm>::exec_byte::{closure#2}
978
0
                        self.follow_epsilons(
979
0
                            inst.goto as InstPtr,
980
0
                            qnext,
981
0
                            empty_flags,
982
0
                        );
983
0
                    }
984
                }
985
            }
986
        }
987
988
0
        let cache = if b.is_eof() && self.prog.matches.len() > 1 {
989
            // If we're processing the last byte of the input and we're
990
            // matching a regex set, then make the next state contain the
991
            // previous states transitions. We do this so that the main
992
            // matching loop can extract all of the match instructions.
993
0
            mem::swap(qcur, qnext);
994
            // And don't cache this state because it's totally bunk.
995
0
            false
996
        } else {
997
0
            true
998
        };
999
1000
        // We've now built up the set of NFA states that ought to comprise the
1001
        // next DFA state, so try to find it in the cache, and if it doesn't
1002
        // exist, cache it.
1003
        //
1004
        // N.B. We pass `&mut si` here because the cache may clear itself if
1005
        // it has gotten too full. When that happens, the location of the
1006
        // current state may change.
1007
0
        let mut next =
1008
0
            match self.cached_state(qnext, state_flags, Some(&mut si)) {
1009
0
                None => return None,
1010
0
                Some(next) => next,
1011
            };
1012
0
        if (self.start & !STATE_START) == next {
1013
            // Start states can never be match states since all matches are
1014
            // delayed by one byte.
1015
0
            debug_assert!(!self.state(next).flags().is_match());
1016
0
            next = self.start_ptr(next);
1017
0
        }
1018
0
        if next <= STATE_MAX && self.state(next).flags().is_match() {
1019
0
            next |= STATE_MATCH;
1020
0
        }
1021
0
        debug_assert!(next != STATE_UNKNOWN);
1022
        // And now store our state in the current state's next list.
1023
0
        if cache {
1024
0
            let cls = self.byte_class(b);
1025
0
            self.cache.trans.set_next(si, cls, next);
1026
0
        }
1027
0
        Some(next)
1028
0
    }
Unexecuted instantiation: <regex::dfa::Fsm>::exec_byte
Unexecuted instantiation: <regex::dfa::Fsm>::exec_byte
1029
1030
    /// Follows the epsilon transitions starting at (and including) `ip`. The
1031
    /// resulting states are inserted into the ordered set `q`.
1032
    ///
1033
    /// Conditional epsilon transitions (i.e., empty width assertions) are only
1034
    /// followed if they are satisfied by the given flags, which should
1035
    /// represent the flags set at the current location in the input.
1036
    ///
1037
    /// If the current location corresponds to the empty string, then only the
1038
    /// end line and/or end text flags may be set. If the current location
1039
    /// corresponds to a real byte in the input, then only the start line
1040
    /// and/or start text flags may be set.
1041
    ///
1042
    /// As an exception to the above, when finding the initial state, any of
1043
    /// the above flags may be set:
1044
    ///
1045
    /// If matching starts at the beginning of the input, then start text and
1046
    /// start line should be set. If the input is empty, then end text and end
1047
    /// line should also be set.
1048
    ///
1049
    /// If matching starts after the beginning of the input, then only start
1050
    /// line should be set if the preceding byte is `\n`. End line should never
1051
    /// be set in this case. (Even if the following byte is a `\n`, it will
1052
    /// be handled in a subsequent DFA state.)
1053
0
    fn follow_epsilons(
1054
0
        &mut self,
1055
0
        ip: InstPtr,
1056
0
        q: &mut SparseSet,
1057
0
        flags: EmptyFlags,
1058
0
    ) {
1059
        use crate::prog::EmptyLook::*;
1060
        use crate::prog::Inst::*;
1061
1062
        // We need to traverse the NFA to follow epsilon transitions, so avoid
1063
        // recursion with an explicit stack.
1064
0
        self.cache.stack.push(ip);
1065
0
        while let Some(mut ip) = self.cache.stack.pop() {
1066
            // Try to munch through as many states as possible without
1067
            // pushes/pops to the stack.
1068
            loop {
1069
                // Don't visit states we've already added.
1070
0
                if q.contains(ip as usize) {
1071
0
                    break;
1072
0
                }
1073
0
                q.insert(ip as usize);
1074
0
                match self.prog[ip as usize] {
1075
0
                    Char(_) | Ranges(_) => unreachable!(),
1076
                    Match(_) | Bytes(_) => {
1077
0
                        break;
1078
                    }
1079
0
                    EmptyLook(ref inst) => {
1080
                        // Only follow empty assertion states if our flags
1081
                        // satisfy the assertion.
1082
0
                        match inst.look {
1083
0
                            StartLine if flags.start_line => {
1084
0
                                ip = inst.goto as InstPtr;
1085
0
                            }
1086
0
                            EndLine if flags.end_line => {
1087
0
                                ip = inst.goto as InstPtr;
1088
0
                            }
1089
0
                            StartText if flags.start => {
1090
0
                                ip = inst.goto as InstPtr;
1091
0
                            }
1092
0
                            EndText if flags.end => {
1093
0
                                ip = inst.goto as InstPtr;
1094
0
                            }
1095
0
                            WordBoundaryAscii if flags.word_boundary => {
1096
0
                                ip = inst.goto as InstPtr;
1097
0
                            }
1098
                            NotWordBoundaryAscii
1099
0
                                if flags.not_word_boundary =>
1100
0
                            {
1101
0
                                ip = inst.goto as InstPtr;
1102
0
                            }
1103
0
                            WordBoundary if flags.word_boundary => {
1104
0
                                ip = inst.goto as InstPtr;
1105
0
                            }
1106
0
                            NotWordBoundary if flags.not_word_boundary => {
1107
0
                                ip = inst.goto as InstPtr;
1108
0
                            }
1109
                            StartLine | EndLine | StartText | EndText
1110
                            | WordBoundaryAscii | NotWordBoundaryAscii
1111
                            | WordBoundary | NotWordBoundary => {
1112
0
                                break;
1113
                            }
1114
                        }
1115
                    }
1116
0
                    Save(ref inst) => {
1117
0
                        ip = inst.goto as InstPtr;
1118
0
                    }
1119
0
                    Split(ref inst) => {
1120
0
                        self.cache.stack.push(inst.goto2 as InstPtr);
1121
0
                        ip = inst.goto1 as InstPtr;
1122
0
                    }
1123
                }
1124
            }
1125
        }
1126
0
    }
Unexecuted instantiation: <regex::dfa::Fsm>::follow_epsilons
Unexecuted instantiation: <regex::dfa::Fsm>::follow_epsilons
1127
1128
    /// Find a previously computed state matching the given set of instructions
1129
    /// and is_match bool.
1130
    ///
1131
    /// The given set of instructions should represent a single state in the
1132
    /// NFA along with all states reachable without consuming any input.
1133
    ///
1134
    /// The is_match bool should be true if and only if the preceding DFA state
1135
    /// contains an NFA matching state. The cached state produced here will
1136
    /// then signify a match. (This enables us to delay a match by one byte,
1137
    /// in order to account for the EOF sentinel byte.)
1138
    ///
1139
    /// If the cache is full, then it is wiped before caching a new state.
1140
    ///
1141
    /// The current state should be specified if it exists, since it will need
1142
    /// to be preserved if the cache clears itself. (Start states are
1143
    /// always saved, so they should not be passed here.) It takes a mutable
1144
    /// pointer to the index because if the cache is cleared, the state's
1145
    /// location may change.
1146
0
    fn cached_state(
1147
0
        &mut self,
1148
0
        q: &SparseSet,
1149
0
        mut state_flags: StateFlags,
1150
0
        current_state: Option<&mut StatePtr>,
1151
0
    ) -> Option<StatePtr> {
1152
        // If we couldn't come up with a non-empty key to represent this state,
1153
        // then it is dead and can never lead to a match.
1154
        //
1155
        // Note that inst_flags represent the set of empty width assertions
1156
        // in q. We use this as an optimization in exec_byte to determine when
1157
        // we should follow epsilon transitions at the empty string preceding
1158
        // the current byte.
1159
0
        let key = match self.cached_state_key(q, &mut state_flags) {
1160
0
            None => return Some(STATE_DEAD),
1161
0
            Some(v) => v,
1162
        };
1163
        // In the cache? Cool. Done.
1164
0
        if let Some(si) = self.cache.compiled.get_ptr(&key) {
1165
0
            return Some(si);
1166
0
        }
1167
        // If the cache has gotten too big, wipe it.
1168
0
        if self.approximate_size() > self.prog.dfa_size_limit
1169
0
            && !self.clear_cache_and_save(current_state)
1170
        {
1171
            // Ooops. DFA is giving up.
1172
0
            return None;
1173
0
        }
1174
        // Allocate room for our state and add it.
1175
0
        self.add_state(key)
1176
0
    }
Unexecuted instantiation: <regex::dfa::Fsm>::cached_state
Unexecuted instantiation: <regex::dfa::Fsm>::cached_state
1177
1178
    /// Produces a key suitable for describing a state in the DFA cache.
1179
    ///
1180
    /// The key invariant here is that equivalent keys are produced for any two
1181
    /// sets of ordered NFA states (and toggling of whether the previous NFA
1182
    /// states contain a match state) that do not discriminate a match for any
1183
    /// input.
1184
    ///
1185
    /// Specifically, q should be an ordered set of NFA states and is_match
1186
    /// should be true if and only if the previous NFA states contained a match
1187
    /// state.
1188
0
    fn cached_state_key(
1189
0
        &mut self,
1190
0
        q: &SparseSet,
1191
0
        state_flags: &mut StateFlags,
1192
0
    ) -> Option<State> {
1193
        use crate::prog::Inst::*;
1194
1195
        // We need to build up enough information to recognize pre-built states
1196
        // in the DFA. Generally speaking, this includes every instruction
1197
        // except for those which are purely epsilon transitions, e.g., the
1198
        // Save and Split instructions.
1199
        //
1200
        // Empty width assertions are also epsilon transitions, but since they
1201
        // are conditional, we need to make them part of a state's key in the
1202
        // cache.
1203
1204
0
        let mut insts =
1205
0
            mem::replace(&mut self.cache.insts_scratch_space, vec![]);
1206
0
        insts.clear();
1207
        // Reserve 1 byte for flags.
1208
0
        insts.push(0);
1209
1210
0
        let mut prev = 0;
1211
0
        for &ip in q {
1212
0
            let ip = usize_to_u32(ip);
1213
0
            match self.prog[ip as usize] {
1214
0
                Char(_) | Ranges(_) => unreachable!(),
1215
0
                Save(_) | Split(_) => {}
1216
0
                Bytes(_) => push_inst_ptr(&mut insts, &mut prev, ip),
1217
                EmptyLook(_) => {
1218
0
                    state_flags.set_empty();
1219
0
                    push_inst_ptr(&mut insts, &mut prev, ip)
1220
                }
1221
                Match(_) => {
1222
0
                    push_inst_ptr(&mut insts, &mut prev, ip);
1223
0
                    if !self.continue_past_first_match() {
1224
0
                        break;
1225
0
                    }
1226
                }
1227
            }
1228
        }
1229
        // If we couldn't transition to any other instructions and we didn't
1230
        // see a match when expanding NFA states previously, then this is a
1231
        // dead state and no amount of additional input can transition out
1232
        // of this state.
1233
0
        let opt_state = if insts.len() == 1 && !state_flags.is_match() {
1234
0
            None
1235
        } else {
1236
0
            let StateFlags(f) = *state_flags;
1237
0
            insts[0] = f;
1238
0
            Some(State { data: Arc::from(&*insts) })
1239
        };
1240
0
        self.cache.insts_scratch_space = insts;
1241
0
        opt_state
1242
0
    }
Unexecuted instantiation: <regex::dfa::Fsm>::cached_state_key
Unexecuted instantiation: <regex::dfa::Fsm>::cached_state_key
1243
1244
    /// Clears the cache, but saves and restores current_state if it is not
1245
    /// none.
1246
    ///
1247
    /// The current state must be provided here in case its location in the
1248
    /// cache changes.
1249
    ///
1250
    /// This returns false if the cache is not cleared and the DFA should
1251
    /// give up.
1252
0
    fn clear_cache_and_save(
1253
0
        &mut self,
1254
0
        current_state: Option<&mut StatePtr>,
1255
0
    ) -> bool {
1256
0
        if self.cache.compiled.is_empty() {
1257
            // Nothing to clear...
1258
0
            return true;
1259
0
        }
1260
0
        match current_state {
1261
0
            None => self.clear_cache(),
1262
0
            Some(si) => {
1263
0
                let cur = self.state(*si).clone();
1264
0
                if !self.clear_cache() {
1265
0
                    return false;
1266
0
                }
1267
                // The unwrap is OK because we just cleared the cache and
1268
                // therefore know that the next state pointer won't exceed
1269
                // STATE_MAX.
1270
0
                *si = self.restore_state(cur).unwrap();
1271
0
                true
1272
            }
1273
        }
1274
0
    }
Unexecuted instantiation: <regex::dfa::Fsm>::clear_cache_and_save
Unexecuted instantiation: <regex::dfa::Fsm>::clear_cache_and_save
1275
1276
    /// Wipes the state cache, but saves and restores the current start state.
1277
    ///
1278
    /// This returns false if the cache is not cleared and the DFA should
1279
    /// give up.
1280
0
    fn clear_cache(&mut self) -> bool {
1281
        // Bail out of the DFA if we're moving too "slowly."
1282
        // A heuristic from RE2: assume the DFA is too slow if it is processing
1283
        // 10 or fewer bytes per state.
1284
        // Additionally, we permit the cache to be flushed a few times before
1285
        // caling it quits.
1286
0
        let nstates = self.cache.compiled.len();
1287
0
        if self.cache.flush_count >= 3
1288
0
            && self.at >= self.last_cache_flush
1289
0
            && (self.at - self.last_cache_flush) <= 10 * nstates
1290
        {
1291
0
            return false;
1292
0
        }
1293
        // Update statistics tracking cache flushes.
1294
0
        self.last_cache_flush = self.at;
1295
0
        self.cache.flush_count += 1;
1296
1297
        // OK, actually flush the cache.
1298
0
        let start = self.state(self.start & !STATE_START).clone();
1299
0
        let last_match = if self.last_match_si <= STATE_MAX {
1300
0
            Some(self.state(self.last_match_si).clone())
1301
        } else {
1302
0
            None
1303
        };
1304
0
        self.cache.reset_size();
1305
0
        self.cache.trans.clear();
1306
0
        self.cache.compiled.clear();
1307
0
        for s in &mut self.cache.start_states {
1308
0
            *s = STATE_UNKNOWN;
1309
0
        }
1310
        // The unwraps are OK because we just cleared the cache and therefore
1311
        // know that the next state pointer won't exceed STATE_MAX.
1312
0
        let start_ptr = self.restore_state(start).unwrap();
1313
0
        self.start = self.start_ptr(start_ptr);
1314
0
        if let Some(last_match) = last_match {
1315
0
            self.last_match_si = self.restore_state(last_match).unwrap();
1316
0
        }
1317
0
        true
1318
0
    }
Unexecuted instantiation: <regex::dfa::Fsm>::clear_cache
Unexecuted instantiation: <regex::dfa::Fsm>::clear_cache
1319
1320
    /// Restores the given state back into the cache, and returns a pointer
1321
    /// to it.
1322
0
    fn restore_state(&mut self, state: State) -> Option<StatePtr> {
1323
        // If we've already stored this state, just return a pointer to it.
1324
        // None will be the wiser.
1325
0
        if let Some(si) = self.cache.compiled.get_ptr(&state) {
1326
0
            return Some(si);
1327
0
        }
1328
0
        self.add_state(state)
1329
0
    }
Unexecuted instantiation: <regex::dfa::Fsm>::restore_state
Unexecuted instantiation: <regex::dfa::Fsm>::restore_state
1330
1331
    /// Returns the next state given the current state si and current byte
1332
    /// b. {qcur,qnext} are used as scratch space for storing ordered NFA
1333
    /// states.
1334
    ///
1335
    /// This tries to fetch the next state from the cache, but if that fails,
1336
    /// it computes the next state, caches it and returns a pointer to it.
1337
    ///
1338
    /// The pointer can be to a real state, or it can be STATE_DEAD.
1339
    /// STATE_UNKNOWN cannot be returned.
1340
    ///
1341
    /// None is returned if a new state could not be allocated (i.e., the DFA
1342
    /// ran out of space and thinks it's running too slowly).
1343
0
    fn next_state(
1344
0
        &mut self,
1345
0
        qcur: &mut SparseSet,
1346
0
        qnext: &mut SparseSet,
1347
0
        si: StatePtr,
1348
0
        b: Byte,
1349
0
    ) -> Option<StatePtr> {
1350
0
        if si == STATE_DEAD {
1351
0
            return Some(STATE_DEAD);
1352
0
        }
1353
0
        match self.cache.trans.next(si, self.byte_class(b)) {
1354
0
            STATE_UNKNOWN => self.exec_byte(qcur, qnext, si, b),
1355
0
            STATE_QUIT => None,
1356
0
            nsi => Some(nsi),
1357
        }
1358
0
    }
Unexecuted instantiation: <regex::dfa::Fsm>::next_state
Unexecuted instantiation: <regex::dfa::Fsm>::next_state
1359
1360
    /// Computes and returns the start state, where searching begins at
1361
    /// position `at` in `text`. If the state has already been computed,
1362
    /// then it is pulled from the cache. If the state hasn't been cached,
1363
    /// then it is computed, cached and a pointer to it is returned.
1364
    ///
1365
    /// This may return STATE_DEAD but never STATE_UNKNOWN.
1366
    #[cfg_attr(feature = "perf-inline", inline(always))]
1367
0
    fn start_state(
1368
0
        &mut self,
1369
0
        q: &mut SparseSet,
1370
0
        empty_flags: EmptyFlags,
1371
0
        state_flags: StateFlags,
1372
0
    ) -> Option<StatePtr> {
1373
        // Compute an index into our cache of start states based on the set
1374
        // of empty/state flags set at the current position in the input. We
1375
        // don't use every flag since not all flags matter. For example, since
1376
        // matches are delayed by one byte, start states can never be match
1377
        // states.
1378
0
        let flagi = {
1379
0
            (((empty_flags.start as u8) << 0)
1380
0
                | ((empty_flags.end as u8) << 1)
1381
0
                | ((empty_flags.start_line as u8) << 2)
1382
0
                | ((empty_flags.end_line as u8) << 3)
1383
0
                | ((empty_flags.word_boundary as u8) << 4)
1384
0
                | ((empty_flags.not_word_boundary as u8) << 5)
1385
0
                | ((state_flags.is_word() as u8) << 6)) as usize
1386
        };
1387
0
        match self.cache.start_states[flagi] {
1388
0
            STATE_UNKNOWN => {}
1389
0
            si => return Some(si),
1390
        }
1391
0
        q.clear();
1392
0
        let start = usize_to_u32(self.prog.start);
1393
0
        self.follow_epsilons(start, q, empty_flags);
1394
        // Start states can never be match states because we delay every match
1395
        // by one byte. Given an empty string and an empty match, the match
1396
        // won't actually occur until the DFA processes the special EOF
1397
        // sentinel byte.
1398
0
        let sp = match self.cached_state(q, state_flags, None) {
1399
0
            None => return None,
1400
0
            Some(sp) => self.start_ptr(sp),
1401
        };
1402
0
        self.cache.start_states[flagi] = sp;
1403
0
        Some(sp)
1404
0
    }
Unexecuted instantiation: <regex::dfa::Fsm>::start_state
Unexecuted instantiation: <regex::dfa::Fsm>::start_state
1405
1406
    /// Computes the set of starting flags for the given position in text.
1407
    ///
1408
    /// This should only be used when executing the DFA forwards over the
1409
    /// input.
1410
0
    fn start_flags(&self, text: &[u8], at: usize) -> (EmptyFlags, StateFlags) {
1411
0
        let mut empty_flags = EmptyFlags::default();
1412
0
        let mut state_flags = StateFlags::default();
1413
0
        empty_flags.start = at == 0;
1414
0
        empty_flags.end = text.is_empty();
1415
0
        empty_flags.start_line = at == 0 || text[at - 1] == b'\n';
1416
0
        empty_flags.end_line = text.is_empty();
1417
1418
0
        let is_word_last = at > 0 && Byte::byte(text[at - 1]).is_ascii_word();
1419
0
        let is_word = at < text.len() && Byte::byte(text[at]).is_ascii_word();
1420
0
        if is_word_last {
1421
0
            state_flags.set_word();
1422
0
        }
1423
0
        if is_word == is_word_last {
1424
0
            empty_flags.not_word_boundary = true;
1425
0
        } else {
1426
0
            empty_flags.word_boundary = true;
1427
0
        }
1428
0
        (empty_flags, state_flags)
1429
0
    }
Unexecuted instantiation: <regex::dfa::Fsm>::start_flags
Unexecuted instantiation: <regex::dfa::Fsm>::start_flags
1430
1431
    /// Computes the set of starting flags for the given position in text.
1432
    ///
1433
    /// This should only be used when executing the DFA in reverse over the
1434
    /// input.
1435
0
    fn start_flags_reverse(
1436
0
        &self,
1437
0
        text: &[u8],
1438
0
        at: usize,
1439
0
    ) -> (EmptyFlags, StateFlags) {
1440
0
        let mut empty_flags = EmptyFlags::default();
1441
0
        let mut state_flags = StateFlags::default();
1442
0
        empty_flags.start = at == text.len();
1443
0
        empty_flags.end = text.is_empty();
1444
0
        empty_flags.start_line = at == text.len() || text[at] == b'\n';
1445
0
        empty_flags.end_line = text.is_empty();
1446
1447
0
        let is_word_last =
1448
0
            at < text.len() && Byte::byte(text[at]).is_ascii_word();
1449
0
        let is_word = at > 0 && Byte::byte(text[at - 1]).is_ascii_word();
1450
0
        if is_word_last {
1451
0
            state_flags.set_word();
1452
0
        }
1453
0
        if is_word == is_word_last {
1454
0
            empty_flags.not_word_boundary = true;
1455
0
        } else {
1456
0
            empty_flags.word_boundary = true;
1457
0
        }
1458
0
        (empty_flags, state_flags)
1459
0
    }
Unexecuted instantiation: <regex::dfa::Fsm>::start_flags_reverse
Unexecuted instantiation: <regex::dfa::Fsm>::start_flags_reverse
1460
1461
    /// Returns a reference to a State given a pointer to it.
1462
0
    fn state(&self, si: StatePtr) -> &State {
1463
0
        self.cache.compiled.get_state(si).unwrap()
1464
0
    }
Unexecuted instantiation: <regex::dfa::Fsm>::state
Unexecuted instantiation: <regex::dfa::Fsm>::state
1465
1466
    /// Adds the given state to the DFA.
1467
    ///
1468
    /// This allocates room for transitions out of this state in
1469
    /// self.cache.trans. The transitions can be set with the returned
1470
    /// StatePtr.
1471
    ///
1472
    /// If None is returned, then the state limit was reached and the DFA
1473
    /// should quit.
1474
0
    fn add_state(&mut self, state: State) -> Option<StatePtr> {
1475
        // This will fail if the next state pointer exceeds STATE_PTR. In
1476
        // practice, the cache limit will prevent us from ever getting here,
1477
        // but maybe callers will set the cache size to something ridiculous...
1478
0
        let si = match self.cache.trans.add() {
1479
0
            None => return None,
1480
0
            Some(si) => si,
1481
        };
1482
        // If the program has a Unicode word boundary, then set any transitions
1483
        // for non-ASCII bytes to STATE_QUIT. If the DFA stumbles over such a
1484
        // transition, then it will quit and an alternative matching engine
1485
        // will take over.
1486
0
        if self.prog.has_unicode_word_boundary {
1487
0
            for b in 128..256 {
1488
0
                let cls = self.byte_class(Byte::byte(b as u8));
1489
0
                self.cache.trans.set_next(si, cls, STATE_QUIT);
1490
0
            }
1491
0
        }
1492
        // Finally, put our actual state on to our heap of states and index it
1493
        // so we can find it later.
1494
0
        self.cache.size += self.cache.trans.state_heap_size()
1495
0
            + state.data.len()
1496
0
            + (2 * mem::size_of::<State>())
1497
0
            + mem::size_of::<StatePtr>();
1498
0
        self.cache.compiled.insert(state, si);
1499
        // Transition table and set of states and map should all be in sync.
1500
0
        debug_assert!(
1501
0
            self.cache.compiled.len() == self.cache.trans.num_states()
1502
        );
1503
0
        Some(si)
1504
0
    }
Unexecuted instantiation: <regex::dfa::Fsm>::add_state
Unexecuted instantiation: <regex::dfa::Fsm>::add_state
1505
1506
    /// Quickly finds the next occurrence of any literal prefixes in the regex.
1507
    /// If there are no literal prefixes, then the current position is
1508
    /// returned. If there are literal prefixes and one could not be found,
1509
    /// then None is returned.
1510
    ///
1511
    /// This should only be called when the DFA is in a start state.
1512
0
    fn prefix_at(&self, text: &[u8], at: usize) -> Option<usize> {
1513
0
        self.prog.prefixes.find(&text[at..]).map(|(s, _)| at + s)
Unexecuted instantiation: <regex::dfa::Fsm>::prefix_at::{closure#0}
Unexecuted instantiation: <regex::dfa::Fsm>::prefix_at::{closure#0}
1514
0
    }
Unexecuted instantiation: <regex::dfa::Fsm>::prefix_at
Unexecuted instantiation: <regex::dfa::Fsm>::prefix_at
1515
1516
    /// Returns the number of byte classes required to discriminate transitions
1517
    /// in each state.
1518
    ///
1519
    /// invariant: num_byte_classes() == len(State.next)
1520
0
    fn num_byte_classes(&self) -> usize {
1521
        // We add 1 to account for the special EOF byte.
1522
0
        (self.prog.byte_classes[255] as usize + 1) + 1
1523
0
    }
Unexecuted instantiation: <regex::dfa::Fsm>::num_byte_classes
Unexecuted instantiation: <regex::dfa::Fsm>::num_byte_classes
1524
1525
    /// Given an input byte or the special EOF sentinel, return its
1526
    /// corresponding byte class.
1527
    #[cfg_attr(feature = "perf-inline", inline(always))]
1528
0
    fn byte_class(&self, b: Byte) -> usize {
1529
0
        match b.as_byte() {
1530
0
            None => self.num_byte_classes() - 1,
1531
0
            Some(b) => self.u8_class(b),
1532
        }
1533
0
    }
Unexecuted instantiation: <regex::dfa::Fsm>::byte_class
Unexecuted instantiation: <regex::dfa::Fsm>::byte_class
1534
1535
    /// Like byte_class, but explicitly for u8s.
1536
    #[cfg_attr(feature = "perf-inline", inline(always))]
1537
0
    fn u8_class(&self, b: u8) -> usize {
1538
0
        self.prog.byte_classes[b as usize] as usize
1539
0
    }
Unexecuted instantiation: <regex::dfa::Fsm>::u8_class
Unexecuted instantiation: <regex::dfa::Fsm>::u8_class
1540
1541
    /// Returns true if the DFA should continue searching past the first match.
1542
    ///
1543
    /// Leftmost first semantics in the DFA are preserved by not following NFA
1544
    /// transitions after the first match is seen.
1545
    ///
1546
    /// On occasion, we want to avoid leftmost first semantics to find either
1547
    /// the longest match (for reverse search) or all possible matches (for
1548
    /// regex sets).
1549
0
    fn continue_past_first_match(&self) -> bool {
1550
0
        self.prog.is_reverse || self.prog.matches.len() > 1
1551
0
    }
Unexecuted instantiation: <regex::dfa::Fsm>::continue_past_first_match
Unexecuted instantiation: <regex::dfa::Fsm>::continue_past_first_match
1552
1553
    /// Returns true if there is a prefix we can quickly search for.
1554
0
    fn has_prefix(&self) -> bool {
1555
0
        !self.prog.is_reverse
1556
0
            && !self.prog.prefixes.is_empty()
1557
0
            && !self.prog.is_anchored_start
1558
0
    }
Unexecuted instantiation: <regex::dfa::Fsm>::has_prefix
Unexecuted instantiation: <regex::dfa::Fsm>::has_prefix
1559
1560
    /// Sets the STATE_START bit in the given state pointer if and only if
1561
    /// we have a prefix to scan for.
1562
    ///
1563
    /// If there's no prefix, then it's a waste to treat the start state
1564
    /// specially.
1565
0
    fn start_ptr(&self, si: StatePtr) -> StatePtr {
1566
0
        if self.has_prefix() {
1567
0
            si | STATE_START
1568
        } else {
1569
0
            si
1570
        }
1571
0
    }
Unexecuted instantiation: <regex::dfa::Fsm>::start_ptr
Unexecuted instantiation: <regex::dfa::Fsm>::start_ptr
1572
1573
    /// Approximate size returns the approximate heap space currently used by
1574
    /// the DFA. It is used to determine whether the DFA's state cache needs to
1575
    /// be wiped. Namely, it is possible that for certain regexes on certain
1576
    /// inputs, a new state could be created for every byte of input. (This is
1577
    /// bad for memory use, so we bound it with a cache.)
1578
0
    fn approximate_size(&self) -> usize {
1579
0
        self.cache.size + self.prog.approximate_size()
1580
0
    }
Unexecuted instantiation: <regex::dfa::Fsm>::approximate_size
Unexecuted instantiation: <regex::dfa::Fsm>::approximate_size
1581
}
1582
1583
/// An abstraction for representing a map of states. The map supports two
1584
/// different ways of state lookup. One is fast constant time access via a
1585
/// state pointer. The other is a hashmap lookup based on the DFA's
1586
/// constituent NFA states.
1587
///
1588
/// A DFA state internally uses an Arc such that we only need to store the
1589
/// set of NFA states on the heap once, even though we support looking up
1590
/// states by two different means. A more natural way to express this might
1591
/// use raw pointers, but an Arc is safe and effectively achieves the same
1592
/// thing.
1593
#[derive(Debug)]
1594
struct StateMap {
1595
    /// The keys are not actually static but rely on always pointing to a
1596
    /// buffer in `states` which will never be moved except when clearing
1597
    /// the map or on drop, in which case the keys of this map will be
1598
    /// removed before
1599
    map: HashMap<State, StatePtr>,
1600
    /// Our set of states. Note that `StatePtr / num_byte_classes` indexes
1601
    /// this Vec rather than just a `StatePtr`.
1602
    states: Vec<State>,
1603
    /// The number of byte classes in the DFA. Used to index `states`.
1604
    num_byte_classes: usize,
1605
}
1606
1607
impl StateMap {
1608
42
    fn new(num_byte_classes: usize) -> StateMap {
1609
42
        StateMap {
1610
42
            map: HashMap::new(),
1611
42
            states: vec![],
1612
42
            num_byte_classes: num_byte_classes,
1613
42
        }
1614
42
    }
<regex::dfa::StateMap>::new
Line
Count
Source
1608
18
    fn new(num_byte_classes: usize) -> StateMap {
1609
18
        StateMap {
1610
18
            map: HashMap::new(),
1611
18
            states: vec![],
1612
18
            num_byte_classes: num_byte_classes,
1613
18
        }
1614
18
    }
<regex::dfa::StateMap>::new
Line
Count
Source
1608
24
    fn new(num_byte_classes: usize) -> StateMap {
1609
24
        StateMap {
1610
24
            map: HashMap::new(),
1611
24
            states: vec![],
1612
24
            num_byte_classes: num_byte_classes,
1613
24
        }
1614
24
    }
1615
1616
0
    fn len(&self) -> usize {
1617
0
        self.states.len()
1618
0
    }
Unexecuted instantiation: <regex::dfa::StateMap>::len
Unexecuted instantiation: <regex::dfa::StateMap>::len
1619
1620
0
    fn is_empty(&self) -> bool {
1621
0
        self.states.is_empty()
1622
0
    }
Unexecuted instantiation: <regex::dfa::StateMap>::is_empty
Unexecuted instantiation: <regex::dfa::StateMap>::is_empty
1623
1624
0
    fn get_ptr(&self, state: &State) -> Option<StatePtr> {
1625
0
        self.map.get(state).cloned()
1626
0
    }
Unexecuted instantiation: <regex::dfa::StateMap>::get_ptr
Unexecuted instantiation: <regex::dfa::StateMap>::get_ptr
1627
1628
0
    fn get_state(&self, si: StatePtr) -> Option<&State> {
1629
0
        self.states.get(si as usize / self.num_byte_classes)
1630
0
    }
Unexecuted instantiation: <regex::dfa::StateMap>::get_state
Unexecuted instantiation: <regex::dfa::StateMap>::get_state
1631
1632
0
    fn insert(&mut self, state: State, si: StatePtr) {
1633
0
        self.map.insert(state.clone(), si);
1634
0
        self.states.push(state);
1635
0
    }
Unexecuted instantiation: <regex::dfa::StateMap>::insert
Unexecuted instantiation: <regex::dfa::StateMap>::insert
1636
1637
0
    fn clear(&mut self) {
1638
0
        self.map.clear();
1639
0
        self.states.clear();
1640
0
    }
Unexecuted instantiation: <regex::dfa::StateMap>::clear
Unexecuted instantiation: <regex::dfa::StateMap>::clear
1641
}
1642
1643
impl Transitions {
1644
    /// Create a new transition table.
1645
    ///
1646
    /// The number of byte classes corresponds to the stride. Every state will
1647
    /// have `num_byte_classes` slots for transitions.
1648
42
    fn new(num_byte_classes: usize) -> Transitions {
1649
42
        Transitions { table: vec![], num_byte_classes: num_byte_classes }
1650
42
    }
<regex::dfa::Transitions>::new
Line
Count
Source
1648
18
    fn new(num_byte_classes: usize) -> Transitions {
1649
18
        Transitions { table: vec![], num_byte_classes: num_byte_classes }
1650
18
    }
<regex::dfa::Transitions>::new
Line
Count
Source
1648
24
    fn new(num_byte_classes: usize) -> Transitions {
1649
24
        Transitions { table: vec![], num_byte_classes: num_byte_classes }
1650
24
    }
1651
1652
    /// Returns the total number of states currently in this table.
1653
0
    fn num_states(&self) -> usize {
1654
0
        self.table.len() / self.num_byte_classes
1655
0
    }
Unexecuted instantiation: <regex::dfa::Transitions>::num_states
Unexecuted instantiation: <regex::dfa::Transitions>::num_states
1656
1657
    /// Allocates room for one additional state and returns a pointer to it.
1658
    ///
1659
    /// If there's no more room, None is returned.
1660
0
    fn add(&mut self) -> Option<StatePtr> {
1661
0
        let si = self.table.len();
1662
0
        if si > STATE_MAX as usize {
1663
0
            return None;
1664
0
        }
1665
0
        self.table.extend(repeat(STATE_UNKNOWN).take(self.num_byte_classes));
1666
0
        Some(usize_to_u32(si))
1667
0
    }
Unexecuted instantiation: <regex::dfa::Transitions>::add
Unexecuted instantiation: <regex::dfa::Transitions>::add
1668
1669
    /// Clears the table of all states.
1670
0
    fn clear(&mut self) {
1671
0
        self.table.clear();
1672
0
    }
Unexecuted instantiation: <regex::dfa::Transitions>::clear
Unexecuted instantiation: <regex::dfa::Transitions>::clear
1673
1674
    /// Sets the transition from (si, cls) to next.
1675
0
    fn set_next(&mut self, si: StatePtr, cls: usize, next: StatePtr) {
1676
0
        self.table[si as usize + cls] = next;
1677
0
    }
Unexecuted instantiation: <regex::dfa::Transitions>::set_next
Unexecuted instantiation: <regex::dfa::Transitions>::set_next
1678
1679
    /// Returns the transition corresponding to (si, cls).
1680
0
    fn next(&self, si: StatePtr, cls: usize) -> StatePtr {
1681
0
        self.table[si as usize + cls]
1682
0
    }
Unexecuted instantiation: <regex::dfa::Transitions>::next
Unexecuted instantiation: <regex::dfa::Transitions>::next
1683
1684
    /// The heap size, in bytes, of a single state in the transition table.
1685
0
    fn state_heap_size(&self) -> usize {
1686
0
        self.num_byte_classes * mem::size_of::<StatePtr>()
1687
0
    }
Unexecuted instantiation: <regex::dfa::Transitions>::state_heap_size
Unexecuted instantiation: <regex::dfa::Transitions>::state_heap_size
1688
1689
    /// Like `next`, but uses unchecked access and is therefore not safe.
1690
0
    unsafe fn next_unchecked(&self, si: StatePtr, cls: usize) -> StatePtr {
1691
0
        debug_assert!((si as usize) < self.table.len());
1692
0
        debug_assert!(cls < self.num_byte_classes);
1693
0
        *self.table.get_unchecked(si as usize + cls)
1694
0
    }
Unexecuted instantiation: <regex::dfa::Transitions>::next_unchecked
Unexecuted instantiation: <regex::dfa::Transitions>::next_unchecked
1695
}
1696
1697
impl StateFlags {
1698
0
    fn is_match(&self) -> bool {
1699
0
        self.0 & 0b0000000_1 > 0
1700
0
    }
Unexecuted instantiation: <regex::dfa::StateFlags>::is_match
Unexecuted instantiation: <regex::dfa::StateFlags>::is_match
1701
1702
0
    fn set_match(&mut self) {
1703
0
        self.0 |= 0b0000000_1;
1704
0
    }
Unexecuted instantiation: <regex::dfa::StateFlags>::set_match
Unexecuted instantiation: <regex::dfa::StateFlags>::set_match
1705
1706
0
    fn is_word(&self) -> bool {
1707
0
        self.0 & 0b000000_1_0 > 0
1708
0
    }
Unexecuted instantiation: <regex::dfa::StateFlags>::is_word
Unexecuted instantiation: <regex::dfa::StateFlags>::is_word
1709
1710
0
    fn set_word(&mut self) {
1711
0
        self.0 |= 0b000000_1_0;
1712
0
    }
Unexecuted instantiation: <regex::dfa::StateFlags>::set_word
Unexecuted instantiation: <regex::dfa::StateFlags>::set_word
1713
1714
0
    fn has_empty(&self) -> bool {
1715
0
        self.0 & 0b00000_1_00 > 0
1716
0
    }
Unexecuted instantiation: <regex::dfa::StateFlags>::has_empty
Unexecuted instantiation: <regex::dfa::StateFlags>::has_empty
1717
1718
0
    fn set_empty(&mut self) {
1719
0
        self.0 |= 0b00000_1_00;
1720
0
    }
Unexecuted instantiation: <regex::dfa::StateFlags>::set_empty
Unexecuted instantiation: <regex::dfa::StateFlags>::set_empty
1721
}
1722
1723
impl Byte {
1724
0
    fn byte(b: u8) -> Self {
1725
0
        Byte(b as u16)
1726
0
    }
Unexecuted instantiation: <regex::dfa::Byte>::byte
Unexecuted instantiation: <regex::dfa::Byte>::byte
1727
0
    fn eof() -> Self {
1728
0
        Byte(256)
1729
0
    }
Unexecuted instantiation: <regex::dfa::Byte>::eof
Unexecuted instantiation: <regex::dfa::Byte>::eof
1730
0
    fn is_eof(&self) -> bool {
1731
0
        self.0 == 256
1732
0
    }
Unexecuted instantiation: <regex::dfa::Byte>::is_eof
Unexecuted instantiation: <regex::dfa::Byte>::is_eof
1733
1734
0
    fn is_ascii_word(&self) -> bool {
1735
0
        let b = match self.as_byte() {
1736
0
            None => return false,
1737
0
            Some(b) => b,
1738
        };
1739
0
        match b {
1740
0
            b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'_' => true,
1741
0
            _ => false,
1742
        }
1743
0
    }
Unexecuted instantiation: <regex::dfa::Byte>::is_ascii_word
Unexecuted instantiation: <regex::dfa::Byte>::is_ascii_word
1744
1745
0
    fn as_byte(&self) -> Option<u8> {
1746
0
        if self.is_eof() {
1747
0
            None
1748
        } else {
1749
0
            Some(self.0 as u8)
1750
        }
1751
0
    }
Unexecuted instantiation: <regex::dfa::Byte>::as_byte
Unexecuted instantiation: <regex::dfa::Byte>::as_byte
1752
}
1753
1754
impl fmt::Debug for State {
1755
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1756
0
        let ips: Vec<usize> = self.inst_ptrs().collect();
1757
0
        f.debug_struct("State")
1758
0
            .field("flags", &self.flags())
1759
0
            .field("insts", &ips)
1760
0
            .finish()
1761
0
    }
Unexecuted instantiation: <regex::dfa::State as core::fmt::Debug>::fmt
Unexecuted instantiation: <regex::dfa::State as core::fmt::Debug>::fmt
1762
}
1763
1764
impl fmt::Debug for Transitions {
1765
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1766
0
        let mut fmtd = f.debug_map();
1767
0
        for si in 0..self.num_states() {
1768
0
            let s = si * self.num_byte_classes;
1769
0
            let e = s + self.num_byte_classes;
1770
0
            fmtd.entry(&si.to_string(), &TransitionsRow(&self.table[s..e]));
1771
0
        }
1772
0
        fmtd.finish()
1773
0
    }
Unexecuted instantiation: <regex::dfa::Transitions as core::fmt::Debug>::fmt
Unexecuted instantiation: <regex::dfa::Transitions as core::fmt::Debug>::fmt
1774
}
1775
1776
struct TransitionsRow<'a>(&'a [StatePtr]);
1777
1778
impl<'a> fmt::Debug for TransitionsRow<'a> {
1779
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1780
0
        let mut fmtd = f.debug_map();
1781
0
        for (b, si) in self.0.iter().enumerate() {
1782
0
            match *si {
1783
0
                STATE_UNKNOWN => {}
1784
0
                STATE_DEAD => {
1785
0
                    fmtd.entry(&vb(b as usize), &"DEAD");
1786
0
                }
1787
0
                si => {
1788
0
                    fmtd.entry(&vb(b as usize), &si.to_string());
1789
0
                }
1790
            }
1791
        }
1792
0
        fmtd.finish()
1793
0
    }
Unexecuted instantiation: <regex::dfa::TransitionsRow as core::fmt::Debug>::fmt
Unexecuted instantiation: <regex::dfa::TransitionsRow as core::fmt::Debug>::fmt
1794
}
1795
1796
impl fmt::Debug for StateFlags {
1797
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1798
0
        f.debug_struct("StateFlags")
1799
0
            .field("is_match", &self.is_match())
1800
0
            .field("is_word", &self.is_word())
1801
0
            .field("has_empty", &self.has_empty())
1802
0
            .finish()
1803
0
    }
Unexecuted instantiation: <regex::dfa::StateFlags as core::fmt::Debug>::fmt
Unexecuted instantiation: <regex::dfa::StateFlags as core::fmt::Debug>::fmt
1804
}
1805
1806
/// Helper function for formatting a byte as a nice-to-read escaped string.
1807
0
fn vb(b: usize) -> String {
1808
    use std::ascii::escape_default;
1809
1810
0
    if b > ::std::u8::MAX as usize {
1811
0
        "EOF".to_owned()
1812
    } else {
1813
0
        let escaped = escape_default(b as u8).collect::<Vec<u8>>();
1814
0
        String::from_utf8_lossy(&escaped).into_owned()
1815
    }
1816
0
}
Unexecuted instantiation: regex::dfa::vb
Unexecuted instantiation: regex::dfa::vb
1817
1818
0
fn usize_to_u32(n: usize) -> u32 {
1819
0
    if (n as u64) > (::std::u32::MAX as u64) {
1820
0
        panic!("BUG: {} is too big to fit into u32", n)
1821
0
    }
1822
0
    n as u32
1823
0
}
Unexecuted instantiation: regex::dfa::usize_to_u32
Unexecuted instantiation: regex::dfa::usize_to_u32
1824
1825
#[allow(dead_code)] // useful for debugging
1826
0
fn show_state_ptr(si: StatePtr) -> String {
1827
0
    let mut s = format!("{:?}", si & STATE_MAX);
1828
0
    if si == STATE_UNKNOWN {
1829
0
        s = format!("{} (unknown)", s);
1830
0
    }
1831
0
    if si == STATE_DEAD {
1832
0
        s = format!("{} (dead)", s);
1833
0
    }
1834
0
    if si == STATE_QUIT {
1835
0
        s = format!("{} (quit)", s);
1836
0
    }
1837
0
    if si & STATE_START > 0 {
1838
0
        s = format!("{} (start)", s);
1839
0
    }
1840
0
    if si & STATE_MATCH > 0 {
1841
0
        s = format!("{} (match)", s);
1842
0
    }
1843
0
    s
1844
0
}
Unexecuted instantiation: regex::dfa::show_state_ptr
Unexecuted instantiation: regex::dfa::show_state_ptr
1845
1846
/// https://developers.google.com/protocol-buffers/docs/encoding#varints
1847
0
fn write_vari32(data: &mut Vec<u8>, n: i32) {
1848
0
    let mut un = (n as u32) << 1;
1849
0
    if n < 0 {
1850
0
        un = !un;
1851
0
    }
1852
0
    write_varu32(data, un)
1853
0
}
Unexecuted instantiation: regex::dfa::write_vari32
Unexecuted instantiation: regex::dfa::write_vari32
1854
1855
/// https://developers.google.com/protocol-buffers/docs/encoding#varints
1856
0
fn read_vari32(data: &[u8]) -> (i32, usize) {
1857
0
    let (un, i) = read_varu32(data);
1858
0
    let mut n = (un >> 1) as i32;
1859
0
    if un & 1 != 0 {
1860
0
        n = !n;
1861
0
    }
1862
0
    (n, i)
1863
0
}
Unexecuted instantiation: regex::dfa::read_vari32
Unexecuted instantiation: regex::dfa::read_vari32
1864
1865
/// https://developers.google.com/protocol-buffers/docs/encoding#varints
1866
0
fn write_varu32(data: &mut Vec<u8>, mut n: u32) {
1867
0
    while n >= 0b1000_0000 {
1868
0
        data.push((n as u8) | 0b1000_0000);
1869
0
        n >>= 7;
1870
0
    }
1871
0
    data.push(n as u8);
1872
0
}
Unexecuted instantiation: regex::dfa::write_varu32
Unexecuted instantiation: regex::dfa::write_varu32
1873
1874
/// https://developers.google.com/protocol-buffers/docs/encoding#varints
1875
0
fn read_varu32(data: &[u8]) -> (u32, usize) {
1876
0
    let mut n: u32 = 0;
1877
0
    let mut shift: u32 = 0;
1878
0
    for (i, &b) in data.iter().enumerate() {
1879
0
        if b < 0b1000_0000 {
1880
0
            return (n | ((b as u32) << shift), i + 1);
1881
0
        }
1882
0
        n |= ((b as u32) & 0b0111_1111) << shift;
1883
0
        shift += 7;
1884
    }
1885
0
    (0, 0)
1886
0
}
Unexecuted instantiation: regex::dfa::read_varu32
Unexecuted instantiation: regex::dfa::read_varu32
1887
1888
#[cfg(test)]
1889
mod tests {
1890
1891
    use super::{
1892
        push_inst_ptr, read_vari32, read_varu32, write_vari32, write_varu32,
1893
        State, StateFlags,
1894
    };
1895
    use quickcheck::{quickcheck, Gen, QuickCheck};
1896
    use std::sync::Arc;
1897
1898
    #[test]
1899
    fn prop_state_encode_decode() {
1900
        fn p(mut ips: Vec<u32>, flags: u8) -> bool {
1901
            // It looks like our encoding scheme can't handle instruction
1902
            // pointers at or above 2**31. We should fix that, but it seems
1903
            // unlikely to occur in real code due to the amount of memory
1904
            // required for such a state machine. So for now, we just clamp
1905
            // our test data.
1906
            for ip in &mut ips {
1907
                if *ip >= 1 << 31 {
1908
                    *ip = (1 << 31) - 1;
1909
                }
1910
            }
1911
            let mut data = vec![flags];
1912
            let mut prev = 0;
1913
            for &ip in ips.iter() {
1914
                push_inst_ptr(&mut data, &mut prev, ip);
1915
            }
1916
            let state = State { data: Arc::from(&data[..]) };
1917
1918
            let expected: Vec<usize> =
1919
                ips.into_iter().map(|ip| ip as usize).collect();
1920
            let got: Vec<usize> = state.inst_ptrs().collect();
1921
            expected == got && state.flags() == StateFlags(flags)
1922
        }
1923
        QuickCheck::new()
1924
            .gen(Gen::new(10_000))
1925
            .quickcheck(p as fn(Vec<u32>, u8) -> bool);
1926
    }
1927
1928
    #[test]
1929
    fn prop_read_write_u32() {
1930
        fn p(n: u32) -> bool {
1931
            let mut buf = vec![];
1932
            write_varu32(&mut buf, n);
1933
            let (got, nread) = read_varu32(&buf);
1934
            nread == buf.len() && got == n
1935
        }
1936
        quickcheck(p as fn(u32) -> bool);
1937
    }
1938
1939
    #[test]
1940
    fn prop_read_write_i32() {
1941
        fn p(n: i32) -> bool {
1942
            let mut buf = vec![];
1943
            write_vari32(&mut buf, n);
1944
            let (got, nread) = read_vari32(&buf);
1945
            nread == buf.len() && got == n
1946
        }
1947
        quickcheck(p as fn(i32) -> bool);
1948
    }
1949
}