cidr/inet/
direct.rs

1#[cfg(feature = "bitstring")]
2#[cfg_attr(doc_cfg, doc(cfg(feature = "bitstring")))]
3use bitstring::FixedBitString;
4
5use core::{
6	fmt,
7	str::FromStr,
8};
9use std::net::{
10	Ipv4Addr,
11	Ipv6Addr,
12};
13
14use super::from_str::inet_from_str;
15use crate::{
16	errors::*,
17	internal_traits::{
18		PrivInet,
19		PrivUnspecAddress,
20	},
21	Family,
22	Inet,
23	Ipv4Cidr,
24	Ipv4Inet,
25	Ipv6Cidr,
26	Ipv6Inet,
27};
28
29macro_rules! impl_inet_for {
30	($n:ident : cidr $cidr:ident : addr $addr:ident : pair $pair:ident : family $family:expr) => {
31		#[cfg(feature = "bitstring")]
32		#[cfg_attr(doc_cfg, doc(cfg(feature = "bitstring")))]
33		impl bitstring::BitString for $n {
34			fn get(&self, ndx: usize) -> bool {
35				self.address.get(ndx)
36			}
37
38			fn set(&mut self, ndx: usize, bit: bool) {
39				assert!(ndx < self.network_length as usize);
40				self.address.set(ndx, bit);
41			}
42
43			fn flip(&mut self, ndx: usize) {
44				assert!(ndx < self.network_length as usize);
45				self.address.flip(ndx);
46			}
47
48			fn len(&self) -> usize {
49				self.network_length as usize
50			}
51
52			fn clip(&mut self, len: usize) {
53				if len > 255 {
54					return;
55				}
56				self.address.set_false_from(len);
57				self.network_length = core::cmp::min(self.network_length, len as u8);
58			}
59
60			fn append(&mut self, bit: bool) {
61				self.address.set(self.network_length as usize, bit);
62				self.network_length += 1;
63			}
64
65			fn null() -> Self {
66				Self {
67					address: FixedBitString::new_all_false(),
68					network_length: 0,
69				}
70			}
71
72			fn shared_prefix_len(&self, other: &Self) -> usize {
73				let max_len = core::cmp::min(self.network_length, other.network_length) as usize;
74				FixedBitString::shared_prefix_len(&self.address, &other.address, max_len)
75			}
76		}
77
78		impl $n {
79			/// Create new host within a network from address and prefix length.
80			/// If the network length exceeds the address length an error is
81			/// returned.
82			pub const fn new(addr: $addr, len: u8) -> Result<Self, NetworkLengthTooLongError> {
83				if len > $family.len() {
84					Err(NetworkLengthTooLongError::new(len as usize, $family))
85				} else {
86					Ok(Self {
87						address: addr,
88						network_length: len,
89					})
90				}
91			}
92
93			/// Create a network containing a single address as host and the
94			/// network (network length = address length).
95			pub const fn new_host(addr: $addr) -> Self {
96				Self {
97					address: addr,
98					network_length: $family.len(),
99				}
100			}
101
102			/// increments host part (without changing the network part);
103			/// returns true on wrap around
104			pub fn increment(&mut self) -> bool {
105				let (address, overflow) = <$addr as PrivUnspecAddress>::_Tools::_overflowing_next(
106					self.address,
107					self.network_length,
108				);
109				self.address = address;
110				overflow
111			}
112
113			/// Returns next address in network or `None` if it was the last address in the network
114			pub const fn next(self) -> Option<Self> {
115				let (address, overflow) = <$addr as PrivUnspecAddress>::_Tools::_overflowing_next(
116					self.address,
117					self.network_length,
118				);
119				if overflow {
120					None
121				} else {
122					Some(Self {
123						address,
124						network_length: self.network_length,
125					})
126				}
127			}
128
129			/// decrements host part (without changing the network part);
130			/// returns true on wrap around
131			pub fn decrement(&mut self) -> bool {
132				let (address, overflow) = <$addr as PrivUnspecAddress>::_Tools::_overflowing_prev(
133					self.address,
134					self.network_length,
135				);
136				self.address = address;
137				overflow
138			}
139
140			/// Returns previous address in network or `None` if it was the first address in the network
141			pub const fn previous(self) -> Option<Self> {
142				let (address, overflow) = <$addr as PrivUnspecAddress>::_Tools::_overflowing_prev(
143					self.address,
144					self.network_length,
145				);
146				if overflow {
147					None
148				} else {
149					Some(Self {
150						address,
151						network_length: self.network_length,
152					})
153				}
154			}
155
156			/// Find the nth host after the current one in the current network
157			///
158			/// Returned boolean indicates whether an overflow occured.
159			pub const fn overflowing_add(self, step: u128) -> (Self, bool) {
160				let (address, overflow) = <$addr as PrivUnspecAddress>::_Tools::_overflowing_inc(
161					self.address,
162					self.network_length,
163					step,
164				);
165				(
166					Self {
167						address,
168						network_length: self.network_length,
169					},
170					overflow,
171				)
172			}
173
174			/// Find the nth host before the current one in the current network
175			///
176			/// Returned boolean indicates whether an overflow occured.
177			pub const fn overflowing_sub(self, step: u128) -> (Self, bool) {
178				let (address, overflow) = <$addr as PrivUnspecAddress>::_Tools::_overflowing_dec(
179					self.address,
180					self.network_length,
181					step,
182				);
183				(
184					Self {
185						address,
186						network_length: self.network_length,
187					},
188					overflow,
189				)
190			}
191
192			/// network (i.e. drops the host information)
193			pub const fn network(&self) -> $cidr {
194				$cidr {
195					address: self.first_address(),
196					network_length: self.network_length,
197				}
198			}
199
200			/// the host
201			pub const fn address(&self) -> $addr {
202				self.address
203			}
204
205			/// first address in the network as plain address
206			pub const fn first_address(&self) -> $addr {
207				<$addr as PrivUnspecAddress>::_Tools::_network_address(
208					self.address,
209					self.network_length,
210				)
211			}
212
213			/// first address in the network
214			pub const fn first(&self) -> Self {
215				Self {
216					address: self.first_address(),
217					network_length: self.network_length,
218				}
219			}
220
221			/// last address in the network as plain address
222			pub const fn last_address(&self) -> $addr {
223				<$addr as PrivUnspecAddress>::_Tools::_last_address(
224					self.address,
225					self.network_length,
226				)
227			}
228
229			/// last address in the network
230			pub const fn last(&self) -> Self {
231				Self {
232					address: self.last_address(),
233					network_length: self.network_length,
234				}
235			}
236
237			/// length in bits of the shared prefix of the contained addresses
238			pub const fn network_length(&self) -> u8 {
239				self.network_length
240			}
241
242			/// IP family of the contained address ([`Ipv4`] or [`Ipv6`]).
243			///
244			/// [`Ipv4`]: Family::Ipv4
245			/// [`Ipv6`]: Family::Ipv6
246			pub const fn family(&self) -> Family {
247				$family
248			}
249
250			/// whether network represents a single host address
251			pub const fn is_host_address(&self) -> bool {
252				self.network_length() == self.family().len()
253			}
254
255			/// network mask: an pseudo address which has the first `network
256			/// length` bits set to 1 and the remaining to 0.
257			pub const fn mask(&self) -> $addr {
258				<$addr as PrivUnspecAddress>::_Tools::_network_mask(self.network_length)
259			}
260
261			/// check whether an address is contained in the network
262			pub const fn contains(&self, addr: &$addr) -> bool {
263				<$addr as PrivUnspecAddress>::_Tools::_prefix_match(
264					self.address,
265					*addr,
266					self.network_length,
267				)
268			}
269		}
270
271		impl PrivInet for $n {}
272
273		impl Inet for $n {
274			type Address = $addr;
275
276			fn new(addr: $addr, len: u8) -> Result<Self, NetworkLengthTooLongError> {
277				Self::new(addr, len)
278			}
279
280			fn new_host(addr: $addr) -> Self {
281				Self::new_host(addr)
282			}
283
284			fn increment(&mut self) -> bool {
285				self.increment()
286			}
287
288			fn next(self) -> Option<Self> {
289				self.next()
290			}
291
292			fn decrement(&mut self) -> bool {
293				self.decrement()
294			}
295
296			fn previous(self) -> Option<Self> {
297				self.previous()
298			}
299
300			fn overflowing_add(self, step: u128) -> (Self, bool) {
301				self.overflowing_add(step)
302			}
303
304			fn overflowing_sub(self, step: u128) -> (Self, bool) {
305				self.overflowing_sub(step)
306			}
307
308			fn network(&self) -> $cidr {
309				self.network()
310			}
311
312			fn address(&self) -> $addr {
313				self.address()
314			}
315
316			fn first_address(&self) -> $addr {
317				self.first_address()
318			}
319
320			fn first(&self) -> Self {
321				self.first()
322			}
323
324			fn last_address(&self) -> $addr {
325				self.last_address()
326			}
327
328			fn last(&self) -> Self {
329				self.last()
330			}
331
332			fn network_length(&self) -> u8 {
333				self.network_length()
334			}
335
336			fn family(&self) -> Family {
337				self.family()
338			}
339
340			fn is_host_address(&self) -> bool {
341				self.is_host_address()
342			}
343
344			fn mask(&self) -> $addr {
345				self.mask()
346			}
347
348			fn contains(&self, addr: &$addr) -> bool {
349				self.contains(addr)
350			}
351		}
352
353		impl fmt::Debug for $n {
354			fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
355				write!(f, "{:?}/{}", self.address, self.network_length)
356			}
357		}
358
359		impl fmt::Display for $n {
360			fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
361				if f.alternate() || !self.is_host_address() {
362					write!(f, "{}/{}", self.address, self.network_length)?;
363				} else {
364					write!(f, "{}", self.address)?;
365				}
366				Ok(())
367			}
368		}
369
370		impl FromStr for $n {
371			type Err = NetworkParseError;
372
373			fn from_str(s: &str) -> Result<Self, NetworkParseError> {
374				inet_from_str(s)
375			}
376		}
377
378		impl core::ops::Add<u128> for $n {
379			type Output = $n;
380
381			fn add(self, step: u128) -> Self::Output {
382				let (result, overflow) = self.overflowing_add(step);
383				debug_assert!(!overflow, "{} + {} overflow", self, step);
384				result
385			}
386		}
387
388		impl core::ops::Sub<u128> for $n {
389			type Output = $n;
390
391			fn sub(self, step: u128) -> Self::Output {
392				let (result, overflow) = self.overflowing_sub(step);
393				debug_assert!(!overflow, "{} - {} overflow", self, step);
394				result
395			}
396		}
397	};
398}
399
400impl_inet_for! {Ipv4Inet : cidr Ipv4Cidr : addr Ipv4Addr : pair Ipv4InetPair : family Family::Ipv4}
401impl_inet_for! {Ipv6Inet : cidr Ipv6Cidr : addr Ipv6Addr : pair Ipv6InetPair : family Family::Ipv6}
402
403impl Ipv4Inet {
404	/// Find the nth host after the current one in the current network (32-bit IPv4 variant)
405	///
406	/// Returned boolean indicates whether an overflow occured.
407	pub const fn overflowing_add_u32(self, step: u32) -> (Self, bool) {
408		let (address, overflow) = <Ipv4Addr as PrivUnspecAddress>::_Tools::_overflowing_inc_u32(
409			self.address,
410			self.network_length,
411			step,
412		);
413		(
414			Self {
415				address,
416				network_length: self.network_length,
417			},
418			overflow,
419		)
420	}
421
422	/// Find the nth host before the current one in the current network (32-bit IPv4 variant)
423	///
424	/// Returned boolean indicates whether an overflow occured.
425	pub const fn overflowing_sub_u32(self, step: u32) -> (Self, bool) {
426		let (address, overflow) = <Ipv4Addr as PrivUnspecAddress>::_Tools::_overflowing_dec_u32(
427			self.address,
428			self.network_length,
429			step,
430		);
431		(
432			Self {
433				address,
434				network_length: self.network_length,
435			},
436			overflow,
437		)
438	}
439}
440
441impl core::ops::Add<u32> for Ipv4Inet {
442	type Output = Ipv4Inet;
443
444	fn add(self, step: u32) -> Self::Output {
445		let (result, overflow) = self.overflowing_add_u32(step);
446		debug_assert!(!overflow, "{} + {} overflow", self, step);
447		result
448	}
449}
450
451impl core::ops::Sub<u32> for Ipv4Inet {
452	type Output = Ipv4Inet;
453
454	fn sub(self, step: u32) -> Self::Output {
455		let (result, overflow) = self.overflowing_sub_u32(step);
456		debug_assert!(!overflow, "{} - {} overflow", self, step);
457		result
458	}
459}