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)] |
13 | fn next(&mut self) -> Option<Self::Item> { |
14 | self.0.next() |
15 | } |
16 | } |
17 | |
18 | macro_rules! check_specialized { |
19 | ($src:expr, |$it:pat| $closure:expr) => { |
20 | let $it = $src.clone(); |
21 | let v1 = $closure; |
22 | |
23 | let $it = Unspecialized($src.clone()); |
24 | let v2 = $closure; |
25 | |
26 | assert_eq!(v1, v2); |
27 | } |
28 | } |
29 | |
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 intersperse(v: Vec<u8>) -> () { |
77 | test_specializations(&v.into_iter().intersperse(0)); |
78 | } |
79 | } |
80 | |
81 | quickcheck! { |
82 | fn put_back_qc(test_vec: Vec<i32>) -> () { |
83 | test_specializations(&itertools::put_back(test_vec.iter())); |
84 | let mut pb = itertools::put_back(test_vec.into_iter()); |
85 | pb.put_back(1); |
86 | test_specializations(&pb); |
87 | } |
88 | } |
89 | |
90 | quickcheck! { |
91 | fn merge_join_by_qc(i1: Vec<usize>, i2: Vec<usize>) -> () { |
92 | test_specializations(&i1.into_iter().merge_join_by(i2.into_iter(), std::cmp::Ord::cmp)); |
93 | } |
94 | } |
95 | |
96 | quickcheck! { |
97 | fn map_into(v: Vec<u8>) -> () { |
98 | test_specializations(&v.into_iter().map_into::<u32>()); |
99 | } |
100 | } |
101 | |
102 | quickcheck! { |
103 | fn map_ok(v: Vec<Result<u8, char>>) -> () { |
104 | test_specializations(&v.into_iter().map_ok(|u| u.checked_add(1))); |
105 | } |
106 | } |
107 | |
108 | quickcheck! { |
109 | fn process_results(v: Vec<Result<u8, u8>>) -> () { |
110 | helper(v.iter().copied()); |
111 | helper(v.iter().copied().filter(Result::is_ok)); |
112 | |
113 | fn helper(it: impl Iterator<Item = Result<u8, u8>> + Clone) { |
114 | macro_rules! check_results_specialized { |
115 | ($src:expr, |$it:pat| $closure:expr) => { |
116 | assert_eq!( |
117 | itertools::process_results($src.clone(), |$it| $closure), |
118 | itertools::process_results($src.clone(), |i| { |
119 | let $it = Unspecialized(i); |
120 | $closure |
121 | }), |
122 | ) |
123 | } |
124 | } |
125 | |
126 | check_results_specialized!(it, |i| i.count()); |
127 | check_results_specialized!(it, |i| i.last()); |
128 | check_results_specialized!(it, |i| i.collect::<Vec<_>>()); |
129 | check_results_specialized!(it, |i| { |
130 | let mut parameters_from_fold = vec![]; |
131 | let fold_result = i.fold(vec![], |mut acc, v| { |
132 | parameters_from_fold.push((acc.clone(), v)); |
133 | acc.push(v); |
134 | acc |
135 | }); |
136 | (parameters_from_fold, fold_result) |
137 | }); |
138 | check_results_specialized!(it, |mut i| { |
139 | let mut parameters_from_all = vec![]; |
140 | let first = i.next(); |
141 | let all_result = i.all(|x| { |
142 | parameters_from_all.push(x); |
143 | Some(x)==first |
144 | }); |
145 | (parameters_from_all, all_result) |
146 | }); |
147 | let size = it.clone().count(); |
148 | for n in 0..size + 2 { |
149 | check_results_specialized!(it, |mut i| i.nth(n)); |
150 | } |
151 | } |
152 | } |
153 | } |
154 | |