1 | use std::fmt; |
2 | use std::iter::repeat; |
3 | |
4 | /// An error that occurred during parsing or compiling a regular expression. |
5 | #[derive (Clone, PartialEq)] |
6 | pub enum Error { |
7 | /// A syntax error. |
8 | Syntax(String), |
9 | /// The compiled program exceeded the set size |
10 | /// limit. The argument is the size limit imposed by |
11 | /// [`RegexBuilder::size_limit`](crate::RegexBuilder::size_limit). Even |
12 | /// when not configured explicitly, it defaults to a reasonable limit. |
13 | /// |
14 | /// If you're getting this error, it occurred because your regex has been |
15 | /// compiled to an intermediate state that is too big. It is important to |
16 | /// note that exceeding this limit does _not_ mean the regex is too big to |
17 | /// _work_, but rather, the regex is big enough that it may wind up being |
18 | /// surprisingly slow when used in a search. In other words, this error is |
19 | /// meant to be a practical heuristic for avoiding a performance footgun, |
20 | /// and especially so for the case where the regex pattern is coming from |
21 | /// an untrusted source. |
22 | /// |
23 | /// There are generally two ways to move forward if you hit this error. |
24 | /// The first is to find some way to use a smaller regex. The second is to |
25 | /// increase the size limit via `RegexBuilder::size_limit`. However, if |
26 | /// your regex pattern is not from a trusted source, then neither of these |
27 | /// approaches may be appropriate. Instead, you'll have to determine just |
28 | /// how big of a regex you want to allow. |
29 | CompiledTooBig(usize), |
30 | /// Hints that destructuring should not be exhaustive. |
31 | /// |
32 | /// This enum may grow additional variants, so this makes sure clients |
33 | /// don't count on exhaustive matching. (Otherwise, adding a new variant |
34 | /// could break existing code.) |
35 | #[doc (hidden)] |
36 | __Nonexhaustive, |
37 | } |
38 | |
39 | impl ::std::error::Error for Error { |
40 | // TODO: Remove this method entirely on the next breaking semver release. |
41 | #[allow (deprecated)] |
42 | fn description(&self) -> &str { |
43 | match *self { |
44 | Error::Syntax(ref err: &String) => err, |
45 | Error::CompiledTooBig(_) => "compiled program too big" , |
46 | Error::__Nonexhaustive => unreachable!(), |
47 | } |
48 | } |
49 | } |
50 | |
51 | impl fmt::Display for Error { |
52 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
53 | match *self { |
54 | Error::Syntax(ref err: &String) => err.fmt(f), |
55 | Error::CompiledTooBig(limit: usize) => write!( |
56 | f, |
57 | "Compiled regex exceeds size limit of {} bytes." , |
58 | limit |
59 | ), |
60 | Error::__Nonexhaustive => unreachable!(), |
61 | } |
62 | } |
63 | } |
64 | |
65 | // We implement our own Debug implementation so that we show nicer syntax |
66 | // errors when people use `Regex::new(...).unwrap()`. It's a little weird, |
67 | // but the `Syntax` variant is already storing a `String` anyway, so we might |
68 | // as well format it nicely. |
69 | impl fmt::Debug for Error { |
70 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
71 | match *self { |
72 | Error::Syntax(ref err: &String) => { |
73 | let hr: String = repeat(elt:'~' ).take(79).collect(); |
74 | writeln!(f, "Syntax(" )?; |
75 | writeln!(f, " {}" , hr)?; |
76 | writeln!(f, " {}" , err)?; |
77 | writeln!(f, " {}" , hr)?; |
78 | write!(f, ")" )?; |
79 | Ok(()) |
80 | } |
81 | Error::CompiledTooBig(limit: usize) => { |
82 | f.debug_tuple(name:"CompiledTooBig" ).field(&limit).finish() |
83 | } |
84 | Error::__Nonexhaustive => { |
85 | f.debug_tuple(name:"__Nonexhaustive" ).finish() |
86 | } |
87 | } |
88 | } |
89 | } |
90 | |