Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 1 | use itertools::Itertools; |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 2 | use std::fmt::Debug; |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 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)] |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 13 | fn next(&mut self) -> Option<Self::Item> { |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 14 | self.0.next() |
| 15 | } |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 16 | } |
| 17 | |
David LeGare | b72e905 | 2022-03-02 16:21:08 +0000 | [diff] [blame] | 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 | } |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 28 | } |
| 29 | |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 30 | fn test_specializations<IterItem, Iter>( |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 31 | it: &Iter, |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 32 | ) where |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 33 | IterItem: Eq + Debug + Clone, |
| 34 | Iter: Iterator<Item = IterItem> + Clone, |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 35 | { |
David LeGare | b72e905 | 2022-03-02 16:21:08 +0000 | [diff] [blame] | 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| { |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 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 | }); |
David LeGare | b72e905 | 2022-03-02 16:21:08 +0000 | [diff] [blame] | 48 | check_specialized!(it, |mut i| { |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 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(); |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 58 | for n in 0..size + 2 { |
David LeGare | b72e905 | 2022-03-02 16:21:08 +0000 | [diff] [blame] | 59 | check_specialized!(it, |mut i| i.nth(n)); |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 60 | } |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 61 | // size_hint is a bit harder to check |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 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(); |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 66 | assert_eq!(size - n.min(size), len); |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 67 | assert!(min <= len); |
| 68 | if let Some(max) = max { |
| 69 | assert!(len <= max); |
| 70 | } |
| 71 | it_sh.next(); |
| 72 | } |
| 73 | } |
| 74 | |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 75 | quickcheck! { |
David LeGare | b72e905 | 2022-03-02 16:21:08 +0000 | [diff] [blame] | 76 | fn intersperse(v: Vec<u8>) -> () { |
| 77 | test_specializations(&v.into_iter().intersperse(0)); |
| 78 | } |
| 79 | } |
| 80 | |
| 81 | quickcheck! { |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 82 | fn put_back_qc(test_vec: Vec<i32>) -> () { |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 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); |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 87 | } |
| 88 | } |
| 89 | |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 90 | quickcheck! { |
| 91 | fn merge_join_by_qc(i1: Vec<usize>, i2: Vec<usize>) -> () { |
Joel Galenson | 6f79871 | 2021-04-01 17:03:06 -0700 | [diff] [blame] | 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))); |
Jakub Kotur | a425e55 | 2020-12-21 17:28:15 +0100 | [diff] [blame] | 105 | } |
| 106 | } |
David LeGare | b72e905 | 2022-03-02 16:21:08 +0000 | [diff] [blame] | 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.clone())); |
| 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.clone()); |
| 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 | } |