| Crates.io | flash-fuzzy-core |
| lib.rs | flash-fuzzy-core |
| version | 0.1.0 |
| created_at | 2025-12-28 05:42:30.170348+00 |
| updated_at | 2025-12-28 05:42:30.170348+00 |
| description | High-performance fuzzy search using Bitap algorithm with bloom filter pre-filtering. Zero dependencies, no_std compatible. |
| homepage | https://github.com/RafaCalRob/FlashFuzzy |
| repository | https://github.com/RafaCalRob/FlashFuzzy |
| max_upload_size | |
| id | 2008275 |
| size | 16,950 |
High-performance fuzzy search engine core using Bitap algorithm with bloom filter pre-filtering.
no_std compatible - Works in embedded and WASM environmentsuse flash_fuzzy_core::{BitapSearcher, BloomFilter, bitap};
// Create a searcher for a pattern
let searcher = BitapSearcher::new(b"keyboard");
// Check bloom filter first (O(1) rejection)
let text = b"Mechanical Keyboard Pro";
let text_bloom = BloomFilter::from_text(text);
if text_bloom.might_contain(searcher.bloom()) {
// Run fuzzy search with max 2 errors
if let Some(match_result) = searcher.search(text, 2) {
let score = bitap::compute_score(
match_result.errors,
searcher.pattern_len() as u32,
match_result.end_pos
);
println!("Found match with {} errors, score: {}", match_result.errors, score);
}
}
Before running expensive fuzzy matching, we check if the search pattern could possibly exist using a 64-bit bloom filter:
Text: "Wireless Laptop Pro" → bloom bits: 01001010...
Pattern: "laptop" → bloom bits: 00001010...
Check: (text_bloom & pattern_bloom) == pattern_bloom
If false → definitely no match, skip (80-95% of records rejected)
If true → might match, run Bitap
The Bitap (Shift-Or) algorithm uses bit-parallel operations for approximate string matching:
// Each error level tracks match state as a bitmask
R[0] = exact matches
R[1] = matches with 1 error (substitution/insertion/deletion)
R[2] = matches with 2 errors
...
BitapSearcherimpl BitapSearcher {
/// Create a new searcher from a pattern (max 32 bytes)
pub fn new(pattern: &[u8]) -> Self;
/// Get the pattern's bloom filter
pub fn bloom(&self) -> BloomFilter;
/// Get the pattern length
pub fn pattern_len(&self) -> usize;
/// Search for pattern in text with up to max_errors
pub fn search(&self, text: &[u8], max_errors: u32) -> Option<SearchMatch>;
}
BloomFilterimpl BloomFilter {
/// Create bloom filter from text
pub fn from_text(text: &[u8]) -> Self;
/// Check if pattern might be contained
pub fn might_contain(&self, pattern_bloom: BloomFilter) -> bool;
}
SearchMatchpub struct SearchMatch {
pub errors: u32, // Number of errors (edit distance)
pub end_pos: usize, // End position of match in text
}
use flash_fuzzy_core::bitap::compute_score;
// Score formula: base (1000 - errors*250) + position bonus (0-50)
let score = compute_score(errors, pattern_len, end_pos);
// Returns: 0-1000 (higher = better match)
| Errors | Base Score | + Start Bonus | Final |
|---|---|---|---|
| 0 | 1000 | +50 | 1000 (capped) |
| 1 | 750 | +25 (near start) | 775 |
| 2 | 500 | +0 | 500 |
| 3 | 250 | +0 | 250 |
no_std UsageThis crate is no_std by default:
[dependencies]
flash-fuzzy-core = "0.1"
Enable std feature for standard library support:
[dependencies]
flash-fuzzy-core = { version = "0.1", features = ["std"] }
Typical benchmark: < 1ms to search 10,000 records.
MIT - see LICENSE
This is the core algorithm crate. For complete bindings see: