Expand description
High-performance multi-pattern text matcher with logical operators and transformation pipelines.
matcher_rs is designed for rule matching tasks where plain substring
search is too rigid. A rule can combine multiple sub-patterns, veto on other
sub-patterns, and match against raw text, transformed text, or both.
The crate is built around three ideas:
- Logical operators — Rules can require co-occurrence of sub-patterns
(
&) or veto a match when a sub-pattern is present (~). - Transformation pipelines — Input can be matched after
Traditional→Simplified CJK variant normalization
(
ProcessType::VariantNorm), deletion of configured codepoints (ProcessType::Delete), replacement-table normalization (ProcessType::Normalize), and CJK romanization (ProcessType::Romanize/ProcessType::RomanizeChar). - Two-pass evaluation — Construction deduplicates emitted patterns and partitions them into ASCII and charwise matcher engines. Search walks the needed transform tree once, scans each produced text variant, then evaluates only touched rules.
§Quick Start
use matcher_rs::{ProcessType, SimpleMatcherBuilder};
let matcher = SimpleMatcherBuilder::new()
.add_word(ProcessType::None, 1, "hello")
// Matches after converting Traditional Chinese and removing noise chars
.add_word(ProcessType::VariantNormDeleteNormalize, 2, "你好")
// Both sub-patterns must appear in the text
.add_word(ProcessType::None, 3, "apple&pie")
// "banana" matches only when "peel" is absent
.add_word(ProcessType::None, 4, "banana~peel")
.build()
.unwrap();
assert!(matcher.is_match("hello world"));
assert!(matcher.is_match("apple and pie"));
assert!(!matcher.is_match("banana peel")); // vetoed by ~peel
let results = matcher.process("hello world");
assert_eq!(results[0].word_id, 1);Composite ProcessType values can also include ProcessType::None to
match against both the raw text and a transformed variant. For example, a
rule with ProcessType::None | ProcessType::Romanize can satisfy one
sub-pattern directly from the input and another via CJK romanization during
the same search.
§Safety
This crate uses unsafe in three categories:
§Thread-local state via #[thread_local] + UnsafeCell
| Static | Location |
|---|---|
SIMPLE_MATCH_STATE | simple_matcher/state.rs |
This uses #[thread_local] + UnsafeCell instead of the thread_local!
macro to avoid per-access closure overhead. Safety relies on two invariants:
(1) #[thread_local] guarantees single-threaded access — no data races.
(2) No public function is re-entrant: the borrow from UnsafeCell::get() is
always dropped before any call that could re-enter the same state.
§Bounds-elided indexing
Hot loops use get_unchecked / get_unchecked_mut to avoid repeated bounds
checks on indices that are structurally guaranteed in-bounds by construction
(e.g. automaton values, rule indices). Every such site communicates the
invariant to the optimizer via core::hint::assert_unchecked.
§Feature Flags
| Flag | Default | Effect |
|---|---|---|
perf | on | Meta-feature enabling dfa + simd_runtime_dispatch |
dfa | via perf | Enables aho-corasick DFA mode in the places where this crate chooses it; other paths still use daachorse-backed matchers |
simd_runtime_dispatch | via perf | Selects the best available transform kernel at runtime (AVX2 on x86-64, NEON on ARM64, portable fallback elsewhere) |
serde | off | Enables Serialize/Deserialize impls for ProcessType and Serialize for SimpleResult |
§Terminology
| Term | Meaning |
|---|---|
| Rule | A user-supplied pattern string, possibly with & (AND), ~ (NOT), | (OR) operators. Identified by a caller-chosen word_id. |
| Segment | One sub-pattern within a rule, delimited by & or ~. A segment may contain |-separated alternatives. |
| Pattern | A deduplicated sub-pattern string stored in the AC automaton. Multiple rules may share the same pattern. |
| Variant | One transformed form of the input text (e.g., after VariantNorm, after Delete). Each variant gets a unique index. |
| Generation | A monotonic u16 counter enabling O(1) amortized state reset between scans. Wraps every ~65K scans. |
| Direct encoding | Bit-packing a single-entry pattern’s metadata into the automaton value, bypassing entry-table indirection. See simple_matcher::pattern. |
For the full architectural walkthrough, see DESIGN.md.
Structs§
- Process
Type - Bitflags controlling which text-transformation steps to apply before matching.
- Simple
Matcher - Multi-pattern matcher with logical operators and text normalization.
- Simple
Matcher Builder - Builder for constructing a
SimpleMatcher. - Simple
Result - A single match returned by
SimpleMatcher::processorSimpleMatcher::process_into.
Enums§
- Matcher
Error - Error returned when
super::SimpleMatcherconstruction fails.
Functions§
- reduce_
text_ process - Applies a composite
ProcessTypepipeline totext, recording every intermediate change. - reduce_
text_ process_ emit - Like
reduce_text_process, but merges replace-type steps in-place. - text_
process - Applies a composite
ProcessTypepipeline totextand returns the final result.
Type Aliases§
- Simple
Table - Raw table format accepted by
SimpleMatcher::new. - Simple
Table Serde - Serde-friendly table format that stores rule strings as
Cow<str>.