use std::error::Error;
use std::net::IpAddr;
use libmaxminddb_rs::{
IpNetwork, MetadataBuilder, MmdbDecode, MmdbEncode, MmdbRecord, Reader, Writer,
};
#[derive(Debug, PartialEq, MmdbEncode, MmdbRecord)]
struct ThreatEntry<'a> {
#[mmdb(network)]
network: IpNetwork,
country: &'a str,
threat_level: &'a str,
score: u32,
category: &'a str,
}
#[derive(Debug, PartialEq, MmdbDecode)]
struct DecodedThreat<'a> {
country: &'a str,
threat_level: &'a str,
score: u32,
category: &'a str,
}
fn main() -> Result<(), Box<dyn Error>> {
println!("=== libmaxminddb-rs Custom Record Derive Example ===\n");
let metadata = MetadataBuilder::new()
.database_type("Threat-Intel-DB")
.ip_version(4)
.description("en", "Threat intelligence database using MmdbRecord derive")
.build()?;
let mut writer = Writer::with_metadata(metadata);
println!("1. Inserting entries using `writer.insert_entry`...");
let entries = vec![
ThreatEntry {
network: "198.51.100.0/24".parse()?,
country: "US",
threat_level: "low",
score: 15,
category: "cloud_provider",
},
ThreatEntry {
network: "203.0.113.64/26".parse()?,
country: "FR",
threat_level: "critical",
score: 95,
category: "botnet_c2",
},
ThreatEntry {
network: "192.0.2.0/25".parse()?,
country: "DE",
threat_level: "medium",
score: 50,
category: "open_proxy",
},
];
for entry in &entries {
println!(" ↳ Inserting entry for subnet: {}", entry.network);
writer.insert_entry(entry)?;
}
let db_bytes = writer.finish()?;
println!(
"\n2. Database built in memory ({} bytes).\n",
db_bytes.len()
);
let reader = Reader::from_bytes(&db_bytes)?;
let test_ips: &[(&str, &str)] = &[
("198.51.100.22", "Expected: cloud_provider"),
("203.0.113.80", "Expected: botnet_c2"),
("192.0.2.10", "Expected: open_proxy"),
];
println!("3. Performing lookups on inserted records:");
for &(ip_str, note) in test_ips {
let ip: IpAddr = ip_str.parse()?;
let threat: DecodedThreat<'_> = reader.lookup_borrowed(ip)?;
println!(" IP: {} ({})", ip, note);
println!(" ↳ Threat Level : {}", threat.threat_level);
println!(" ↳ Threat Score : {}/100", threat.score);
println!(" ↳ Category : {}", threat.category);
println!(" ↳ Country : {}\n", threat.country);
}
println!("Custom record derive example completed successfully!");
Ok(())
}