ieviev/resharp

RE# - A high-performance, derivative-based regex engine with first-class support for intersection and complement operations.

Rust

185

227 commits

updated Sep 17, 2026

See the code

README

RE#

crates.io docs.rs

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

Quick start

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();

When to use RE#

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 Err instead 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.

Syntax extensions

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.

Differences from PCRE-style engines

  • Leftmost-longest, not leftmost-first. y|yes on "yes" matches yes. Branch order is irrelevant.
  • Multiline on by default. ^/$ match start/end of line, disable with multiline(false). \A/\z match 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.

Configuration

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();

Benchmarks

RE# against regex, fancy-regex, and PCRE2 on a few popular patterns from crates.io. Regenerate with:

node scripts/bench-popular-table.mts

Full benchmark source: resharp-engine/examples/popular-crates.rs.

CPU: AMD Ryzen 7 5800X 8-Core Processor

Scan (find_all over a 1 MiB haystack), throughput

Patternresharpregexfancy-regexpcre2
\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;]*m11.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)
test12.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)

Validate (is_match on a single value), latency

Patternresharpregexfancy-regexpcre2
^[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)

Lookaround scan

Patternresharpfancy-regexpcre2
(?<!_)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)

Lookaround validate

Patternresharpfancy-regexpcre2
^(?=.*[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)
automata
regex
regex-engine

Contributors

ieviev

197 commits

Aquaticat

28 commits

maximaximal

1 commits

SKalt

1 commits

ieviev/resharp

RE# - A high-performance, derivative-based regex engine with first-class support for intersection and complement operations.

Rust

185

227 commits

updated Sep 17, 2026

See the code

README

RE#

crates.io docs.rs

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

Quick start

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();

When to use RE#

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 Err instead 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.

Syntax extensions

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.

Differences from PCRE-style engines

  • Leftmost-longest, not leftmost-first. y|yes on "yes" matches yes. Branch order is irrelevant.
  • Multiline on by default. ^/$ match start/end of line, disable with multiline(false). \A/\z match 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.

Configuration

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();

Benchmarks

RE# against regex, fancy-regex, and PCRE2 on a few popular patterns from crates.io. Regenerate with:

node scripts/bench-popular-table.mts

Full benchmark source: resharp-engine/examples/popular-crates.rs.

CPU: AMD Ryzen 7 5800X 8-Core Processor

Scan (find_all over a 1 MiB haystack), throughput

Patternresharpregexfancy-regexpcre2
\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;]*m11.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)
test12.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)

Validate (is_match on a single value), latency

Patternresharpregexfancy-regexpcre2
^[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)

Lookaround scan

Patternresharpfancy-regexpcre2
(?<!_)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)

Lookaround validate

Patternresharpfancy-regexpcre2
^(?=.*[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)
automata
regex
regex-engine

Contributors

ieviev

197 commits

Aquaticat

28 commits

maximaximal

1 commits

SKalt

1 commits

Languages

Rust

99.4%