1use crate::PrefixLenError;
2#[cfg(not(feature = "std"))]
3use core::net::{IpAddr, Ipv4Addr, Ipv6Addr};
4#[cfg(feature = "std")]
5use 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`.
11pub 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`.
22pub 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`.
37pub 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)]
49mod 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