cidr/cidr/
combined.rs

1use core::{
2	fmt,
3	net::{
4		IpAddr,
5		Ipv4Addr,
6		Ipv6Addr,
7	},
8	str::FromStr,
9};
10
11use crate::{
12	errors::*,
13	internal_traits::PrivCidr,
14	Cidr,
15	Family,
16	InetIterator,
17	IpCidr,
18	IpInet,
19	IpInetPair,
20	Ipv4Cidr,
21	Ipv6Cidr,
22};
23
24impl IpCidr {
25	/// Whether representing an IPv4 network
26	pub const fn is_ipv4(&self) -> bool {
27		match self {
28			Self::V4(_) => true,
29			Self::V6(_) => false,
30		}
31	}
32
33	/// Whether representing an IPv6 network
34	pub const fn is_ipv6(&self) -> bool {
35		match self {
36			Self::V4(_) => false,
37			Self::V6(_) => true,
38		}
39	}
40
41	// --- copy of trait API
42
43	/// Create new network from address and prefix length.  If the
44	/// network length exceeds the address length or the address is not
45	/// the first address in the network ("host part not zero") an
46	/// error is returned.
47	pub const fn new(addr: IpAddr, len: u8) -> Result<Self, NetworkParseError> {
48		match addr {
49			IpAddr::V4(a) => match Ipv4Cidr::new(a, len) {
50				Ok(cidr) => Ok(Self::V4(cidr)),
51				Err(e) => Err(e),
52			},
53			IpAddr::V6(a) => match Ipv6Cidr::new(a, len) {
54				Ok(cidr) => Ok(Self::V6(cidr)),
55				Err(e) => Err(e),
56			},
57		}
58	}
59
60	/// Create a network containing a single address (network length =
61	/// address length).
62	pub const fn new_host(addr: IpAddr) -> Self {
63		match addr {
64			IpAddr::V4(a) => Self::V4(Ipv4Cidr::new_host(a)),
65			IpAddr::V6(a) => Self::V6(Ipv6Cidr::new_host(a)),
66		}
67	}
68
69	/// Iterate over all addresses in the range.  With IPv6 addresses
70	/// this can produce really long iterations (up to 2<sup>128</sup>
71	/// addresses).
72	pub const fn iter(&self) -> InetIterator<IpAddr> {
73		self._range_pair().iter()
74	}
75
76	/// first address in the network as plain address
77	pub const fn first_address(&self) -> IpAddr {
78		match self {
79			Self::V4(c) => IpAddr::V4(c.first_address()),
80			Self::V6(c) => IpAddr::V6(c.first_address()),
81		}
82	}
83
84	/// first address in the network
85	pub const fn first(&self) -> IpInet {
86		match self {
87			Self::V4(c) => IpInet::V4(c.first()),
88			Self::V6(c) => IpInet::V6(c.first()),
89		}
90	}
91
92	/// last address in the network as plain address
93	pub const fn last_address(&self) -> IpAddr {
94		match self {
95			Self::V4(c) => IpAddr::V4(c.last_address()),
96			Self::V6(c) => IpAddr::V6(c.last_address()),
97		}
98	}
99
100	/// last address in the network
101	pub const fn last(&self) -> IpInet {
102		match self {
103			Self::V4(c) => IpInet::V4(c.last()),
104			Self::V6(c) => IpInet::V6(c.last()),
105		}
106	}
107
108	/// length in bits of the shared prefix of the contained addresses
109	pub const fn network_length(&self) -> u8 {
110		match self {
111			Self::V4(c) => c.network_length(),
112			Self::V6(c) => c.network_length(),
113		}
114	}
115
116	/// IP family of the contained address ([`Ipv4`] or [`Ipv6`]).
117	///
118	/// [`Ipv4`]: Family::Ipv4
119	/// [`Ipv6`]: Family::Ipv6
120	pub const fn family(&self) -> Family {
121		match self {
122			Self::V4(_) => Family::Ipv4,
123			Self::V6(_) => Family::Ipv6,
124		}
125	}
126
127	/// whether network represents a single host address
128	pub const fn is_host_address(&self) -> bool {
129		match self {
130			Self::V4(c) => c.is_host_address(),
131			Self::V6(c) => c.is_host_address(),
132		}
133	}
134
135	/// network mask: an pseudo address which has the first `network
136	/// length` bits set to 1 and the remaining to 0.
137	pub const fn mask(&self) -> IpAddr {
138		match self {
139			Self::V4(c) => IpAddr::V4(c.mask()),
140			Self::V6(c) => IpAddr::V6(c.mask()),
141		}
142	}
143
144	/// check whether an address is contained in the network
145	pub const fn contains(&self, addr: &IpAddr) -> bool {
146		match self {
147			Self::V4(c) => match addr {
148				IpAddr::V4(a) => c.contains(a),
149				IpAddr::V6(_) => false,
150			},
151			Self::V6(c) => match addr {
152				IpAddr::V4(_) => false,
153				IpAddr::V6(a) => c.contains(a),
154			},
155		}
156	}
157
158	pub(crate) const fn _range_pair(&self) -> IpInetPair {
159		match self {
160			Self::V4(c) => IpInetPair::V4(c._range_pair()),
161			Self::V6(c) => IpInetPair::V6(c._range_pair()),
162		}
163	}
164}
165
166impl PrivCidr for IpCidr {}
167
168impl Cidr for IpCidr {
169	type Address = IpAddr;
170
171	fn new(addr: IpAddr, len: u8) -> Result<Self, NetworkParseError> {
172		Self::new(addr, len)
173	}
174
175	fn new_host(addr: IpAddr) -> Self {
176		Self::new_host(addr)
177	}
178
179	fn iter(&self) -> InetIterator<IpAddr> {
180		self.iter()
181	}
182
183	fn first_address(&self) -> IpAddr {
184		self.first_address()
185	}
186
187	fn first(&self) -> IpInet {
188		self.first()
189	}
190
191	fn last_address(&self) -> IpAddr {
192		self.last_address()
193	}
194
195	fn last(&self) -> IpInet {
196		self.last()
197	}
198
199	fn network_length(&self) -> u8 {
200		self.network_length()
201	}
202
203	fn family(&self) -> Family {
204		self.family()
205	}
206
207	fn is_host_address(&self) -> bool {
208		self.is_host_address()
209	}
210
211	fn mask(&self) -> IpAddr {
212		self.mask()
213	}
214
215	fn contains(&self, addr: &IpAddr) -> bool {
216		self.contains(addr)
217	}
218}
219
220impl fmt::Display for IpCidr {
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 FromStr for IpCidr {
230	type Err = NetworkParseError;
231
232	fn from_str(s: &str) -> Result<Self, NetworkParseError> {
233		crate::parsers::parse_cidr(s, FromStr::from_str)
234	}
235}
236
237impl From<Ipv4Cidr> for IpCidr {
238	fn from(c: Ipv4Cidr) -> Self {
239		Self::V4(c)
240	}
241}
242
243impl From<Ipv4Addr> for IpCidr {
244	fn from(address: Ipv4Addr) -> Self {
245		Self::V4(address.into())
246	}
247}
248
249impl From<Ipv6Cidr> for IpCidr {
250	fn from(c: Ipv6Cidr) -> Self {
251		Self::V6(c)
252	}
253}
254
255impl From<Ipv6Addr> for IpCidr {
256	fn from(address: Ipv6Addr) -> Self {
257		Self::V6(address.into())
258	}
259}
260
261impl From<IpAddr> for IpCidr {
262	fn from(address: IpAddr) -> Self {
263		Self::new_host(address)
264	}
265}
266
267impl IntoIterator for IpCidr {
268	type IntoIter = InetIterator<IpAddr>;
269	type Item = IpInet;
270
271	fn into_iter(self) -> Self::IntoIter {
272		InetIterator::_new(self._range_pair())
273	}
274}