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