Skip to main content

regex_automata/hybrid/
error.rs

1use crate::{hybrid::id::LazyStateIDError, nfa, util::search::Anchored};
2
3/// An error that occurs when initial construction of a lazy DFA fails.
4///
5/// A build error can occur when insufficient cache capacity is configured or
6/// if something about the NFA is unsupported. (For example, if one attempts
7/// to build a lazy DFA without heuristic Unicode support but with an NFA that
8/// contains a Unicode word boundary.)
9///
10/// This error does not provide many introspection capabilities. There are
11/// generally only two things you can do with it:
12///
13/// * Obtain a human readable message via its `std::fmt::Display` impl.
14/// * Access an underlying
15/// [`nfa::thompson::BuildError`](crate::nfa::thompson::BuildError)
16/// type from its `source` method via the `std::error::Error` trait. This error
17/// only occurs when using convenience routines for building a lazy DFA
18/// directly from a pattern string.
19///
20/// When the `std` feature is enabled, this implements the `std::error::Error`
21/// trait.
22#[derive(#[automatically_derived]
impl ::core::clone::Clone for BuildError {
    #[inline]
    fn clone(&self) -> BuildError {
        BuildError { kind: ::core::clone::Clone::clone(&self.kind) }
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for BuildError {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field1_finish(f, "BuildError",
            "kind", &&self.kind)
    }
}Debug)]
23pub struct BuildError {
24    kind: BuildErrorKind,
25}
26
27#[derive(#[automatically_derived]
impl ::core::clone::Clone for BuildErrorKind {
    #[inline]
    fn clone(&self) -> BuildErrorKind {
        match self {
            BuildErrorKind::NFA(__self_0) =>
                BuildErrorKind::NFA(::core::clone::Clone::clone(__self_0)),
            BuildErrorKind::InsufficientCacheCapacity {
                minimum: __self_0, given: __self_1 } =>
                BuildErrorKind::InsufficientCacheCapacity {
                    minimum: ::core::clone::Clone::clone(__self_0),
                    given: ::core::clone::Clone::clone(__self_1),
                },
            BuildErrorKind::InsufficientStateIDCapacity { err: __self_0 } =>
                BuildErrorKind::InsufficientStateIDCapacity {
                    err: ::core::clone::Clone::clone(__self_0),
                },
            BuildErrorKind::Unsupported(__self_0) =>
                BuildErrorKind::Unsupported(::core::clone::Clone::clone(__self_0)),
        }
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for BuildErrorKind {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            BuildErrorKind::NFA(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "NFA",
                    &__self_0),
            BuildErrorKind::InsufficientCacheCapacity {
                minimum: __self_0, given: __self_1 } =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f,
                    "InsufficientCacheCapacity", "minimum", __self_0, "given",
                    &__self_1),
            BuildErrorKind::InsufficientStateIDCapacity { err: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "InsufficientStateIDCapacity", "err", &__self_0),
            BuildErrorKind::Unsupported(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "Unsupported", &__self_0),
        }
    }
}Debug)]
28enum BuildErrorKind {
29    NFA(nfa::thompson::BuildError),
30    InsufficientCacheCapacity { minimum: usize, given: usize },
31    InsufficientStateIDCapacity { err: LazyStateIDError },
32    Unsupported(&'static str),
33}
34
35impl BuildError {
36    pub(crate) fn nfa(err: nfa::thompson::BuildError) -> BuildError {
37        BuildError { kind: BuildErrorKind::NFA(err) }
38    }
39
40    pub(crate) fn insufficient_cache_capacity(
41        minimum: usize,
42        given: usize,
43    ) -> BuildError {
44        BuildError {
45            kind: BuildErrorKind::InsufficientCacheCapacity { minimum, given },
46        }
47    }
48
49    pub(crate) fn insufficient_state_id_capacity(
50        err: LazyStateIDError,
51    ) -> BuildError {
52        BuildError {
53            kind: BuildErrorKind::InsufficientStateIDCapacity { err },
54        }
55    }
56
57    pub(crate) fn unsupported_dfa_word_boundary_unicode() -> BuildError {
58        let msg = "cannot build lazy DFAs for regexes with Unicode word \
59                   boundaries; switch to ASCII word boundaries, or \
60                   heuristically enable Unicode word boundaries or use a \
61                   different regex engine";
62        BuildError { kind: BuildErrorKind::Unsupported(msg) }
63    }
64}
65
66#[cfg(feature = "std")]
67impl std::error::Error for BuildError {
68    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
69        match self.kind {
70            BuildErrorKind::NFA(ref err) => Some(err),
71            _ => None,
72        }
73    }
74}
75
76impl core::fmt::Display for BuildError {
77    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
78        match self.kind {
79            BuildErrorKind::NFA(_) => f.write_fmt(format_args!("error building NFA"))write!(f, "error building NFA"),
80            BuildErrorKind::InsufficientCacheCapacity { minimum, given } => {
81                f.write_fmt(format_args!("given cache capacity ({0}) is smaller than minimum required ({1})",
        given, minimum))write!(
82                    f,
83                    "given cache capacity ({given}) is smaller than \
84                     minimum required ({minimum})",
85                )
86            }
87            BuildErrorKind::InsufficientStateIDCapacity { ref err } => {
88                err.fmt(f)
89            }
90            BuildErrorKind::Unsupported(ref msg) => {
91                f.write_fmt(format_args!("unsupported regex feature for DFAs: {0}", msg))write!(f, "unsupported regex feature for DFAs: {msg}")
92            }
93        }
94    }
95}
96
97/// An error that can occur when computing the start state for a search.
98///
99/// Computing a start state can fail for a few reasons, either
100/// based on incorrect configuration or even based on whether
101/// the look-behind byte triggers a quit state. Typically
102/// one does not need to handle this error if you're using
103/// [`DFA::start_state_forward`](crate::hybrid::dfa::DFA::start_state_forward)
104/// (or its reverse counterpart), as that routine automatically converts
105/// `StartError` to a [`MatchError`](crate::MatchError) for you.
106///
107/// This error may be returned by the
108/// [`DFA::start_state`](crate::hybrid::dfa::DFA::start_state) routine.
109///
110/// This error implements the `std::error::Error` trait when the `std` feature
111/// is enabled.
112///
113/// This error is marked as non-exhaustive. New variants may be added in a
114/// semver compatible release.
115#[non_exhaustive]
116#[derive(#[automatically_derived]
impl ::core::clone::Clone for StartError {
    #[inline]
    fn clone(&self) -> StartError {
        match self {
            StartError::Cache { err: __self_0 } =>
                StartError::Cache {
                    err: ::core::clone::Clone::clone(__self_0),
                },
            StartError::Quit { byte: __self_0 } =>
                StartError::Quit {
                    byte: ::core::clone::Clone::clone(__self_0),
                },
            StartError::UnsupportedAnchored { mode: __self_0 } =>
                StartError::UnsupportedAnchored {
                    mode: ::core::clone::Clone::clone(__self_0),
                },
        }
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for StartError {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            StartError::Cache { err: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f, "Cache",
                    "err", &__self_0),
            StartError::Quit { byte: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f, "Quit",
                    "byte", &__self_0),
            StartError::UnsupportedAnchored { mode: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "UnsupportedAnchored", "mode", &__self_0),
        }
    }
}Debug)]
117pub enum StartError {
118    /// An error that occurs when cache inefficiency has dropped below the
119    /// configured heuristic thresholds.
120    Cache {
121        /// The underlying cache error that occurred.
122        err: CacheError,
123    },
124    /// An error that occurs when a starting configuration's look-behind byte
125    /// is in this DFA's quit set.
126    Quit {
127        /// The quit byte that was found.
128        byte: u8,
129    },
130    /// An error that occurs when the caller requests an anchored mode that
131    /// isn't supported by the DFA.
132    UnsupportedAnchored {
133        /// The anchored mode given that is unsupported.
134        mode: Anchored,
135    },
136}
137
138impl StartError {
139    pub(crate) fn cache(err: CacheError) -> StartError {
140        StartError::Cache { err }
141    }
142
143    pub(crate) fn quit(byte: u8) -> StartError {
144        StartError::Quit { byte }
145    }
146
147    pub(crate) fn unsupported_anchored(mode: Anchored) -> StartError {
148        StartError::UnsupportedAnchored { mode }
149    }
150}
151
152#[cfg(feature = "std")]
153impl std::error::Error for StartError {
154    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
155        match *self {
156            StartError::Cache { ref err } => Some(err),
157            _ => None,
158        }
159    }
160}
161
162impl core::fmt::Display for StartError {
163    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
164        match *self {
165            StartError::Cache { .. } => f.write_fmt(format_args!("error computing start state because of cache inefficiency"))write!(
166                f,
167                "error computing start state because of cache inefficiency"
168            ),
169            StartError::Quit { byte } => f.write_fmt(format_args!("error computing start state because the look-behind byte {0:?} triggered a quit state",
        crate::util::escape::DebugByte(byte)))write!(
170                f,
171                "error computing start state because the look-behind byte \
172                 {:?} triggered a quit state",
173                crate::util::escape::DebugByte(byte),
174            ),
175            StartError::UnsupportedAnchored { mode: Anchored::Yes } => {
176                f.write_fmt(format_args!("error computing start state because anchored searches are not supported or enabled"))write!(
177                    f,
178                    "error computing start state because \
179                     anchored searches are not supported or enabled"
180                )
181            }
182            StartError::UnsupportedAnchored { mode: Anchored::No } => {
183                f.write_fmt(format_args!("error computing start state because unanchored searches are not supported or enabled"))write!(
184                    f,
185                    "error computing start state because \
186                     unanchored searches are not supported or enabled"
187                )
188            }
189            StartError::UnsupportedAnchored {
190                mode: Anchored::Pattern(pid),
191            } => {
192                f.write_fmt(format_args!("error computing start state because anchored searches for a specific pattern ({0}) are not supported or enabled",
        pid.as_usize()))write!(
193                    f,
194                    "error computing start state because \
195                     anchored searches for a specific pattern ({}) \
196                     are not supported or enabled",
197                    pid.as_usize(),
198                )
199            }
200        }
201    }
202}
203
204/// An error that occurs when cache usage has become inefficient.
205///
206/// One of the weaknesses of a lazy DFA is that it may need to clear its
207/// cache repeatedly if it's not big enough. If this happens too much, then it
208/// can slow searching down significantly. A mitigation to this is to use
209/// heuristics to detect whether the cache is being used efficiently or not.
210/// If not, then a lazy DFA can return a `CacheError`.
211///
212/// The default configuration of a lazy DFA in this crate is
213/// set such that a `CacheError` will never occur. Instead,
214/// callers must opt into this behavior with settings like
215/// [`dfa::Config::minimum_cache_clear_count`](crate::hybrid::dfa::Config::minimum_cache_clear_count)
216/// and
217/// [`dfa::Config::minimum_bytes_per_state`](crate::hybrid::dfa::Config::minimum_bytes_per_state).
218///
219/// When the `std` feature is enabled, this implements the `std::error::Error`
220/// trait.
221#[derive(#[automatically_derived]
impl ::core::clone::Clone for CacheError {
    #[inline]
    fn clone(&self) -> CacheError {
        CacheError(::core::clone::Clone::clone(&self.0))
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for CacheError {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_tuple_field1_finish(f, "CacheError",
            &&self.0)
    }
}Debug)]
222pub struct CacheError(());
223
224impl CacheError {
225    pub(crate) fn too_many_cache_clears() -> CacheError {
226        CacheError(())
227    }
228
229    pub(crate) fn bad_efficiency() -> CacheError {
230        CacheError(())
231    }
232}
233
234#[cfg(feature = "std")]
235impl std::error::Error for CacheError {}
236
237impl core::fmt::Display for CacheError {
238    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
239        f.write_fmt(format_args!("lazy DFA cache has been cleared too many times"))write!(f, "lazy DFA cache has been cleared too many times")
240    }
241}