cidr/inet/
combined.rs

1use core::{
2	fmt,
3	str::FromStr,
4};
5use std::net::IpAddr;
6
7use super::from_str::inet_from_str;
8use crate::{
9	errors::*,
10	internal_traits::PrivInet,
11	Family,
12	Inet,
13	IpCidr,
14	IpInet,
15	Ipv4Inet,
16	Ipv6Inet,
17};
18
19impl IpInet {
20	/// Whether representing an IPv4 network
21	pub const fn is_ipv4(&self) -> bool {
22		match self {
23			Self::V4(_) => true,
24			Self::V6(_) => false,
25		}
26	}
27
28	/// Whether representing an IPv6 network
29	pub const fn is_ipv6(&self) -> bool {
30		match self {
31			Self::V4(_) => false,
32			Self::V6(_) => true,
33		}
34	}
35
36	// --- copy of trait api
37
38	/// Create new host within a network from address and prefix length.
39	/// If the network length exceeds the address length an error is
40	/// returned.
41	pub const fn new(addr: IpAddr, len: u8) -> Result<Self, NetworkLengthTooLongError> {
42		match addr {
43			IpAddr::V4(a) => match Ipv4Inet::new(a, len) {
44				Ok(inet) => Ok(Self::V4(inet)),
45				Err(e) => Err(e),
46			},
47			IpAddr::V6(a) => match Ipv6Inet::new(a, len) {
48				Ok(inet) => Ok(Self::V6(inet)),
49				Err(e) => Err(e),
50			},
51		}
52	}
53
54	/// Create a network containing a single address as host and the
55	/// network (network length = address length).
56	pub const fn new_host(addr: IpAddr) -> Self {
57		match addr {
58			IpAddr::V4(a) => Self::V4(Ipv4Inet::new_host(a)),
59			IpAddr::V6(a) => Self::V6(Ipv6Inet::new_host(a)),
60		}
61	}
62
63	/// increments host part (without changing the network part);
64	/// returns true on wrap around
65	pub fn increment(&mut self) -> bool {
66		match self {
67			Self::V4(mut c) => c.increment(),
68			Self::V6(mut c) => c.increment(),
69		}
70	}
71
72	/// Returns next address in network or `None` if it was the last address in the network
73	pub const fn next(self) -> Option<Self> {
74		match self {
75			Self::V4(c) => match c.next() {
76				Some(c) => Some(Self::V4(c)),
77				None => None,
78			},
79			Self::V6(c) => match c.next() {
80				Some(c) => Some(Self::V6(c)),
81				None => None,
82			},
83		}
84	}
85
86	/// decrements host part (without changing the network part);
87	/// returns true on wrap around
88	pub fn decrement(&mut self) -> bool {
89		match self {
90			Self::V4(mut c) => c.decrement(),
91			Self::V6(mut c) => c.decrement(),
92		}
93	}
94
95	/// Returns previous address in network or `None` if it was the first address in the network
96	pub const fn previous(self) -> Option<Self> {
97		match self {
98			Self::V4(c) => match c.previous() {
99				Some(c) => Some(Self::V4(c)),
100				None => None,
101			},
102			Self::V6(c) => match c.previous() {
103				Some(c) => Some(Self::V6(c)),
104				None => None,
105			},
106		}
107	}
108
109	/// Find the nth host after the current one in the current network
110	///
111	/// Returned boolean indicates whether an overflow occured.
112	pub const fn overflowing_add(self, step: u128) -> (Self, bool) {
113		match self {
114			Self::V4(c) => {
115				let (c, overflow) = c.overflowing_add(step);
116				(Self::V4(c), overflow)
117			},
118			Self::V6(c) => {
119				let (c, overflow) = c.overflowing_add(step);
120				(Self::V6(c), overflow)
121			},
122		}
123	}
124
125	/// Find the nth host before the current one in the current network
126	///
127	/// Returned boolean indicates whether an overflow occured.
128	pub const fn overflowing_sub(self, step: u128) -> (Self, bool) {
129		match self {
130			Self::V4(c) => {
131				let (c, overflow) = c.overflowing_sub(step);
132				(Self::V4(c), overflow)
133			},
134			Self::V6(c) => {
135				let (c, overflow) = c.overflowing_sub(step);
136				(Self::V6(c), overflow)
137			},
138		}
139	}
140
141	/// network (i.e. drops the host information)
142	pub const fn network(&self) -> IpCidr {
143		match self {
144			Self::V4(c) => IpCidr::V4(c.network()),
145			Self::V6(c) => IpCidr::V6(c.network()),
146		}
147	}
148
149	/// the host
150	pub const fn address(&self) -> IpAddr {
151		match self {
152			Self::V4(c) => IpAddr::V4(c.address()),
153			Self::V6(c) => IpAddr::V6(c.address()),
154		}
155	}
156
157	/// first address in the network as plain address
158	pub const fn first_address(&self) -> IpAddr {
159		match self {
160			Self::V4(c) => IpAddr::V4(c.first_address()),
161			Self::V6(c) => IpAddr::V6(c.first_address()),
162		}
163	}
164
165	/// first address in the network
166	pub const fn first(&self) -> Self {
167		match self {
168			Self::V4(c) => Self::V4(c.first()),
169			Self::V6(c) => Self::V6(c.first()),
170		}
171	}
172
173	/// last address in the network as plain address
174	pub const fn last_address(&self) -> IpAddr {
175		match self {
176			Self::V4(c) => IpAddr::V4(c.last_address()),
177			Self::V6(c) => IpAddr::V6(c.last_address()),
178		}
179	}
180
181	/// last address in the network
182	pub const fn last(&self) -> Self {
183		match self {
184			Self::V4(c) => Self::V4(c.last()),
185			Self::V6(c) => Self::V6(c.last()),
186		}
187	}
188
189	/// length in bits of the shared prefix of the contained addresses
190	pub const fn network_length(&self) -> u8 {
191		match self {
192			Self::V4(c) => c.network_length(),
193			Self::V6(c) => c.network_length(),
194		}
195	}
196
197	/// IP family of the contained address ([`Ipv4`] or [`Ipv6`]).
198	///
199	/// [`Ipv4`]: Family::Ipv4
200	/// [`Ipv6`]: Family::Ipv6
201	pub const fn family(&self) -> Family {
202		match self {
203			Self::V4(_) => Family::Ipv4,
204			Self::V6(_) => Family::Ipv6,
205		}
206	}
207
208	/// whether network represents a single host address
209	pub const fn is_host_address(&self) -> bool {
210		match self {
211			Self::V4(c) => c.is_host_address(),
212			Self::V6(c) => c.is_host_address(),
213		}
214	}
215
216	/// network mask: an pseudo address which has the first `network
217	/// length` bits set to 1 and the remaining to 0.
218	pub const fn mask(&self) -> IpAddr {
219		match self {
220			Self::V4(c) => IpAddr::V4(c.mask()),
221			Self::V6(c) => IpAddr::V6(c.mask()),
222		}
223	}
224
225	/// check whether an address is contained in the network
226	pub const fn contains(&self, addr: &IpAddr) -> bool {
227		match self {
228			Self::V4(c) => match addr {
229				IpAddr::V4(a) => c.contains(a),
230				IpAddr::V6(_) => false,
231			},
232			Self::V6(c) => match addr {
233				IpAddr::V4(_) => false,
234				IpAddr::V6(a) => c.contains(a),
235			},
236		}
237	}
238}
239
240impl PrivInet for IpInet {}
241
242impl Inet for IpInet {
243	type Address = IpAddr;
244
245	fn new(addr: IpAddr, len: u8) -> Result<Self, NetworkLengthTooLongError> {
246		Self::new(addr, len)
247	}
248
249	fn new_host(addr: IpAddr) -> Self {
250		Self::new_host(addr)
251	}
252
253	fn increment(&mut self) -> bool {
254		self.increment()
255	}
256
257	fn next(self) -> Option<Self> {
258		self.next()
259	}
260
261	fn decrement(&mut self) -> bool {
262		self.decrement()
263	}
264
265	fn previous(self) -> Option<Self> {
266		self.previous()
267	}
268
269	fn overflowing_add(self, step: u128) -> (Self, bool) {
270		self.overflowing_add(step)
271	}
272
273	fn overflowing_sub(self, step: u128) -> (Self, bool) {
274		self.overflowing_sub(step)
275	}
276
277	fn network(&self) -> IpCidr {
278		self.network()
279	}
280
281	fn address(&self) -> IpAddr {
282		self.address()
283	}
284
285	fn first_address(&self) -> IpAddr {
286		self.first_address()
287	}
288
289	fn first(&self) -> Self {
290		self.first()
291	}
292
293	fn last_address(&self) -> IpAddr {
294		self.last_address()
295	}
296
297	fn last(&self) -> Self {
298		self.last()
299	}
300
301	fn network_length(&self) -> u8 {
302		self.network_length()
303	}
304
305	fn family(&self) -> Family {
306		self.family()
307	}
308
309	fn is_host_address(&self) -> bool {
310		self.is_host_address()
311	}
312
313	fn mask(&self) -> IpAddr {
314		self.mask()
315	}
316
317	fn contains(&self, addr: &IpAddr) -> bool {
318		self.contains(addr)
319	}
320}
321
322impl fmt::Display for IpInet {
323	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
324		match self {
325			Self::V4(c) => fmt::Display::fmt(c, f),
326			Self::V6(c) => fmt::Display::fmt(c, f),
327		}
328	}
329}
330
331impl FromStr for IpInet {
332	type Err = NetworkParseError;
333
334	fn from_str(s: &str) -> Result<Self, NetworkParseError> {
335		inet_from_str(s)
336	}
337}
338
339impl From<Ipv4Inet> for IpInet {
340	fn from(c: Ipv4Inet) -> Self {
341		Self::V4(c)
342	}
343}
344
345impl From<Ipv6Inet> for IpInet {
346	fn from(c: Ipv6Inet) -> Self {
347		Self::V6(c)
348	}
349}
350
351impl core::ops::Add<u128> for IpInet {
352	type Output = IpInet;
353
354	fn add(self, step: u128) -> Self::Output {
355		let (result, overflow) = self.overflowing_add(step);
356		debug_assert!(!overflow, "{} + {} overflow", self, step);
357		result
358	}
359}
360
361impl core::ops::Sub<u128> for IpInet {
362	type Output = IpInet;
363
364	fn sub(self, step: u128) -> Self::Output {
365		let (result, overflow) = self.overflowing_sub(step);
366		debug_assert!(!overflow, "{} - {} overflow", self, step);
367		result
368	}
369}