1 use itertools::{EitherOrBoth, Itertools};
2 use std::fmt::Debug;
3 use std::ops::BitXor;
4 use quickcheck::quickcheck;
5 
6 struct Unspecialized<I>(I);
7 impl<I> Iterator for Unspecialized<I>
8 where
9     I: Iterator,
10 {
11     type Item = I::Item;
12 
13     #[inline(always)]
next(&mut self) -> Option<I::Item>14     fn next(&mut self) -> Option<I::Item> {
15         self.0.next()
16     }
17 
18     #[inline(always)]
size_hint(&self) -> (usize, Option<usize>)19     fn size_hint(&self) -> (usize, Option<usize>) {
20         self.0.size_hint()
21     }
22 }
23 
check_specialized<'a, V, IterItem, Iter, F>(iterator: &Iter, mapper: F) where V: Eq + Debug, IterItem: 'a, Iter: Iterator<Item = IterItem> + Clone + 'a, F: Fn(Box<dyn Iterator<Item = IterItem> + 'a>) -> V,24 fn check_specialized<'a, V, IterItem, Iter, F>(iterator: &Iter, mapper: F)
25 where
26     V: Eq + Debug,
27     IterItem: 'a,
28     Iter: Iterator<Item = IterItem> + Clone + 'a,
29     F: Fn(Box<dyn Iterator<Item = IterItem> + 'a>) -> V,
30 {
31     assert_eq!(
32         mapper(Box::new(Unspecialized(iterator.clone()))),
33         mapper(Box::new(iterator.clone()))
34     )
35 }
36 
check_specialized_count_last_nth_sizeh<'a, IterItem, Iter>( it: &Iter, known_expected_size: Option<usize>, ) where IterItem: 'a + Eq + Debug, Iter: Iterator<Item = IterItem> + Clone + 'a,37 fn check_specialized_count_last_nth_sizeh<'a, IterItem, Iter>(
38     it: &Iter,
39     known_expected_size: Option<usize>,
40 ) where
41     IterItem: 'a + Eq + Debug,
42     Iter: Iterator<Item = IterItem> + Clone + 'a,
43 {
44     let size = it.clone().count();
45     if let Some(expected_size) = known_expected_size {
46         assert_eq!(size, expected_size);
47     }
48     check_specialized(it, |i| i.count());
49     check_specialized(it, |i| i.last());
50     for n in 0..size + 2 {
51         check_specialized(it, |mut i| i.nth(n));
52     }
53     let mut it_sh = it.clone();
54     for n in 0..size + 2 {
55         let len = it_sh.clone().count();
56         let (min, max) = it_sh.size_hint();
57         assert_eq!((size - n.min(size)), len);
58         assert!(min <= len);
59         if let Some(max) = max {
60             assert!(len <= max);
61         }
62         it_sh.next();
63     }
64 }
65 
check_specialized_fold_xor<'a, IterItem, Iter>(it: &Iter) where IterItem: 'a + BitXor + Eq + Debug + BitXor<<IterItem as BitXor>::Output, Output = <IterItem as BitXor>::Output> + Clone, <IterItem as BitXor>::Output: BitXor<Output = <IterItem as BitXor>::Output> + Eq + Debug + Clone, Iter: Iterator<Item = IterItem> + Clone + 'a,66 fn check_specialized_fold_xor<'a, IterItem, Iter>(it: &Iter)
67 where
68     IterItem: 'a
69         + BitXor
70         + Eq
71         + Debug
72         + BitXor<<IterItem as BitXor>::Output, Output = <IterItem as BitXor>::Output>
73         + Clone,
74     <IterItem as BitXor>::Output:
75         BitXor<Output = <IterItem as BitXor>::Output> + Eq + Debug + Clone,
76     Iter: Iterator<Item = IterItem> + Clone + 'a,
77 {
78     check_specialized(it, |mut i| {
79         let first = i.next().map(|f| f.clone() ^ (f.clone() ^ f));
80         i.fold(first, |acc, v: IterItem| acc.map(move |a| v ^ a))
81     });
82 }
83 
put_back_test(test_vec: Vec<i32>, known_expected_size: Option<usize>)84 fn put_back_test(test_vec: Vec<i32>, known_expected_size: Option<usize>) {
85     {
86         // Lexical lifetimes support
87         let pb = itertools::put_back(test_vec.iter());
88         check_specialized_count_last_nth_sizeh(&pb, known_expected_size);
89         check_specialized_fold_xor(&pb);
90     }
91 
92     let mut pb = itertools::put_back(test_vec.into_iter());
93     pb.put_back(1);
94     check_specialized_count_last_nth_sizeh(&pb, known_expected_size.map(|x| x + 1));
95     check_specialized_fold_xor(&pb)
96 }
97 
98 #[test]
put_back()99 fn put_back() {
100     put_back_test(vec![7, 4, 1], Some(3));
101 }
102 
103 quickcheck! {
104     fn put_back_qc(test_vec: Vec<i32>) -> () {
105         put_back_test(test_vec, None)
106     }
107 }
108 
merge_join_by_test(i1: Vec<usize>, i2: Vec<usize>, known_expected_size: Option<usize>)109 fn merge_join_by_test(i1: Vec<usize>, i2: Vec<usize>, known_expected_size: Option<usize>) {
110     let i1 = i1.into_iter();
111     let i2 = i2.into_iter();
112     let mjb = i1.clone().merge_join_by(i2.clone(), std::cmp::Ord::cmp);
113     check_specialized_count_last_nth_sizeh(&mjb, known_expected_size);
114     // Rust 1.24 compatibility:
115     fn eob_left_z(eob: EitherOrBoth<usize, usize>) -> usize {
116         eob.left().unwrap_or(0)
117     }
118     fn eob_right_z(eob: EitherOrBoth<usize, usize>) -> usize {
119         eob.left().unwrap_or(0)
120     }
121     fn eob_both_z(eob: EitherOrBoth<usize, usize>) -> usize {
122         let (a, b) = eob.both().unwrap_or((0, 0));
123         assert_eq!(a, b);
124         a
125     }
126     check_specialized_fold_xor(&mjb.clone().map(eob_left_z));
127     check_specialized_fold_xor(&mjb.clone().map(eob_right_z));
128     check_specialized_fold_xor(&mjb.clone().map(eob_both_z));
129 
130     // And the other way around
131     let mjb = i2.merge_join_by(i1, std::cmp::Ord::cmp);
132     check_specialized_count_last_nth_sizeh(&mjb, known_expected_size);
133     check_specialized_fold_xor(&mjb.clone().map(eob_left_z));
134     check_specialized_fold_xor(&mjb.clone().map(eob_right_z));
135     check_specialized_fold_xor(&mjb.clone().map(eob_both_z));
136 }
137 
138 #[test]
merge_join_by()139 fn merge_join_by() {
140     let i1 = vec![1, 3, 5, 7, 8, 9];
141     let i2 = vec![0, 3, 4, 5];
142     merge_join_by_test(i1, i2, Some(8));
143 }
144 
145 quickcheck! {
146     fn merge_join_by_qc(i1: Vec<usize>, i2: Vec<usize>) -> () {
147         merge_join_by_test(i1, i2, None)
148     }
149 }
150