summaryrefslogtreecommitdiffstats
path: root/vendor/ipnet/src/mask.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/ipnet/src/mask.rs')
-rw-r--r--vendor/ipnet/src/mask.rs128
1 files changed, 128 insertions, 0 deletions
diff --git a/vendor/ipnet/src/mask.rs b/vendor/ipnet/src/mask.rs
new file mode 100644
index 000000000..1047bf980
--- /dev/null
+++ b/vendor/ipnet/src/mask.rs
@@ -0,0 +1,128 @@
+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.checked_shl(prefix).unwrap_or(0) == 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.checked_shl(prefix).unwrap_or(0) == 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 v4_mask_to_prefix_max() {
+ let mask = Ipv4Addr::from(u32::MAX);
+ let prefix = ipv4_mask_to_prefix(mask);
+ assert_eq!(prefix, Ok(32));
+ }
+
+ #[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 v6_mask_to_prefix_max() {
+ let mask = Ipv6Addr::from(u128::MAX);
+ let prefix = ipv6_mask_to_prefix(mask);
+ assert_eq!(prefix, Ok(128));
+ }
+
+ #[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();
+ }
+ }
+}