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