1use crate::*;
2use ipnet::{Ipv4Net, Ipv6Net};
3use std::cmp::Ordering;
4use std::net::{Ipv4Addr, Ipv6Addr};
5
6#[doc(hidden)]
7#[derive(Copy, Clone, PartialEq, Eq, Debug)]
8pub enum IpPrefixCoverage {
9 NoCover,
10 WiderRange,
11 SameRange,
12}
13
14impl IpPrefixCoverage {
15 #[inline]
16 fn is_wider(&self) -> bool {
17 *self == IpPrefixCoverage::WiderRange
18 }
19 #[inline]
20 fn is_same(&self) -> bool {
21 *self == IpPrefixCoverage::SameRange
22 }
23 #[inline]
24 fn is_covering(&self) -> bool {
25 *self != IpPrefixCoverage::NoCover
26 }
27}
28
29pub trait IpPrefixCovering<P> {
31 #[doc(hidden)]
49 fn covering(&self, other: &P) -> IpPrefixCoverage;
50
51 #[inline]
65 fn covers(&self, other: &P) -> bool {
66 self.covering(other).is_covering()
67 }
68
69 #[inline]
70 #[doc(hidden)]
71 fn covers_striclty(&self, other: &P) -> bool {
72 self.covering(other).is_wider()
73 }
74 #[inline]
75 #[doc(hidden)]
76 fn covers_equally(&self, other: &P) -> bool {
77 self.covering(other).is_same()
78 }
79}
80
81impl<P: IpPrefix> IpPrefixCovering<Self> for P {
82 #[inline]
83 fn covering(&self, other: &Self) -> IpPrefixCoverage {
84 if other.bitslot() & self.bitmask() != self.bitslot_trunc() {
85 IpPrefixCoverage::NoCover
86 } else {
87 match self.len().cmp(&other.len()) {
88 Ordering::Less => IpPrefixCoverage::WiderRange,
89 Ordering::Equal => IpPrefixCoverage::SameRange,
90 Ordering::Greater => IpPrefixCoverage::NoCover,
91 }
92 }
93 }
94}
95
96macro_rules! ipcover {
98 ($self:ty, $other:ty) => {
99 impl IpPrefixCovering<$other> for $self {
100 #[inline]
101 fn covering(&self, other: &$other) -> IpPrefixCoverage {
102 if other.bitslot() & self.bitmask() != self.bitslot_trunc() {
103 IpPrefixCoverage::NoCover
104 } else {
105 match self.len().cmp(&other.len()) {
106 Ordering::Less => IpPrefixCoverage::WiderRange,
107 Ordering::Equal => IpPrefixCoverage::SameRange,
108 Ordering::Greater => IpPrefixCoverage::NoCover,
109 }
110 }
111 }
112 }
113 };
114}
115
116ipcover!(Ipv4Prefix, Ipv4Net);
117ipcover!(Ipv4Prefix, Ipv4Addr);
118
119ipcover!(Ipv4Net, Ipv4Prefix);
120ipcover!(Ipv4Net, Ipv4Addr);
121
122ipcover!(Ipv6Prefix, Ipv6Net);
123ipcover!(Ipv6Prefix, Ipv6Addr);
124
125ipcover!(Ipv6Net, Ipv6Prefix);
126ipcover!(Ipv6Net, Ipv6Addr);
127
128macro_rules! ipcover_for_ipv6_on_u64 {
131 ($short:ty, $other:ty) => {
132 impl IpPrefixCovering<$other> for $short {
133 #[inline]
134 fn covering(&self, other: &$other) -> IpPrefixCoverage {
135 if ((other.bitslot() >> 64) as u64) & self.bitmask() != self.bitslot_trunc() {
136 IpPrefixCoverage::NoCover
137 } else {
138 match self.len().cmp(&other.len()) {
139 Ordering::Less => IpPrefixCoverage::WiderRange,
140 Ordering::Equal => IpPrefixCoverage::SameRange,
141 Ordering::Greater => IpPrefixCoverage::NoCover,
142 }
143 }
144 }
145 }
146 };
147}
148
149ipcover_for_ipv6_on_u64!(Ipv6NetPrefix, Ipv6Prefix);
150ipcover_for_ipv6_on_u64!(Ipv6NetPrefix, Ipv6Net);
151ipcover_for_ipv6_on_u64!(Ipv6NetPrefix, Ipv6Addr);
152
153macro_rules! ipcover_of_ipv6_on_u64 {
154 ($self:ty, $short:ty) => {
155 impl IpPrefixCovering<$short> for $self {
156 #[inline]
157 fn covering(&self, other: &$short) -> IpPrefixCoverage {
158 if ((other.bitslot() as u128) << 64) & self.bitmask() != self.bitslot_trunc() {
159 IpPrefixCoverage::NoCover
160 } else {
161 match self.len().cmp(&other.len()) {
162 Ordering::Less => IpPrefixCoverage::WiderRange,
163 Ordering::Equal => IpPrefixCoverage::SameRange,
164 Ordering::Greater => IpPrefixCoverage::NoCover,
165 }
166 }
167 }
168 }
169 };
170}
171
172ipcover_of_ipv6_on_u64!(Ipv6Prefix, Ipv6NetPrefix);
173ipcover_of_ipv6_on_u64!(Ipv6Net, Ipv6NetPrefix);
174
175macro_rules! ipprefix_eq {
177 ($self:ty, $other:ty) => {
178 impl PartialEq<$other> for $self {
179 #[inline]
180 fn eq(&self, other: &$other) -> bool {
181 self.covers_equally(other)
182 }
183 }
184 };
185}
186
187ipprefix_eq!(Ipv6Net, Ipv6NetPrefix);
188ipprefix_eq!(Ipv6Net, Ipv6Prefix);
189
190ipprefix_eq!(Ipv6NetPrefix, Ipv6Net);
191ipprefix_eq!(Ipv6NetPrefix, Ipv6Prefix);
192
193ipprefix_eq!(Ipv6Prefix, Ipv6Net);
194ipprefix_eq!(Ipv6Prefix, Ipv6NetPrefix);