pub struct LookupResult<'a, S: AsRef<[u8]>> { /* private fields */ }Expand description
The result of looking up an IP address in a MaxMind DB.
This is a lightweight handle (~40 bytes) that stores the lookup result without immediately decoding the data. You can:
- Check if data exists with
has_data() - Get the network containing the IP with
network() - Decode the full record with
decode() - Decode a specific path with
decode_path()
§Example
use maxminddb::{geoip2, path, Reader};
use std::net::IpAddr;
let reader = Reader::open_readfile("test-data/test-data/GeoIP2-City-Test.mmdb").unwrap();
let ip: IpAddr = "89.160.20.128".parse().unwrap();
let result = reader.lookup(ip).unwrap();
if result.has_data() {
// Full decode
let city: geoip2::City = result.decode().unwrap().unwrap();
// Or selective decode via path
let country_code: Option<String> = result
.decode_path(&path!["country", "iso_code"])
.unwrap();
println!("Country: {:?}", country_code);
}Implementations§
Source§impl<'a, S: AsRef<[u8]>> LookupResult<'a, S>
impl<'a, S: AsRef<[u8]>> LookupResult<'a, S>
Sourcepub fn has_data(&self) -> bool
pub fn has_data(&self) -> bool
Returns true if the database contains data for this IP address.
Note that false means the database has no data for this IP,
which is different from an error during lookup.
Sourcepub fn network(&self) -> Result<IpNetwork, MaxMindDbError>
pub fn network(&self) -> Result<IpNetwork, MaxMindDbError>
Returns the network containing the looked-up IP address.
This is the most specific network in the database that contains the IP, regardless of whether data was found.
The returned network preserves the IP version of the original lookup:
- IPv4 lookups return IPv4 networks (unless the match occurs before the IPv4 subtree begins, see below)
- IPv6 lookups return IPv6 networks (including IPv4-mapped addresses)
Special case: If an IPv4 address is looked up in an IPv6 database but the matching record is above the IPv4 subtree (e.g., a database with no IPv4 subtree), an IPv6 network is returned since there’s no valid IPv4 representation.
Sourcepub fn offset(&self) -> Option<usize>
pub fn offset(&self) -> Option<usize>
Returns the data section offset if found, for use as a cache key.
Multiple IP addresses often point to the same data record. This offset can be used to deduplicate decoding or cache results.
Returns None if the IP was not found.
Sourcepub fn decode<T>(&self) -> Result<Option<T>, MaxMindDbError>where
T: Deserialize<'a>,
pub fn decode<T>(&self) -> Result<Option<T>, MaxMindDbError>where
T: Deserialize<'a>,
Decodes the full record into the specified type.
Returns:
Ok(Some(T))if found and successfully decodedOk(None)if the IP was not found in the databaseErr(...)if decoding fails
Any operation that enters an MMDB map or array has an expansion budget
of 65,536 logical values and 2 MiB of string and bytes payload. Dynamic
deserialize_any, enum, and raw-string-helper entry points activate the
budget before the value’s type is known. Only scalar values requested
directly through a typed scalar entry point avoid this bookkeeping. The
decoder reserves a container’s declared children before Serde can
allocate for them, repeated pointer targets are charged on every
expansion, and ignored fields do not expand pointer targets. Exceeding
either decoder-wide operation limit returns
MaxMindDbError::ResourceLimit rather than treating the database as
necessarily corrupt.
Concrete-schema identifiers get a 32-byte allowance per logical value before using the 2 MiB payload counter, whether they are encoded inline or behind a pointer. The logical-value limit bounds all such allowances to another 2 MiB. Thus, after an operation activates its budget, expanded string and byte payload remains bounded to at most 4 MiB even for custom identifier visitors. A scalar-only typed decode remains limited only by the MMDB format’s maximum encoded payload size.
These general limits do not replace tighter bounds implied by an
application’s schema. A collection with a small semantic maximum should
enforce it in its Deserialize implementation or a Serde
deserialize_with visitor, before allocating or consuming its elements.
The built-in crate::geoip2::City and crate::geoip2::Enterprise
schemas cap their subdivision lists at
crate::geoip2::MAX_SUBDIVISIONS in every Serde format. An otherwise
valid oversized MMDB list that reaches the schema visitor returns
MaxMindDbError::Decoding; malformed data and decoder-wide limits may
fail earlier with their corresponding error variants.
Custom deserializers that bypass Serde’s map and sequence entry points
remain responsible for bounding their own traversal over untrusted data.
§Example
use maxminddb::{Reader, geoip2};
use std::net::IpAddr;
let reader = Reader::open_readfile("test-data/test-data/GeoIP2-City-Test.mmdb").unwrap();
let ip: IpAddr = "89.160.20.128".parse().unwrap();
let result = reader.lookup(ip).unwrap();
if let Some(city) = result.decode::<geoip2::City>()? {
println!("Found city data");
}Sourcepub fn decode_path<T>(
&self,
path: &[PathElement<'_>],
) -> Result<Option<T>, MaxMindDbError>where
T: Deserialize<'a>,
pub fn decode_path<T>(
&self,
path: &[PathElement<'_>],
) -> Result<Option<T>, MaxMindDbError>where
T: Deserialize<'a>,
Decodes a value at a specific path within the record.
Returns:
Ok(Some(T))if the path exists and was successfully decodedOk(None)if the path doesn’t exist (key missing, index out of bounds)Err(...)if there’s a type mismatch during navigation (e.g.,Keyon an array)
If has_data() == false, returns Ok(None).
Path traversal does not expand skipped pointer targets. Navigation and
the selected value share the container and payload budgets described by
decode(); resource-limit errors include the path reached
when the limit was detected.
§Path Elements
PathElement::Key("name")- Navigate into a map by keyPathElement::Index(0)- Navigate into an array by index (0 = first element)PathElement::IndexFromEnd(0)- Navigate from the end (0 = last element)
§Example
use maxminddb::{path, Reader};
use std::net::IpAddr;
let reader = Reader::open_readfile("test-data/test-data/GeoIP2-City-Test.mmdb").unwrap();
let ip: IpAddr = "89.160.20.128".parse().unwrap();
let result = reader.lookup(ip).unwrap();
// Navigate to country.iso_code
let iso_code: Option<String> = result
.decode_path(&path!["country", "iso_code"])
.unwrap();
// Navigate to subdivisions[0].names.en
let subdiv_name: Option<String> = result
.decode_path(&path!["subdivisions", 0, "names", "en"])
.unwrap();Trait Implementations§
Source§impl<'a, S: Clone + AsRef<[u8]>> Clone for LookupResult<'a, S>
impl<'a, S: Clone + AsRef<[u8]>> Clone for LookupResult<'a, S>
Source§fn clone(&self) -> LookupResult<'a, S>
fn clone(&self) -> LookupResult<'a, S>
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more