fancy_regex/
error.rs

1use alloc::string::String;
2use core::fmt;
3use regex_automata::meta::BuildError as RaBuildError;
4
5/// Result type for this crate with specific error enum.
6pub type Result<T> = ::core::result::Result<T, Error>;
7
8pub type ParseErrorPosition = usize;
9
10/// An error as the result of parsing, compiling or running a regex.
11#[derive(Clone, Debug)]
12#[non_exhaustive]
13pub enum Error {
14    /// An error as a result of parsing a regex pattern, with the position where the error occurred
15    ParseError(ParseErrorPosition, ParseError),
16    /// An error as a result of compiling a regex
17    CompileError(CompileError),
18    /// An error as a result of running a regex
19    RuntimeError(RuntimeError),
20}
21
22/// An error for the result of parsing a regex pattern.
23#[derive(Clone, Debug)]
24#[non_exhaustive]
25pub enum ParseError {
26    /// General parsing error
27    GeneralParseError(String),
28    /// Opening parenthesis without closing parenthesis, e.g. `(a|b`
29    UnclosedOpenParen,
30    /// Invalid repeat syntax
31    InvalidRepeat,
32    /// Pattern too deeply nested
33    RecursionExceeded,
34    /// Backslash without following character
35    TrailingBackslash,
36    /// Invalid escape
37    InvalidEscape(String),
38    /// Unicode escape not closed
39    UnclosedUnicodeName,
40    /// Invalid hex escape
41    InvalidHex,
42    /// Invalid codepoint for hex or unicode escape
43    InvalidCodepointValue,
44    /// Invalid character class
45    InvalidClass,
46    /// Unknown group flag
47    UnknownFlag(String),
48    /// Disabling Unicode not supported
49    NonUnicodeUnsupported,
50    /// Invalid back reference
51    InvalidBackref,
52    /// Quantifier on lookaround or other zero-width assertion
53    TargetNotRepeatable,
54    /// Couldn't parse group name
55    InvalidGroupName,
56    /// Invalid group id in escape sequence
57    InvalidGroupNameBackref(String),
58}
59
60/// An error as the result of compiling a regex.
61#[derive(Clone, Debug)]
62#[non_exhaustive]
63pub enum CompileError {
64    /// Regex crate error
65    InnerError(RaBuildError),
66    /// Look-behind assertion without constant size
67    LookBehindNotConst,
68    /// Couldn't parse group name
69    InvalidGroupName,
70    /// Invalid group id in escape sequence
71    InvalidGroupNameBackref(String),
72    /// Invalid back reference
73    InvalidBackref,
74    /// Once named groups are used you cannot refer to groups by number
75    NamedBackrefOnly,
76    /// Feature not supported yet
77    FeatureNotYetSupported(String),
78    /// Subroutine call to non-existent group
79    SubroutineCallTargetNotFound(String, usize),
80}
81
82/// An error as the result of executing a regex.
83#[derive(Clone, Debug)]
84#[non_exhaustive]
85pub enum RuntimeError {
86    /// Max stack size exceeded for backtracking while executing regex.
87    StackOverflow,
88    /// Max limit for backtracking count exceeded while executing the regex.
89    /// Configure using
90    /// [`RegexBuilder::backtrack_limit`](struct.RegexBuilder.html#method.backtrack_limit).
91    BacktrackLimitExceeded,
92}
93
94#[cfg(feature = "std")]
95impl ::std::error::Error for Error {}
96
97impl fmt::Display for ParseError {
98    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
99        match self {
100            ParseError::GeneralParseError(s) => write!(f, "General parsing error: {}", s),
101            ParseError::UnclosedOpenParen => {
102                write!(f, "Opening parenthesis without closing parenthesis")
103            }
104            ParseError::InvalidRepeat => write!(f, "Invalid repeat syntax"),
105            ParseError::RecursionExceeded => write!(f, "Pattern too deeply nested"),
106            ParseError::TrailingBackslash => write!(f, "Backslash without following character"),
107            ParseError::InvalidEscape(s) => write!(f, "Invalid escape: {}", s),
108            ParseError::UnclosedUnicodeName => write!(f, "Unicode escape not closed"),
109            ParseError::InvalidHex => write!(f, "Invalid hex escape"),
110            ParseError::InvalidCodepointValue => {
111                write!(f, "Invalid codepoint for hex or unicode escape")
112            }
113            ParseError::InvalidClass => write!(f, "Invalid character class"),
114            ParseError::UnknownFlag(s) => write!(f, "Unknown group flag: {}", s),
115            ParseError::NonUnicodeUnsupported => write!(f, "Disabling Unicode not supported"),
116            ParseError::InvalidBackref => write!(f, "Invalid back reference"),
117            ParseError::InvalidGroupName => write!(f, "Could not parse group name"),
118            ParseError::InvalidGroupNameBackref(s) => {
119                write!(f, "Invalid group name in back reference: {}", s)
120            }
121            ParseError::TargetNotRepeatable => write!(f, "Target of repeat operator is invalid"),
122        }
123    }
124}
125
126impl fmt::Display for CompileError {
127    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
128        match self {
129            CompileError::InnerError(e) => write!(f, "Regex error: {}", e),
130            CompileError::LookBehindNotConst => {
131                write!(f, "Look-behind assertion without constant size")
132            },
133            CompileError::InvalidGroupName => write!(f, "Could not parse group name"),
134            CompileError::InvalidGroupNameBackref(s) => write!(f, "Invalid group name in back reference: {}", s),
135            CompileError::InvalidBackref => write!(f, "Invalid back reference"),
136            CompileError::NamedBackrefOnly => write!(f, "Numbered backref/call not allowed because named group was used, use a named backref instead"),
137            CompileError::FeatureNotYetSupported(s) => write!(f, "Regex uses currently unimplemented feature: {}", s),
138            CompileError::SubroutineCallTargetNotFound(s, ix) => {
139                write!(f, "Subroutine call target not found at position {}: {}", ix, s)
140            }
141        }
142    }
143}
144
145impl fmt::Display for RuntimeError {
146    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
147        match self {
148            RuntimeError::StackOverflow => write!(f, "Max stack size exceeded for backtracking"),
149            RuntimeError::BacktrackLimitExceeded => {
150                write!(f, "Max limit for backtracking count exceeded")
151            }
152        }
153    }
154}
155
156impl fmt::Display for Error {
157    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
158        match self {
159            Error::ParseError(position, parse_error) => {
160                write!(f, "Parsing error at position {}: {}", position, parse_error)
161            }
162            Error::CompileError(compile_error) => {
163                write!(f, "Error compiling regex: {}", compile_error)
164            }
165            Error::RuntimeError(runtime_error) => {
166                write!(f, "Error executing regex: {}", runtime_error)
167            }
168        }
169    }
170}
171
172impl From<CompileError> for Error {
173    fn from(compile_error: CompileError) -> Self {
174        Error::CompileError(compile_error)
175    }
176}