Builder Pattern Usage
This crate supports ergonomic builder patterns for both PatternElem
and Pattern
:
let elem = new.value.build;
let pat = new
.pattern
.deduplication
.overlap
.build;
- Mixed patterns: You can combine value and function elements in a single pattern.
- Empty patterns or windows: Returns no matches.
- Overlap and deduplication: Fine-grained control per pattern.
- Callback invocation: Use closures to collect or process matches.
- Builder pattern: Use for complex pattern construction and configuration.
# Contributing
We welcome contributions! Here’s how to get started:
## Project Structure
- `src/lib.rs`: Main matcher API and types
- `src/lib_tests.rs`: Comprehensive unit tests
- `README.md`: User and contributor documentation
## Running and Writing Tests
- Run all tests: `cargo test`
- Add new tests in `src/lib_tests.rs` using the existing patterns as examples
- Doc tests: Add examples to doc comments for public methods
## Coding Style
- Follow Rust’s standard formatting
- Use clear, descriptive names and thorough doc comments
- Prefer builder patterns for complex configuration
## Submitting Issues and Pull Requests
- Open issues for bugs, feature requests, or documentation improvements
- Fork the repo, create a feature branch, and submit a pull request
- Include tests and documentation for new features
## Adding Features or Improving Docs
- Add new matcher types or pattern features in `src/lib.rs`
- Expand doc comments and README with examples and edge cases
- Add tests for all new functionality
## Benchmarks and Debug Logging
- Use the
- No unnecessary trait bounds: PartialEq is only required for value-based patterns
- Accepts Vec, slice, or array for both window and patterns (no manual conversion needed)
Usage: Value/Mixed Patterns with Multiple Patterns
use ;
let window = vec!;
let patterns = vec!;
let matcher = new;
// You can pass Vec, slice, or array for window and patterns:
let matches = matcher.find_matches;
// Or:
let matches = matcher.find_matches;
// Or with arrays:
let arr_window = ;
let arr_patterns =
use ;
use Rc;
use RefCell;
let window = vec!;
let results: = new;
let results1 = results.clone;
let results2 = results.clone;
let patterns = vec!;
let matcher = new;
matcher.find_matches_with_callbacks;
let results = results.borrow;
assert!;
assert!;
use ;
use Rc;
use RefCell;
let window = vec!;
let results: = new;
let results1 = results.clone;
let results2 = results.clone;
let patterns = vec!;
let matcher = new;
- `find_matches`: Use for value, mixed, or callback patterns , supports multiple patterns and multi-element patterns. Accepts any type convertible to a slice for window and patterns. Automatically invokes callbacks and respects overlap/deduplication settings.
## Overlap Settings
- `allow_overlap_with_others`: If false, this pattern will not match if it would overlap with any previous match.
- `allow_others_to_overlap`: If false, once this pattern matches, no future matches can overlap its matched region.
## Debug Logging
This crate uses the
Then run your program or tests with:
RUST_LOG=debug cargo test
To disable logging (e.g., in production), do not initialize a logger, or set a higher log level:
RUST_LOG=info cargo run
Debug logs provide detailed information about matcher execution, pattern matching, overlap checks, and callback invocations.
API
find_matches
: Use for value or mixed patterns (requires PartialEq for T), supports multiple patterns and multi-element patterns. Accepts any type convertible to a slice for window and patterns.find_matches_with_callbacks
: Use for value/mixed patterns with per-pattern callbacks and overlap settings
See tests for more comprehensive examples and edge cases.
Edge Cases
-
Empty window or patterns: returns no matches
-
Patterns can be all values, all functions, or mixed
-
Multiple patterns and multi-element patterns supported
-
Deduplication and overlap settings can be combined
-
Patterns of length 1 and longer are supported
-
Overlap exclusion can prevent some matches (see tests)
-
Window and patterns can be Vec, slice, or array
//! ## Example: Value patterns //! let patterns = vec![ //! Pattern::new(vec![&1, &2]), //! Pattern::new(vec![&2, &1]), //! ]; //! let matches = matcher.find_matches(&window, &patterns); //! assert!(matches.contains(&(0, 0))); // [1,2] at 0 //! assert!(matches.contains(&(1, 1))); // [2,1] at 1 //! assert!(matches.contains(&(2, 0))); // [1] at 0 //! assert!(matches.contains(&(3, 1))); // [2] at 1 //! //! ## Example: Callback pattern //! let patterns = vec![ //! Pattern::with_callback(vec![&1, &2], |x: &&i32| **x == 1 ||**x == 2), //! ]; //! let matches = matcher.find_matches(&window, &patterns); //! assert!(matches.contains(&(0, 0))); // [1,2] at 0 //! assert!(matches.contains(&(1, 1))); // [2,1] at 1 //! assert!(matches.contains(&(2, 0))); // [1] at 0 //! assert!(matches.contains(&(3, 1))); // [2] at 1 //!
//! let patterns_fn: Vec<Vec<Box<dyn Fn(&i32) -> bool>>> = vec![ //! vec![Box::new(|x| *x == 1)], //! vec![Box::new(|x|*x == 4)], //! ]; //! let matches = matcher.find_matches(&window, &patterns_fn, false, None::<fn(usize, usize)>); //! assert!(matches.contains(&(0, 0))); //! assert!(matches.contains(&(1, 3))); //! with callback //! let patterns = vec![
//! pattern: vec![Box::new(|x: &i32| *x == 1), Box::new(|x: &i32|*x == 2)], //! callback: Box::new(move |matched| results1.borrow_mut().push(matched.iter().map(|x| **x).collect::<Vec<_>>())), //! allow_overlap_with_others: false, //! allow_others_to_overlap: true, //! },
//! pattern: vec![Box::new(|x: &i32| *x == 2), Box::new(|x: &i32|*x == 3)], //! callback: Box::new(move |matched| results2.borrow_mut().push(matched.iter().map(|x| **x).collect::<Vec<_>>())), //! allow_overlap_with_others: true, //! allow_others_to_overlap: false, //! }, //! ]; //! let matches = matcher.find_matches_with_callbacks(&window, &patterns); //! assert!(results.contains(&vec![1, 2])); //! assert!(results.contains(&vec![2, 3]));