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