1use core::cmp::Ordering;
2use core::ops::{Add, BitAnd, BitOr, BitXor, Mul, Not, Sub};
3
4use num_traits::{One, Zero};
5
6use super::{Prefix, Range};
7use crate::{
8 concrete::{self, Ipv4, Ipv6},
9 traits,
10};
11
12#[derive(Clone, Debug, Default, PartialEq, Eq)]
29pub struct Set {
30 ipv4: concrete::PrefixSet<Ipv4>,
31 ipv6: concrete::PrefixSet<Ipv6>,
32}
33
34impl Set {
35 fn aggregate(&mut self) -> &mut Self {
36 _ = self.ipv4.aggregate();
37 _ = self.ipv6.aggregate();
38 self
39 }
40
41 #[must_use]
62 #[allow(clippy::missing_const_for_fn)]
63 pub fn partition(self) -> (concrete::PrefixSet<Ipv4>, concrete::PrefixSet<Ipv6>) {
64 (self.ipv4, self.ipv6)
65 }
66
67 #[must_use]
88 pub const fn as_partitions(&self) -> (&concrete::PrefixSet<Ipv4>, &concrete::PrefixSet<Ipv6>) {
89 (&self.ipv4, &self.ipv6)
90 }
91
92 #[must_use]
112 pub fn as_mut_partitions(
113 &mut self,
114 ) -> (
115 &mut concrete::PrefixSet<Ipv4>,
116 &mut concrete::PrefixSet<Ipv6>,
117 ) {
118 (&mut self.ipv4, &mut self.ipv6)
119 }
120}
121
122#[derive(Debug)]
123pub struct Prefixes<'a> {
124 ipv4: <concrete::PrefixSet<Ipv4> as traits::PrefixSet<'a>>::Prefixes,
125 ipv6: <concrete::PrefixSet<Ipv6> as traits::PrefixSet<'a>>::Prefixes,
126}
127
128impl Iterator for Prefixes<'_> {
129 type Item = Prefix;
130
131 fn next(&mut self) -> Option<Self::Item> {
132 self.ipv4
133 .next()
134 .map(Prefix::Ipv4)
135 .or_else(|| self.ipv6.next().map(Prefix::Ipv6))
136 }
137}
138
139#[derive(Debug)]
140pub struct Ranges<'a> {
141 ipv4: <concrete::PrefixSet<Ipv4> as traits::PrefixSet<'a>>::Ranges,
142 ipv6: <concrete::PrefixSet<Ipv6> as traits::PrefixSet<'a>>::Ranges,
143}
144
145impl Iterator for Ranges<'_> {
146 type Item = Range;
147
148 fn next(&mut self) -> Option<Self::Item> {
149 self.ipv4
150 .next()
151 .map(Self::Item::Ipv4)
152 .or_else(|| self.ipv6.next().map(Self::Item::Ipv6))
153 }
154}
155
156impl<'a> traits::PrefixSet<'a> for Set {
157 type Prefix = Prefix;
158 type Range = Range;
159 type Prefixes = Prefixes<'a>;
160 type Ranges = Ranges<'a>;
161
162 fn prefixes(&'a self) -> Self::Prefixes {
163 Self::Prefixes {
164 ipv4: self.ipv4.prefixes(),
165 ipv6: self.ipv6.prefixes(),
166 }
167 }
168
169 fn ranges(&'a self) -> Self::Ranges {
170 Self::Ranges {
171 ipv4: self.ipv4.ranges(),
172 ipv6: self.ipv6.ranges(),
173 }
174 }
175
176 fn contains(&self, prefix: Self::Prefix) -> bool {
177 match prefix {
178 Self::Prefix::Ipv4(prefix) => self.ipv4.contains(prefix),
179 Self::Prefix::Ipv6(prefix) => self.ipv6.contains(prefix),
180 }
181 }
182}
183
184impl From<concrete::PrefixSet<Ipv4>> for Set {
185 fn from(value: concrete::PrefixSet<Ipv4>) -> Self {
186 Self {
187 ipv4: value,
188 ..Default::default()
189 }
190 }
191}
192
193impl From<concrete::PrefixSet<Ipv6>> for Set {
194 fn from(value: concrete::PrefixSet<Ipv6>) -> Self {
195 Self {
196 ipv6: value,
197 ..Default::default()
198 }
199 }
200}
201
202impl Extend<Prefix> for Set {
203 #[allow(unused_results)]
204 fn extend<I>(&mut self, iter: I)
205 where
206 I: IntoIterator<Item = Prefix>,
207 {
208 iter.into_iter().for_each(|prefix| match prefix {
209 Prefix::Ipv4(prefix) => {
210 self.ipv4.insert_only(prefix);
211 }
212 Prefix::Ipv6(prefix) => {
213 self.ipv6.insert_only(prefix);
214 }
215 });
216 self.aggregate();
217 }
218}
219
220impl Extend<Range> for Set {
221 #[allow(unused_results)]
222 fn extend<I>(&mut self, iter: I)
223 where
224 I: IntoIterator<Item = Range>,
225 {
226 iter.into_iter().for_each(|range| match range {
227 Range::Ipv4(range) => {
228 self.ipv4.insert_only(range);
229 }
230 Range::Ipv6(range) => {
231 self.ipv6.insert_only(range);
232 }
233 });
234 self.aggregate();
235 }
236}
237
238impl<T> FromIterator<T> for Set
239where
240 Self: Extend<T>,
241{
242 fn from_iter<I>(iter: I) -> Self
243 where
244 I: IntoIterator<Item = T>,
245 {
246 let mut this = Self::default();
247 this.extend(iter);
248 this
249 }
250}
251
252impl One for Set {
253 fn one() -> Self {
254 Self {
255 ipv4: concrete::PrefixSet::one(),
256 ipv6: concrete::PrefixSet::one(),
257 }
258 }
259}
260
261impl Zero for Set {
262 fn zero() -> Self {
263 Self {
264 ipv4: concrete::PrefixSet::zero(),
265 ipv6: concrete::PrefixSet::zero(),
266 }
267 }
268
269 fn is_zero(&self) -> bool {
270 self == &Self::zero()
271 }
272}
273
274impl BitAnd for Set {
275 type Output = Self;
276
277 fn bitand(self, rhs: Self) -> Self::Output {
278 Self {
279 ipv4: self.ipv4 & rhs.ipv4,
280 ipv6: self.ipv6 & rhs.ipv6,
281 }
282 }
283}
284
285impl BitOr for Set {
286 type Output = Self;
287
288 fn bitor(self, rhs: Self) -> Self::Output {
289 Self {
290 ipv4: self.ipv4 | rhs.ipv4,
291 ipv6: self.ipv6 | rhs.ipv6,
292 }
293 }
294}
295
296impl BitXor for Set {
297 type Output = Self;
298
299 fn bitxor(self, rhs: Self) -> Self::Output {
300 Self {
301 ipv4: self.ipv4 ^ rhs.ipv4,
302 ipv6: self.ipv6 ^ rhs.ipv6,
303 }
304 }
305}
306
307impl Not for Set {
308 type Output = Self;
309
310 fn not(self) -> Self::Output {
311 Self {
312 ipv4: !self.ipv4,
313 ipv6: !self.ipv6,
314 }
315 }
316}
317
318impl Add for Set {
319 type Output = Self;
320
321 fn add(self, rhs: Self) -> Self::Output {
322 Self {
323 ipv4: self.ipv4 + rhs.ipv4,
324 ipv6: self.ipv6 + rhs.ipv6,
325 }
326 }
327}
328
329impl Mul for Set {
330 type Output = Self;
331
332 fn mul(self, rhs: Self) -> Self::Output {
333 Self {
334 ipv4: self.ipv4 * rhs.ipv4,
335 ipv6: self.ipv6 * rhs.ipv6,
336 }
337 }
338}
339
340impl Sub for Set {
341 type Output = Self;
342
343 fn sub(self, rhs: Self) -> Self::Output {
344 Self {
345 ipv4: self.ipv4 - rhs.ipv4,
346 ipv6: self.ipv6 - rhs.ipv6,
347 }
348 }
349}
350
351impl PartialOrd for Set {
352 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
353 use Ordering::{Equal, Greater, Less};
354 match (
355 self.ipv4.partial_cmp(&other.ipv4),
356 self.ipv6.partial_cmp(&other.ipv6),
357 ) {
358 (Some(ord4), Some(ord6)) => match (ord4, ord6) {
359 (Equal, Equal) => Some(Equal),
360 (Less | Equal, Less | Equal) => Some(Less),
361 (Greater | Equal, Greater | Equal) => Some(Greater),
362 _ => None,
363 },
364 _ => None,
365 }
366 }
367}