xdb-parse

Crates.ioxdb-parse
lib.rsxdb-parse
version0.1.0
created_at2025-09-23 06:31:00.009766+00
updated_at2025-09-23 06:31:00.009766+00
descriptionA parser to xdb files like ip2region
homepagehttps://github.com/RuntimeBroker/xdb_parse
repositoryhttps://github.com/RuntimeBroker/xdb_parse
max_upload_size
id1851055
size47,750
(RuntimeBroker)

documentation

https://docs.rs/xdb_parse

README

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:

[dependencies]
xdb-parse = "0.1.0"

Quick Start

Basic Usage

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

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:

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:

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:

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<Vec<u8>, 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<String, XdbError>

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:

// 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:

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:

# 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
Commit count: 4

cargo fmt