1use std::{fmt, iter::Iterator};
2
3use crate::errors::*;
4
5pub fn assert_iter_eq<T, U>(x: T, y: U)
14where
15 T: IntoIterator,
16 U: IntoIterator,
17 T::Item: fmt::Debug + PartialEq<U::Item>,
18 U::Item: fmt::Debug,
19{
20 let mut x = x.into_iter();
21 let mut y = y.into_iter();
22 loop {
23 let (a, b) = (x.next(), y.next());
24 if a.is_none() && b.is_none() {
25 return;
26 }
27 let equal = match (&a, &b) {
28 (Some(a), Some(b)) => a == b,
30
31 _ => false,
33 };
34 assert!(equal, "Iterators not equal {:?} != {:?}", a, b);
35 }
36}
37
38pub trait IteratorExt: Iterator {
40 fn consume(self) -> Self
50 where
51 Self: Sized;
52
53 fn drop(self, n: isize) -> Self
65 where
66 Self: Sized,
67 Self: DoubleEndedIterator;
68
69 fn first(self) -> Option<Self::Item>
81 where
82 Self: Sized;
83
84 fn first_result(self) -> RvResult<Self::Item>
94 where
95 Self: Sized;
96
97 fn last_result(self) -> RvResult<Self::Item>
107 where
108 Self: Sized;
109
110 fn single(self) -> RvResult<Self::Item>
120 where
121 Self: Sized;
122
123 fn slice(self, left: isize, right: isize) -> Self
146 where
147 Self: Sized,
148 Self: Clone,
149 Self: DoubleEndedIterator;
150
151 fn some(self) -> bool
160 where
161 Self: Sized;
162}
163
164impl<T: ?Sized> IteratorExt for T
165where
166 T: Iterator,
167{
168 #[allow(clippy::all)]
169 fn consume(mut self) -> Self
170 where
171 Self: Sized,
172 {
173 let mut iter = (&mut self).peekable();
174 while let Some(_) = iter.next() {}
175 self
176 }
177
178 fn drop(mut self, n: isize) -> Self
179 where
180 Self: Sized,
181 Self: DoubleEndedIterator,
182 {
183 if n > 0 {
185 self.nth(n as usize - 1);
186 }
187
188 if n < 0 {
190 (&mut self).rev().nth(n.unsigned_abs() - 1);
191 }
192 self
193 }
194
195 fn first(mut self) -> Option<Self::Item>
196 where
197 Self: Sized,
198 {
199 self.next()
200 }
201
202 fn first_result(mut self) -> RvResult<Self::Item>
203 where
204 Self: Sized,
205 {
206 match self.next() {
207 Some(first) => Ok(first),
208 None => Err(IterError::item_not_found().into()),
209 }
210 }
211
212 fn last_result(self) -> RvResult<Self::Item>
213 where
214 Self: Sized,
215 {
216 match self.last() {
217 Some(item) => Ok(item),
218 None => Err(IterError::item_not_found().into()),
219 }
220 }
221
222 fn single(mut self) -> RvResult<Self::Item>
223 where
224 Self: Sized,
225 {
226 match self.next() {
227 Some(item) => match self.next() {
228 Some(_) => Err(IterError::multiple_items_found().into()),
229 None => Ok(item),
230 },
231 None => Err(IterError::item_not_found().into()),
232 }
233 }
234
235 fn slice(mut self, left: isize, right: isize) -> Self
236 where
237 Self: Sized,
238 Self: Clone,
239 Self: DoubleEndedIterator,
240 {
241 let (mut l, mut r): (usize, usize) = (left as usize, 0);
243 let len = (self.clone()).count() as isize;
244 if left < 0 {
245 l = (len + left) as usize;
246 }
247 if l > 0 {
248 self.nth(l - 1);
249 }
250
251 if right > 0 && right < len {
254 r = (right - len + 1).unsigned_abs();
255 } else if right < 0 && right.abs() <= len {
256 r = (right.abs() - 1).unsigned_abs();
257 } else if right < 0 {
258 r = len as usize;
259 }
260 if r > 0 {
261 (&mut self).rev().nth(r - 1);
262 }
263
264 if left == 0 && right == 0 {
266 let i = len - 2;
267 if i > 0 {
268 (&mut self).rev().nth(i as usize);
269 }
270 }
271
272 self
273 }
274
275 fn some(mut self) -> bool
276 where
277 Self: Sized,
278 {
279 self.next().is_some()
280 }
281}
282
283#[cfg(test)]
284mod tests {
285 use std::ffi::OsStr;
286 use std::path::{Component, PathBuf};
287
288 use crate::core::*;
289 use crate::errors::*;
290
291 #[test]
292 fn test_slice() {
293 assert_eq!(vec![0, 1, 2, 3].into_iter().slice(-1, -5).next(), None); assert_iter_eq(vec![0, 1, 2, 3], vec![0, 1, 2, 3].into_iter().slice(-4, -1)); assert_iter_eq(vec![0, 1, 2], vec![0, 1, 2, 3].into_iter().slice(-4, -2)); assert_iter_eq(vec![0, 1], vec![0, 1, 2, 3].into_iter().slice(-4, -3)); assert_iter_eq(vec![3], vec![0, 1, 2, 3].into_iter().slice(-1, -1)); assert_iter_eq(vec![2], vec![0, 1, 2, 3].into_iter().slice(-2, -2)); assert_iter_eq(vec![1], vec![0, 1, 2, 3].into_iter().slice(-3, -3)); assert_iter_eq(vec![0], vec![0, 1, 2, 3].into_iter().slice(-4, -4)); assert_iter_eq(vec![1, 2, 3], vec![0, 1, 2, 3].into_iter().slice(-3, -1)); assert_iter_eq(vec![1, 2], vec![0, 1, 2, 3].into_iter().slice(-3, -2)); assert_eq!(vec![0, 1, 2, 3].into_iter().slice(-1, -2).next(), None); assert_iter_eq(vec![0, 1, 2, 3], vec![0, 1, 2, 3].into_iter().slice(0, 4)); assert_iter_eq(vec![0, 1, 2, 3], vec![0, 1, 2, 3].into_iter().slice(0, 3)); assert_iter_eq(vec![0, 1, 2], vec![0, 1, 2, 3].into_iter().slice(0, 2)); assert_iter_eq(vec![0, 1], vec![0, 1, 2, 3].into_iter().slice(0, 1)); assert_iter_eq(vec![3], vec![0, 1, 2, 3].into_iter().slice(3, 3)); assert_iter_eq(vec![2], vec![0, 1, 2, 3].into_iter().slice(2, 2)); assert_iter_eq(vec![1], vec![0, 1, 2, 3].into_iter().slice(1, 1)); assert_iter_eq(vec![0], vec![0, 1, 2, 3].into_iter().slice(0, 0)); assert_iter_eq(vec![1, 2, 3], vec![0, 1, 2, 3].into_iter().slice(1, 3)); assert_iter_eq(vec![1, 2], vec![0, 1, 2, 3].into_iter().slice(1, 2)); assert_eq!(vec![0, 1, 2, 3].into_iter().slice(3, 2).next(), None); assert_eq!(vec![0, 1, 2, 3].into_iter().slice(4, 3).next(), None); assert_eq!(vec![0, 1, 2, 3].into_iter().slice(0, -5).next(), None); assert_iter_eq(vec![0, 1, 2, 3], vec![0, 1, 2, 3].into_iter().slice(0, -1)); assert_iter_eq(vec![0, 1, 2], vec![0, 1, 2, 3].into_iter().slice(0, -2)); assert_iter_eq(vec![0, 1], vec![0, 1, 2, 3].into_iter().slice(0, -3)); assert_iter_eq(vec![3], vec![0, 1, 2, 3].into_iter().slice(3, -1)); assert_iter_eq(vec![2], vec![0, 1, 2, 3].into_iter().slice(2, -2)); assert_iter_eq(vec![1], vec![0, 1, 2, 3].into_iter().slice(1, -3)); assert_iter_eq(vec![0], vec![0, 1, 2, 3].into_iter().slice(0, -4)); assert_iter_eq(vec![1, 2, 3], vec![0, 1, 2, 3].into_iter().slice(1, -1)); assert_iter_eq(vec![1, 2], vec![0, 1, 2, 3].into_iter().slice(1, -2)); assert_eq!(vec![0, 1, 2, 3].into_iter().slice(3, -2).next(), None); assert_eq!(vec![0, 1, 2, 3].into_iter().slice(4, -1).next(), None); }
335
336 #[test]
337 fn test_consume() {
338 assert_eq!(vec![0].into_iter().nth(0), Some(0));
339 assert_eq!(vec![0, 1, 2].into_iter().consume().nth(0), None);
340 }
341
342 #[test]
343 fn test_drop() {
344 assert_iter_eq(vec![2, 3], vec![1, 2, 3].into_iter().drop(1));
346 assert_iter_eq(PathBuf::from("bar").components(), PathBuf::from("foo/bar").components().drop(1));
347 assert_iter_eq(PathBuf::from("bar").components(), PathBuf::from("/foo/bar").components().drop(2));
348
349 assert_iter_eq(vec![1, 2], vec![1, 2, 3].into_iter().drop(-1));
351 assert_eq!(1, vec![1, 2, 3].into_iter().drop(-1).next().unwrap());
352 assert_iter_eq(PathBuf::from("foo").components(), PathBuf::from("foo/bar").components().drop(-1));
353 assert_iter_eq(PathBuf::from("/").components(), PathBuf::from("/foo/bar").components().drop(-2));
354 }
355
356 #[test]
357 fn test_eq() {
358 assert_iter_eq(vec![1, 2], vec![1, 2]);
359 assert!(std::panic::catch_unwind(|| assert_iter_eq(vec![1, 2], vec![1])).is_err());
360 assert!(std::panic::catch_unwind(|| assert_iter_eq(vec![1, 2], vec![1, 3])).is_err());
361 assert_iter_eq(PathBuf::from("foo/bar").components(), PathBuf::from("foo/bar").components());
362 assert!(std::panic::catch_unwind(|| assert_iter_eq(
363 PathBuf::from("foo/bar").components(),
364 PathBuf::from("bar").components()
365 ))
366 .is_err());
367 }
368
369 #[test]
370 fn test_first() {
371 assert_eq!(Component::Normal(OsStr::new("foo")), PathBuf::from("foo/bar").components().first().unwrap());
372 assert_ne!(Component::Normal(OsStr::new("bar")), PathBuf::from("foo/bar").components().first().unwrap());
373 }
374
375 #[test]
376 fn test_first_result() {
377 assert_eq!(
378 Component::Normal(OsStr::new("foo")),
379 PathBuf::from("foo/bar").components().first_result().unwrap()
380 );
381 assert_ne!(
382 Component::Normal(OsStr::new("bar")),
383 PathBuf::from("foo/bar").components().first_result().unwrap()
384 );
385 }
386
387 #[test]
388 fn test_last_result() {
389 assert_eq!(
390 Component::Normal(OsStr::new("bar")),
391 PathBuf::from("foo/bar").components().last_result().unwrap()
392 );
393 assert_ne!(
394 Component::Normal(OsStr::new("foo")),
395 PathBuf::from("foo/bar").components().last_result().unwrap()
396 );
397 }
398
399 #[test]
400 fn test_single() {
401 assert_eq!((0..10).filter(|&x| x == 2).single().unwrap(), 2);
402 assert_eq!(
403 (0..10).filter(|&x| x > 2).single().unwrap_err().downcast_ref::<IterError>(),
404 Some(&IterError::multiple_items_found())
405 );
406 assert_eq!(
407 (0..10).filter(|&x| x > 2 && x < 5).single().unwrap_err().downcast_ref::<IterError>(),
408 Some(&IterError::multiple_items_found())
409 );
410 }
411
412 #[test]
413 fn test_some() {
414 assert_eq!((0..10).filter(|&x| x == 2).some(), true);
415 assert_eq!((0..10).filter(|&x| x == 11).some(), false);
416 }
417}