| use crate::util::{ |
| captures, look, |
| primitives::{PatternID, StateID}, |
| }; |
| |
| /// An error that can occurred during the construction of a thompson NFA. |
| /// |
| /// This error does not provide many introspection capabilities. There are |
| /// generally only two things you can do with it: |
| /// |
| /// * Obtain a human readable message via its `std::fmt::Display` impl. |
| /// * Access an underlying [`regex_syntax::Error`] type from its `source` |
| /// method via the `std::error::Error` trait. This error only occurs when using |
| /// convenience routines for building an NFA directly from a pattern string. |
| /// |
| /// Otherwise, errors typically occur when a limit has been breeched. For |
| /// example, if the total heap usage of the compiled NFA exceeds the limit |
| /// set by [`Config::nfa_size_limit`](crate::nfa::thompson::Config), then |
| /// building the NFA will fail. |
| #[derive(Clone, Debug)] |
| pub struct BuildError { |
| kind: BuildErrorKind, |
| } |
| |
| /// The kind of error that occurred during the construction of a thompson NFA. |
| #[derive(Clone, Debug)] |
| enum BuildErrorKind { |
| /// An error that occurred while parsing a regular expression. Note that |
| /// this error may be printed over multiple lines, and is generally |
| /// intended to be end user readable on its own. |
| #[cfg(feature = "syntax")] |
| Syntax(regex_syntax::Error), |
| /// An error that occurs if the capturing groups provided to an NFA builder |
| /// do not satisfy the documented invariants. For example, things like |
| /// too many groups, missing groups, having the first (zeroth) group be |
| /// named or duplicate group names within the same pattern. |
| Captures(captures::GroupInfoError), |
| /// An error that occurs when an NFA contains a Unicode word boundary, but |
| /// where the crate was compiled without the necessary data for dealing |
| /// with Unicode word boundaries. |
| Word(look::UnicodeWordBoundaryError), |
| /// An error that occurs if too many patterns were given to the NFA |
| /// compiler. |
| TooManyPatterns { |
| /// The number of patterns given, which exceeds the limit. |
| given: usize, |
| /// The limit on the number of patterns. |
| limit: usize, |
| }, |
| /// An error that occurs if too states are produced while building an NFA. |
| TooManyStates { |
| /// The minimum number of states that are desired, which exceeds the |
| /// limit. |
| given: usize, |
| /// The limit on the number of states. |
| limit: usize, |
| }, |
| /// An error that occurs when NFA compilation exceeds a configured heap |
| /// limit. |
| ExceededSizeLimit { |
| /// The configured limit, in bytes. |
| limit: usize, |
| }, |
| /// An error that occurs when an invalid capture group index is added to |
| /// the NFA. An "invalid" index can be one that would otherwise overflow |
| /// a `usize` on the current target. |
| InvalidCaptureIndex { |
| /// The invalid index that was given. |
| index: u32, |
| }, |
| /// An error that occurs when one tries to build a reverse NFA with |
| /// captures enabled. Currently, this isn't supported, but we probably |
| /// should support it at some point. |
| #[cfg(feature = "syntax")] |
| UnsupportedCaptures, |
| } |
| |
| impl BuildError { |
| /// If this error occurred because the NFA exceeded the configured size |
| /// limit before being built, then this returns the configured size limit. |
| /// |
| /// The limit returned is what was configured, and corresponds to the |
| /// maximum amount of heap usage in bytes. |
| pub fn size_limit(&self) -> Option<usize> { |
| match self.kind { |
| BuildErrorKind::ExceededSizeLimit { limit } => Some(limit), |
| _ => None, |
| } |
| } |
| |
| fn kind(&self) -> &BuildErrorKind { |
| &self.kind |
| } |
| |
| #[cfg(feature = "syntax")] |
| pub(crate) fn syntax(err: regex_syntax::Error) -> BuildError { |
| BuildError { kind: BuildErrorKind::Syntax(err) } |
| } |
| |
| pub(crate) fn captures(err: captures::GroupInfoError) -> BuildError { |
| BuildError { kind: BuildErrorKind::Captures(err) } |
| } |
| |
| pub(crate) fn word(err: look::UnicodeWordBoundaryError) -> BuildError { |
| BuildError { kind: BuildErrorKind::Word(err) } |
| } |
| |
| pub(crate) fn too_many_patterns(given: usize) -> BuildError { |
| let limit = PatternID::LIMIT; |
| BuildError { kind: BuildErrorKind::TooManyPatterns { given, limit } } |
| } |
| |
| pub(crate) fn too_many_states(given: usize) -> BuildError { |
| let limit = StateID::LIMIT; |
| BuildError { kind: BuildErrorKind::TooManyStates { given, limit } } |
| } |
| |
| pub(crate) fn exceeded_size_limit(limit: usize) -> BuildError { |
| BuildError { kind: BuildErrorKind::ExceededSizeLimit { limit } } |
| } |
| |
| pub(crate) fn invalid_capture_index(index: u32) -> BuildError { |
| BuildError { kind: BuildErrorKind::InvalidCaptureIndex { index } } |
| } |
| |
| #[cfg(feature = "syntax")] |
| pub(crate) fn unsupported_captures() -> BuildError { |
| BuildError { kind: BuildErrorKind::UnsupportedCaptures } |
| } |
| } |
| |
| #[cfg(feature = "std")] |
| impl std::error::Error for BuildError { |
| fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { |
| match self.kind() { |
| #[cfg(feature = "syntax")] |
| BuildErrorKind::Syntax(ref err) => Some(err), |
| BuildErrorKind::Captures(ref err) => Some(err), |
| _ => None, |
| } |
| } |
| } |
| |
| impl core::fmt::Display for BuildError { |
| fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { |
| match self.kind() { |
| #[cfg(feature = "syntax")] |
| BuildErrorKind::Syntax(_) => write!(f, "error parsing regex"), |
| BuildErrorKind::Captures(_) => { |
| write!(f, "error with capture groups") |
| } |
| BuildErrorKind::Word(_) => { |
| write!(f, "NFA contains Unicode word boundary") |
| } |
| BuildErrorKind::TooManyPatterns { given, limit } => write!( |
| f, |
| "attempted to compile {} patterns, \ |
| which exceeds the limit of {}", |
| given, limit, |
| ), |
| BuildErrorKind::TooManyStates { given, limit } => write!( |
| f, |
| "attempted to compile {} NFA states, \ |
| which exceeds the limit of {}", |
| given, limit, |
| ), |
| BuildErrorKind::ExceededSizeLimit { limit } => write!( |
| f, |
| "heap usage during NFA compilation exceeded limit of {}", |
| limit, |
| ), |
| BuildErrorKind::InvalidCaptureIndex { index } => write!( |
| f, |
| "capture group index {} is invalid (too big or discontinuous)", |
| index, |
| ), |
| #[cfg(feature = "syntax")] |
| BuildErrorKind::UnsupportedCaptures => write!( |
| f, |
| "currently captures must be disabled when compiling \ |
| a reverse NFA", |
| ), |
| } |
| } |
| } |