Skip to content

Commit b13e35f

Browse files
committed
Specialization test framework + tests
1 parent 33a2465 commit b13e35f

File tree

2 files changed

+136
-0
lines changed

2 files changed

+136
-0
lines changed

src/merge_join.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,23 @@ pub struct MergeJoinBy<I: Iterator, J: Iterator, F> {
3131
cmp_fn: F
3232
}
3333

34+
impl<I, J, F> Clone for MergeJoinBy<I, J, F>
35+
where
36+
I: Iterator,
37+
J: Iterator,
38+
PutBack<Fuse<I>>: Clone,
39+
PutBack<Fuse<J>>: Clone,
40+
F: Clone,
41+
{
42+
fn clone(&self) -> Self {
43+
MergeJoinBy {
44+
left: self.left.clone(),
45+
right: self.right.clone(),
46+
cmp_fn: self.cmp_fn.clone(),
47+
}
48+
}
49+
}
50+
3451
impl<I, J, F> fmt::Debug for MergeJoinBy<I, J, F>
3552
where I: Iterator + fmt::Debug,
3653
I::Item: fmt::Debug,

tests/specializations.rs

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
extern crate itertools;
2+
3+
use itertools::{EitherOrBoth, Itertools};
4+
5+
use std::fmt::Debug;
6+
use std::ops::BitXor;
7+
8+
struct Unspecialized<I>(I);
9+
impl<I> Iterator for Unspecialized<I>
10+
where
11+
I: Iterator,
12+
{
13+
type Item = I::Item;
14+
15+
#[inline(always)]
16+
fn next(&mut self) -> Option<I::Item> {
17+
self.0.next()
18+
}
19+
20+
#[inline(always)]
21+
fn size_hint(&self) -> (usize, Option<usize>) {
22+
self.0.size_hint()
23+
}
24+
}
25+
26+
fn check_specialized<'a, V, IterItem, Iter, F>(iterator: &Iter, mapper: F)
27+
where
28+
V: Eq + Debug,
29+
IterItem: 'a,
30+
Iter: Iterator<Item = IterItem> + Clone + 'a,
31+
F: Fn(Box<Iterator<Item = IterItem> + 'a>) -> V,
32+
{
33+
assert_eq!(
34+
mapper(Box::new(Unspecialized(iterator.clone()))),
35+
mapper(Box::new(iterator.clone()))
36+
)
37+
}
38+
39+
fn check_specialized_count_last_nth_sizeh<'a, IterItem, Iter>(it: &Iter, expected_size: usize)
40+
where
41+
IterItem: 'a + Eq + Debug,
42+
Iter: Iterator<Item = IterItem> + Clone + 'a,
43+
{
44+
let size = it.clone().count();
45+
assert_eq!(size, expected_size);
46+
check_specialized(it, |i| i.count());
47+
check_specialized(it, |i| i.last());
48+
for n in 0..size + 2 {
49+
check_specialized(it, |mut i| i.nth(n));
50+
}
51+
let mut it_sh = it.clone();
52+
for n in 0..size + 2 {
53+
let len = it_sh.clone().count();
54+
let (min, max) = it_sh.size_hint();
55+
assert_eq!((size - n.min(size)), len);
56+
assert!(min <= len);
57+
if let Some(max) = max {
58+
assert!(len <= max);
59+
}
60+
it_sh.next();
61+
}
62+
}
63+
64+
fn check_specialized_fold_xor<'a, IterItem, Iter>(it: &Iter)
65+
where
66+
IterItem: 'a
67+
+ BitXor
68+
+ Eq
69+
+ Debug
70+
+ BitXor<<IterItem as BitXor>::Output, Output = <IterItem as BitXor>::Output>
71+
+ Clone,
72+
<IterItem as BitXor>::Output:
73+
BitXor<Output = <IterItem as BitXor>::Output> + Eq + Debug + Clone,
74+
Iter: Iterator<Item = IterItem> + Clone + 'a,
75+
{
76+
check_specialized(it, |mut i| {
77+
let first = i.next().map(|f| f.clone() ^ (f.clone() ^ f));
78+
i.fold(first, |acc, v: IterItem| acc.map(move |a| v ^ a))
79+
});
80+
}
81+
82+
#[test]
83+
fn put_back() {
84+
let test_vec = vec![7, 4, 1];
85+
{
86+
// Lexical lifetimes support
87+
let pb = itertools::put_back(test_vec.iter());
88+
check_specialized_count_last_nth_sizeh(&pb, 3);
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, 4);
95+
check_specialized_fold_xor(&pb);
96+
}
97+
98+
#[test]
99+
fn merge_join_by() {
100+
let i1 = vec![1, 3, 5].into_iter();
101+
let i2 = vec![0, 3, 4, 5].into_iter();
102+
let mjb = i1.merge_join_by(i2, std::cmp::Ord::cmp);
103+
check_specialized_count_last_nth_sizeh(&mjb, 5);
104+
// Rust 1.24 compatibility:
105+
fn eob_left_z(eob: EitherOrBoth<usize, usize>) -> usize {
106+
eob.left().unwrap_or(0)
107+
}
108+
fn eob_right_z(eob: EitherOrBoth<usize, usize>) -> usize {
109+
eob.left().unwrap_or(0)
110+
}
111+
fn eob_both_z(eob: EitherOrBoth<usize, usize>) -> usize {
112+
let (a, b) = eob.both().unwrap_or((0, 0));
113+
assert_eq!(a, b);
114+
a
115+
}
116+
check_specialized_fold_xor(&mjb.clone().map(eob_left_z));
117+
check_specialized_fold_xor(&mjb.clone().map(eob_right_z));
118+
check_specialized_fold_xor(&mjb.clone().map(eob_both_z));
119+
}

0 commit comments

Comments
 (0)