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`.
ip_mask_to_prefix(mask: IpAddr) -> Result<u8, PrefixLenError>11 pub fn ip_mask_to_prefix(mask: IpAddr) -> Result<u8, PrefixLenError> {
12 match mask {
13 IpAddr::V4(mask) => ipv4_mask_to_prefix(mask),
14 IpAddr::V6(mask) => 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`.
ipv4_mask_to_prefix(mask: Ipv4Addr) -> Result<u8, PrefixLenError>22 pub fn ipv4_mask_to_prefix(mask: Ipv4Addr) -> Result<u8, PrefixLenError> {
23 let mask = u32::from(mask);
24
25 let prefix = mask.leading_ones();
26 if mask.checked_shl(prefix).unwrap_or(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`.
ipv6_mask_to_prefix(mask: Ipv6Addr) -> Result<u8, PrefixLenError>37 pub fn ipv6_mask_to_prefix(mask: Ipv6Addr) -> Result<u8, PrefixLenError> {
38 let mask = u128::from(mask);
39
40 let prefix = mask.leading_ones();
41 if mask.checked_shl(prefix).unwrap_or(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]
v4_mask_to_prefix()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]
v4_mask_to_prefix_max()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]
invalid_v4_mask_to_prefix()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]
ipv4net_with_netmask()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]
v6_mask_to_prefix()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]
v6_mask_to_prefix_max()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]
invalid_v6_mask_to_prefix()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]
ipv6net_with_netmask()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