Skip to main content

Reader

Struct Reader 

Source
pub struct Reader<'a> { /* private fields */ }
Expand description

Parsed MaxMind DB reader.

Opening from &[u8] does not copy the database bytes. Opening prepares native-endian children for every valid record size; common 24/28/32-bit records also use a cache-aligned tree and bounded byte-stride or radix tables. This increases open time and reader memory use, but the first lookup performs no index construction. Generic lookup_value materializes map and array containers; typed borrowed decoding avoids those containers.

Implementations§

Source§

impl Reader<'static>

Source

pub fn open(path: impl AsRef<Path>) -> Result<Self>

Opens a MaxMind DB file into an owned byte buffer.

Returns an I/O or format error if the file cannot be read or validated. Preparing the search-tree index is part of the open cost.

§Examples
use libmaxminddb_rs::Reader;
let path = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/fixtures/doc.mmdb");
let reader = Reader::open(path)?;
assert_eq!(reader.metadata().ip_version, 4);
Source

pub unsafe fn open_mmap(path: impl AsRef<Path>) -> Result<Self>

Opens a MaxMind DB file through a read-only memory mapping. The search-tree index is prepared before this method returns.

§Safety

The mapped file must not be modified or truncated for as long as the returned reader exists. Violating this operating-system mmap requirement can make subsequent memory accesses invalid.

§Examples
use libmaxminddb_rs::Reader;
let path = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/fixtures/doc.mmdb");
// SAFETY: This checked-in fixture is not changed while the reader exists.
let reader = unsafe { Reader::open_mmap(path)? };
assert_eq!(reader.metadata().ip_version, 4);
Source

pub fn from_vec(data: Vec<u8>) -> Result<Self>

Builds a reader that owns the provided bytes.

Returns a format error when the byte vector is not a valid MMDB. The search-tree index is prepared before this method returns.

§Examples
use libmaxminddb_rs::Reader;
let bytes = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/fixtures/doc.mmdb"));
let reader = Reader::from_vec(bytes.to_vec())?;
assert_eq!(reader.metadata().ip_version, 4);
Source§

impl<'a> Reader<'a>

Source

pub fn from_bytes(data: &'a [u8]) -> Result<Self>

Opens a MaxMind DB directly from a borrowed byte slice without copying it. Returns a format error when the bytes are not a valid MMDB. The search-tree index is prepared before this method returns.

§Examples
use libmaxminddb_rs::Reader;
let bytes = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/fixtures/doc.mmdb"));
let reader = Reader::from_bytes(bytes)?;
assert_eq!(reader.metadata().ip_version, 4);
Source

pub const fn metadata(&self) -> &Metadata

Returns parsed database metadata.

§Examples
use libmaxminddb_rs::Reader;
let bytes = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/fixtures/doc.mmdb"));
let reader = Reader::from_bytes(bytes)?;
assert_eq!(reader.metadata().database_type, "libmaxminddb-rs-compat");
Source

pub fn as_bytes(&self) -> &[u8] ⓘ

Returns the underlying database bytes.

§Examples
use libmaxminddb_rs::Reader;
let bytes = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/fixtures/doc.mmdb"));
let reader = Reader::from_bytes(bytes)?;
assert_eq!(reader.as_bytes(), bytes);
Source

pub fn lookup_value(&self, ip: IpAddr) -> Result<ValueRef<'_>>

Looks up an IP and returns a borrowed generic value. Returns Error::NotFound on a miss; malformed data can also produce a decode error.

§Examples
use libmaxminddb_rs::Reader;
let bytes = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/fixtures/doc.mmdb"));
let reader = Reader::from_bytes(bytes)?;
let value = reader.lookup_value("203.0.113.7".parse()?)?;
assert!(value.get("country").is_some());
Source

pub fn lookup_value_with_prefix(&self, ip: IpAddr) -> Result<(ValueRef<'_>, u8)>

Looks up an IP and returns the borrowed value and matched prefix length. Returns Error::NotFound on a miss. The prefix is the matched network’s CIDR length, not the address width.

§Examples
use libmaxminddb_rs::Reader;
let bytes = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/fixtures/doc.mmdb"));
let reader = Reader::from_bytes(bytes)?;
let (_, prefix) = reader.lookup_value_with_prefix("203.0.113.7".parse()?)?;
assert_eq!(prefix, 24);
Source

pub fn lookup_borrowed<'s, T>(&'s self, ip: IpAddr) -> Result<T>
where T: MmdbDecode<'s>,

Decodes an IP record into a user type generated with #[derive(MmdbDecode)].

Derived types are decoded in a single pass straight from the database bytes: strings borrow the buffer, unknown fields are skipped without being decoded, and no intermediate ValueRef tree is built, so the lookup performs no heap allocation beyond the Vec/String fields the target type itself owns.

Returns Error::NotFound when the IP matches no network in the database. No record is decoded on this miss path.

The traversal and miss handling stay on the inlined fast path; only a hit enters the (cold) decode machinery. This keeps the dominant miss case from materializing the large Result<T, Error> return value that a user-sized T (for example a CityRecord) would force onto the hot loop, and lets lookup_borrowed match tree-only traversal on the miss path.

§Examples
use libmaxminddb_rs::{MmdbDecode, Reader};
#[derive(MmdbDecode)]
struct Record<'a> { category: &'a str }
let bytes = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/fixtures/doc.mmdb"));
let reader = Reader::from_bytes(bytes)?;
let record: Record<'_> = reader.lookup_borrowed("203.0.113.7".parse()?)?;
assert_eq!(record.category, "compat");
Source

pub fn lookup_borrowed_opt<'s, T>(&'s self, ip: IpAddr) -> Option<T>
where T: MmdbDecode<'s>,

Like lookup_borrowed but returns Option<T> instead of Result<T, Error>.

On a miss the function returns None without ever constructing the Error enum. This avoids the out-of-line Error drop-glue that the Result<T, Error> return type forces on every miss when the caller discards the error (via .ok(), match, etc.). Because Error has String-bearing variants, its drop-glue is a non-inlined function call; eliminating it shaves several nanoseconds from the miss path — the dominant shape for random/absent workloads.

Decode failures (only reachable on a corrupt or malicious database) are also folded into None. Callers that must distinguish “not found” from “found but undecodable” should use lookup_borrowed instead.

§Performance

On the miss path this matches tree-only traversal — no Error is constructed or dropped. On the hit path it is identical to lookup_borrowed.

§Examples
use libmaxminddb_rs::{MmdbDecode, Reader};
#[derive(MmdbDecode)]
struct Record<'a> { category: &'a str }
let bytes = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/fixtures/doc.mmdb"));
let reader = Reader::from_bytes(bytes)?;
let record: Option<Record<'_>> = reader.lookup_borrowed_opt("192.0.2.1".parse()?);
assert!(record.is_none());
Source

pub fn lookup_borrowed_map<'s, T, R>( &'s self, ip: IpAddr, on_hit: impl FnOnce(T) -> R, ) -> Result<Option<R>>
where T: MmdbDecode<'s>,

Decodes a borrowed record and passes it to on_hit, returning None when no network matches the address.

A caller that only needs a small result can return it from the callback without carrying a potentially large T through the miss path. Decode and invalid-pointer errors are preserved as Error values.

§Examples
use libmaxminddb_rs::{MmdbDecode, Reader};
#[derive(MmdbDecode)]
struct Record<'a> { category: &'a str }
let bytes = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/fixtures/doc.mmdb"));
let reader = Reader::from_bytes(bytes)?;
let category = reader.lookup_borrowed_map("203.0.113.7".parse()?, |r: Record<'_>| r.category)?;
assert_eq!(category, Some("compat"));
Source

pub fn lookup<T: DeserializeOwned>(&self, ip: IpAddr) -> Result<T>

Deserializes through serde into an owned type. Returns Error::NotFound on a miss and a conversion error if the stored value does not match the requested type. This path allocates.

§Examples
use libmaxminddb_rs::Reader;
let bytes = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/fixtures/doc.mmdb"));
let reader = Reader::from_bytes(bytes)?;
let value: serde_json::Value = reader.lookup("203.0.113.7".parse()?)?;
assert_eq!(value["category"], "compat");
Source

pub fn lookup_many(&self, ips: &[IpAddr]) -> Vec<Result<ValueRef<'_>>> ⓘ

Looks up many IPs and returns borrowed values in the same order as ips.

The output vector and decoded map/array containers allocate. For large batches, work is split across threads with std::thread::scope. Each result independently reports a miss or decode error.

§Examples
use libmaxminddb_rs::{Error, Reader};
let bytes = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/fixtures/doc.mmdb"));
let reader = Reader::from_bytes(bytes)?;
let ips = ["203.0.113.7".parse()?, "192.0.2.1".parse()?];
let results = reader.lookup_many(&ips);
assert!(results[0].is_ok());
assert!(matches!(results[1], Err(Error::NotFound)));
Source

pub fn lookup_exists(&self, ip: IpAddr) -> bool

Checks if an IP address exists in the database without decoding or allocating.

It traverses the tree and validates the resulting data offset.

§Examples
use libmaxminddb_rs::Reader;
let bytes = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/fixtures/doc.mmdb"));
let reader = Reader::from_bytes(bytes)?;
assert!(reader.lookup_exists("203.0.113.7".parse()?));
assert!(!reader.lookup_exists("192.0.2.1".parse()?));

Trait Implementations§

Source§

impl<'a> Debug for Reader<'a>

Source§

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

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<'a> Freeze for Reader<'a>

§

impl<'a> RefUnwindSafe for Reader<'a>

§

impl<'a> Send for Reader<'a>

§

impl<'a> Sync for Reader<'a>

§

impl<'a> Unpin for Reader<'a>

§

impl<'a> UnsafeUnpin for Reader<'a>

§

impl<'a> UnwindSafe for Reader<'a>

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 = !

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

fn try_from(value: U) -> Result<T, !>

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.