1use core::{
2 fmt,
3 net::{
4 IpAddr,
5 Ipv4Addr,
6 Ipv6Addr,
7 },
8 str::FromStr,
9};
10
11use crate::{
12 errors::*,
13 Family,
14 IpCidr,
15 IpInet,
16 Ipv4Cidr,
17 Ipv6Cidr,
18};
19
20#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
34pub enum AnyIpCidr {
35 Any,
37 V4(Ipv4Cidr),
39 V6(Ipv6Cidr),
41}
42
43impl AnyIpCidr {
44 pub const fn is_any(&self) -> bool {
46 match self {
47 Self::Any => true,
48 _ => false,
49 }
50 }
51
52 pub const fn is_ipv4(&self) -> bool {
54 match self {
55 Self::V4(_) => true,
56 _ => false,
57 }
58 }
59
60 pub const fn is_ipv6(&self) -> bool {
62 match self {
63 Self::V4(_) => false,
64 _ => true,
65 }
66 }
67}
68
69impl AnyIpCidr {
71 pub const fn new(addr: IpAddr, len: u8) -> Result<Self, NetworkParseError> {
76 match addr {
77 IpAddr::V4(a) => match Ipv4Cidr::new(a, len) {
78 Ok(cidr) => Ok(Self::V4(cidr)),
79 Err(e) => Err(e),
80 },
81 IpAddr::V6(a) => match Ipv6Cidr::new(a, len) {
82 Ok(cidr) => Ok(Self::V6(cidr)),
83 Err(e) => Err(e),
84 },
85 }
86 }
87
88 pub const fn new_host(addr: IpAddr) -> Self {
91 match addr {
92 IpAddr::V4(a) => Self::V4(Ipv4Cidr::new_host(a)),
93 IpAddr::V6(a) => Self::V6(Ipv6Cidr::new_host(a)),
94 }
95 }
96
97 pub const fn first_address(&self) -> Option<IpAddr> {
103 match self {
104 Self::Any => None,
105 Self::V4(c) => Some(IpAddr::V4(c.first_address())),
106 Self::V6(c) => Some(IpAddr::V6(c.first_address())),
107 }
108 }
109
110 pub const fn first(&self) -> Option<IpInet> {
116 match self {
117 Self::Any => None,
118 Self::V4(c) => Some(IpInet::V4(c.first())),
119 Self::V6(c) => Some(IpInet::V6(c.first())),
120 }
121 }
122
123 pub const fn last_address(&self) -> Option<IpAddr> {
129 match self {
130 Self::Any => None,
131 Self::V4(c) => Some(IpAddr::V4(c.last_address())),
132 Self::V6(c) => Some(IpAddr::V6(c.last_address())),
133 }
134 }
135
136 pub const fn last(&self) -> Option<IpInet> {
142 match self {
143 Self::Any => None,
144 Self::V4(c) => Some(IpInet::V4(c.last())),
145 Self::V6(c) => Some(IpInet::V6(c.last())),
146 }
147 }
148
149 pub const fn network_length(&self) -> Option<u8> {
155 match self {
156 Self::Any => None,
157 Self::V4(c) => Some(c.network_length()),
158 Self::V6(c) => Some(c.network_length()),
159 }
160 }
161
162 pub const fn family(&self) -> Option<Family> {
170 match self {
171 Self::Any => None,
172 Self::V4(_) => Some(Family::Ipv4),
173 Self::V6(_) => Some(Family::Ipv6),
174 }
175 }
176
177 pub const fn is_host_address(&self) -> bool {
179 match self {
180 Self::Any => false,
181 Self::V4(c) => c.is_host_address(),
182 Self::V6(c) => c.is_host_address(),
183 }
184 }
185
186 pub const fn mask(&self) -> Option<IpAddr> {
193 match self {
194 Self::Any => None,
195 Self::V4(c) => Some(IpAddr::V4(c.mask())),
196 Self::V6(c) => Some(IpAddr::V6(c.mask())),
197 }
198 }
199
200 pub const fn contains(&self, addr: &IpAddr) -> bool {
202 match self {
203 Self::Any => true,
204 Self::V4(c) => match addr {
205 IpAddr::V4(a) => c.contains(a),
206 IpAddr::V6(_) => false,
207 },
208 Self::V6(c) => match addr {
209 IpAddr::V4(_) => false,
210 IpAddr::V6(a) => c.contains(a),
211 },
212 }
213 }
214}
215
216impl fmt::Display for AnyIpCidr {
217 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
218 match self {
219 Self::Any => write!(f, "any"),
220 Self::V4(c) => fmt::Display::fmt(c, f),
221 Self::V6(c) => fmt::Display::fmt(c, f),
222 }
223 }
224}
225
226impl From<AnyIpCidr> for Option<IpCidr> {
227 fn from(value: AnyIpCidr) -> Option<IpCidr> {
228 match value {
229 AnyIpCidr::Any => None,
230 AnyIpCidr::V4(c) => Some(IpCidr::V4(c)),
231 AnyIpCidr::V6(c) => Some(IpCidr::V6(c)),
232 }
233 }
234}
235
236impl From<Option<IpCidr>> for AnyIpCidr {
237 fn from(a: Option<IpCidr>) -> Self {
238 match a {
239 None => Self::Any,
240 Some(IpCidr::V4(c)) => Self::V4(c),
241 Some(IpCidr::V6(c)) => Self::V6(c),
242 }
243 }
244}
245
246impl FromStr for AnyIpCidr {
247 type Err = NetworkParseError;
248
249 fn from_str(s: &str) -> Result<Self, NetworkParseError> {
250 crate::parsers::parse_any_cidr(s, str::parse)
251 }
252}
253
254impl From<IpCidr> for AnyIpCidr {
255 fn from(c: IpCidr) -> Self {
256 match c {
257 IpCidr::V4(c) => Self::V4(c),
258 IpCidr::V6(c) => Self::V6(c),
259 }
260 }
261}
262
263impl From<Ipv4Cidr> for AnyIpCidr {
264 fn from(c: Ipv4Cidr) -> Self {
265 Self::V4(c)
266 }
267}
268
269impl From<Ipv4Addr> for AnyIpCidr {
270 fn from(address: Ipv4Addr) -> Self {
271 Self::V4(address.into())
272 }
273}
274
275impl From<Ipv6Cidr> for AnyIpCidr {
276 fn from(c: Ipv6Cidr) -> Self {
277 Self::V6(c)
278 }
279}
280
281impl From<Ipv6Addr> for AnyIpCidr {
282 fn from(address: Ipv6Addr) -> Self {
283 Self::V6(address.into())
284 }
285}
286
287impl From<IpAddr> for AnyIpCidr {
288 fn from(address: IpAddr) -> Self {
289 Self::new_host(address)
290 }
291}
292
293#[cfg(feature = "bitstring")]
294impl bitstring::BitString for AnyIpCidr {
295 fn get(&self, ndx: usize) -> bool {
296 assert!(!self.is_any());
297 if 0 == ndx {
298 self.is_ipv6()
299 } else {
300 match self {
301 Self::Any => unreachable!(),
302 Self::V4(c) => c.get(ndx - 1),
303 Self::V6(c) => c.get(ndx - 1),
304 }
305 }
306 }
307
308 fn set(&mut self, ndx: usize, bit: bool) {
309 assert!(!self.is_any());
310 if 0 == ndx {
311 if bit {
312 *self = Self::V6(Ipv6Cidr::null());
313 } else {
314 *self = Self::V4(Ipv4Cidr::null());
315 }
316 } else {
317 match self {
318 Self::Any => unreachable!(),
319 Self::V4(ref mut c) => c.set(ndx - 1, bit),
320 Self::V6(ref mut c) => c.set(ndx - 1, bit),
321 }
322 }
323 }
324
325 fn flip(&mut self, ndx: usize) {
326 assert!(!self.is_any());
327 if 0 == ndx {
328 if self.is_ipv6() {
329 *self = Self::V4(Ipv4Cidr::null())
330 } else {
331 *self = Self::V6(Ipv6Cidr::null())
332 }
333 } else {
334 match self {
335 Self::Any => unreachable!(),
336 Self::V4(ref mut c) => c.flip(ndx - 1),
337 Self::V6(ref mut c) => c.flip(ndx - 1),
338 }
339 }
340 }
341
342 fn len(&self) -> usize {
343 match self {
344 Self::Any => 0,
345 Self::V4(c) => c.len() + 1,
346 Self::V6(c) => c.len() + 1,
347 }
348 }
349
350 fn clip(&mut self, len: usize) {
351 if len > 128 {
353 return;
354 }
355 if 0 == len {
356 *self = Self::Any;
357 } else {
358 match self {
359 Self::Any => (),
360 Self::V4(ref mut c) => c.clip(len - 1),
361 Self::V6(ref mut c) => c.clip(len - 1),
362 }
363 }
364 }
365
366 fn append(&mut self, bit: bool) {
367 match self {
368 Self::Any => {
369 if bit {
370 *self = Self::V6(Ipv6Cidr::null());
371 } else {
372 *self = Self::V4(Ipv4Cidr::null());
373 }
374 },
375 Self::V4(ref mut c) => c.append(bit),
376 Self::V6(ref mut c) => c.append(bit),
377 }
378 }
379
380 fn null() -> Self {
381 Self::Any
382 }
383
384 fn shared_prefix_len(&self, other: &Self) -> usize {
385 match (self, other) {
386 (Self::V4(a), Self::V4(b)) => 1 + a.shared_prefix_len(b),
387 (Self::V6(a), Self::V6(b)) => 1 + a.shared_prefix_len(b),
388 _ => 0,
389 }
390 }
391}