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 | |