1#[cfg(feature = "bitstring")]
2#[cfg_attr(doc_cfg, doc(cfg(feature = "bitstring")))]
3use bitstring::FixedBitString;
4
5use core::{
6 fmt,
7 str::FromStr,
8};
9use std::net::{
10 Ipv4Addr,
11 Ipv6Addr,
12};
13
14use super::from_str::cidr_from_str;
15use crate::{
16 errors::*,
17 internal_traits::{
18 PrivCidr,
19 PrivUnspecAddress,
20 },
21 Cidr,
22 Family,
23 InetIterator,
24 Ipv4Cidr,
25 Ipv4Inet,
26 Ipv4InetPair,
27 Ipv6Cidr,
28 Ipv6Inet,
29 Ipv6InetPair,
30};
31
32macro_rules! impl_cidr_for {
33 ($n:ident : inet $inet:ident : addr $addr:ident : pair $pair:ident : family $family:expr) => {
34 #[cfg(feature = "bitstring")]
35 #[cfg_attr(doc_cfg, doc(cfg(feature = "bitstring")))]
36 impl bitstring::BitString for $n {
37 fn get(&self, ndx: usize) -> bool {
38 self.address.get(ndx)
39 }
40
41 fn set(&mut self, ndx: usize, bit: bool) {
42 assert!(ndx < self.network_length as usize);
43 self.address.set(ndx, bit);
44 }
45
46 fn flip(&mut self, ndx: usize) {
47 assert!(ndx < self.network_length as usize);
48 self.address.flip(ndx);
49 }
50
51 fn len(&self) -> usize {
52 self.network_length as usize
53 }
54
55 fn clip(&mut self, len: usize) {
56 if len > 255 {
57 return;
58 }
59 self.address.set_false_from(len);
60 self.network_length = core::cmp::min(self.network_length, len as u8);
61 }
62
63 fn append(&mut self, bit: bool) {
64 self.address.set(self.network_length as usize, bit);
65 self.network_length += 1;
66 }
67
68 fn null() -> Self {
69 Self {
70 address: FixedBitString::new_all_false(),
71 network_length: 0,
72 }
73 }
74
75 fn shared_prefix_len(&self, other: &Self) -> usize {
76 let max_len = core::cmp::min(self.network_length, other.network_length) as usize;
77 FixedBitString::shared_prefix_len(&self.address, &other.address, max_len)
78 }
79 }
80
81 impl $n {
82 pub const fn new(addr: $addr, len: u8) -> Result<Self, NetworkParseError> {
87 if len > $family.len() {
88 Err(NetworkParseError::NetworkLengthTooLongError(
89 NetworkLengthTooLongError::new(len as usize, $family),
90 ))
91 } else if !<$addr as PrivUnspecAddress>::_Tools::_has_zero_host_part(addr, len) {
92 Err(NetworkParseError::InvalidHostPart)
93 } else {
94 Ok(Self {
95 address: addr,
96 network_length: len,
97 })
98 }
99 }
100
101 pub const fn new_host(addr: $addr) -> Self {
104 Self {
105 address: addr,
106 network_length: $family.len(),
107 }
108 }
109
110 pub const fn iter(&self) -> InetIterator<$addr> {
114 self._range_pair().iter()
115 }
116
117 pub const fn first_address(&self) -> $addr {
119 self.address
120 }
121
122 pub const fn first(&self) -> $inet {
124 $inet {
125 address: self.first_address(),
126 network_length: self.network_length,
127 }
128 }
129
130 pub const fn last_address(&self) -> $addr {
132 <$addr as PrivUnspecAddress>::_Tools::_last_address(
133 self.address,
134 self.network_length,
135 )
136 }
137
138 pub const fn last(&self) -> $inet {
140 $inet {
141 address: self.last_address(),
142 network_length: self.network_length,
143 }
144 }
145
146 pub const fn network_length(&self) -> u8 {
148 self.network_length
149 }
150
151 pub const fn family(&self) -> Family {
156 $family
157 }
158
159 pub const fn is_host_address(&self) -> bool {
161 self.network_length() == self.family().len()
162 }
163
164 pub const fn mask(&self) -> $addr {
167 <$addr as PrivUnspecAddress>::_Tools::_network_mask(self.network_length)
168 }
169
170 pub const fn contains(&self, addr: &$addr) -> bool {
172 <$addr as PrivUnspecAddress>::_Tools::_prefix_match(
173 self.address,
174 *addr,
175 self.network_length,
176 )
177 }
178
179 pub(crate) const fn _range_pair(&self) -> $pair {
180 $pair {
181 first: self.first_address(),
182 second: self.last_address(),
183 network_length: self.network_length,
184 }
185 }
186 }
187
188 impl PrivCidr for $n {}
189
190 impl Cidr for $n {
191 type Address = $addr;
192
193 fn new(addr: $addr, len: u8) -> Result<Self, NetworkParseError> {
194 Self::new(addr, len)
195 }
196
197 fn new_host(addr: $addr) -> Self {
198 Self::new_host(addr)
199 }
200
201 fn iter(&self) -> InetIterator<$addr> {
202 self.iter()
203 }
204
205 fn first_address(&self) -> $addr {
206 self.first_address()
207 }
208
209 fn first(&self) -> $inet {
210 self.first()
211 }
212
213 fn last_address(&self) -> $addr {
214 self.last_address()
215 }
216
217 fn last(&self) -> $inet {
218 self.last()
219 }
220
221 fn network_length(&self) -> u8 {
222 self.network_length()
223 }
224
225 fn family(&self) -> Family {
226 self.family()
227 }
228
229 fn is_host_address(&self) -> bool {
230 self.is_host_address()
231 }
232
233 fn mask(&self) -> $addr {
234 self.mask()
235 }
236
237 fn contains(&self, addr: &$addr) -> bool {
238 self.contains(addr)
239 }
240 }
241
242 impl fmt::Debug for $n {
243 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
244 write!(f, "{:?}/{}", self.address, self.network_length)
245 }
246 }
247
248 impl fmt::Display for $n {
249 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
250 if f.alternate() || !self.is_host_address() {
251 write!(f, "{}/{}", self.address, self.network_length)?;
252 } else {
253 write!(f, "{}", self.address)?;
254 }
255 Ok(())
256 }
257 }
258
259 impl PartialOrd<$n> for $n {
260 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
261 Some(self.cmp(other))
262 }
263 }
264
265 impl Ord for $n {
266 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
267 self.address
268 .cmp(&other.address)
269 .then(self.network_length.cmp(&other.network_length))
270 }
271 }
272
273 impl FromStr for $n {
274 type Err = NetworkParseError;
275
276 fn from_str(s: &str) -> Result<$n, NetworkParseError> {
277 cidr_from_str(s)
278 }
279 }
280
281 impl IntoIterator for $n {
283 type IntoIter = $crate::InetIterator<$addr>;
284 type Item = $inet;
285
286 fn into_iter(self) -> Self::IntoIter {
287 self._range_pair().iter()
288 }
289 }
290 };
291}
292
293impl_cidr_for! {Ipv4Cidr : inet Ipv4Inet : addr Ipv4Addr : pair Ipv4InetPair : family Family::Ipv4}
294impl_cidr_for! {Ipv6Cidr : inet Ipv6Inet : addr Ipv6Addr : pair Ipv6InetPair : family Family::Ipv6}
295
296#[cfg(test)]
297mod tests {
298 use std::net::Ipv4Addr;
299
300 use crate::Ipv4Cidr;
301
302 #[test]
303 fn v4_ref_into_iter() {
304 let cidr = Ipv4Cidr::new(Ipv4Addr::new(1, 2, 3, 0), 30).unwrap();
305 assert_eq!(
306 vec![
307 Ipv4Addr::new(1, 2, 3, 0),
308 Ipv4Addr::new(1, 2, 3, 1),
309 Ipv4Addr::new(1, 2, 3, 2),
310 Ipv4Addr::new(1, 2, 3, 3),
311 ],
312 cidr.into_iter().addresses().collect::<Vec<_>>()
313 );
314 }
315
316 #[test]
317 fn v4_owned_into_iter() {
318 let cidr = Ipv4Cidr::new(Ipv4Addr::new(1, 2, 3, 0), 30).unwrap();
319 assert_eq!(
320 vec![
321 Ipv4Addr::new(1, 2, 3, 0),
322 Ipv4Addr::new(1, 2, 3, 1),
323 Ipv4Addr::new(1, 2, 3, 2),
324 Ipv4Addr::new(1, 2, 3, 3),
325 ],
326 cidr.into_iter().addresses().collect::<Vec<_>>()
327 );
328 }
329}