mirror of
https://github.com/openharmony/third_party_rust_ipnet.git
synced 2026-07-01 20:24:06 -04:00
Add mask to prefix conversion
This commit is contained in:
@@ -8,6 +8,7 @@ use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
|
||||
use std::option::Option::{Some, None};
|
||||
|
||||
use crate::ipext::{IpAdd, IpSub, IpStep, IpAddrRange, Ipv4AddrRange, Ipv6AddrRange};
|
||||
use crate::mask::{ip_mask_to_prefix, ipv4_mask_to_prefix, ipv6_mask_to_prefix};
|
||||
|
||||
/// An IP network address, either IPv4 or IPv6.
|
||||
///
|
||||
@@ -142,6 +143,25 @@ impl IpNet {
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a new IP network address from an `IpAddr` and netmask.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::net::Ipv6Addr;
|
||||
/// use ipnet::{IpNet, PrefixLenError};
|
||||
///
|
||||
/// let net = IpNet::with_netmask(Ipv6Addr::LOCALHOST.into(), Ipv6Addr::from(0xffff_ffff_ffff_0000_0000_0000_0000_0000).into());
|
||||
/// assert!(net.is_ok());
|
||||
///
|
||||
/// let bad_prefix_len = IpNet::with_netmask(Ipv6Addr::LOCALHOST.into(), Ipv6Addr::from(0xffff_ffff_ffff_0000_0001_0000_0000_0000).into());
|
||||
/// assert_eq!(bad_prefix_len, Err(PrefixLenError));
|
||||
/// ```
|
||||
pub fn with_netmask(ip: IpAddr, netmask: IpAddr) -> Result<IpNet, PrefixLenError> {
|
||||
let prefix = ip_mask_to_prefix(netmask)?;
|
||||
Self::new(ip, prefix)
|
||||
}
|
||||
|
||||
/// Returns a copy of the network with the address truncated to the
|
||||
/// prefix length.
|
||||
///
|
||||
@@ -565,6 +585,25 @@ impl Ipv4Net {
|
||||
Ok(Ipv4Net { addr: ip, prefix_len: prefix_len })
|
||||
}
|
||||
|
||||
/// Creates a new IPv4 network address from an `Ipv4Addr` and netmask.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::net::Ipv4Addr;
|
||||
/// use ipnet::{Ipv4Net, PrefixLenError};
|
||||
///
|
||||
/// let net = Ipv4Net::with_netmask(Ipv4Addr::new(10, 1, 1, 0), Ipv4Addr::new(255, 255, 255, 0));
|
||||
/// assert!(net.is_ok());
|
||||
///
|
||||
/// let bad_prefix_len = Ipv4Net::with_netmask(Ipv4Addr::new(10, 1, 1, 0), Ipv4Addr::new(255, 255, 0, 1));
|
||||
/// assert_eq!(bad_prefix_len, Err(PrefixLenError));
|
||||
/// ```
|
||||
pub fn with_netmask(ip: Ipv4Addr, netmask: Ipv4Addr) -> Result<Ipv4Net, PrefixLenError> {
|
||||
let prefix = ipv4_mask_to_prefix(netmask)?;
|
||||
Self::new(ip, prefix)
|
||||
}
|
||||
|
||||
/// Returns a copy of the network with the address truncated to the
|
||||
/// prefix length.
|
||||
///
|
||||
@@ -899,6 +938,25 @@ impl Ipv6Net {
|
||||
Ok(Ipv6Net { addr: ip, prefix_len: prefix_len })
|
||||
}
|
||||
|
||||
/// Creates a new IPv6 network address from an `Ipv6Addr` and netmask.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::net::Ipv6Addr;
|
||||
/// use ipnet::{Ipv6Net, PrefixLenError};
|
||||
///
|
||||
/// let net = Ipv6Net::with_netmask(Ipv6Addr::new(0xfd, 0, 0, 0, 0, 0, 0, 0), Ipv6Addr::from(0xffff_ff00_0000_0000_0000_0000_0000_0000));
|
||||
/// assert!(net.is_ok());
|
||||
///
|
||||
/// let bad_prefix_len = Ipv6Net::with_netmask(Ipv6Addr::new(0xfd, 0, 0, 0, 0, 0, 0, 0), Ipv6Addr::from(0xffff_ff00_0000_0000_0001_0000_0000_0000));
|
||||
/// assert_eq!(bad_prefix_len, Err(PrefixLenError));
|
||||
/// ```
|
||||
pub fn with_netmask(ip: Ipv6Addr, netmask: Ipv6Addr) -> Result<Ipv6Net, PrefixLenError> {
|
||||
let prefix = ipv6_mask_to_prefix(netmask)?;
|
||||
Self::new(ip, prefix)
|
||||
}
|
||||
|
||||
/// Returns a copy of the network with the address truncated to the
|
||||
/// prefix length.
|
||||
///
|
||||
|
||||
@@ -86,10 +86,12 @@ extern crate schemars;
|
||||
pub use self::ipext::{IpAdd, IpSub, IpBitAnd, IpBitOr, IpAddrRange, Ipv4AddrRange, Ipv6AddrRange};
|
||||
pub use self::ipnet::{IpNet, Ipv4Net, Ipv6Net, PrefixLenError, IpSubnets, Ipv4Subnets, Ipv6Subnets};
|
||||
pub use self::parser::AddrParseError;
|
||||
pub use self::mask::{ip_mask_to_prefix, ipv4_mask_to_prefix, ipv6_mask_to_prefix};
|
||||
|
||||
mod ipext;
|
||||
mod ipnet;
|
||||
mod parser;
|
||||
mod mask;
|
||||
#[cfg(feature = "serde")]
|
||||
mod ipnet_serde;
|
||||
#[cfg(feature = "schemars")]
|
||||
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
use crate::PrefixLenError;
|
||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
|
||||
|
||||
/// Converts a `IpAddr` network mask into a prefix.
|
||||
///
|
||||
/// # Errors
|
||||
/// If the mask is invalid this will return an `PrefixLenError`.
|
||||
pub fn ip_mask_to_prefix(mask: IpAddr) -> Result<u8, PrefixLenError> {
|
||||
match mask {
|
||||
IpAddr::V4(mask) => ipv4_mask_to_prefix(mask),
|
||||
IpAddr::V6(mask) => ipv6_mask_to_prefix(mask),
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a `Ipv4Addr` network mask into a prefix.
|
||||
///
|
||||
/// # Errors
|
||||
/// If the mask is invalid this will return an `PrefixLenError`.
|
||||
pub fn ipv4_mask_to_prefix(mask: Ipv4Addr) -> Result<u8, PrefixLenError> {
|
||||
let mask = u32::from(mask);
|
||||
|
||||
let prefix = mask.leading_ones();
|
||||
if (mask << prefix) == 0 {
|
||||
Ok(prefix as u8)
|
||||
} else {
|
||||
Err(PrefixLenError)
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a `Ipv6Addr` network mask into a prefix.
|
||||
///
|
||||
/// # Errors
|
||||
/// If the mask is invalid this will return an `PrefixLenError`.
|
||||
pub fn ipv6_mask_to_prefix(mask: Ipv6Addr) -> Result<u8, PrefixLenError> {
|
||||
let mask = u128::from(mask);
|
||||
|
||||
let prefix = mask.leading_ones();
|
||||
if (mask << prefix) == 0 {
|
||||
Ok(prefix as u8)
|
||||
} else {
|
||||
Err(PrefixLenError)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{Ipv4Net, Ipv6Net};
|
||||
|
||||
#[test]
|
||||
fn v4_mask_to_prefix() {
|
||||
let mask = Ipv4Addr::new(255, 255, 255, 128);
|
||||
let prefix = ipv4_mask_to_prefix(mask);
|
||||
assert_eq!(prefix, Ok(25));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_v4_mask_to_prefix() {
|
||||
let mask = Ipv4Addr::new(255, 0, 255, 0);
|
||||
let prefix = ipv4_mask_to_prefix(mask);
|
||||
assert!(prefix.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ipv4net_with_netmask() {
|
||||
{
|
||||
// Positive test-case.
|
||||
let addr = Ipv4Addr::new(127, 0, 0, 1);
|
||||
let mask = Ipv4Addr::new(255, 0, 0, 0);
|
||||
let net = Ipv4Net::with_netmask(addr, mask).unwrap();
|
||||
let expected = Ipv4Net::new(Ipv4Addr::new(127, 0, 0, 1), 8).unwrap();
|
||||
assert_eq!(net, expected);
|
||||
}
|
||||
{
|
||||
// Negative test-case.
|
||||
let addr = Ipv4Addr::new(127, 0, 0, 1);
|
||||
let mask = Ipv4Addr::new(255, 0, 255, 0);
|
||||
Ipv4Net::with_netmask(addr, mask).unwrap_err();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn v6_mask_to_prefix() {
|
||||
let mask = Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0, 0, 0, 0, 0);
|
||||
let prefix = ipv6_mask_to_prefix(mask);
|
||||
assert_eq!(prefix, Ok(48));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_v6_mask_to_prefix() {
|
||||
let mask = Ipv6Addr::new(0, 0, 0xffff, 0xffff, 0, 0, 0, 0);
|
||||
let prefix = ipv6_mask_to_prefix(mask);
|
||||
assert!(prefix.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ipv6net_with_netmask() {
|
||||
{
|
||||
// Positive test-case.
|
||||
let addr = Ipv6Addr::new(0xff01, 0, 0, 0x17, 0, 0, 0, 0x2);
|
||||
let mask = Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0, 0, 0, 0, 0);
|
||||
let net = Ipv6Net::with_netmask(addr, mask).unwrap();
|
||||
let expected =
|
||||
Ipv6Net::new(Ipv6Addr::new(0xff01, 0, 0, 0x17, 0, 0, 0, 0x2), 48).unwrap();
|
||||
assert_eq!(net, expected);
|
||||
}
|
||||
{
|
||||
// Negative test-case.
|
||||
let addr = Ipv6Addr::new(0xff01, 0, 0, 0x17, 0, 0, 0, 0x2);
|
||||
let mask = Ipv6Addr::new(0, 0, 0xffff, 0xffff, 0, 0, 0, 0);
|
||||
Ipv6Net::with_netmask(addr, mask).unwrap_err();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user