cidr/inet_pair/
combined.rs

1use core::{
2	fmt,
3	net::IpAddr,
4};
5
6use crate::{
7	errors::*,
8	internal_traits::PrivInetPair,
9	num::NumberOfAddresses,
10	Family,
11	InetIterator,
12	InetPair,
13	IpCidr,
14	IpInet,
15	IpInetPair,
16	Ipv4InetPair,
17	Ipv6InetPair,
18};
19
20impl IpInetPair {
21	/// Whether representing an IPv4 network
22	pub const fn is_ipv4(&self) -> bool {
23		match self {
24			Self::V4(_) => true,
25			Self::V6(_) => false,
26		}
27	}
28
29	/// Whether representing an IPv6 network
30	pub const fn is_ipv6(&self) -> bool {
31		match self {
32			Self::V4(_) => false,
33			Self::V6(_) => true,
34		}
35	}
36
37	// --- copy of trait API
38
39	/// Create new pair from two addresses in the same network
40	///
41	/// Fails if the addresses are not in the same network.
42	pub const fn new(first: IpInet, second: IpInet) -> Result<Self, InetTupleError> {
43		match (first, second) {
44			(IpInet::V4(first), IpInet::V4(second)) => match Ipv4InetPair::new(first, second) {
45				Ok(pair) => Ok(Self::V4(pair)),
46				Err(e) => Err(e),
47			},
48			(IpInet::V6(first), IpInet::V6(second)) => match Ipv6InetPair::new(first, second) {
49				Ok(pair) => Ok(Self::V6(pair)),
50				Err(e) => Err(e),
51			},
52			_ => Err(InetTupleError::NotInSharedNetwork),
53		}
54	}
55
56	/// Create new pair from two addresses and a common length
57	///
58	/// Fails if the network length is invalid for the addresses or the addresses are not in the same network.
59	pub const fn new_from_addresses(
60		first: IpAddr,
61		second: IpAddr,
62		len: u8,
63	) -> Result<Self, InetTupleError> {
64		match (first, second) {
65			(IpAddr::V4(first), IpAddr::V4(second)) => {
66				match Ipv4InetPair::new_from_addresses(first, second, len) {
67					Ok(pair) => Ok(Self::V4(pair)),
68					Err(e) => Err(e),
69				}
70			},
71			(IpAddr::V6(first), IpAddr::V6(second)) => {
72				match Ipv6InetPair::new_from_addresses(first, second, len) {
73					Ok(pair) => Ok(Self::V6(pair)),
74					Err(e) => Err(e),
75				}
76			},
77			_ => Err(InetTupleError::NotInSharedNetwork),
78		}
79	}
80
81	/// First address
82	pub const fn first(&self) -> IpInet {
83		match self {
84			Self::V4(p) => IpInet::V4(p.first()),
85			Self::V6(p) => IpInet::V6(p.first()),
86		}
87	}
88
89	/// Second address
90	pub const fn second(&self) -> IpInet {
91		match self {
92			Self::V4(p) => IpInet::V4(p.second()),
93			Self::V6(p) => IpInet::V6(p.second()),
94		}
95	}
96
97	/// network (i.e. drops the host information)
98	pub const fn network(&self) -> IpCidr {
99		match self {
100			Self::V4(p) => IpCidr::V4(p.network()),
101			Self::V6(p) => IpCidr::V6(p.network()),
102		}
103	}
104
105	/// length in bits of the shared prefix of the contained addresses
106	pub const fn network_length(&self) -> u8 {
107		match self {
108			Self::V4(p) => p.network_length(),
109			Self::V6(p) => p.network_length(),
110		}
111	}
112
113	/// IP family of the contained address ([`Ipv4`] or [`Ipv6`]).
114	///
115	/// [`Ipv4`]: Family::Ipv4
116	/// [`Ipv6`]: Family::Ipv6
117	pub const fn family(&self) -> Family {
118		match self {
119			Self::V4(_) => Family::Ipv4,
120			Self::V6(_) => Family::Ipv6,
121		}
122	}
123
124	/// Iterate over `first..=second` (inclusive)
125	pub const fn iter(self) -> InetIterator<IpAddr> {
126		InetIterator::_new(self)
127	}
128}
129
130impl PrivInetPair for IpInetPair {
131	fn _covered_addresses(&self) -> NumberOfAddresses {
132		match self {
133			Self::V4(p) => p._covered_addresses(),
134			Self::V6(p) => p._covered_addresses(),
135		}
136	}
137
138	fn _inc_first(&mut self) -> bool {
139		match self {
140			Self::V4(p) => p._inc_first(),
141			Self::V6(p) => p._inc_first(),
142		}
143	}
144
145	fn _dec_second(&mut self) -> bool {
146		match self {
147			Self::V4(p) => p._dec_second(),
148			Self::V6(p) => p._dec_second(),
149		}
150	}
151}
152
153impl InetPair for IpInetPair {
154	type Address = IpAddr;
155
156	fn new(first: IpInet, second: IpInet) -> Result<Self, InetTupleError> {
157		match (first, second) {
158			(IpInet::V4(first), IpInet::V4(second)) => {
159				Ok(Self::V4(Ipv4InetPair::new(first, second)?))
160			},
161			(IpInet::V6(first), IpInet::V6(second)) => {
162				Ok(Self::V6(Ipv6InetPair::new(first, second)?))
163			},
164			_ => Err(InetTupleError::NotInSharedNetwork),
165		}
166	}
167
168	fn new_from_addresses(first: IpAddr, second: IpAddr, len: u8) -> Result<Self, InetTupleError> {
169		match (first, second) {
170			(IpAddr::V4(first), IpAddr::V4(second)) => Ok(Self::V4(
171				Ipv4InetPair::new_from_addresses(first, second, len)?,
172			)),
173			(IpAddr::V6(first), IpAddr::V6(second)) => Ok(Self::V6(
174				Ipv6InetPair::new_from_addresses(first, second, len)?,
175			)),
176			_ => Err(InetTupleError::NotInSharedNetwork),
177		}
178	}
179
180	fn first(&self) -> IpInet {
181		match self {
182			Self::V4(p) => IpInet::V4(p.first()),
183			Self::V6(p) => IpInet::V6(p.first()),
184		}
185	}
186
187	fn second(&self) -> IpInet {
188		match self {
189			Self::V4(p) => IpInet::V4(p.second()),
190			Self::V6(p) => IpInet::V6(p.second()),
191		}
192	}
193
194	fn network(&self) -> IpCidr {
195		match self {
196			Self::V4(p) => IpCidr::V4(p.network()),
197			Self::V6(p) => IpCidr::V6(p.network()),
198		}
199	}
200
201	fn network_length(&self) -> u8 {
202		match self {
203			Self::V4(p) => p.network_length(),
204			Self::V6(p) => p.network_length(),
205		}
206	}
207
208	fn family(&self) -> Family {
209		match self {
210			Self::V4(_) => Family::Ipv4,
211			Self::V6(_) => Family::Ipv6,
212		}
213	}
214
215	fn iter(self) -> InetIterator<IpAddr> {
216		self.iter()
217	}
218}
219
220impl fmt::Display for IpInetPair {
221	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
222		match self {
223			Self::V4(c) => fmt::Display::fmt(c, f),
224			Self::V6(c) => fmt::Display::fmt(c, f),
225		}
226	}
227}
228
229impl From<Ipv4InetPair> for IpInetPair {
230	fn from(c: Ipv4InetPair) -> Self {
231		Self::V4(c)
232	}
233}
234
235impl From<Ipv6InetPair> for IpInetPair {
236	fn from(c: Ipv6InetPair) -> Self {
237		Self::V6(c)
238	}
239}
240
241impl IntoIterator for IpInetPair {
242	type IntoIter = InetIterator<IpAddr>;
243	type Item = IpInet;
244
245	fn into_iter(self) -> Self::IntoIter {
246		self.iter()
247	}
248}