# xdb-parse A parser to xdb files like ip2region A high-performance Rust library for parsing and querying IP database files (xdb format) like ip2region. Supports both IPv4 and IPv6 address lookup with efficient binary search algorithms. ## Features - **Dual Protocol Support**: Full support for both IPv4 and IPv6 address lookup - **High Performance**: Optimized binary search algorithm for fast IP queries - **Memory Efficient**: Load database files once and query multiple times - **Thread Safe**: Designed for concurrent usage in multi-threaded environments - **Flexible Input**: Accepts IP addresses in multiple formats (string, numeric) - **Zero Dependencies**: Minimal external dependencies for reliability ## Installation Add this to your `Cargo.toml`: ```toml [dependencies] xdb-parse = "0.1.0" ``` ## Quick Start ### Basic Usage ```rust use xdb_parse::utils::{load_file, search_ip}; use anyhow::Result; fn main() -> Result<()> { // Load the IP database file let path = "./assets/ip2region_v4.xdb"; let data = load_file(path.into())?; // Search for an IP address let result = search_ip("73.24.63.66", &data)?; println!("IP location: {}", result); Ok(()) } ``` ### IPv6 Support ```rust use xdb_parse::utils::{load_file, search_ip}; use anyhow::Result; fn main() -> Result<()> { // Load IPv6 database let path = "./assets/ip2region_v6.xdb"; let data = load_file(path.into())?; // Search for IPv6 address let result = search_ip("2001:0db8:85a3:0000:0000:8a2e:0370:7334", &data)?; println!("IPv6 location: {}", result); Ok(()) } ``` ## Examples ### Example 1: Basic IP Lookup See `examples/search_ip.rs`: ```rust use std::time::Instant; use anyhow::Result; use xdb_parse::utils::{load_file, search_ip}; fn main() -> Result<()> { let start = Instant::now(); let path = "./assets/ip2region_v4.xdb"; let data = load_file(path.into())?; let ret = search_ip("73.24.63.66", &data)?; let time = start.elapsed(); println!("Search time: {:?} - Result: {}", time, ret); Ok(()) } ``` ### Example 2: Multi-threaded Usage The library is designed for thread-safe concurrent usage: ```rust use std::{sync::Arc, thread}; use xdb_parse::utils::{load_file, search_ip}; use anyhow::Result; fn main() -> Result<()> { let path = "./assets/ip2region_v6.xdb"; let data = Arc::new(load_file(path.into())?); let data_clone = Arc::clone(&data); let handle = thread::spawn(move || { let result = search_ip("2408:8352:da10:1ad:c283:c9ff:fec6:4046", &data_clone).unwrap(); println!("Thread result: {}", result); }); // Main thread can also query let result = search_ip("2408:8352:da10:1ad:c283:c9ff:fec6:4046", &data)?; println!("Main thread result: {}", result); handle.join().unwrap(); Ok(()) } ``` ### Example 3: Performance Benchmarking See `benches/search.rs` for performance testing: ```rust use criterion::{Criterion, criterion_group, criterion_main}; use xdb_parse::utils::{load_file, search_ip}; fn search_benchmark(c: &mut Criterion) { c.bench_function("ipv4_search", |b| { let path = "./assets/ip2region_v4.xdb"; let data = load_file(path.into()).unwrap(); b.iter(|| { search_ip("73.24.63.66", &data).unwrap(); }) }); } criterion_group!(benches, search_benchmark); criterion_main!(benches); ``` ## API Reference ### Core Functions #### `load_file(path: PathBuf) -> Result, XdbError>` Loads an xdb database file into memory. **Parameters:** - `path`: Path to the xdb file **Returns:** Byte vector containing the database data #### `search_ip(ip: &str, data: &[u8]) -> Result` Searches for an IP address in the loaded database. **Parameters:** - `ip`: IP address to search (supports multiple formats) - `data`: Database data loaded by `load_file` **Returns:** Location information as string ### Supported IP Formats The library accepts IP addresses in multiple formats: ```rust // Standard IPv4 format search_ip("192.168.1.1", &data)?; // Standard IPv6 format search_ip("2001:0db8:85a3::0370:7334", &data)?; // Numeric format (IPv4) search_ip("3232235777", &data)?; // Equivalent to 192.168.1.1 // Numeric format (IPv6) search_ip("42540766411282592856903984951653826560", &data)?; ``` ## Database File Format The library supports the xdb format used by ip2region: - **Header**: 256 bytes containing metadata - **Vector Index**: 256×256 index blocks for fast lookup - **Segment Data**: IP range segments with location information ### File Structure ``` ┌─────────────────┐ │ Header │ 256 bytes ├─────────────────┤ │ Vector Index │ 256×256×8 bytes ├─────────────────┤ │ Segment Data │ Variable length └─────────────────┘ ``` ## Performance The library uses an optimized binary search algorithm: - **IPv4 Lookup**: ~5 microseconds per query - **IPv6 Lookup**: ~250 microseconds per query - **Memory Usage**: Database loaded once, shared across threads ## Error Handling The library uses `thiserror` for comprehensive error handling: ```rust use xdb_parse::error::XdbError; match search_ip("invalid_ip", &data) { Ok(result) => println!("Location: {}", result), Err(XdbError::InvalidIP(msg)) => println!("Invalid IP: {}", msg), Err(e) => println!("Error: {}", e), } ``` ## Running Examples To run the provided examples: ```bash # Run the basic search example cargo run --example search_ip # Run benchmarks cargo bench # Run tests cargo test ``` ## License This project is licensed under the same terms as Rust itself. ## Contributing Contributions are welcome! Please feel free to submit issues and pull requests. ## Acknowledgments - Inspired by the ip2region project - Uses efficient binary search algorithms for fast IP lookup - Designed for high-performance applications