Reader

Struct Reader 

Source
pub struct Reader<S: AsRef<[u8]>> {
    pub metadata: Metadata,
    /* private fields */
}
Expand description

A reader for the MaxMind DB format. The lifetime 'data is tied to the lifetime of the underlying buffer holding the contents of the database file.

The Reader supports both file-based and memory-mapped access to MaxMind DB files, including GeoIP2 and GeoLite2 databases.

§Features

  • mmap: Enable memory-mapped file access for better performance
  • simdutf8: Use SIMD-accelerated UTF-8 validation (faster string decoding)
  • unsafe-str-decode: Skip UTF-8 validation entirely (unsafe, but ~20% faster)

Fields§

§metadata: Metadata

Database metadata.

Implementations§

Source§

impl Reader<Vec<u8>>

Source

pub fn open_readfile<P: AsRef<Path>>( database: P, ) -> Result<Reader<Vec<u8>>, MaxMindDbError>

Open a MaxMind DB database file by loading it into memory.

§Example
let reader = maxminddb::Reader::open_readfile(
    "test-data/test-data/GeoIP2-City-Test.mmdb").unwrap();
Source§

impl<'de, S: AsRef<[u8]>> Reader<S>

Source

pub fn from_source(buf: S) -> Result<Reader<S>, MaxMindDbError>

Open a MaxMind DB database from anything that implements AsRef<u8>

§Example
use std::fs;
let buf = fs::read("test-data/test-data/GeoIP2-City-Test.mmdb").unwrap();
let reader = maxminddb::Reader::from_source(buf).unwrap();
Source

pub fn lookup( &'de self, address: IpAddr, ) -> Result<LookupResult<'de, S>, MaxMindDbError>

Lookup an IP address in the database.

Returns a LookupResult that can be used to:

§Examples

Basic city lookup:

let reader = maxminddb::Reader::open_readfile(
    "test-data/test-data/GeoIP2-City-Test.mmdb")?;

let ip: IpAddr = "89.160.20.128".parse().unwrap();
let result = reader.lookup(ip)?;

if let Some(city) = result.decode::<geoip2::City>()? {
    // Access nested structs directly - no Option unwrapping needed
    if let Some(name) = city.city.names.english {
        println!("City: {}", name);
    }
} else {
    println!("No data found for IP {}", ip);
}

Selective field access:

let reader = Reader::open_readfile(
    "test-data/test-data/GeoIP2-City-Test.mmdb")?;
let ip: IpAddr = "89.160.20.128".parse().unwrap();

let result = reader.lookup(ip)?;
let country_code: Option<String> = result.decode_path(&[
    PathElement::Key("country"),
    PathElement::Key("iso_code"),
])?;

println!("Country: {:?}", country_code);
Source

pub fn networks( &'de self, options: WithinOptions, ) -> Result<Within<'de, S>, MaxMindDbError>

Iterate over all networks in the database.

This is a convenience method equivalent to calling within() with 0.0.0.0/0 for IPv4-only databases or ::/0 for IPv6 databases.

§Arguments
  • options - Controls which networks are yielded. Use Default::default() for standard behavior.
§Examples

Iterate over all networks with default options:

use maxminddb::{geoip2, Reader};

let reader = Reader::open_readfile(
    "test-data/test-data/GeoIP2-City-Test.mmdb").unwrap();

let mut count = 0;
for result in reader.networks(Default::default()).unwrap() {
    let lookup = result.unwrap();
    count += 1;
    if count >= 10 { break; }
}
Source

pub fn within( &'de self, cidr: IpNetwork, options: WithinOptions, ) -> Result<Within<'de, S>, MaxMindDbError>

Iterate over IP networks within a CIDR range.

Returns an iterator that yields LookupResult for each network in the database that falls within the specified CIDR range.

§Arguments
  • cidr - The CIDR range to iterate over.
  • options - Controls which networks are yielded. Use Default::default() for standard behavior (skip aliases, skip networks without data, include empty values).
§Examples

Iterate over all IPv4 networks:

use ipnetwork::IpNetwork;
use maxminddb::{geoip2, Reader};

let reader = Reader::open_readfile(
    "test-data/test-data/GeoIP2-City-Test.mmdb").unwrap();

let ipv4_all = IpNetwork::V4("0.0.0.0/0".parse().unwrap());
let mut count = 0;
for result in reader.within(ipv4_all, Default::default()).unwrap() {
    let lookup = result.unwrap();
    let network = lookup.network().unwrap();
    let city: geoip2::City = lookup.decode().unwrap().unwrap();
    let city_name = city.city.names.english;
    println!("Network: {}, City: {:?}", network, city_name);
    count += 1;
    if count >= 10 { break; } // Limit output for example
}

Search within a specific subnet:

use ipnetwork::IpNetwork;
use maxminddb::{geoip2, Reader};

let reader = Reader::open_readfile(
    "test-data/test-data/GeoIP2-City-Test.mmdb").unwrap();

let subnet = IpNetwork::V4("192.168.0.0/16".parse().unwrap());
for result in reader.within(subnet, Default::default()).unwrap() {
    match result {
        Ok(lookup) => {
            let network = lookup.network().unwrap();
            println!("Found: {}", network);
        }
        Err(e) => eprintln!("Error: {}", e),
    }
}

Include networks without data:

use ipnetwork::IpNetwork;
use maxminddb::{Reader, WithinOptions};

let reader = Reader::open_readfile(
    "test-data/test-data/MaxMind-DB-test-mixed-24.mmdb").unwrap();

let opts = WithinOptions::default().include_networks_without_data();
for result in reader.within("1.0.0.0/8".parse().unwrap(), opts).unwrap() {
    let lookup = result.unwrap();
    if !lookup.has_data() {
        println!("Network {} has no data", lookup.network().unwrap());
    }
}
Source

pub fn verify(&self) -> Result<(), MaxMindDbError>

Performs comprehensive validation of the MaxMind DB file.

This method validates:

  • Metadata section: format versions, required fields, and value constraints
  • Search tree: traverses all networks to verify tree structure integrity
  • Data section separator: validates the 16-byte separator between tree and data
  • Data section: verifies all data records referenced by the search tree

The verifier is stricter than the MaxMind DB specification and may return errors on some databases that are still readable by normal operations. This method is useful for:

  • Validating database files after download or generation
  • Debugging database corruption issues
  • Ensuring database integrity in critical applications

Note: Verification traverses the entire database and may be slow on large files. The method is thread-safe and can be called on an active Reader.

§Example
use maxminddb::Reader;

let reader = Reader::open_readfile("test-data/test-data/GeoIP2-City-Test.mmdb").unwrap();
reader.verify().expect("Database should be valid");

Trait Implementations§

Source§

impl<S: AsRef<[u8]>> Debug for Reader<S>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<S> Freeze for Reader<S>
where S: Freeze,

§

impl<S> RefUnwindSafe for Reader<S>
where S: RefUnwindSafe,

§

impl<S> Send for Reader<S>
where S: Send,

§

impl<S> Sync for Reader<S>
where S: Sync,

§

impl<S> Unpin for Reader<S>
where S: Unpin,

§

impl<S> UnwindSafe for Reader<S>
where S: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.