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 performancesimdutf8
: Use SIMD-accelerated UTF-8 validation (faster string decoding)unsafe-str-decode
: Skip UTF-8 validation entirely (unsafe, but ~20% faster)
Fields§
§metadata: Metadata
Implementations§
Source§impl Reader<Vec<u8>>
impl Reader<Vec<u8>>
Sourcepub fn open_readfile<P: AsRef<Path>>(
database: P,
) -> Result<Reader<Vec<u8>>, MaxMindDbError>
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>
impl<'de, S: AsRef<[u8]>> Reader<S>
Sourcepub fn from_source(buf: S) -> Result<Reader<S>, MaxMindDbError>
pub fn from_source(buf: S) -> Result<Reader<S>, MaxMindDbError>
Sourcepub fn lookup<T>(
&'de self,
address: IpAddr,
) -> Result<Option<T>, MaxMindDbError>where
T: Deserialize<'de>,
pub fn lookup<T>(
&'de self,
address: IpAddr,
) -> Result<Option<T>, MaxMindDbError>where
T: Deserialize<'de>,
Lookup the socket address in the opened MaxMind DB.
Returns Ok(None)
if the address is not found in the database.
§Examples
Basic city lookup:
let reader = maxminddb::Reader::open_readfile(
"test-data/test-data/GeoIP2-City-Test.mmdb")?;
let ip: IpAddr = FromStr::from_str("89.160.20.128").unwrap();
match reader.lookup::<geoip2::City>(ip)? {
Some(city) => {
if let Some(city_names) = city.city.and_then(|c| c.names) {
if let Some(name) = city_names.get("en") {
println!("City: {}", name);
}
}
if let Some(country) = city.country.and_then(|c| c.iso_code) {
println!("Country: {}", country);
}
}
None => println!("No data found for IP {}", ip),
}
Lookup with different record types:
let reader = maxminddb::Reader::open_readfile(
"test-data/test-data/GeoIP2-City-Test.mmdb")?;
let ip: IpAddr = "89.160.20.128".parse().unwrap();
// Different record types for the same IP
let city: Option<geoip2::City> = reader.lookup(ip)?;
let country: Option<geoip2::Country> = reader.lookup(ip)?;
println!("City data available: {}", city.is_some());
println!("Country data available: {}", country.is_some());
Sourcepub fn lookup_prefix<T>(
&'de self,
address: IpAddr,
) -> Result<(Option<T>, usize), MaxMindDbError>where
T: Deserialize<'de>,
pub fn lookup_prefix<T>(
&'de self,
address: IpAddr,
) -> Result<(Option<T>, usize), MaxMindDbError>where
T: Deserialize<'de>,
Lookup the socket address in the opened MaxMind DB, returning the found value (if any) and the prefix length of the network associated with the lookup.
Returns Ok((None, prefix_len))
if the address is found in the tree but has no data record.
Returns Err(...)
for database errors (IO, corruption, decoding).
Example:
let reader = maxminddb::Reader::open_readfile(
"test-data/test-data/GeoIP2-City-Test.mmdb")?;
let ip: IpAddr = "89.160.20.128".parse().unwrap(); // Known IP
let ip_unknown: IpAddr = "10.0.0.1".parse().unwrap(); // Unknown IP
let (city_option, prefix_len) = reader.lookup_prefix::<geoip2::City>(ip)?;
if let Some(city) = city_option {
println!("Found {:?} at prefix length {}", city.city.unwrap().names.unwrap().get("en").unwrap(), prefix_len);
} else {
// This case is less likely with lookup_prefix if the IP resolves in the tree
println!("IP found in tree but no data (prefix_len: {})", prefix_len);
}
let (city_option_unknown, prefix_len_unknown) = reader.lookup_prefix::<geoip2::City>(ip_unknown)?;
assert!(city_option_unknown.is_none());
println!("Unknown IP resolved to prefix_len: {}", prefix_len_unknown);
Sourcepub fn within<T>(
&'de self,
cidr: IpNetwork,
) -> Result<Within<'de, T, S>, MaxMindDbError>where
T: Deserialize<'de>,
pub fn within<T>(
&'de self,
cidr: IpNetwork,
) -> Result<Within<'de, T, S>, MaxMindDbError>where
T: Deserialize<'de>,
Iterate over blocks of IP networks in the opened MaxMind DB
This method returns an iterator that yields all IP network blocks that fall within the specified CIDR range and have associated data in the database.
§Examples
Iterate over all IPv4 networks:
use ipnetwork::IpNetwork;
use maxminddb::{geoip2, Within};
let reader = maxminddb::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::<geoip2::City>(ipv4_all).unwrap() {
let item = result.unwrap();
let city_name = item.info.city.as_ref().and_then(|c| c.names.as_ref()).and_then(|n| n.get("en"));
println!("Network: {}, City: {:?}", item.ip_net, city_name);
count += 1;
if count >= 10 { break; } // Limit output for example
}
Search within a specific subnet:
use ipnetwork::IpNetwork;
use maxminddb::geoip2;
let reader = maxminddb::Reader::open_readfile(
"test-data/test-data/GeoIP2-City-Test.mmdb").unwrap();
let subnet = IpNetwork::V4("192.168.0.0/16".parse().unwrap());
match reader.within::<geoip2::City>(subnet) {
Ok(iter) => {
for result in iter {
match result {
Ok(item) => println!("Found: {}", item.ip_net),
Err(e) => eprintln!("Error processing item: {}", e),
}
}
}
Err(e) => eprintln!("Failed to create iterator: {}", e),
}