Skip to main content

IpnetTrie

Struct IpnetTrie 

Source
pub struct IpnetTrie<T> { /* private fields */ }
Expand description

Table holding IPv4 and IPv6 network prefixes with value.

Implementations§

Source§

impl<T> IpnetTrie<T>

Source

pub fn new() -> Self

Constructs a new, empty IpnetTrie<T>.

Source

pub fn len(&self) -> (usize, usize)

Returns the number of elements in the table. First value is number of IPv4 networks and second is number of IPv6 networks.

Source

pub fn is_empty(&self) -> bool

Returns true if table is empty.

Source

pub fn insert<N: Into<IpNet>>(&mut self, network: N, data: T) -> Option<T>

Insert a value for the IpNet. If prefix existed previously, the old value is returned.

§Examples
use ipnet_trie::IpnetTrie;
use ipnet::Ipv6Net;
use std::net::Ipv6Addr;

let mut table = IpnetTrie::new();
let network = Ipv6Net::new(Ipv6Addr::new(0x2001, 0xdb8, 0xdead, 0xbeef, 0, 0, 0, 0), 64).unwrap();

assert_eq!(table.insert(network, "foo"), None);
// Insert duplicate
assert_eq!(table.insert(network, "bar"), Some("foo"));
// Value is replaced
assert_eq!(table.insert(network, "null"), Some("bar"));
Source

pub fn remove<N: Into<IpNet>>(&mut self, network: N) -> Option<T>

Remove a IpNet from table. If prefix existed, the value is returned.

§Examples
use ipnet_trie::IpnetTrie;
use std::net::Ipv6Addr;
use ipnet::Ipv6Net;

let mut table = IpnetTrie::new();
let network = Ipv6Net::new(Ipv6Addr::new(0x2001, 0xdb8, 0xdead, 0xbeef, 0, 0, 0, 0), 64).unwrap();

assert_eq!(table.insert(network, "foo"), None);
// Remove network from table
assert_eq!(table.remove(network), Some("foo"));
// Network is removed
assert_eq!(table.exact_match(network), None);
Source

pub fn exact_match<N: Into<IpNet>>(&self, network: N) -> Option<&T>

Get pointer to value from table based on exact network match. If network is not in table, None is returned.

§Examples
use ipnet_trie::IpnetTrie;
use std::net::Ipv6Addr;
use ipnet::Ipv6Net;

let mut table = IpnetTrie::new();
let network_a = Ipv6Net::new(Ipv6Addr::new(0x2001, 0xdb8, 0xdead, 0xbeef, 0, 0, 0, 0), 64).unwrap();
let network_b = Ipv6Net::new(Ipv6Addr::new(0x2001, 0xdb8, 0xdead, 0xbeef, 0, 0, 0, 0), 128).unwrap();

assert_eq!(table.insert(network_a, "foo"), None);
// Get value for network from trie
assert_eq!(table.exact_match(network_a), Some(&"foo"));
// Network B doesn not exist in trie
assert_eq!(table.exact_match(network_b), None);
Source

pub fn exact_match_mut<N: Into<IpNet>>(&mut self, network: N) -> Option<&mut T>

Get mutable pointer to value from table based on exact network match. If network is not in table, None is returned.

§Examples
use ipnet_trie::IpnetTrie;
use std::net::Ipv6Addr;
use ipnet::Ipv6Net;

let mut table = IpnetTrie::new();
let network_a = Ipv6Net::new(Ipv6Addr::new(0x2001, 0xdb8, 0xdead, 0xbeef, 0, 0, 0, 0), 64).unwrap();
let network_b = Ipv6Net::new(Ipv6Addr::new(0x2001, 0xdb8, 0xdead, 0xbeef, 0, 0, 0, 0), 128).unwrap();

assert_eq!(table.insert(network_a, "foo"), None);
// Get value for network from trie
assert_eq!(table.exact_match_mut(network_a), Some(&mut "foo"));
// Network B does not exist in trie
assert_eq!(table.exact_match(network_b), None);
Source

pub fn longest_match(&self, ipnet: &IpNet) -> Option<(IpNet, &T)>

Find most specific IP network in table that contains given IP address. If no network in table contains given IP address, None is returned.

§Examples
use ipnet_trie::IpnetTrie;
use ipnet::{IpNet, Ipv6Net};
use std::net::{IpAddr, Ipv6Addr};

let mut table = IpnetTrie::new();
let network = IpNet::new(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0xdead, 0xbeef, 0, 0, 0, 0)), 64).unwrap();
let ip_address = Ipv6Addr::new(0x2001, 0xdb8, 0xdead, 0xbeef, 0, 0, 0, 0x1);

assert_eq!(table.insert(network, "foo"), None);
// Get value for network from table
assert_eq!(table.longest_match(&IpNet::from(ip_address.to_canonical())), Some((network, &"foo")));
Source

pub fn longest_match_mut(&mut self, ipnet: &IpNet) -> Option<(IpNet, &mut T)>

Find most specific IP network in table that contains given IP address. If no network in table contains given IP address, None is returned.

§Examples
use ipnet_trie::IpnetTrie;
use ipnet::{IpNet, Ipv6Net};
use std::net::{IpAddr, Ipv6Addr};

let mut table = IpnetTrie::new();
let network = IpNet::new(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0xdead, 0xbeef, 0, 0, 0, 0)), 64).unwrap();
let ip_address = Ipv6Addr::new(0x2001, 0xdb8, 0xdead, 0xbeef, 0, 0, 0, 0x1);

assert_eq!(table.insert(network, "foo"), None);
// Get value for network from table
assert_eq!(table.longest_match_mut(&IpNet::from(ip_address.to_canonical())), Some((network, &mut "foo")));
Source

pub fn longest_match_ipv4(&self, net: &Ipv4Net) -> Option<(&Ipv4Net, &T)>

Specific version of longest_match for IPv4 address.

Source

pub fn longest_match_ipv6(&self, net: &Ipv6Net) -> Option<(&Ipv6Net, &T)>

Specific version of longest_match for IPv6 address.

Source

pub fn longest_match_ipv4_mut( &mut self, net: &Ipv4Net, ) -> Option<(&Ipv4Net, &mut T)>

Specific version of longest_match for IPv4 address.

Source

pub fn longest_match_ipv6_mut( &mut self, net: &Ipv6Net, ) -> Option<(&Ipv6Net, &mut T)>

Specific version of longest_match for IPv6 address.

Source

pub fn matches(&self, ipnet: &IpNet) -> Vec<(IpNet, &T)>

Find all IP networks in table that contains given IP address. Returns iterator of IpNet and reference to value.

§Examples
use ipnet_trie::IpnetTrie;
use ipnet::{IpNet, Ipv6Net};
use std::net::{IpAddr, Ipv6Addr};

let mut table = IpnetTrie::new();
let network = IpNet::new(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0xdead, 0xbeef, 0, 0, 0, 0)), 64).unwrap();
let ip_address = Ipv6Addr::new(0x2001, 0xdb8, 0xdead, 0xbeef, 0, 0, 0, 0x1);

assert_eq!(table.insert(network, "foo"), None);
// Get value for network from table
assert_eq!(table.matches(&IpNet::from(ip_address.to_canonical())).len(), 1);
Source

pub fn matches_ipv4(&self, net: &Ipv4Net) -> Vec<(&Ipv4Net, &T)>

Specific version of matches for IPv4 address.

Source

pub fn matches_ipv6(&self, net: &Ipv6Net) -> Vec<(&Ipv6Net, &T)>

Specific version of matches for IPv6 address.

Source

pub fn iter(&self) -> impl Iterator<Item = (IpNet, &T)>

Iterator for all networks in table, first are iterated IPv4 and then IPv6 networks. Order is not guaranteed.

§Examples
use ipnet_trie::IpnetTrie;
use ipnet::{IpNet, Ipv4Net, Ipv6Net};
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};

let mut table: IpnetTrie<&str> = IpnetTrie::new();
let network_a = Ipv4Net::new(Ipv4Addr::new(192, 168, 0, 0), 24).unwrap();
assert_eq!(table.insert(network_a, "foo"), None);
let network_b = Ipv6Net::new(Ipv6Addr::new(0x2001, 0xdb8, 0xdead, 0xbeef, 0, 0, 0, 0), 64).unwrap();
assert_eq!(table.insert(network_b, "foo"), None);

let mut iterator = table.iter();
assert_eq!(iterator.next(), Some((IpNet::V4(network_a), &"foo")));
assert_eq!(iterator.next(), Some((IpNet::V6(network_b), &"foo")));
assert_eq!(iterator.next(), None);
Source

pub fn iter_mut(&mut self) -> impl Iterator<Item = (IpNet, &mut T)>

Mutable iterator for all networks in table, first are iterated IPv4 and then IPv6 networks. Order is not guaranteed.

§Examples
use ipnet_trie::IpnetTrie;
use ipnet::{IpNet, Ipv4Net, Ipv6Net};
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};

let mut table: IpnetTrie<&str> = IpnetTrie::new();
let network_a = Ipv4Net::new(Ipv4Addr::new(192, 168, 0, 0), 24).unwrap();
assert_eq!(table.insert(network_a, "foo"), None);
let network_b = Ipv6Net::new(Ipv6Addr::new(0x2001, 0xdb8, 0xdead, 0xbeef, 0, 0, 0, 0), 64).unwrap();
assert_eq!(table.insert(network_b, "foo"), None);

let mut iterator = table.iter_mut();
for (network, value) in iterator {
   *value = "bar";
}

assert_eq!(table.exact_match(network_a), Some(&"bar"));
assert_eq!(table.exact_match(network_b), Some(&"bar"));
Source

pub fn iter_ipv4(&self) -> impl Iterator<Item = (&Ipv4Net, &T)>

Iterator for all IPv4 networks in table. Order is not guaranteed.

Source

pub fn iter_ipv6(&self) -> impl Iterator<Item = (&Ipv6Net, &T)>

Iterator for all IPv6 networks in table. Order is not guaranteed.

Source

pub fn retain<F>(&mut self, f: F)
where F: FnMut(IpNet, &mut T) -> bool,

Retains only the elements specified by the predicate.

In other words, remove all pairs (k, v) such that f(ip_network, &mut v) returns false.

§Examples
use ipnet_trie::IpnetTrie;
use ipnet::{IpNet, Ipv4Net, Ipv6Net};
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};

let mut table: IpnetTrie<&str> = IpnetTrie::new();
let network_a = Ipv4Net::new(Ipv4Addr::new(192, 168, 0, 0), 24).unwrap();
assert_eq!(table.insert(network_a, "foo"), None);
let network_b = Ipv6Net::new(Ipv6Addr::new(0x2001, 0xdb8, 0xdead, 0xbeef, 0, 0, 0, 0), 64).unwrap();
assert_eq!(table.insert(network_b, "foo"), None);

// Keep just IPv4 networks
table.retain(|network, _| network.network().is_ipv4());

assert_eq!(table.exact_match(network_a), Some(&"foo"));
assert_eq!(table.exact_match(network_b), None);
Source

pub fn ip_count(&self) -> IpCount

Count the number of unique IPv4 and IPv6 addresses in the trie.

Returns an IpCount struct. The ipv4 field uses u64 and can represent the entire IPv4 address space (2³²). The ipv6 field is Option<u128>: Some(count) for any value up to 2¹²⁸−1, and None when the entire IPv6 address space (2¹²⁸ addresses) is covered, since that value cannot be represented in a u128.

use std::str::FromStr;
use ipnet::{Ipv4Net, Ipv6Net};
use ipnet_trie::{IpnetTrie, IpCount};

let mut table = IpnetTrie::new();
table.insert(Ipv4Net::from_str("192.0.2.129/25").unwrap(), 1);
table.insert(Ipv4Net::from_str("192.0.2.0/24").unwrap(), 1);
table.insert(Ipv4Net::from_str("192.0.2.0/24").unwrap(), 1);
table.insert(Ipv4Net::from_str("192.0.2.0/24").unwrap(), 1);
assert_eq!(table.ip_count(), IpCount { ipv4: 256, ipv6: Some(0) });

table.insert(Ipv4Net::from_str("198.51.100.0/25").unwrap(), 1);
table.insert(Ipv4Net::from_str("198.51.100.64/26").unwrap(), 1);
assert_eq!(table.ip_count(), IpCount { ipv4: 384, ipv6: Some(0) });

table.insert(Ipv4Net::from_str("198.51.100.65/26").unwrap(), 1);
assert_eq!(table.ip_count(), IpCount { ipv4: 384, ipv6: Some(0) });

table.insert(Ipv6Net::from_str("2001:DB80::/48").unwrap(), 1);
assert_eq!(table.ip_count(), IpCount { ipv4: 384, ipv6: Some(2_u128.pow(80)) });
table.insert(Ipv6Net::from_str("2001:DB80::/49").unwrap(), 1);
assert_eq!(table.ip_count(), IpCount { ipv4: 384, ipv6: Some(2_u128.pow(80)) });
table.insert(Ipv6Net::from_str("2001:DB81::/48").unwrap(), 1);
assert_eq!(table.ip_count(), IpCount { ipv4: 384, ipv6: Some(2_u128.pow(81)) });

// Full IPv4 space (0.0.0.0/0) — 2^32 addresses, fits in u64
let mut v4_full = IpnetTrie::new();
v4_full.insert(Ipv4Net::from_str("0.0.0.0/0").unwrap(), 1);
assert_eq!(v4_full.ip_count(), IpCount { ipv4: 1u64 << 32, ipv6: Some(0) });

// Full IPv6 space (::/0) — 2^128 addresses, cannot fit in u128
let mut v6_full = IpnetTrie::new();
v6_full.insert(Ipv6Net::from_str("::/0").unwrap(), 1);
assert_eq!(v6_full.ip_count(), IpCount { ipv4: 0, ipv6: None });
Source

pub fn get_aggregated_prefixes(&self) -> (Vec<Ipv4Net>, Vec<Ipv6Net>)

Retrieves the aggregated prefixes for both IPv4 and IPv6 from the given data.

§Returns

A tuple containing two vectors. The first vector contains the aggregated IPv4 prefixes, and the second vector contains the aggregated IPv6 prefixes.

Source

pub fn diff(&self, other: &Self) -> (Vec<IpNet>, Vec<IpNet>)

Find the difference between two prefix tries, returning two vectors of IpNets, one for added prefixes, and one for removed prefixes.

  • added prefixes: all prefixes in other that are not in self
  • removed prefixes: all prefixes in self that are not in other

Trait Implementations§

Source§

impl<T> Clone for IpnetTrie<T>
where T: Clone,

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T: Default> Default for IpnetTrie<T>

Source§

fn default() -> IpnetTrie<T>

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl<T> !Freeze for IpnetTrie<T>

§

impl<T> !RefUnwindSafe for IpnetTrie<T>

§

impl<T> Send for IpnetTrie<T>
where T: Send,

§

impl<T> Sync for IpnetTrie<T>
where T: Sync,

§

impl<T> Unpin for IpnetTrie<T>
where T: Unpin,

§

impl<T> UnsafeUnpin for IpnetTrie<T>

§

impl<T> UnwindSafe for IpnetTrie<T>
where T: 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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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.