cidr/
inet_iterator.rs

1use crate::{
2	internal_traits::PrivInetPair,
3	num::NumberOfAddresses,
4	Address,
5	Inet,
6	InetPair,
7};
8
9/// Iterator type to iterate over a list of IP addresses within a network
10#[derive(Clone, Copy, Debug)]
11pub struct InetIterator<A: Address> {
12	state: Option<A::InetPair>,
13}
14
15impl<A: Address> InetIterator<A> {
16	pub(crate) const fn _new(range_pair: A::InetPair) -> Self {
17		Self {
18			state: Some(range_pair),
19		}
20	}
21
22	/// Iterate only over addresses (without network prefix length)
23	pub const fn addresses(self) -> InetAddressIterator<A> {
24		InetAddressIterator { inner: self }
25	}
26}
27
28impl<A: Address> Iterator for InetIterator<A> {
29	type Item = A::Inet;
30
31	fn next(&mut self) -> Option<Self::Item> {
32		let state = self.state.as_mut().take()?;
33		let res = state.first();
34		if !state._inc_first() {
35			self.state = None;
36		}
37		Some(res)
38	}
39
40	fn size_hint(&self) -> (usize, Option<usize>) {
41		let state = match &self.state {
42			None => return (0, Some(0)),
43			Some(state) => state,
44		};
45		match state._covered_addresses() {
46			NumberOfAddresses::MaxIpv6Addresses => (0, None),
47			NumberOfAddresses::Count(c) => {
48				if c > (usize::MAX as u128) {
49					(usize::MAX, None)
50				} else {
51					let c = c as usize;
52					(c, Some(c))
53				}
54			},
55		}
56	}
57
58	fn count(self) -> usize
59	where
60		Self: Sized,
61	{
62		self.size_hint().1.expect("iterator count overflow")
63	}
64}
65
66impl<A: Address> core::iter::DoubleEndedIterator for InetIterator<A> {
67	fn next_back(&mut self) -> Option<Self::Item> {
68		let state = self.state.as_mut().take()?;
69		let res = state.second();
70		if !state._dec_second() {
71			self.state = None;
72		}
73		Some(res)
74	}
75}
76
77impl<A: Address> core::iter::FusedIterator for InetIterator<A> {}
78
79/// Iterator type to iterate over a list of IP addresses in a network
80#[derive(Clone, Copy, Debug)]
81pub struct InetAddressIterator<A: Address> {
82	inner: InetIterator<A>,
83}
84
85impl<A: Address> Iterator for InetAddressIterator<A> {
86	type Item = A;
87
88	fn next(&mut self) -> Option<Self::Item> {
89		Some(self.inner.next()?.address())
90	}
91
92	fn size_hint(&self) -> (usize, Option<usize>) {
93		self.inner.size_hint()
94	}
95
96	fn count(self) -> usize
97	where
98		Self: Sized,
99	{
100		self.inner.count()
101	}
102}
103
104impl<A: Address> core::iter::DoubleEndedIterator for InetAddressIterator<A> {
105	fn next_back(&mut self) -> Option<Self::Item> {
106		Some(self.inner.next_back()?.address())
107	}
108}
109
110impl<A: Address> core::iter::FusedIterator for InetAddressIterator<A> {}
111
112#[cfg(test)]
113mod tests {
114	use crate::{
115		IpCidr,
116		Ipv4Cidr,
117		Ipv6Cidr,
118	};
119	use std::net::{
120		IpAddr,
121		Ipv4Addr,
122		Ipv6Addr,
123	};
124
125	fn test_v4(s: &'static str, l: &[Ipv4Addr]) {
126		assert_eq!(
127			s.parse::<Ipv4Cidr>()
128				.unwrap()
129				.iter()
130				.addresses()
131				.collect::<Vec<_>>(),
132			l
133		);
134
135		assert_eq!(
136			s.parse::<IpCidr>()
137				.unwrap()
138				.iter()
139				.addresses()
140				.collect::<Vec<_>>(),
141			l.iter().map(|e| IpAddr::V4(*e)).collect::<Vec<_>>()
142		);
143
144		assert_eq!(
145			s.parse::<Ipv4Cidr>()
146				.unwrap()
147				.iter()
148				.addresses()
149				.rev()
150				.collect::<Vec<_>>(),
151			l.iter().cloned().rev().collect::<Vec<_>>(),
152		);
153
154		assert_eq!(
155			s.parse::<IpCidr>()
156				.unwrap()
157				.iter()
158				.addresses()
159				.rev()
160				.collect::<Vec<_>>(),
161			l.iter().map(|e| IpAddr::V4(*e)).rev().collect::<Vec<_>>(),
162		);
163	}
164
165	fn test_v6(s: &'static str, l: &[Ipv6Addr]) {
166		assert_eq!(
167			s.parse::<Ipv6Cidr>()
168				.unwrap()
169				.iter()
170				.addresses()
171				.collect::<Vec<_>>(),
172			l
173		);
174
175		assert_eq!(
176			s.parse::<IpCidr>()
177				.unwrap()
178				.iter()
179				.addresses()
180				.collect::<Vec<_>>(),
181			l.iter().map(|e| IpAddr::V6(*e)).collect::<Vec<_>>(),
182		);
183
184		assert_eq!(
185			s.parse::<Ipv6Cidr>()
186				.unwrap()
187				.iter()
188				.addresses()
189				.rev()
190				.collect::<Vec<_>>(),
191			l.iter().cloned().rev().collect::<Vec<_>>(),
192		);
193
194		assert_eq!(
195			s.parse::<IpCidr>()
196				.unwrap()
197				.iter()
198				.addresses()
199				.rev()
200				.collect::<Vec<_>>(),
201			l.iter().map(|e| IpAddr::V6(*e)).rev().collect::<Vec<_>>(),
202		);
203	}
204
205	#[test]
206	fn range_v4_28bit() {
207		test_v4(
208			"192.168.4.48/28",
209			&[
210				Ipv4Addr::new(192, 168, 4, 48),
211				Ipv4Addr::new(192, 168, 4, 49),
212				Ipv4Addr::new(192, 168, 4, 50),
213				Ipv4Addr::new(192, 168, 4, 51),
214				Ipv4Addr::new(192, 168, 4, 52),
215				Ipv4Addr::new(192, 168, 4, 53),
216				Ipv4Addr::new(192, 168, 4, 54),
217				Ipv4Addr::new(192, 168, 4, 55),
218				Ipv4Addr::new(192, 168, 4, 56),
219				Ipv4Addr::new(192, 168, 4, 57),
220				Ipv4Addr::new(192, 168, 4, 58),
221				Ipv4Addr::new(192, 168, 4, 59),
222				Ipv4Addr::new(192, 168, 4, 60),
223				Ipv4Addr::new(192, 168, 4, 61),
224				Ipv4Addr::new(192, 168, 4, 62),
225				Ipv4Addr::new(192, 168, 4, 63),
226			],
227		);
228	}
229
230	#[test]
231	fn range_v6_28bit() {
232		test_v6(
233			"::192.168.4.48/124",
234			&[
235				Ipv6Addr::new(0, 0, 0, 0, 0, 0, 192 * 256 + 168, 4 * 256 + 48),
236				Ipv6Addr::new(0, 0, 0, 0, 0, 0, 192 * 256 + 168, 4 * 256 + 49),
237				Ipv6Addr::new(0, 0, 0, 0, 0, 0, 192 * 256 + 168, 4 * 256 + 50),
238				Ipv6Addr::new(0, 0, 0, 0, 0, 0, 192 * 256 + 168, 4 * 256 + 51),
239				Ipv6Addr::new(0, 0, 0, 0, 0, 0, 192 * 256 + 168, 4 * 256 + 52),
240				Ipv6Addr::new(0, 0, 0, 0, 0, 0, 192 * 256 + 168, 4 * 256 + 53),
241				Ipv6Addr::new(0, 0, 0, 0, 0, 0, 192 * 256 + 168, 4 * 256 + 54),
242				Ipv6Addr::new(0, 0, 0, 0, 0, 0, 192 * 256 + 168, 4 * 256 + 55),
243				Ipv6Addr::new(0, 0, 0, 0, 0, 0, 192 * 256 + 168, 4 * 256 + 56),
244				Ipv6Addr::new(0, 0, 0, 0, 0, 0, 192 * 256 + 168, 4 * 256 + 57),
245				Ipv6Addr::new(0, 0, 0, 0, 0, 0, 192 * 256 + 168, 4 * 256 + 58),
246				Ipv6Addr::new(0, 0, 0, 0, 0, 0, 192 * 256 + 168, 4 * 256 + 59),
247				Ipv6Addr::new(0, 0, 0, 0, 0, 0, 192 * 256 + 168, 4 * 256 + 60),
248				Ipv6Addr::new(0, 0, 0, 0, 0, 0, 192 * 256 + 168, 4 * 256 + 61),
249				Ipv6Addr::new(0, 0, 0, 0, 0, 0, 192 * 256 + 168, 4 * 256 + 62),
250				Ipv6Addr::new(0, 0, 0, 0, 0, 0, 192 * 256 + 168, 4 * 256 + 63),
251			],
252		);
253	}
254}