| 1 | use crate::PrefixLenError; |
| 2 | #[cfg (not(feature = "std" ))] |
| 3 | use core::net::{IpAddr, Ipv4Addr, Ipv6Addr}; |
| 4 | #[cfg (feature = "std" )] |
| 5 | use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; |
| 6 | |
| 7 | /// Converts a `IpAddr` network mask into a prefix. |
| 8 | /// |
| 9 | /// # Errors |
| 10 | /// If the mask is invalid this will return an `PrefixLenError`. |
| 11 | pub fn ip_mask_to_prefix(mask: IpAddr) -> Result<u8, PrefixLenError> { |
| 12 | match mask { |
| 13 | IpAddr::V4(mask: Ipv4Addr) => ipv4_mask_to_prefix(mask), |
| 14 | IpAddr::V6(mask: Ipv6Addr) => ipv6_mask_to_prefix(mask), |
| 15 | } |
| 16 | } |
| 17 | |
| 18 | /// Converts a `Ipv4Addr` network mask into a prefix. |
| 19 | /// |
| 20 | /// # Errors |
| 21 | /// If the mask is invalid this will return an `PrefixLenError`. |
| 22 | pub fn ipv4_mask_to_prefix(mask: Ipv4Addr) -> Result<u8, PrefixLenError> { |
| 23 | let mask: u32 = u32::from(mask); |
| 24 | |
| 25 | let prefix: u32 = mask.leading_ones(); |
| 26 | if mask.checked_shl(prefix).unwrap_or(default:0) == 0 { |
| 27 | Ok(prefix as u8) |
| 28 | } else { |
| 29 | Err(PrefixLenError) |
| 30 | } |
| 31 | } |
| 32 | |
| 33 | /// Converts a `Ipv6Addr` network mask into a prefix. |
| 34 | /// |
| 35 | /// # Errors |
| 36 | /// If the mask is invalid this will return an `PrefixLenError`. |
| 37 | pub fn ipv6_mask_to_prefix(mask: Ipv6Addr) -> Result<u8, PrefixLenError> { |
| 38 | let mask: u128 = u128::from(mask); |
| 39 | |
| 40 | let prefix: u32 = mask.leading_ones(); |
| 41 | if mask.checked_shl(prefix).unwrap_or(default:0) == 0 { |
| 42 | Ok(prefix as u8) |
| 43 | } else { |
| 44 | Err(PrefixLenError) |
| 45 | } |
| 46 | } |
| 47 | |
| 48 | #[cfg (test)] |
| 49 | mod tests { |
| 50 | use super::*; |
| 51 | use crate::{Ipv4Net, Ipv6Net}; |
| 52 | |
| 53 | #[test ] |
| 54 | fn v4_mask_to_prefix() { |
| 55 | let mask = Ipv4Addr::new(255, 255, 255, 128); |
| 56 | let prefix = ipv4_mask_to_prefix(mask); |
| 57 | assert_eq!(prefix, Ok(25)); |
| 58 | } |
| 59 | |
| 60 | #[test ] |
| 61 | fn v4_mask_to_prefix_max() { |
| 62 | let mask = Ipv4Addr::from(u32::MAX); |
| 63 | let prefix = ipv4_mask_to_prefix(mask); |
| 64 | assert_eq!(prefix, Ok(32)); |
| 65 | } |
| 66 | |
| 67 | #[test ] |
| 68 | fn invalid_v4_mask_to_prefix() { |
| 69 | let mask = Ipv4Addr::new(255, 0, 255, 0); |
| 70 | let prefix = ipv4_mask_to_prefix(mask); |
| 71 | assert!(prefix.is_err()); |
| 72 | } |
| 73 | |
| 74 | #[test ] |
| 75 | fn ipv4net_with_netmask() { |
| 76 | { |
| 77 | // Positive test-case. |
| 78 | let addr = Ipv4Addr::new(127, 0, 0, 1); |
| 79 | let mask = Ipv4Addr::new(255, 0, 0, 0); |
| 80 | let net = Ipv4Net::with_netmask(addr, mask).unwrap(); |
| 81 | let expected = Ipv4Net::new(Ipv4Addr::new(127, 0, 0, 1), 8).unwrap(); |
| 82 | assert_eq!(net, expected); |
| 83 | } |
| 84 | { |
| 85 | // Negative test-case. |
| 86 | let addr = Ipv4Addr::new(127, 0, 0, 1); |
| 87 | let mask = Ipv4Addr::new(255, 0, 255, 0); |
| 88 | Ipv4Net::with_netmask(addr, mask).unwrap_err(); |
| 89 | } |
| 90 | } |
| 91 | |
| 92 | #[test ] |
| 93 | fn v6_mask_to_prefix() { |
| 94 | let mask = Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0, 0, 0, 0, 0); |
| 95 | let prefix = ipv6_mask_to_prefix(mask); |
| 96 | assert_eq!(prefix, Ok(48)); |
| 97 | } |
| 98 | |
| 99 | #[test ] |
| 100 | fn v6_mask_to_prefix_max() { |
| 101 | let mask = Ipv6Addr::from(u128::MAX); |
| 102 | let prefix = ipv6_mask_to_prefix(mask); |
| 103 | assert_eq!(prefix, Ok(128)); |
| 104 | } |
| 105 | |
| 106 | #[test ] |
| 107 | fn invalid_v6_mask_to_prefix() { |
| 108 | let mask = Ipv6Addr::new(0, 0, 0xffff, 0xffff, 0, 0, 0, 0); |
| 109 | let prefix = ipv6_mask_to_prefix(mask); |
| 110 | assert!(prefix.is_err()); |
| 111 | } |
| 112 | |
| 113 | #[test ] |
| 114 | fn ipv6net_with_netmask() { |
| 115 | { |
| 116 | // Positive test-case. |
| 117 | let addr = Ipv6Addr::new(0xff01, 0, 0, 0x17, 0, 0, 0, 0x2); |
| 118 | let mask = Ipv6Addr::new(0xffff, 0xffff, 0xffff, 0, 0, 0, 0, 0); |
| 119 | let net = Ipv6Net::with_netmask(addr, mask).unwrap(); |
| 120 | let expected = |
| 121 | Ipv6Net::new(Ipv6Addr::new(0xff01, 0, 0, 0x17, 0, 0, 0, 0x2), 48).unwrap(); |
| 122 | assert_eq!(net, expected); |
| 123 | } |
| 124 | { |
| 125 | // Negative test-case. |
| 126 | let addr = Ipv6Addr::new(0xff01, 0, 0, 0x17, 0, 0, 0, 0x2); |
| 127 | let mask = Ipv6Addr::new(0, 0, 0xffff, 0xffff, 0, 0, 0, 0); |
| 128 | Ipv6Net::with_netmask(addr, mask).unwrap_err(); |
| 129 | } |
| 130 | } |
| 131 | } |
| 132 | |