cidr/inet_pair/
direct.rs

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			/// Create new pair from two addresses in the same network
29			///
30			/// Fails if the addresses are not in the same network.
31			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			/// Create new pair from two addresses and a common length
50			///
51			/// Fails if the network length is invalid for the addresses or the addresses are not in the same network.
52			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			/// First address
68			pub const fn first(&self) -> $inet {
69				$inet {
70					address: self.first,
71					network_length: self.network_length,
72				}
73			}
74
75			/// Second address
76			pub const fn second(&self) -> $inet {
77				$inet {
78					address: self.second,
79					network_length: self.network_length,
80				}
81			}
82
83			/// network (i.e. drops the host information)
84			pub const fn network(&self) -> $cidr {
85				self.first().network()
86			}
87
88			/// length in bits of the shared prefix of the contained addresses
89			pub const fn network_length(&self) -> u8 {
90				self.network_length
91			}
92
93			/// IP family of the contained address ([`Ipv4`] or [`Ipv6`]).
94			///
95			/// [`Ipv4`]: Family::Ipv4
96			/// [`Ipv6`]: Family::Ipv6
97			pub const fn family(&self) -> Family {
98				$family
99			}
100
101			/// Iterate over `first..=second` (inclusive)
102			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		/// Iterate over all the addresses in the CIDR.
197		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}