1 use itertools::Itertools;
2 use std::fmt::Debug;
3 use quickcheck::quickcheck;
4 
5 struct Unspecialized<I>(I);
6 impl<I> Iterator for Unspecialized<I>
7 where
8     I: Iterator,
9 {
10     type Item = I::Item;
11 
12     #[inline(always)]
next(&mut self) -> Option<Self::Item>13     fn next(&mut self) -> Option<Self::Item> {
14         self.0.next()
15     }
16 }
17 
check_specialized<'a, V, IterItem, Iter, F>(iterator: &Iter, mapper: F) where V: Eq + Debug, Iter: Iterator<Item = IterItem> + Clone + 'a, F: Fn(Box<dyn Iterator<Item = IterItem> + 'a>) -> V,18 fn check_specialized<'a, V, IterItem, Iter, F>(iterator: &Iter, mapper: F)
19 where
20     V: Eq + Debug,
21     Iter: Iterator<Item = IterItem> + Clone + 'a,
22     F: Fn(Box<dyn Iterator<Item = IterItem> + 'a>) -> V,
23 {
24     assert_eq!(
25         mapper(Box::new(Unspecialized(iterator.clone()))),
26         mapper(Box::new(iterator.clone()))
27     )
28 }
29 
test_specializations<IterItem, Iter>( it: &Iter, ) where IterItem: Eq + Debug + Clone, Iter: Iterator<Item = IterItem> + Clone,30 fn test_specializations<IterItem, Iter>(
31     it: &Iter,
32 ) where
33     IterItem: Eq + Debug + Clone,
34     Iter: Iterator<Item = IterItem> + Clone,
35 {
36     check_specialized(it, |i| i.count());
37     check_specialized(it, |i| i.last());
38     check_specialized(it, |i| i.collect::<Vec<_>>());
39     check_specialized(it, |i| {
40         let mut parameters_from_fold = vec![];
41         let fold_result = i.fold(vec![], |mut acc, v: IterItem| {
42             parameters_from_fold.push((acc.clone(), v.clone()));
43             acc.push(v);
44             acc
45         });
46         (parameters_from_fold, fold_result)
47     });
48     check_specialized(it, |mut i| {
49         let mut parameters_from_all = vec![];
50         let first = i.next();
51         let all_result = i.all(|x| {
52             parameters_from_all.push(x.clone());
53             Some(x)==first
54         });
55         (parameters_from_all, all_result)
56     });
57     let size = it.clone().count();
58     for n in 0..size + 2 {
59         check_specialized(it, |mut i| i.nth(n));
60     }
61     // size_hint is a bit harder to check
62     let mut it_sh = it.clone();
63     for n in 0..size + 2 {
64         let len = it_sh.clone().count();
65         let (min, max) = it_sh.size_hint();
66         assert_eq!(size - n.min(size), len);
67         assert!(min <= len);
68         if let Some(max) = max {
69             assert!(len <= max);
70         }
71         it_sh.next();
72     }
73 }
74 
75 quickcheck! {
76     fn put_back_qc(test_vec: Vec<i32>) -> () {
77         test_specializations(&itertools::put_back(test_vec.iter()));
78         let mut pb = itertools::put_back(test_vec.into_iter());
79         pb.put_back(1);
80         test_specializations(&pb);
81     }
82 }
83 
84 quickcheck! {
85     fn merge_join_by_qc(i1: Vec<usize>, i2: Vec<usize>) -> () {
86         test_specializations(&i1.into_iter().merge_join_by(i2.into_iter(), std::cmp::Ord::cmp));
87     }
88 }
89 
90 quickcheck! {
91     fn map_into(v: Vec<u8>) -> () {
92         test_specializations(&v.into_iter().map_into::<u32>());
93     }
94 }
95 
96 quickcheck! {
97     fn map_ok(v: Vec<Result<u8, char>>) -> () {
98         test_specializations(&v.into_iter().map_ok(|u| u.checked_add(1)));
99     }
100 }
101