A high-performance, derivative-based regex engine with first-class support for intersection (&) and complement (~). Non-backtracking. Built for complex patterns (large alternations, lookarounds, boolean combinations) that make other engines degrade or fall back to slower paths.
paper | blog post | syntax docs | dotnet version and web playground
cargo add resharp// 8+ alphanumeric & digit & uppercase
let re = resharp::Regex::new(r"[A-Za-z0-9]{8,}&_*[0-9]_*&_*[A-Z]_*").unwrap();
let found = re.is_match(b"Hunter2024").unwrap();
let matches = re.find_all(b"try Hunter2024 or password1").unwrap();On standard patterns RE# matches regex throughput. Key features:
- intersection (
&), complement (~) and lookarounds - large alternations with high throughput (at the cost of memory)
- linear time for all matches, see hardened mode
- fail-loud behavior: capacity / lookahead overflow returns
Errinstead of silently degrading
RE# supports is_match and find_all. No single-match find/captures, apart from a few special cases like find_anchored. See docs/api.md and docs/features.md.
RE# supports standard regex syntax plus three extensions: _ (any byte), & (intersection), and ~(...) (complement). _* means "any string".
_* any string
a_* any string that starts with 'a'
_*a any string that ends with 'a'
_*a_* any string that contains 'a'
~(_*a_*) any string that does NOT contain 'a'
(_*a_*)&~(_*b_*) contains 'a' AND does not contain 'b'
(?<=b)_*&_*(?=a) preceded by 'b' AND followed by 'a'You combine all of these with & to get more complex patterns. RE# also supports lookarounds ((?=...), (?<=...), (?!...), (?<!...)), compiled into the automaton with no backtracking.
- Leftmost-longest, not leftmost-first.
y|yeson"yes"matchesyes. Branch order is irrelevant. - Multiline on by default.
^/$match start/end of line, disable withmultiline(false).\A/\zmatch start/end of input.
Lazy quantifiers (*?, +?, ...) are parse errors: rewrite with complement when possible: <div>.*?</div> -> <div>(.*&~(_*</div>_*))</div>. other unsupported features. Full syntax: syntax.md.
All options and their defaults:
use resharp::{RegexOptions, UnicodeMode};
let defaults = RegexOptions {
max_dfa_capacity: u16::MAX as usize, // max cached DFA states
lookahead_context_max: 800, // max lookahead context distance
unicode: UnicodeMode::Default, // Ascii | Default | Full | Javascript
case_insensitive: false,
dot_matches_new_line: false, // `.` matches `\n`
multiline: true, // `^`/`$` match start/end of line
ignore_whitespace: false, // verbose mode
hardened: false, // true: linear find_all, slower
unbounded_size: false, // lift size caps
..Default::default()
};Override with the builder methods:
let opts = RegexOptions::default().unicode(UnicodeMode::Ascii).hardened(true);
let re = resharp::Regex::with_options(r"pattern", opts).unwrap();RE# against regex, fancy-regex, and PCRE2 on a few popular patterns from crates.io. Regenerate with:
node scripts/bench-popular-table.mtsFull benchmark source: resharp-engine/examples/popular-crates.rs.
CPU: AMD Ryzen 7 5800X 8-Core Processor
| Pattern | resharp | regex | fancy-regex | pcre2 |
|---|---|---|---|---|
\s+ |
295.24 MiB/s (1.00x) | 146.08 MiB/s (2.02x) | 135.37 MiB/s (2.18x) | 153.13 MiB/s (1.93x) |
\d+ |
1.76 GiB/s (1.00x) | 434.06 MiB/s (4.15x) | 423.04 MiB/s (4.26x) | 358.25 MiB/s (5.03x) |
.* |
2.27 GiB/s (1.00x) | 186.8 MiB/s (12.47x) | 186.98 MiB/s (12.45x) | 768.24 MiB/s (3.03x) |
<[^>]+> |
2.09 GiB/s (1.25x) | 530.64 MiB/s (5.03x) | 513.61 MiB/s (5.20x) | 2.61 GiB/s (1.00x) |
\n{3,} |
19.68 GiB/s (1.00x) | 14.36 GiB/s (1.37x) | 13.57 GiB/s (1.45x) | 6.61 GiB/s (2.98x) |
\x1b\[[0-9;]*m |
11.78 GiB/s (1.00x) | 7.98 GiB/s (1.48x) | 7.58 GiB/s (1.55x) | 11.07 GiB/s (1.06x) |
\$\{([^}]+)\} |
5.63 GiB/s (1.89x) | 885.98 MiB/s (12.32x) | 884.81 MiB/s (12.33x) | 10.66 GiB/s (1.00x) |
<[^>]*> |
2.82 GiB/s (1.07x) | 531.41 MiB/s (5.80x) | 527.65 MiB/s (5.85x) | 3.01 GiB/s (1.00x) |
\w+ |
270.3 MiB/s (1.00x) | 129.23 MiB/s (2.09x) | 114.57 MiB/s (2.36x) | 203.64 MiB/s (1.33x) |
-+ |
6.8 GiB/s (1.00x) | 2.34 GiB/s (2.91x) | 2.24 GiB/s (3.03x) | 4.49 GiB/s (1.52x) |
test |
12.06 GiB/s (1.48x) | 17.89 GiB/s (1.00x) | 15.1 GiB/s (1.19x) | 6.07 GiB/s (2.95x) |
\d+\.\d+\.\d+ |
4.86 GiB/s (1.00x) | 2.88 GiB/s (1.69x) | 2.82 GiB/s (1.73x) | 395.43 MiB/s (12.59x) |
[0-9]+ |
1.92 GiB/s (1.00x) | 548.14 MiB/s (3.58x) | 503.93 MiB/s (3.90x) | 997.63 MiB/s (1.97x) |
([^`]+) |
12.99 GiB/s (1.09x) | 8.28 GiB/s (1.71x) | 8.25 GiB/s (1.72x) | 14.17 GiB/s (1.00x) |
"([^"]+)" |
5.44 GiB/s (1.00x) | 2.93 GiB/s (1.85x) | 2.78 GiB/s (1.96x) | 5.43 GiB/s (1.00x) |
\[([^\]]+)\]\(([^)]+)\) |
4.99 GiB/s (1.13x) | 578.99 MiB/s (9.98x) | 576.55 MiB/s (10.03x) | 5.65 GiB/s (1.00x) |
\s{2,} |
609.32 MiB/s (1.04x) | 631.77 MiB/s (1.00x) | 627.11 MiB/s (1.01x) | 324.2 MiB/s (1.95x) |
[A-Z] |
2.18 GiB/s (1.00x) | 405.69 MiB/s (5.51x) | 391.59 MiB/s (5.71x) | 1.12 GiB/s (1.96x) |
(?is)<script[^>]*>.*?</script> * |
807.97 MiB/s (8.97x) | 651.21 MiB/s (11.13x) | 637.2 MiB/s (11.38x) | 7.08 GiB/s (1.00x) |
| Pattern | resharp | regex | fancy-regex | pcre2 |
|---|---|---|---|---|
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.... |
43.45 ns (1.20x) | 43.08 ns (1.19x) | 39.3 ns (1.09x) | 36.22 ns (1.00x) |
^\d{4}-\d{2}-\d{2}$ |
22.88 ns (1.05x) | 22.57 ns (1.04x) | 21.75 ns (1.00x) | 27.97 ns (1.29x) |
^$ |
2.76 ns (1.00x) | 18.05 ns (6.55x) | 14.29 ns (5.18x) | 18.56 ns (6.73x) |
^\d+$ |
24.04 ns (1.07x) | 23.77 ns (1.06x) | 22.46 ns (1.00x) | 30.05 ns (1.34x) |
^[a-zA-Z_][a-zA-Z0-9_]*$ |
35.05 ns (1.10x) | 34.92 ns (1.10x) | 31.81 ns (1.00x) | 32.37 ns (1.02x) |
^[a-zA-Z0-9_-]+$ |
35.67 ns (1.20x) | 34.64 ns (1.17x) | 31.28 ns (1.05x) | 29.66 ns (1.00x) |
| Pattern | resharp | fancy-regex | pcre2 |
|---|---|---|---|
(?<!_)deleted_at(?!_) * |
8.32 GiB/s (1.00x) | 37.6 MiB/s (226.64x) | 6.24 GiB/s (1.33x) |
(?<=\d)\.(?=\S) |
2.61 GiB/s (1.19x) | 32.87 MiB/s (97.06x) | 3.12 GiB/s (1.00x) |
(?<="|')\s+(?=[^<>\s]+=) |
2.55 GiB/s (1.00x) | 39.62 MiB/s (65.84x) | 406.05 MiB/s (6.42x) |
| Pattern | resharp | fancy-regex | pcre2 |
|---|---|---|---|
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d... |
21.28 ns (1.00x) | 414.81 ns (19.50x) | 65.23 ns (3.07x) |
^(?![-_]*$)[A-Za-z0-9][A-Za-z0... * |
19.94 ns (1.00x) | 352.32 ns (17.67x) | 31.32 ns (1.57x) |