regexsolver 1.0.0

High-performance Rust library for building, combining, and analyzing regular expressions and finite automata
Documentation
# Changelog

All notable changes to this crate are documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.0.0] - 2026-08-08

This is a major redesign of the public API around the `Term` enum (wrapping
either a `RegularExpression` or a `FastAutomaton`), which dispatches each
operation to the cheaper representation when possible. See the crate-level
docs for the architecture. Almost the entire public surface changed; highlights
below.

### Added
- New `Term` constructors and conversions: `new_empty`, `new_total`,
  `new_empty_string`, `from_pattern`, `from_regex(RegularExpression)`,
  `from_automaton(FastAutomaton)`, plus `From<RegularExpression>`,
  `From<FastAutomaton>`, `FromStr`, `Display`, and `Default` (= `new_empty`).
- New `Term` operations: `concat`, `complement`, `determinize`, `minimize`,
  `matches`, `is_deterministic`, `is_minimal`, `is_finite`, `to_pattern`, and
  `iter_strings` (lazy `StringGenerator` iterator).
- `RegularExpression::MAX_NESTING_DEPTH` and a depth check in `to_automaton`
  that returns the new `EngineError::RegexTooDeeplyNested` for hand-built trees
  nested past the limit, instead of overflowing the stack.
- `to_automaton` returns `Cow` to avoid unnecessary cloning; `to_regex`
  returns `Result<Cow<…>, EngineError>` (see Changed — it is now fallible).
- `FastAutomaton` gained corresponding low-level constructors/operations
  (`new_empty`, `new_total`, `new_empty_string`, `determinize`, `minimize`
  using Hopcroft's algorithm, `is_minimal`, `unaccept`, `print_dot`,
  `try_add_transition`) and inspection helpers (`states`, `direct_states`,
  `transitions_from`, `transitions_to_vec`, `has_transition`, ...).
- New `EngineError` variants: `InvalidRepetitionBounds`,
  `IncompatibleSpanningSet`, `DeterministicAutomatonRequired`,
  `UnsupportedRegexFeature`, `RegexTooDeeplyNested`; the enum is now
  `#[non_exhaustive]`.
- `tracing` instrumentation on the core `Term`, `FastAutomaton`, and
  `RegularExpression` operations (concat, union, intersection, difference,
  complement, repeat, determinize, minimize, equivalence/subset checks,
  string generation, conversions). No-op unless a `tracing` subscriber is
  installed.
- Parallel (Rayon-backed) variants of union/intersection for >3 operands,
  gated behind the default-on `parallel` feature, with sequential fallbacks
  for `--no-default-features`.
- `cargo fmt --check`, `cargo clippy -- -D warnings`, `cargo doc --no-deps`
  (with `RUSTDOCFLAGS=-D warnings`), and a dependency vulnerability audit
  (`rustsec/audit-check`) to CI.
- `regex_charclass` is re-exported at the crate root, so automata can be
  built by hand (`Char`, `CharRange`) without adding a separately
  version-matched dependency.
- `NoHashHasher`, the crate-owned no-op hasher behind the `IntSet` state-id
  sets (replaces the `nohash-hasher` dependency, keeping 0.x types out of
  the public API).
- `EngineError` implements `Clone`; `StringGenerator` implements `Debug` and
  `FusedIterator`; `ExecutionProfileBuilder` implements `Debug` and `Clone`.
- `PathOrder` and `CharacterOrder`, the two independent axes
  `generate_strings`/`iter_strings` enumerate a language along.
  `PathOrder::Sweep` is the previous behaviour: shortest strings first, one
  path expanded in full before the next. `PathOrder::Interleave` covers
  every shape the automaton holds before asking any of them for a second
  string, so `.*abc.*` yields `abc`, `abc\u{0}`, `\u{0}abc`, ... instead of
  a million variations of `abc\u{0}`. `PathOrder::Shuffled` interleaves and
  additionally visits same-length shapes in a seed-drawn order, so *which*
  shapes a small `limit` reaches looks random too.
  `CharacterOrder::Ascending` (the default) expands each position from the
  low end of its character range; `CharacterOrder::Shuffled` draws each
  path's combinations through a seeded permutation instead — `[a-z]{8}`
  yields something like `sjtwsive` rather than `aaaaaaaa` (the exact
  shuffled sequence is implementation-defined). Every combination of the axes
  enumerates the same strings, stays deterministic (the seed defaults to 0),
  and pages with `offset` the same way; both axes shuffled is the mode to
  derive realistic test cases from a pattern.
- `GenerationOptions`, what `generate_strings`/`iter_strings` may generate:
  the two axes, the seed behind the `Shuffled` modes of both
  (`with_seed(u64)`), an optional charset (`with_charset(CharRange)`) that
  keeps generation to a set of characters — only strings made entirely of
  them come out; a path needing a ruled-out character is dropped whole,
  never shortened, so `.*abc.*` over `[ -~]` yields `abc`, `abc `, `abc!`,
  ... — plus optional length bounds (`with_min_length`/`with_max_length`)
  that confine the enumeration to a band of string lengths, `offset` never
  counting the strings outside it. Without a max, a deep `offset` into a
  looping language like `.*` pages into arbitrarily long strings.

### Changed
- `Term::to_regex`/`to_pattern` and `FastAutomaton::to_regex` are now fallible
  (`Result<_, EngineError>`) and honor the `ExecutionProfile` timeout, since
  state elimination can grow super-polynomially on adversarial automata.
  `Term`'s `Display` therefore renders a pattern only for regex-backed terms;
  automaton-backed terms display as Graphviz DOT (use `to_pattern` for a
  parseable pattern).
- `ExecutionProfile` redesigned as an immutable, thread-local-aware config
  built via the new `ExecutionProfileBuilder`, governing execution timeouts,
  state-count limits, and an `implicit_determinization` toggle.
- `union`/`intersection`/`concat` now take
  `impl IntoIterator<Item = impl Borrow<Term>>` instead of `&[Term]`, so
  `&[a, b]`, `[&a, &b]`, and `Vec<Term>` all work without cloning.
- `repeat` now takes `impl RangeBounds<u32>` (e.g. `3..6`, `..=2`) instead of
  explicit min/max parameters.
- `generate_strings` now takes `(limit, offset, options)`: pagination instead
  of a single `count`, plus the `GenerationOptions` to generate under (the
  two enumeration axes, a seed, and optionally a charset and length bounds).
  A `PathOrder`, a `CharacterOrder`, or a `(PathOrder, CharacterOrder)` pair
  converts into options, so any of them can be passed on its own.
  `iter_strings` takes the same `options`.
- `is_empty`, `is_total`, and `is_empty_string` now return
  `Result<bool, EngineError>` instead of `bool`.
- `are_equivalent`/`is_subset_of` renamed to `equivalent`/`subset`.
- `subtraction` renamed to `difference`, kept single-operand by design.
- Renamed `FastAutomaton::as_dot` to `to_dot` (old printing `to_dot` is now
  `print_dot`), matching the crate's `to_*` convention for allocating
  conversions (`to_pattern`, `to_regex`, `to_automaton`, `to_range`).
- Renamed `get_*` accessors to drop the `get_` prefix, per the Rust API
  Guidelines' C-GETTER convention: `Term::get_length` to `length`,
  `Term::get_cardinality` to `cardinality`, `FastAutomaton::get_length` to
  `length`, `FastAutomaton::get_cardinality` to `cardinality`,
  `FastAutomaton::get_number_of_states` to `number_of_states`,
  `FastAutomaton::get_condition` to `condition`,
  `FastAutomaton::get_start_state` to `start_state`,
  `FastAutomaton::get_accept_states` to `accept_states`,
  `FastAutomaton::get_spanning_set` to `spanning_set`,
  `FastAutomaton::get_live_states` to `live_states`,
  `FastAutomaton::get_spanning_bases` to `spanning_bases`,
  `RegularExpression::get_length` to `length`,
  `RegularExpression::get_cardinality` to `cardinality`,
  `SpanningSet::get_spanning_ranges` to `spanning_ranges`,
  `SpanningSet::get_number_of_spanning_ranges` to
  `number_of_spanning_ranges`, `SpanningSet::get_spanning_range` to
  `spanning_range`, `SpanningSet::get_rest` to `rest`,
  `Condition::get_cardinality` to `cardinality`,
  `Condition::get_binary_representation` to `binary_representation`,
  `ConditionConverter::get_from_spanning_set`/`get_to_spanning_set` to
  `from_spanning_set`/`to_spanning_set`.
- Error messages follow the std convention (lowercase, no trailing
  punctuation) so they compose cleanly when wrapped by callers.
- Edition bumped to 2024 and `Cargo.toml` metadata (`description`,
  `categories`) updated.

### Removed
- The `serde` feature and all serialization, FAIR (base85) encoding,
  encryption, and compression support (`serde`, `ciborium`, `z85`,
  `aes-gcm-siv`, `sha2`, `flate2` dependencies).
- `Term::get_details` and the `Details` type.
- The `tokenizer` module.
- Unused `log`, `rand`, and `lazy_static` dependencies, and the `regex`
  crate dependency (now dev-only, used by integration tests).
- The `nohash-hasher` dependency (replaced by the crate-owned
  `NoHashHasher`; see Added).
- `EngineError` variants `AutomatonShouldBeDeterministic`, `TooMuchTerms`,
  `ConditionIndexOutOfBound`, `TokenError`, and the `is_server_error` method.
- The `max_number_of_terms` execution-profile limit (no longer enforced).

## Earlier releases

Releases prior to 1.0.0 (`v0.1.0` through `v0.3.1`) predate this changelog;
see the [GitHub tags](https://github.com/RegexSolver/regexsolver/tags) and
commit history for details.

[Unreleased]: https://github.com/RegexSolver/regexsolver/compare/v1.0.0...HEAD
[1.0.0]: https://github.com/RegexSolver/regexsolver/compare/v0.3.1...v1.0.0