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