mirror of
https://github.com/achanda/ipnetwork.git
synced 2025-06-15 16:43:00 +00:00
Compare commits
12 Commits
v0.21.1
...
dependabot
Author | SHA1 | Date | |
---|---|---|---|
a21cb4d081 | |||
c3af07d69a | |||
35977adc81 | |||
0deb2abd8b | |||
170fc4ca6b | |||
aa65f088b1 | |||
5f929258ef | |||
a21f5df04e | |||
876f882523 | |||
49f07a4838 | |||
2f219a2ada | |||
9ae719637d |
@ -9,10 +9,11 @@ keywords = ["network", "ip", "address", "cidr"]
|
||||
readme = "README.md"
|
||||
categories = ["network-programming", "parser-implementations"]
|
||||
edition = "2021"
|
||||
rust-version = "1.80.0"
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "1.0.200", optional = true }
|
||||
schemars = { version = "0.8.17", optional = true }
|
||||
schemars = { version = "0.9.0", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
serde_json = "1.0.116"
|
||||
|
77
src/ipv4.rs
77
src/ipv4.rs
@ -140,11 +140,11 @@ impl Ipv4Network {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ip(self) -> Ipv4Addr {
|
||||
pub const fn ip(self) -> Ipv4Addr {
|
||||
self.addr
|
||||
}
|
||||
|
||||
pub fn prefix(self) -> u8 {
|
||||
pub const fn prefix(self) -> u8 {
|
||||
self.prefix
|
||||
}
|
||||
|
||||
@ -180,13 +180,13 @@ impl Ipv4Network {
|
||||
/// let net: Ipv4Network = "127.0.0.0/16".parse().unwrap();
|
||||
/// assert_eq!(net.mask(), Ipv4Addr::new(255, 255, 0, 0));
|
||||
/// ```
|
||||
pub fn mask(&self) -> Ipv4Addr {
|
||||
pub const fn mask(&self) -> Ipv4Addr {
|
||||
debug_assert!(self.prefix <= 32);
|
||||
if self.prefix == 0 {
|
||||
return Ipv4Addr::new(0, 0, 0, 0);
|
||||
}
|
||||
let mask = u32::MAX << (IPV4_BITS - self.prefix);
|
||||
Ipv4Addr::from(mask)
|
||||
Ipv4Addr::from_bits(mask)
|
||||
}
|
||||
|
||||
/// Returns the address of the network denoted by this `Ipv4Network`.
|
||||
@ -201,10 +201,10 @@ impl Ipv4Network {
|
||||
/// let net: Ipv4Network = "10.1.9.32/16".parse().unwrap();
|
||||
/// assert_eq!(net.network(), Ipv4Addr::new(10, 1, 0, 0));
|
||||
/// ```
|
||||
pub fn network(&self) -> Ipv4Addr {
|
||||
let mask = u32::from(self.mask());
|
||||
let ip = u32::from(self.addr) & mask;
|
||||
Ipv4Addr::from(ip)
|
||||
pub const fn network(&self) -> Ipv4Addr {
|
||||
let mask = self.mask().to_bits();
|
||||
let ip = self.addr.to_bits() & mask;
|
||||
Ipv4Addr::from_bits(ip)
|
||||
}
|
||||
|
||||
/// Returns the broadcasting address of this `Ipv4Network`.
|
||||
@ -219,10 +219,10 @@ impl Ipv4Network {
|
||||
/// let net: Ipv4Network = "10.9.0.32/16".parse().unwrap();
|
||||
/// assert_eq!(net.broadcast(), Ipv4Addr::new(10, 9, 255, 255));
|
||||
/// ```
|
||||
pub fn broadcast(&self) -> Ipv4Addr {
|
||||
let mask = u32::from(self.mask());
|
||||
let broadcast = u32::from(self.addr) | !mask;
|
||||
Ipv4Addr::from(broadcast)
|
||||
pub const fn broadcast(&self) -> Ipv4Addr {
|
||||
let mask = self.mask().to_bits();
|
||||
let broadcast = self.addr.to_bits() | !mask;
|
||||
Ipv4Addr::from_bits(broadcast)
|
||||
}
|
||||
|
||||
/// Checks if a given `Ipv4Addr` is in this `Ipv4Network`
|
||||
@ -238,12 +238,12 @@ impl Ipv4Network {
|
||||
/// assert!(!net.contains(Ipv4Addr::new(127, 0, 1, 70)));
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn contains(&self, ip: Ipv4Addr) -> bool {
|
||||
pub const fn contains(&self, ip: Ipv4Addr) -> bool {
|
||||
debug_assert!(self.prefix <= IPV4_BITS);
|
||||
|
||||
let mask = !(0xffff_ffff_u64 >> self.prefix) as u32;
|
||||
let net = u32::from(self.addr) & mask;
|
||||
(u32::from(ip) & mask) == net
|
||||
let net = self.addr.to_bits() & mask;
|
||||
(ip.to_bits() & mask) == net
|
||||
}
|
||||
|
||||
/// Returns number of possible host addresses in this `Ipv4Network`.
|
||||
@ -368,6 +368,15 @@ impl Iterator for Ipv4NetworkIterator {
|
||||
};
|
||||
Some(next.into())
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
if let Some(n) = self.next {
|
||||
let elms = (self.end - n + 1) as usize;
|
||||
(elms, Some(elms))
|
||||
} else {
|
||||
(0, None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoIterator for &'_ Ipv4Network {
|
||||
@ -382,13 +391,24 @@ impl IntoIterator for &'_ Ipv4Network {
|
||||
///
|
||||
/// If the mask is invalid this will return an `IpNetworkError::InvalidPrefix`.
|
||||
pub fn ipv4_mask_to_prefix(mask: Ipv4Addr) -> Result<u8, IpNetworkError> {
|
||||
let mask = u32::from(mask);
|
||||
match ipv4_mask_to_prefix_checked(mask) {
|
||||
Some(prefix) => Ok(prefix),
|
||||
None => Err(IpNetworkError::InvalidPrefix),
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a `Ipv4Addr` network mask into a prefix.
|
||||
///
|
||||
/// If the mask is invalid this will return `None`. This is useful in const contexts where
|
||||
/// [`Option::unwrap`] may be called to trigger a compile-time error if the prefix is invalid.
|
||||
pub const fn ipv4_mask_to_prefix_checked(mask: Ipv4Addr) -> Option<u8> {
|
||||
let mask = mask.to_bits();
|
||||
|
||||
let prefix = (!mask).leading_zeros() as u8;
|
||||
if (u64::from(mask) << prefix) & 0xffff_ffff != 0 {
|
||||
Err(IpNetworkError::InvalidPrefix)
|
||||
if ((mask as u64) << prefix) & 0xffff_ffff != 0 {
|
||||
None
|
||||
} else {
|
||||
Ok(prefix)
|
||||
Some(prefix)
|
||||
}
|
||||
}
|
||||
|
||||
@ -571,6 +591,25 @@ mod test {
|
||||
assert_eq!(None, iter.next());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iterator_v4_size_hint() {
|
||||
let cidr: Ipv4Network = "192.168.0.0/24".parse().unwrap();
|
||||
let mut iter = cidr.iter();
|
||||
assert_eq!((256, Some(256)), iter.size_hint());
|
||||
iter.next();
|
||||
assert_eq!((255, Some(255)), iter.size_hint());
|
||||
|
||||
let cidr: Ipv4Network = "192.168.0.0/32".parse().unwrap();
|
||||
let mut iter = cidr.iter();
|
||||
assert_eq!((1, Some(1)), iter.size_hint());
|
||||
iter.next();
|
||||
assert_eq!((0, None), iter.size_hint());
|
||||
|
||||
let cidr: Ipv4Network = "192.168.0.0/0".parse().unwrap();
|
||||
let iter = cidr.iter();
|
||||
assert_eq!((4294967295, Some(4294967295)), iter.size_hint());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn v4_mask_to_prefix() {
|
||||
let mask = Ipv4Addr::new(255, 255, 255, 128);
|
||||
|
80
src/ipv6.rs
80
src/ipv6.rs
@ -160,11 +160,11 @@ impl Ipv6Network {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ip(&self) -> Ipv6Addr {
|
||||
pub const fn ip(&self) -> Ipv6Addr {
|
||||
self.addr
|
||||
}
|
||||
|
||||
pub fn prefix(&self) -> u8 {
|
||||
pub const fn prefix(&self) -> u8 {
|
||||
self.prefix
|
||||
}
|
||||
|
||||
@ -200,14 +200,14 @@ impl Ipv6Network {
|
||||
/// let net: Ipv6Network = "ff01::0/32".parse().unwrap();
|
||||
/// assert_eq!(net.mask(), Ipv6Addr::new(0xffff, 0xffff, 0, 0, 0, 0, 0, 0));
|
||||
/// ```
|
||||
pub fn mask(&self) -> Ipv6Addr {
|
||||
pub const fn mask(&self) -> Ipv6Addr {
|
||||
debug_assert!(self.prefix <= IPV6_BITS);
|
||||
|
||||
if self.prefix == 0 {
|
||||
return Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
let mask = u128::MAX << (IPV6_BITS - self.prefix);
|
||||
Ipv6Addr::from(mask)
|
||||
Ipv6Addr::from_bits(mask)
|
||||
}
|
||||
|
||||
/// Returns the address of the network denoted by this `Ipv6Network`.
|
||||
@ -222,10 +222,10 @@ impl Ipv6Network {
|
||||
/// let net: Ipv6Network = "2001:db8::/96".parse().unwrap();
|
||||
/// assert_eq!(net.network(), Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0));
|
||||
/// ```
|
||||
pub fn network(&self) -> Ipv6Addr {
|
||||
let mask = u128::from(self.mask());
|
||||
let network = u128::from(self.addr) & mask;
|
||||
Ipv6Addr::from(network)
|
||||
pub const fn network(&self) -> Ipv6Addr {
|
||||
let mask = self.mask().to_bits();
|
||||
let network = self.addr.to_bits() & mask;
|
||||
Ipv6Addr::from_bits(network)
|
||||
}
|
||||
|
||||
/// Returns the broadcast address of this `Ipv6Network`.
|
||||
@ -240,10 +240,10 @@ impl Ipv6Network {
|
||||
/// let net: Ipv6Network = "2001:db8::/96".parse().unwrap();
|
||||
/// assert_eq!(net.broadcast(), Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0xffff, 0xffff));
|
||||
/// ```
|
||||
pub fn broadcast(&self) -> Ipv6Addr {
|
||||
let mask = u128::from(self.mask());
|
||||
let broadcast = u128::from(self.addr) | !mask;
|
||||
Ipv6Addr::from(broadcast)
|
||||
pub const fn broadcast(&self) -> Ipv6Addr {
|
||||
let mask = self.mask().to_bits();
|
||||
let broadcast = self.addr.to_bits() | !mask;
|
||||
Ipv6Addr::from_bits(broadcast)
|
||||
}
|
||||
|
||||
/// Checks if a given `Ipv6Addr` is in this `Ipv6Network`
|
||||
@ -259,10 +259,10 @@ impl Ipv6Network {
|
||||
/// assert!(!net.contains(Ipv6Addr::new(0xffff, 0, 0, 0, 0, 0, 0, 0x1)));
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn contains(&self, ip: Ipv6Addr) -> bool {
|
||||
let ip = u128::from(ip);
|
||||
let net = u128::from(self.network());
|
||||
let mask = u128::from(self.mask());
|
||||
pub const fn contains(&self, ip: Ipv6Addr) -> bool {
|
||||
let ip = ip.to_bits();
|
||||
let net = self.network().to_bits();
|
||||
let mask = self.mask().to_bits();
|
||||
(ip & mask) == net
|
||||
}
|
||||
|
||||
@ -372,6 +372,15 @@ impl Iterator for Ipv6NetworkIterator {
|
||||
};
|
||||
Some(next.into())
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
if let Some(n) = self.next {
|
||||
let elms = (self.end - n + 1) as usize;
|
||||
(elms, Some(elms))
|
||||
} else {
|
||||
(0, None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoIterator for &'_ Ipv6Network {
|
||||
@ -391,12 +400,25 @@ impl fmt::Display for Ipv6Network {
|
||||
/// Converts a `Ipv6Addr` network mask into a prefix.
|
||||
/// If the mask is invalid this will return an `IpNetworkError::InvalidPrefix`.
|
||||
pub fn ipv6_mask_to_prefix(mask: Ipv6Addr) -> Result<u8, IpNetworkError> {
|
||||
match ipv6_mask_to_prefix_checked(mask) {
|
||||
Some(prefix) => Ok(prefix),
|
||||
None => Err(IpNetworkError::InvalidPrefix),
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a `Ipv6Addr` network mask into a prefix.
|
||||
///
|
||||
/// If the mask is invalid this will return `None`. This is useful in const contexts where
|
||||
/// [`Option::unwrap`] may be called to trigger a compile-time error if the prefix is invalid.
|
||||
pub const fn ipv6_mask_to_prefix_checked(mask: Ipv6Addr) -> Option<u8> {
|
||||
let mask = mask.segments();
|
||||
let mut mask_iter = mask.iter();
|
||||
|
||||
// Count the number of set bits from the start of the address
|
||||
let mut prefix = 0;
|
||||
for &segment in &mut mask_iter {
|
||||
let mut i = 0;
|
||||
while i < mask.len() {
|
||||
let segment = mask[i];
|
||||
i += 1;
|
||||
if segment == 0xffff {
|
||||
prefix += IPV6_SEGMENT_BITS;
|
||||
} else if segment == 0 {
|
||||
@ -406,7 +428,7 @@ pub fn ipv6_mask_to_prefix(mask: Ipv6Addr) -> Result<u8, IpNetworkError> {
|
||||
let prefix_bits = (!segment).leading_zeros() as u8;
|
||||
// Check that the remainder of the bits are all unset
|
||||
if segment << prefix_bits != 0 {
|
||||
return Err(IpNetworkError::InvalidPrefix);
|
||||
return None;
|
||||
}
|
||||
prefix += prefix_bits;
|
||||
break;
|
||||
@ -414,13 +436,15 @@ pub fn ipv6_mask_to_prefix(mask: Ipv6Addr) -> Result<u8, IpNetworkError> {
|
||||
}
|
||||
|
||||
// Now check all the remaining bits are unset
|
||||
for &segment in mask_iter {
|
||||
while i < mask.len() {
|
||||
let segment = mask[i];
|
||||
i += 1;
|
||||
if segment != 0 {
|
||||
return Err(IpNetworkError::InvalidPrefix);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(prefix)
|
||||
Some(prefix)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -597,6 +621,18 @@ mod test {
|
||||
assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 2), iter.next().unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iterator_v6_size_hint() {
|
||||
let cidr: Ipv6Network = "2001:db8::/128".parse().unwrap();
|
||||
let mut iter = cidr.iter();
|
||||
assert_eq!((1, Some(1)), iter.size_hint());
|
||||
assert_eq!(
|
||||
Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0),
|
||||
iter.next().unwrap()
|
||||
);
|
||||
assert_eq!((0, None), iter.size_hint());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn network_v6() {
|
||||
let cidr: Ipv6Network = "2001:db8::0/96".parse().unwrap();
|
||||
|
62
src/lib.rs
62
src/lib.rs
@ -8,7 +8,12 @@
|
||||
unused_import_braces
|
||||
)]
|
||||
|
||||
use std::{convert::TryFrom, fmt, net::IpAddr, str::FromStr};
|
||||
use std::{
|
||||
convert::TryFrom,
|
||||
fmt,
|
||||
net::{IpAddr, Ipv4Addr, Ipv6Addr},
|
||||
str::FromStr,
|
||||
};
|
||||
|
||||
mod error;
|
||||
mod ipv4;
|
||||
@ -16,11 +21,11 @@ mod ipv6;
|
||||
mod parse;
|
||||
mod size;
|
||||
|
||||
pub use crate::error::{NetworkSizeError, IpNetworkError};
|
||||
pub use crate::error::{IpNetworkError, NetworkSizeError};
|
||||
pub use crate::ipv4::Ipv4NetworkIterator;
|
||||
pub use crate::ipv4::{ipv4_mask_to_prefix, Ipv4Network};
|
||||
pub use crate::ipv4::{ipv4_mask_to_prefix, ipv4_mask_to_prefix_checked, Ipv4Network};
|
||||
pub use crate::ipv6::Ipv6NetworkIterator;
|
||||
pub use crate::ipv6::{ipv6_mask_to_prefix, Ipv6Network};
|
||||
pub use crate::ipv6::{ipv6_mask_to_prefix, ipv6_mask_to_prefix_checked, Ipv6Network};
|
||||
pub use crate::size::NetworkSize;
|
||||
|
||||
/// Represents a generic network range. This type can have two variants:
|
||||
@ -141,7 +146,7 @@ impl IpNetwork {
|
||||
}
|
||||
|
||||
/// Returns the IP part of a given `IpNetwork`
|
||||
pub fn ip(&self) -> IpAddr {
|
||||
pub const fn ip(&self) -> IpAddr {
|
||||
match *self {
|
||||
IpNetwork::V4(ref a) => IpAddr::V4(a.ip()),
|
||||
IpNetwork::V6(ref a) => IpAddr::V6(a.ip()),
|
||||
@ -160,7 +165,7 @@ impl IpNetwork {
|
||||
/// assert_eq!(IpNetwork::V6("ff01::0".parse().unwrap()).prefix(), 128u8);
|
||||
/// assert_eq!(IpNetwork::V6("ff01::0/32".parse().unwrap()).prefix(), 32u8);
|
||||
/// ```
|
||||
pub fn prefix(&self) -> u8 {
|
||||
pub const fn prefix(&self) -> u8 {
|
||||
match *self {
|
||||
IpNetwork::V4(ref a) => a.prefix(),
|
||||
IpNetwork::V6(ref a) => a.prefix(),
|
||||
@ -181,7 +186,7 @@ impl IpNetwork {
|
||||
/// let net: IpNetwork = "2001:db8::/96".parse().unwrap();
|
||||
/// assert_eq!(net.network(), Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0));
|
||||
/// ```
|
||||
pub fn network(&self) -> IpAddr {
|
||||
pub const fn network(&self) -> IpAddr {
|
||||
match *self {
|
||||
IpNetwork::V4(ref a) => IpAddr::V4(a.network()),
|
||||
IpNetwork::V6(ref a) => IpAddr::V6(a.network()),
|
||||
@ -200,7 +205,7 @@ impl IpNetwork {
|
||||
/// let net: Ipv4Network = "10.9.0.32/16".parse().unwrap();
|
||||
/// assert_eq!(net.broadcast(), Ipv4Addr::new(10, 9, 255, 255));
|
||||
/// ```
|
||||
pub fn broadcast(&self) -> IpAddr {
|
||||
pub const fn broadcast(&self) -> IpAddr {
|
||||
match *self {
|
||||
IpNetwork::V4(ref a) => IpAddr::V4(a.broadcast()),
|
||||
IpNetwork::V6(ref a) => IpAddr::V6(a.broadcast()),
|
||||
@ -226,7 +231,7 @@ impl IpNetwork {
|
||||
/// let v6_net: IpNetwork = "ff01::0/32".parse().unwrap();
|
||||
/// assert_eq!(v6_net.mask(), Ipv6Addr::new(0xffff, 0xffff, 0, 0, 0, 0, 0, 0));
|
||||
/// ```
|
||||
pub fn mask(&self) -> IpAddr {
|
||||
pub const fn mask(&self) -> IpAddr {
|
||||
match *self {
|
||||
IpNetwork::V4(ref a) => IpAddr::V4(a.mask()),
|
||||
IpNetwork::V6(ref a) => IpAddr::V6(a.mask()),
|
||||
@ -245,7 +250,7 @@ impl IpNetwork {
|
||||
/// assert_eq!(v4.is_ipv4(), true);
|
||||
/// assert_eq!(v4.is_ipv6(), false);
|
||||
///```
|
||||
pub fn is_ipv4(&self) -> bool {
|
||||
pub const fn is_ipv4(&self) -> bool {
|
||||
match *self {
|
||||
IpNetwork::V4(_) => true,
|
||||
IpNetwork::V6(_) => false,
|
||||
@ -264,7 +269,7 @@ impl IpNetwork {
|
||||
/// assert_eq!(v6.is_ipv6(), true);
|
||||
/// assert_eq!(v6.is_ipv4(), false);
|
||||
///```
|
||||
pub fn is_ipv6(&self) -> bool {
|
||||
pub const fn is_ipv6(&self) -> bool {
|
||||
match *self {
|
||||
IpNetwork::V4(_) => false,
|
||||
IpNetwork::V6(_) => true,
|
||||
@ -292,7 +297,7 @@ impl IpNetwork {
|
||||
/// assert!(!net.contains(ip4));
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn contains(&self, ip: IpAddr) -> bool {
|
||||
pub const fn contains(&self, ip: IpAddr) -> bool {
|
||||
match (*self, ip) {
|
||||
(IpNetwork::V4(net), IpAddr::V4(ip)) => net.contains(ip),
|
||||
(IpNetwork::V6(net), IpAddr::V6(ip)) => net.contains(ip),
|
||||
@ -377,11 +382,23 @@ impl From<Ipv6Network> for IpNetwork {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Ipv4Addr> for IpNetwork {
|
||||
fn from(addr: Ipv4Addr) -> IpNetwork {
|
||||
IpNetwork::V4(Ipv4Network::from(addr))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Ipv6Addr> for IpNetwork {
|
||||
fn from(addr: Ipv6Addr) -> IpNetwork {
|
||||
IpNetwork::V6(Ipv6Network::from(addr))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<IpAddr> for IpNetwork {
|
||||
fn from(addr: IpAddr) -> IpNetwork {
|
||||
match addr {
|
||||
IpAddr::V4(a) => IpNetwork::V4(Ipv4Network::from(a)),
|
||||
IpAddr::V6(a) => IpNetwork::V6(Ipv6Network::from(a)),
|
||||
IpAddr::V4(a) => IpNetwork::from(a),
|
||||
IpAddr::V6(a) => IpNetwork::from(a),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -414,6 +431,12 @@ impl Iterator for IpNetworkIterator {
|
||||
IpNetworkIteratorInner::V6(iter) => iter.next().map(IpAddr::V6),
|
||||
}
|
||||
}
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
match &self.inner {
|
||||
IpNetworkIteratorInner::V4(iter) => iter.size_hint(),
|
||||
IpNetworkIteratorInner::V6(iter) => iter.size_hint(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoIterator for &'_ IpNetwork {
|
||||
@ -433,6 +456,17 @@ pub fn ip_mask_to_prefix(mask: IpAddr) -> Result<u8, IpNetworkError> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a `IpAddr` network mask into a prefix.
|
||||
///
|
||||
/// If the mask is invalid this will return `None`. This is useful in const contexts where
|
||||
/// [`Option::unwrap`] may be called to trigger a compile-time error if the prefix is invalid.
|
||||
pub const fn ip_mask_to_prefix_checked(mask: IpAddr) -> Option<u8> {
|
||||
match mask {
|
||||
IpAddr::V4(mask) => ipv4_mask_to_prefix_checked(mask),
|
||||
IpAddr::V6(mask) => ipv6_mask_to_prefix_checked(mask),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
#[test]
|
||||
|
Reference in New Issue
Block a user