Quick Start
Get up and running with Matchy in minutes.
Installation
From Source
git clone https://github.com/matchylabs/matchy
cd matchy
cargo build --release
As a Rust Dependency
Add to your Cargo.toml:
[dependencies]
matchy = "0.5"
Your First Database (Rust)
Here’s a complete example that builds and queries a threat intelligence database:
use matchy::{Database, DatabaseBuilder, MatchMode, DataValue, QueryResult};
use std::collections::HashMap;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 1. Create a builder
let mut builder = DatabaseBuilder::new(MatchMode::CaseSensitive);
// 2. Add IP address with threat data
let mut ip_data = HashMap::new();
ip_data.insert("threat_level".to_string(), DataValue::String("high".to_string()));
ip_data.insert("score".to_string(), DataValue::Uint32(95));
builder.add_entry("1.2.3.4", ip_data)?;
// 3. Add CIDR range
let mut cidr_data = HashMap::new();
cidr_data.insert("type".to_string(), DataValue::String("internal".to_string()));
builder.add_entry("10.0.0.0/8", cidr_data)?;
// 4. Add glob pattern
let mut pattern_data = HashMap::new();
pattern_data.insert("category".to_string(), DataValue::String("malware".to_string()));
builder.add_entry("*.evil.com", pattern_data)?;
// 5. Build and save
let database_bytes = builder.build()?;
std::fs::write("threats.mxy", &database_bytes)?;
println!("✅ Database built: {} bytes", database_bytes.len());
// 6. Open database (memory-mapped)
let db = Database::from("threats.mxy").open()?;
println!("✅ Database opened");
// 7. Query IP address
match db.lookup("1.2.3.4")? {
Some(QueryResult::Ip { data, prefix_len, .. }) => {
println!("🔍 IP match: {:?} (/{prefix_len})", data);
}
_ => println!("No match"),
}
// 8. Query pattern
match db.lookup("malware.evil.com")? {
Some(QueryResult::Pattern { pattern_ids, data, .. }) => {
println!("🔍 Pattern match: {} patterns", pattern_ids.len());
for (i, d) in data.iter().enumerate() {
if let Some(threat_data) = d {
println!(" Pattern {}: {:?}", pattern_ids[i], threat_data);
}
}
}
_ => println!("No match"),
}
Ok(())
}
Your First Database (C)
Complete C example:
#include <matchy/matchy.h>
#include <stdio.h>
int main() {
// 1. Build database
matchy_builder_t *builder = matchy_builder_new();
if (!builder) {
fprintf(stderr, "Failed to create builder\n");
return 1;
}
// 2. Add entries with JSON data
matchy_builder_add(builder, "1.2.3.4",
"{\"threat_level\": \"high\", \"score\": 95}");
matchy_builder_add(builder, "10.0.0.0/8",
"{\"type\": \"internal\"}");
matchy_builder_add(builder, "*.evil.com",
"{\"category\": \"malware\"}");
// 3. Save to file
int err = matchy_builder_save(builder, "threats.mxy");
if (err != MATCHY_SUCCESS) {
fprintf(stderr, "Failed to save database\n");
matchy_builder_free(builder);
return 1;
}
printf("✅ Database built\n");
matchy_builder_free(builder);
// 4. Open database
matchy_t *db = matchy_open("threats.mxy");
if (!db) {
fprintf(stderr, "Failed to open database\n");
return 1;
}
printf("✅ Database loaded\n");
// 5. Query IP address
matchy_result_t result = matchy_query(db, "1.2.3.4");
if (result.found) {
char *json = matchy_result_to_json(&result);
if (json != NULL) {
printf("🔍 IP match: %s\n", json);
matchy_free_string(json);
}
}
matchy_free_result(&result);
// 6. Query pattern
result = matchy_query(db, "malware.evil.com");
if (result.found) {
char *json = matchy_result_to_json(&result);
if (json != NULL) {
printf("🔍 Pattern match: %s\n", json);
matchy_free_string(json);
}
}
matchy_free_result(&result);
// 7. Cleanup
matchy_close(db);
printf("✅ Done\n");
return 0;
}
Compile and run:
gcc -o example example.c -I./crates/matchy/include -L./target/release -lmatchy
LD_LIBRARY_PATH=./target/release ./example
What Just Happened?
- Built a database - Added IPs, CIDR ranges, and patterns with structured data
- Saved to disk - Wrote optimized binary format (
.mxyfile) - Opened efficiently - Memory-mapped the file and validated its structural envelopes
- Queried through specialized indexes - Used the IP trie, exact hash, or pattern candidate engine as appropriate
Key Concepts
Automatic Type Detection
You don’t need to specify whether an entry is an IP, CIDR, or pattern. Matchy detects automatically:
#![allow(unused)]
fn main() {
builder.add_entry("1.2.3.4", data)?; // Detected as IP
builder.add_entry("10.0.0.0/8", data)?; // Detected as CIDR
builder.add_entry("*.evil.com", data)?; // Detected as glob pattern
builder.add_entry("evil.com", data)?; // Detected as exact string
}
Database Immutability
Databases are read-only once built. To update:
- Create new builder
- Add all entries (old + new + modified)
- Build new database
- Atomically replace old file
This ensures readers always see consistent state.
Memory Mapping
Databases use mmap() for:
- Demand-paged opening - Avoids whole-file deserialization while retaining bounded structural checks
- Memory efficiency - OS shares pages across processes
- Large databases - Work with databases larger than RAM
Next Steps
- Installation Guide - Detailed setup instructions
- Rust API Guide - Complete Rust API documentation
- C API Guide - Complete C API documentation
- Architecture - How Matchy works internally