ScrollingWindowPatternMatcher
A flexible, ergonomic pattern matcher for slices, arrays, and windows, supporting wildcards, custom logic, and builder patterns.
Features
- Wildcard matching (
PatternElem::Any
) - Flexible matcher signatures: pass window and patterns as Vec, slice, or array, and patterns as owned or referenced
- Ergonomic builder patterns
- Custom matcher logic
- Flexible callback and overlap configuration
Choosing Between find_matches
and find_matches_flexible
These two functions are the core of the crate. Understanding their differences will help you select the right one for your use case:
find_matches
- Signature:
find_matches(&self, window: &[T], patterns: &[Pattern<T>])
- Accepts: Slices (
&[T]
) for both window and patterns. - Performance: Zero-copy; does not clone window elements. Efficient for large windows.
- Trait Bounds: Only requires
T: PartialEq + Clone
for matching logic. - Use When:
- You already have slices or references to arrays/Vectors.
- You want maximum performance and minimal memory usage.
- Your element type is not
Clone
.
- Limitation: Cannot accept owned containers directly (e.g.,
Vec<T>
by value); must convert to a slice first.
find_matches_flexible
- Signature:
find_matches_flexible(&self, window: W, patterns: P)
whereW: IntoIterator, W::Item: Borrow<T>
- Accepts: Owned containers (
Vec<T>
, arrays), references to containers (&Vec<T>
,&[T]
), or slices. - Performance: Clones all window elements into a new
Vec<T>
; may use more memory for large windows. - Trait Bounds: Requires
T: Clone + PartialEq
. - Use When:
- You want ergonomic API and flexibility in passing owned or referenced data.
- You don't mind cloning window elements.
- You want to avoid manual conversion to slices.
- Limitation: Requires
T: Clone
; may be less efficient for large windows or non-cloneable types.
Summary Table
Function | Accepts | Performance | Requires T: Clone |
Use When |
---|---|---|---|---|
find_matches |
Slices | Zero-copy | No (unless callback) | You have slices, want speed |
find_matches_flexible |
Owned or borrowed | Clones window | Yes | You want ergonomic flexibility |
Tip: If in doubt, use find_matches
for performance, and find_matches_flexible
for convenience.
Choosing an Appropriate window_len
The window_len
parameter in ScrollingWindowPatternMatcherRef
determines the maximum number of elements (T
) held in memory at one time for matching. It does not directly limit the length of patterns you can match, since partial matches are tracked independently.
How to Choose window_len
- For most use cases: Set
window_len
to the length of your input data (e.g.,window.len()
for a slice or vector). This ensures all elements are available for matching and is the most ergonomic choice for batch processing. - For streaming or large datasets: Use a smaller
window_len
to limit memory usage. The matcher will process data in chunks, but you must ensure your pattern logic can handle matches that span window boundaries (advanced usage). - For single-element processing: You can set
window_len = 1
to process one element at a time, but this is rarely needed unless you have strict memory constraints or want to implement a custom streaming matcher.
Trade-offs
- Larger
window_len
:- Pros: Simpler API, all data available for matching, best for batch or small datasets.
- Cons: Higher memory usage for very large datasets.
- Smaller
window_len
:- Pros: Lower memory usage, suitable for streaming or real-time processing.
- Cons: Requires careful handling of partial matches and patterns that span windows.
Practical Advice
- For most users, set
window_len
to the size of your window or input data. - If you need to process data in a streaming fashion, consider implementing logic to handle partial matches across window boundaries.
- Pattern length is not limited by
window_len
—the matcher tracks partial matches as needed.
Summary:
Set window_len
to match your data size for convenience, or use a smaller value for streaming/low-memory scenarios. Pattern matching will work as long as your logic accounts for the chosen window size.
Usage Example
use ;
let window = vec!;
let patterns = vec!;
let matcher = new;
let named = matcher.find_matches;
assert!;
let twos_matches = &named;
assert!;
assert!;
let gap_matches = &named;
assert!;
Documentation
See doc comments and tests for more examples.
Planned Features
Advanced Features
- Ergonomic builder API for repeat and capture settings (gaps are represented by PatternElem::Any with repeat settings)
- Named patterns and named captures
- Flexible callback/overlap configuration
use ;
let window = vec!;
let patterns = vec!;
let matcher = new;
let named = matcher.find_matches;
assert!;
assert!;
Example: Callback pattern
This example demonstrates using a callback to process matches:
use ;
let window = vec!;
let patterns = vec!;
let matcher = new;
let named = matcher.find_matches;
assert!;
assert!;
Example: Advanced callback with overlap settings
This example demonstrates using advanced callback and overlap settings:
use ;
let patterns = vec!;
let window = vec!;
let matcher = new;
matcher.find_matches;
- 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 =
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 log crate for debug logging. To enable debug output during development, add the following to your main function or test harness:
;
init
Then run your program or tests with:
RUST_LOG=debug
To disable logging (e.g., in production), do not initialize a logger, or set a higher log level:
RUST_LOG=info
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_named_matches
: Returns named pattern/capture results asHashMap<String, Vec<HashMap<String, Vec<T>>>>
.
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
- Gaps are represented by PatternElem::Any with repeat settings
Example: Value patterns
let patterns = vec!;
let window = vec!;
let matcher = new;
let named = matcher.find_matches;
assert!;
assert!;
Planned Features (Not Yet Implemented)
All currently planned features have been implemented.
If you need additional features, please open an issue so we can discuss it!
API Reference
All major types and builders are available at the crate root:
Pattern
,PatternBuilder
PatternElem
(struct-style variants; gaps are represented by PatternElem::Any with repeat settings)ScrollingWindowPatternMatcherRef
Callback
,SliceCallback
See the tests and examples above for usage patterns.
This example demonstrates using a callback to process matches:
use ;
let patterns = vec!;
let window = vec!;
let matcher = new;
matcher.find_matches;
Example: Function patterns
This example shows how to use function-based patterns:
use ;
let patterns = vec!;
let window = vec!;
let matcher = new;
let named = matcher.find_matches;
assert!;
assert!;