]> git.proxmox.com Git - rustc.git/blame - vendor/regex-automata/src/dfa/error.rs
New upstream version 1.73.0+dfsg1
[rustc.git] / vendor / regex-automata / src / dfa / error.rs
CommitLineData
487cf647
FG
1use crate::{
2 nfa,
3 util::{
4 id::{PatternID, StateID},
5 start::Start,
6 },
7};
8
9/// An error that occurred during the construction of a DFA.
10///
11/// This error does not provide many introspection capabilities. There are
12/// generally only two things you can do with it:
13///
14/// * Obtain a human readable message via its `std::fmt::Display` impl.
15/// * Access an underlying [`nfa::thompson::Error`] type from its `source`
16/// method via the `std::error::Error` trait. This error only occurs when using
17/// convenience routines for building a DFA directly from a pattern string.
18///
19/// When the `std` feature is enabled, this implements the `std::error::Error`
20/// trait.
21#[derive(Clone, Debug)]
22pub struct Error {
23 kind: ErrorKind,
24}
25
26/// The kind of error that occurred during the construction of a DFA.
27///
28/// Note that this error is non-exhaustive. Adding new variants is not
29/// considered a breaking change.
30#[derive(Clone, Debug)]
31enum ErrorKind {
32 /// An error that occurred while constructing an NFA as a precursor step
33 /// before a DFA is compiled.
34 NFA(nfa::thompson::Error),
35 /// An error that occurred because an unsupported regex feature was used.
36 /// The message string describes which unsupported feature was used.
37 ///
38 /// The primary regex feature that is unsupported by DFAs is the Unicode
39 /// word boundary look-around assertion (`\b`). This can be worked around
40 /// by either using an ASCII word boundary (`(?-u:\b)`) or by enabling the
41 /// [`dense::Builder::allow_unicode_word_boundary`](dense/struct.Builder.html#method.allow_unicode_word_boundary)
42 /// option when building a DFA.
43 Unsupported(&'static str),
44 /// An error that occurs if too many states are produced while building a
45 /// DFA.
46 TooManyStates,
47 /// An error that occurs if too many start states are needed while building
48 /// a DFA.
49 ///
50 /// This is a kind of oddball error that occurs when building a DFA with
51 /// start states enabled for each pattern and enough patterns to cause
52 /// the table of start states to overflow `usize`.
53 TooManyStartStates,
54 /// This is another oddball error that can occur if there are too many
55 /// patterns spread out across too many match states.
56 TooManyMatchPatternIDs,
57 /// An error that occurs if the DFA got too big during determinization.
58 DFAExceededSizeLimit { limit: usize },
59 /// An error that occurs if auxiliary storage (not the DFA) used during
60 /// determinization got too big.
61 DeterminizeExceededSizeLimit { limit: usize },
62}
63
64impl Error {
65 /// Return the kind of this error.
66 fn kind(&self) -> &ErrorKind {
67 &self.kind
68 }
69
70 pub(crate) fn nfa(err: nfa::thompson::Error) -> Error {
71 Error { kind: ErrorKind::NFA(err) }
72 }
73
74 pub(crate) fn unsupported_dfa_word_boundary_unicode() -> Error {
75 let msg = "cannot build DFAs for regexes with Unicode word \
76 boundaries; switch to ASCII word boundaries, or \
77 heuristically enable Unicode word boundaries or use a \
78 different regex engine";
79 Error { kind: ErrorKind::Unsupported(msg) }
80 }
81
82 pub(crate) fn too_many_states() -> Error {
83 Error { kind: ErrorKind::TooManyStates }
84 }
85
86 pub(crate) fn too_many_start_states() -> Error {
87 Error { kind: ErrorKind::TooManyStartStates }
88 }
89
90 pub(crate) fn too_many_match_pattern_ids() -> Error {
91 Error { kind: ErrorKind::TooManyMatchPatternIDs }
92 }
93
94 pub(crate) fn dfa_exceeded_size_limit(limit: usize) -> Error {
95 Error { kind: ErrorKind::DFAExceededSizeLimit { limit } }
96 }
97
98 pub(crate) fn determinize_exceeded_size_limit(limit: usize) -> Error {
99 Error { kind: ErrorKind::DeterminizeExceededSizeLimit { limit } }
100 }
101}
102
103#[cfg(feature = "std")]
104impl std::error::Error for Error {
105 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
106 match self.kind() {
107 ErrorKind::NFA(ref err) => Some(err),
108 ErrorKind::Unsupported(_) => None,
109 ErrorKind::TooManyStates => None,
110 ErrorKind::TooManyStartStates => None,
111 ErrorKind::TooManyMatchPatternIDs => None,
112 ErrorKind::DFAExceededSizeLimit { .. } => None,
113 ErrorKind::DeterminizeExceededSizeLimit { .. } => None,
114 }
115 }
116}
117
118impl core::fmt::Display for Error {
119 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
120 match self.kind() {
121 ErrorKind::NFA(_) => write!(f, "error building NFA"),
122 ErrorKind::Unsupported(ref msg) => {
123 write!(f, "unsupported regex feature for DFAs: {}", msg)
124 }
125 ErrorKind::TooManyStates => write!(
126 f,
127 "number of DFA states exceeds limit of {}",
128 StateID::LIMIT,
129 ),
130 ErrorKind::TooManyStartStates => {
131 let stride = Start::count();
132 // The start table has `stride` entries for starting states for
133 // the entire DFA, and then `stride` entries for each pattern
134 // if start states for each pattern are enabled (which is the
135 // only way this error can occur). Thus, the total number of
136 // patterns that can fit in the table is `stride` less than
137 // what we can allocate.
138 let limit = ((core::isize::MAX as usize) - stride) / stride;
139 write!(
140 f,
141 "compiling DFA with start states exceeds pattern \
142 pattern limit of {}",
143 limit,
144 )
145 }
146 ErrorKind::TooManyMatchPatternIDs => write!(
147 f,
148 "compiling DFA with total patterns in all match states \
149 exceeds limit of {}",
150 PatternID::LIMIT,
151 ),
152 ErrorKind::DFAExceededSizeLimit { limit } => write!(
153 f,
154 "DFA exceeded size limit of {:?} during determinization",
155 limit,
156 ),
157 ErrorKind::DeterminizeExceededSizeLimit { limit } => {
158 write!(f, "determinization exceeded size limit of {:?}", limit)
159 }
160 }
161 }
162}