|
13 | 13 | # limitations under the License. |
14 | 14 |
|
15 | 15 | import math |
16 | | -import re |
17 | 16 | import typing |
18 | 17 | from urllib import parse as urlparse |
19 | 18 |
|
20 | 19 | import celpy |
| 20 | +import re2 |
21 | 21 | from celpy import celtypes |
22 | 22 |
|
23 | 23 | from protovalidate.internal import string_format |
24 | 24 | from protovalidate.internal.rules import MessageType, field_to_cel |
25 | 25 |
|
26 | 26 | # See https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address |
27 | | -_email_regex = re.compile( |
| 27 | +_email_regex = re2.compile( |
28 | 28 | r"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$" |
29 | 29 | ) |
30 | 30 |
|
@@ -1553,13 +1553,22 @@ def __peek(self, char: str) -> bool: |
1553 | 1553 | return self._index < len(self._string) and self._string[self._index] == char |
1554 | 1554 |
|
1555 | 1555 |
|
| 1556 | +def matches(text: str, pattern: str) -> celpy.Result: |
| 1557 | + try: |
| 1558 | + m = re2.search(pattern, text) |
| 1559 | + except re2.error as ex: |
| 1560 | + return celpy.CELEvalError("match error", ex.__class__, ex.args) |
| 1561 | + return celtypes.BoolType(m is not None) |
| 1562 | + |
| 1563 | + |
1556 | 1564 | def make_extra_funcs(locale: str) -> dict[str, celpy.CELFunction]: |
1557 | 1565 | # TODO(#257): Fix types and add tests for StringFormat. |
1558 | 1566 | # For now, ignoring the type. |
1559 | 1567 | string_fmt = string_format.StringFormat(locale) # type: ignore |
1560 | 1568 | return { |
1561 | 1569 | # Missing standard functions |
1562 | 1570 | "format": string_fmt.format, |
| 1571 | + "matches": matches, |
1563 | 1572 | # protovalidate specific functions |
1564 | 1573 | "getField": cel_get_field, |
1565 | 1574 | "isNan": cel_is_nan, |
|
0 commit comments