pub struct Writer { /* private fields */ }Expand description
Builds a MaxMind DB and serializes it.
Construct one with Writer::new for the common case, or Writer::builder to set
options such as the IpVersion, descriptions, or a fixed RecordSize. Then add data
with insert / insert_value and produce bytes
with to_bytes or write_to.
use ipnet::IpNet;
use mmdb_writer::{Value, Writer};
let mut writer = Writer::new("Example-DB");
writer.insert_value(
"192.0.2.0/24".parse::<IpNet>()?,
Value::map([("hello", Value::from("world"))]),
)?;
let bytes = writer.to_bytes()?;
assert!(!bytes.is_empty());Implementations§
Source§impl Writer
impl Writer
Sourcepub fn load_from_path(path: impl AsRef<Path>) -> Result<Self, Error>
pub fn load_from_path(path: impl AsRef<Path>) -> Result<Self, Error>
Load an existing database from a file, ready to be extended.
The returned Writer is seeded with every network in the file and the file’s
metadata (database type, languages, descriptions, IP version, record size, and build
epoch). Reserved-network and aliasing options are not stored in the format, so they
take their defaults.
§Errors
Returns Error::Io if the file cannot be read, or Error::Load if it is not a
valid database.
Sourcepub fn load(bytes: impl AsRef<[u8]>) -> Result<Self, Error>
pub fn load(bytes: impl AsRef<[u8]>) -> Result<Self, Error>
Load an existing database from a byte buffer, ready to be extended.
See load_from_path for details.
§Errors
Returns Error::Load if bytes is not a valid database.
Source§impl Writer
impl Writer
Sourcepub fn builder(database_type: impl Into<String>) -> WriterBuilder
pub fn builder(database_type: impl Into<String>) -> WriterBuilder
Start building a Writer with options.
database_type names the database for readers (conventionally Vendor-Dataset).
Every other option has a default, so the terminal build can
follow immediately.
use mmdb_writer::{IpVersion, RecordSize, Writer};
let writer = Writer::builder("Example-DB")
.ip_version(IpVersion::V4)
.record_size(RecordSize::Bits32)
.languages(["en", "de"])
.build();Source§impl Writer
impl Writer
Sourcepub fn new(database_type: impl Into<String>) -> Self
pub fn new(database_type: impl Into<String>) -> Self
Create a Writer with all default options and the given database type.
Sourcepub fn insert<N: Into<IpNet>, T: Serialize + ?Sized>(
&mut self,
network: N,
value: &T,
) -> Result<(), Error>
pub fn insert<N: Into<IpNet>, T: Serialize + ?Sized>( &mut self, network: N, value: &T, ) -> Result<(), Error>
Insert any Serialize value at every address in network.
The value is projected onto the MMDB type system: structs and maps become MMDB maps,
sequences become arrays, Option::None and unit values are dropped, and enums are
serialized in serde’s externally tagged form. Later inserts win, as with
insert_value.
§Errors
Returns Error::UnsupportedValue if the value uses a type MMDB cannot represent
(such as i64), Error::Serialize if serialization fails, or
Error::Ipv6InIpv4Tree for an IPv6 network in an IPv4 database.
use ipnet::IpNet;
use mmdb_writer::Writer;
use serde::Serialize;
#[derive(Serialize)]
struct Asn { autonomous_system_number: u32, autonomous_system_organization: String }
let mut writer = Writer::new("ASN-DB");
writer.insert(
"192.0.2.0/24".parse::<IpNet>()?,
&Asn { autonomous_system_number: 64_512, autonomous_system_organization: "Example".into() },
)?;Sourcepub fn insert_value<N: Into<IpNet>>(
&mut self,
network: N,
value: Value,
) -> Result<(), Error>
pub fn insert_value<N: Into<IpNet>>( &mut self, network: N, value: Value, ) -> Result<(), Error>
Insert a Value at every address in network.
Later inserts win: a more-specific network inserted afterward overrides the covered
addresses, and a less-specific one overwrites everything it covers. Host bits in
network are ignored.
§Errors
Returns Error::Ipv6InIpv4Tree if network is IPv6 but the database is
IpVersion::V4.
Sourcepub fn insert_with<N, F>(&mut self, network: N, op: F) -> Result<(), Error>
pub fn insert_with<N, F>(&mut self, network: N, op: F) -> Result<(), Error>
Insert into network by computing each covered leaf’s new value from its current one.
The operation receives the value currently covering a leaf (None where there is
none) and returns the value to store, or None to clear it. Because a network can
cover many existing leaves, the operation may be called more than once per insert —
once per distinct value it paints over. This mirrors the Go writer’s InsertFunc.
use ipnet::IpNet;
use mmdb_writer::{Value, Writer};
let mut w = Writer::new("Counter");
let mut bump = |net: &str| {
w.insert_with(net.parse::<IpNet>().unwrap(), |existing| {
let n = match existing {
Some(Value::U32(n)) => *n + 1,
_ => 1,
};
Some(Value::from(n))
})
.unwrap();
};
bump("192.0.2.0/24");
bump("192.0.2.0/25"); // overlaps: sees the existing 1, stores 2§Errors
Returns Error::Ipv6InIpv4Tree for an IPv6 network in an IPv4 database.
Sourcepub fn insert_value_merged<N: Into<IpNet>>(
&mut self,
network: N,
value: Value,
strategy: MergeStrategy,
) -> Result<(), Error>
pub fn insert_value_merged<N: Into<IpNet>>( &mut self, network: N, value: Value, strategy: MergeStrategy, ) -> Result<(), Error>
Insert a Value into network, combining it with any existing value per strategy.
With MergeStrategy::Replace this is insert_value; the other
strategies merge maps (and, for DeepMerge, nested maps
and arrays) rather than overwriting.
§Errors
Returns Error::Ipv6InIpv4Tree for an IPv6 network in an IPv4 database.
Sourcepub fn insert_merged<N: Into<IpNet>, T: Serialize + ?Sized>(
&mut self,
network: N,
value: &T,
strategy: MergeStrategy,
) -> Result<(), Error>
pub fn insert_merged<N: Into<IpNet>, T: Serialize + ?Sized>( &mut self, network: N, value: &T, strategy: MergeStrategy, ) -> Result<(), Error>
Insert any Serialize value into network, merging per strategy.
The serde equivalent of insert_value_merged.
§Errors
As insert plus insert_value_merged.
Sourcepub fn insert_range(
&mut self,
start: IpAddr,
end: IpAddr,
value: &Value,
) -> Result<(), Error>
pub fn insert_range( &mut self, start: IpAddr, end: IpAddr, value: &Value, ) -> Result<(), Error>
Insert a Value at every address in the inclusive range [start, end].
The range is decomposed into the minimal set of CIDR networks and each is inserted
(with insert_value semantics). Useful for data sources that
express coverage as start–end pairs rather than CIDRs.
§Errors
Returns Error::InvalidRange if start and end are different IP families or
start is above end, or Error::Ipv6InIpv4Tree for an IPv6 range in an IPv4
database.
Sourcepub fn get(&self, ip: IpAddr) -> Option<&Value>
pub fn get(&self, ip: IpAddr) -> Option<&Value>
Look up the value currently covering ip, if any.
Reflects the most-specific matching insert, including the effect of merges and removals. Handy for tests and debugging. IPv4 aliases are not consulted (they are installed only at serialization time), so query IPv4 addresses directly.
Sourcepub fn to_bytes(&self) -> Result<Vec<u8>, Error>
pub fn to_bytes(&self) -> Result<Vec<u8>, Error>
Serialize the database to a byte vector.
This does not consume the writer, so more data can be inserted afterward and the database re-serialized.
§Errors
Returns Error::TreeTooLarge if the tree and data section exceed what the chosen
RecordSize can address.