1use core::fmt;
2use std::net::{
3 Ipv4Addr,
4 Ipv6Addr,
5};
6
7use crate::{
8 errors::*,
9 internal_traits::{
10 PrivInetPair,
11 PrivUnspecAddress,
12 },
13 num::NumberOfAddresses,
14 Family,
15 InetIterator,
16 InetPair,
17 Ipv4Cidr,
18 Ipv4Inet,
19 Ipv4InetPair,
20 Ipv6Cidr,
21 Ipv6Inet,
22 Ipv6InetPair,
23};
24
25macro_rules! impl_inet_pair_for {
26 ($n:ident : inet $inet:ident : cidr $cidr:ident : addr $addr:ty : native $native:ident : family $family:expr) => {
27 impl $n {
28 pub const fn new(first: $inet, second: $inet) -> Result<Self, InetTupleError> {
32 if first.network_length != second.network_length {
33 return Err(InetTupleError::NotInSharedNetwork);
34 }
35 if !<$addr as PrivUnspecAddress>::_Tools::_prefix_match(
36 first.address,
37 second.address,
38 first.network_length,
39 ) {
40 return Err(InetTupleError::NotInSharedNetwork);
41 }
42 Ok(Self {
43 first: first.address,
44 second: second.address,
45 network_length: first.network_length,
46 })
47 }
48
49 pub const fn new_from_addresses(
53 first: $addr,
54 second: $addr,
55 len: u8,
56 ) -> Result<Self, InetTupleError> {
57 if !<$addr as PrivUnspecAddress>::_Tools::_prefix_match(first, second, len) {
58 return Err(InetTupleError::NotInSharedNetwork);
59 }
60 Ok(Self {
61 first,
62 second,
63 network_length: len,
64 })
65 }
66
67 pub const fn first(&self) -> $inet {
69 $inet {
70 address: self.first,
71 network_length: self.network_length,
72 }
73 }
74
75 pub const fn second(&self) -> $inet {
77 $inet {
78 address: self.second,
79 network_length: self.network_length,
80 }
81 }
82
83 pub const fn network(&self) -> $cidr {
85 self.first().network()
86 }
87
88 pub const fn network_length(&self) -> u8 {
90 self.network_length
91 }
92
93 pub const fn family(&self) -> Family {
98 $family
99 }
100
101 pub const fn iter(self) -> InetIterator<$addr> {
103 InetIterator::_new(self)
104 }
105 }
106
107 impl PrivInetPair for $n {
108 fn _covered_addresses(&self) -> NumberOfAddresses {
109 let first: $native = <$addr as PrivUnspecAddress>::_Tools::to_native(self.first);
110 let second: $native = <$addr as PrivUnspecAddress>::_Tools::to_native(self.second);
111 NumberOfAddresses::count_from_distance((second - first) as u128)
112 }
113
114 fn _inc_first(&mut self) -> bool {
115 if self.first < self.second {
116 let current = <$addr as PrivUnspecAddress>::_Tools::to_native(self.first);
117 self.first = <$addr as PrivUnspecAddress>::_Tools::from_native(current + 1);
118 true
119 } else {
120 false
121 }
122 }
123
124 fn _dec_second(&mut self) -> bool {
125 if self.first < self.second {
126 let current = <$addr as PrivUnspecAddress>::_Tools::to_native(self.second);
127 self.second = <$addr as PrivUnspecAddress>::_Tools::from_native(current - 1);
128 true
129 } else {
130 false
131 }
132 }
133 }
134
135 impl InetPair for $n {
136 type Address = $addr;
137
138 fn new(first: $inet, second: $inet) -> Result<Self, InetTupleError> {
139 Self::new(first, second)
140 }
141
142 fn new_from_addresses(
143 first: Self::Address,
144 second: Self::Address,
145 len: u8,
146 ) -> Result<Self, InetTupleError> {
147 Self::new_from_addresses(first, second, len)
148 }
149
150 fn first(&self) -> $inet {
151 self.first()
152 }
153
154 fn second(&self) -> $inet {
155 self.second()
156 }
157
158 fn network(&self) -> $cidr {
159 self.network()
160 }
161
162 fn network_length(&self) -> u8 {
163 self.network_length()
164 }
165
166 fn family(&self) -> Family {
167 self.family()
168 }
169
170 fn iter(self) -> InetIterator<$addr> {
171 self.iter()
172 }
173 }
174
175 impl fmt::Debug for $n {
176 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
177 f.debug_struct(stringify!($n))
178 .field("first", &self.first())
179 .field("second", &self.second())
180 .finish()
181 }
182 }
183
184 impl fmt::Display for $n {
185 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
186 use core::fmt::Write;
187 f.write_char('(')?;
188 self.first().fmt(f)?;
189 f.write_str(", ")?;
190 self.second().fmt(f)?;
191 f.write_char(')')?;
192 Ok(())
193 }
194 }
195
196 impl IntoIterator for $n {
198 type IntoIter = crate::InetIterator<$addr>;
199 type Item = $inet;
200
201 fn into_iter(self) -> Self::IntoIter {
202 self.iter()
203 }
204 }
205 };
206}
207
208impl_inet_pair_for! {Ipv4InetPair : inet Ipv4Inet : cidr Ipv4Cidr : addr Ipv4Addr : native u32 : family Family::Ipv4}
209impl_inet_pair_for! {Ipv6InetPair : inet Ipv6Inet : cidr Ipv6Cidr : addr Ipv6Addr : native u128 : family Family::Ipv6}