Skip to content
This repository was archived by the owner on Aug 30, 2026. It is now read-only.

Repository files navigation

Fuzzies

Fuzzies is a memory-mapped FST spellchecker and fuzzy dictionary built on fst and levenshtein-automata.

Crates.io NPM Version Docs.rs Crates.io

More information about this crate can be found in the crate documentation.


Installation

cargo add fuzzies

See the Node.js README for Node-specific APIs and its usage details.


Example

use fuzzies::{Dictionary, DictionaryError};

fn main() -> Result<(), DictionaryError> {
    // Prepare your raw text file (must be sorted lexicographically)
    // Fuzzies provides a handy in-place sorter for convenience:
    Dictionary::sort("words.txt")?;

    // Build the immutable binary FST from the sorted text file
    Dictionary::build("words.txt", "words.fst")?;

    // Load the dictionary (memory-mapped from disk)
    let dict = Dictionary::open("words.fst")?;

    // Check for exact matches instantly
    if dict.contains("banana") {
        println!("Exact match found!");
    }

    // Quick single-suggestion lookup
    if let Some(top_match) = dict.suggest("banaan")? {
        println!("Best suggestion: {}", top_match.key);
    }

    // Perform a fuzzy search with custom options
    let results = dict.search("banaan")
        .distance(2)
        .transposition(true) // Handles adjacent swaps (e.g., "teh" -> "the")
        .prefix(false)       // Set to true for prefix fuzzy lookups
        .ge("a")             // Optionally restrict search bounds (key >= "a")
        .lt("e")             // (key < "e")
        .limit(5)
        .execute()?;
    
    for result in results {
        println!("Found: {}", result);
    }

    // Batch search (multithreaded, defaults to a distance of 1)
    let queries = vec!["aple", "baxana", "cherri"];
    let batch_results = dict.batch_search(&queries).execute();

    for (query, result) in queries.iter().zip(batch_results) {
        match result {
            Ok(matches) => println!("Query '{}' found {} matches", query, matches.len()),
            Err(e) => eprintln!("Error searching for '{}': {}", query, e),
        }
    }

    Ok(())
}

If you don't want to manage external .fst files on disk, you can construct a Dictionary directly:

// From an embedded FST binary slice:
static DICT_DATA: &[u8] = include_bytes!("../assets/words.fst");
let dict = Dictionary::from_embedded(DICT_DATA)?;

// From an iterator of strings (automatically sorted and deduplicated):
let words = vec!["apple", "banana", "cherry"];
let dict = Dictionary::from_iterator(words)?;

See examples for more.


🎈 Performance

  • Instant Exact Matches: Finding a word takes about 130ns. If a word isn't in the dictionary, it figures that out and rejects it in under 10ns.
  • Fast Typo Correction: Searching for a word with a 1-character typo through 50,000 words takes about 75µs.
  • Multithreading: Throwing 1,000 fuzzy searches at it in parallel (via Rayon) finishes in just ~5ms.
  • Zero Loading Screen: Opening a saved dictionary is instant, no matter how huge the file is, because it just maps the file directly to memory.

Want the hard numbers? Check out the Benchmarks.


Safety

This crate uses unsafe in a single location:

  • Memory-Mapped I/O (Dictionary::open): Calls memmap2::Mmap::map(&file) to map FST data directly from disk into memory.

License

This project is licensed under the MIT license.

About

Fast memory-mapped fuzzy string matching in Rust.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages