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 |