1use core::ops::{Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive};
30
31mod impls;
32
33const ONE: u8 = 1;
34
35#[derive(Debug, Eq, PartialEq, Hash, Clone)]
70pub struct IPv4ComponentRange {
71 start: Option<u8>,
72 end: Option<u8>,
73}
74
75impl From<u8> for IPv4ComponentRange {
76
77 fn from(n: u8) -> Self {
78 Self {
79 start: Some(n),
80 end: Some(n),
81 }
82 }
83
84}
85
86impl From<Range<u8>> for IPv4ComponentRange {
87
88 fn from(range: Range<u8>) -> Self {
89 Self {
90 start: Some(range.start),
91 end: range.end.checked_sub(ONE),
92 }
93 }
94
95}
96
97impl From<RangeFrom<u8>> for IPv4ComponentRange {
98
99 fn from(range: RangeFrom<u8>) -> Self {
100 Self {
101 start: Some(range.start),
102 end: Some(u8::max_value()),
103 }
104 }
105
106}
107
108impl From<RangeFull> for IPv4ComponentRange {
109
110 fn from(_: RangeFull) -> Self {
111 Self {
112 start: Some(u8::min_value()),
113 end: Some(u8::max_value()),
114 }
115 }
116
117}
118
119impl From<RangeInclusive<u8>> for IPv4ComponentRange {
120
121 fn from(range: RangeInclusive<u8>) -> Self {
122 Self {
123 start: Some(*range.start()),
124 end: Some(*range.end()),
125 }
126 }
127
128}
129
130impl From<RangeTo<u8>> for IPv4ComponentRange {
131
132 fn from(range: RangeTo<u8>) -> Self {
133 Self {
134 start: Some(u8::min_value()),
135 end: range.end.checked_sub(ONE),
136 }
137 }
138
139}
140
141impl From<RangeToInclusive<u8>> for IPv4ComponentRange {
142
143 fn from(range: RangeToInclusive<u8>) -> Self {
144 Self {
145 start: Some(u8::min_value()),
146 end: Some(range.end),
147 }
148 }
149
150}
151
152impl Iterator for IPv4ComponentRange {
153
154 type Item = u8;
155
156 fn next(&mut self) -> Option<Self::Item> {
157 match (self.start, self.end) {
158 (Some(start), Some(end)) if start <= end => {
159 self.start = start.checked_add(ONE);
160 Some(start)
161 },
162 _ => None,
163 }
164 }
165
166 fn nth(&mut self, mut n: usize) -> Option<Self::Item> {
167 while n > 0 {
168 match (self.start, self.end) {
169 (Some(start), Some(end)) => match end.checked_sub(start).map(|skip| usize::from(skip).min(n)) {
170 Some(skip) if skip > 0 => {
171 self.start = Some(start + skip as u8);
172 n -= skip;
173 },
174 _ => self.start = None,
175 },
176 _ => return None,
177 };
178 }
179
180 self.next()
181 }
182
183 #[cfg(not(target_pointer_width = "8"))]
185 fn size_hint(&self) -> (usize, Option<usize>) {
186 match (self.start, self.end) {
187 (Some(start), Some(end)) if end >= start => {
188 let result = usize::from(end - start);
189 match result.checked_add(ONE.into()) {
190 None => (result, None),
191 Some(result) => (result, Some(result)),
192 }
193 },
194 _ => (0, Some(0)),
195 }
196 }
197
198}
199
200#[cfg(not(target_pointer_width = "8"))]
203impl ExactSizeIterator for IPv4ComponentRange {}
204
205#[test]
206fn test_iterator_nth() -> crate::Result<()> {
207 use alloc::vec::Vec;
208
209 for (range, size_hint, values) in [
210 (0..5, (5, Some(5)), (0_usize..=9).collect::<Vec<_>>()), (0..255, (255, Some(255)), (0..512).collect()),
211 ] {
212 for n in values {
213 let mut ipv4_component_range = IPv4ComponentRange::from(range.clone());
214
215 assert_eq!(ipv4_component_range.size_hint(), size_hint);
216 assert_eq!(size_hint.0, ipv4_component_range.clone().count());
217
218 if n < range.end.into() {
219 assert_eq!(n, ipv4_component_range.nth(n).unwrap().into());
220 } else {
221 assert!(ipv4_component_range.nth(n).is_none());
222 assert!(ipv4_component_range.next().is_none());
223 }
224 }
225 }
226 for (range, size_hint, values) in [
227 (0..=5, (6, Some(6)), (0_usize..=9).collect::<Vec<_>>()), (0..=255, (256, Some(256)), (0..512).collect()),
228 ] {
229 for n in values {
230 let mut ipv4_component_range = IPv4ComponentRange::from(range.clone());
231
232 assert_eq!(ipv4_component_range.size_hint(), size_hint);
233 assert_eq!(size_hint.0, ipv4_component_range.clone().count());
234
235 if n <= (*range.end()).into() {
236 assert_eq!(n, ipv4_component_range.nth(n).unwrap().into());
237 } else {
238 assert!(ipv4_component_range.nth(n).is_none());
239 assert!(ipv4_component_range.next().is_none());
240 }
241 }
242 }
243
244 Ok(())
245}
246
247#[test]
248fn test_iterator() -> crate::Result<()> {
249 use core::str::FromStr;
250
251 for range in ["[1,0]", "(0,0)", "(0,1)"] {
252 assert_eq!(IPv4ComponentRange::from_str(range)?.count(), 0);
253 }
254 for (range, expected) in [("0", 0), ("1", 1), ("[0,0]", 0), ("(0,1]", 1), ("(1,3)", 2)] {
255 let mut range = IPv4ComponentRange::from_str(range)?;
256 assert_eq!(range.size_hint(), (1, Some(1)));
257 assert_eq!(range.nth(0), Some(expected));
258 assert_eq!(range.next(), None);
259 }
260 for (range, expected) in [
261 ("(0,2)", None), ("(0,3)", Some(2)), ("(1,4)", Some(3)),
262 ("[0,2]", Some(1)), ("[0,3]", Some(1)), ("[1,4]", Some(2)),
263 ("[0,2)", Some(1)), ("[0,1)", None),
264 ("(1,3]", Some(3)), ("(1,2]", None),
265 ] {
266 let mut range = IPv4ComponentRange::from_str(range)?;
267 assert_eq!(range.nth(1), expected);
268 }
269
270 Ok(())
271}