cidr_utils/separator/
v6.rs1use std::cmp::Ordering;
2
3use cidr::Ipv6Cidr;
4use num_bigint::BigUint;
5use num_traits::{One, ToPrimitive};
6
7use crate::{combiner::Ipv6CidrCombiner, iterator::Ipv6CidrIpv6AddrIterator, Ipv6CidrSize};
8
9#[derive(Debug)]
11pub struct Ipv6CidrSeparator;
12
13impl Ipv6CidrSeparator {
14 pub fn divide_by(cidr: &Ipv6Cidr, n: usize) -> Option<Vec<Ipv6CidrCombiner>> {
16 let size = cidr.size();
17
18 let n_big_int = BigUint::from(n);
19
20 if n == 0 || n_big_int > size {
21 return None;
22 } else if n == 1 {
23 let mut combiner = Ipv6CidrCombiner::with_capacity(1);
24
25 combiner.push(*cidr);
26
27 return Some(vec![combiner]);
28 }
29
30 let d = size.clone() / n_big_int.clone();
31
32 let mut output = Vec::with_capacity(n);
33
34 if d.clone() * n_big_int == size {
35 let mut iter = Ipv6CidrIpv6AddrIterator::new(cidr);
36
37 let bits = cidr.network_length() + n.ilog2() as u8;
38
39 let usize_max_big_int = BigUint::from(usize::MAX);
40
41 if d <= usize_max_big_int {
42 for ip in iter.step_by(d.to_usize().unwrap()) {
43 let mut combiner = Ipv6CidrCombiner::with_capacity(1);
44
45 combiner.push(Ipv6Cidr::new(ip, bits).unwrap());
46
47 output.push(combiner);
48 }
49 } else {
50 let nth = d - BigUint::one();
51
52 if let Some(ip) = iter.next() {
53 let mut combiner = Ipv6CidrCombiner::with_capacity(1);
54
55 combiner.push(Ipv6Cidr::new(ip, bits).unwrap());
56
57 output.push(combiner);
58
59 while let Some(ip) = iter.nth_big_uint(nth.clone()) {
60 let mut combiner = Ipv6CidrCombiner::with_capacity(1);
61
62 combiner.push(Ipv6Cidr::new(ip, bits).unwrap());
63
64 output.push(combiner);
65 }
66 }
67 }
68 } else {
69 let iter = Ipv6CidrIpv6AddrIterator::new(cidr);
70
71 let mut current_combiner = Ipv6CidrCombiner::new();
72
73 let mut i = BigUint::one();
74
75 for ip in iter {
76 current_combiner.push(Ipv6Cidr::new(ip, 128).unwrap());
77
78 if i == d {
79 output.push(current_combiner);
80
81 current_combiner = Ipv6CidrCombiner::new();
82
83 i = BigUint::one();
84 } else {
85 i += BigUint::one();
86 }
87 }
88
89 let last_combiner = output.last_mut().unwrap();
90
91 for cidr in current_combiner.into_ipv6_cidr_vec().into_iter() {
92 last_combiner.push(cidr);
93 }
94 }
95
96 Some(output)
97 }
98
99 pub fn sub_networks(cidr: &Ipv6Cidr, bits: u8) -> Option<Vec<Ipv6Cidr>> {
101 let cidr_bits = cidr.network_length();
102
103 match cidr_bits.cmp(&bits) {
104 Ordering::Greater => return None,
105 Ordering::Equal => return Some(vec![*cidr]),
106 Ordering::Less => (),
107 }
108
109 let n = 2usize.pow(u32::from(bits - cidr_bits));
110
111 let n_big_int = BigUint::from(n);
112
113 let mut output = Vec::with_capacity(n);
114
115 let size = cidr.size();
116
117 let d = size / n_big_int;
118
119 let mut iter = Ipv6CidrIpv6AddrIterator::new(cidr);
120
121 let usize_max_big_int = BigUint::from(usize::MAX);
122
123 if d <= usize_max_big_int {
124 for ip in iter.step_by(d.to_usize().unwrap()) {
125 output.push(Ipv6Cidr::new(ip, bits).unwrap());
126 }
127 } else {
128 let nth = d - BigUint::one();
129
130 if let Some(ip) = iter.next() {
131 output.push(Ipv6Cidr::new(ip, bits).unwrap());
132
133 while let Some(ip) = iter.nth_big_uint(nth.clone()) {
134 output.push(Ipv6Cidr::new(ip, bits).unwrap());
135 }
136 }
137 }
138
139 Some(output)
140 }
141}