Coverage Report

Created: 2025-10-12 08:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/itertools-0.12.1/src/unique_impl.rs
Line
Count
Source
1
use std::collections::hash_map::Entry;
2
use std::collections::HashMap;
3
use std::fmt;
4
use std::hash::Hash;
5
use std::iter::FusedIterator;
6
7
/// An iterator adapter to filter out duplicate elements.
8
///
9
/// See [`.unique_by()`](crate::Itertools::unique) for more information.
10
#[derive(Clone)]
11
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
12
pub struct UniqueBy<I: Iterator, V, F> {
13
    iter: I,
14
    // Use a Hashmap for the Entry API in order to prevent hashing twice.
15
    // This can maybe be replaced with a HashSet once `get_or_insert_with`
16
    // or a proper Entry API for Hashset is stable and meets this msrv
17
    used: HashMap<V, ()>,
18
    f: F,
19
}
20
21
impl<I, V, F> fmt::Debug for UniqueBy<I, V, F>
22
where
23
    I: Iterator + fmt::Debug,
24
    V: fmt::Debug + Hash + Eq,
25
{
26
    debug_fmt_fields!(UniqueBy, iter, used);
27
}
28
29
/// Create a new `UniqueBy` iterator.
30
0
pub fn unique_by<I, V, F>(iter: I, f: F) -> UniqueBy<I, V, F>
31
0
where
32
0
    V: Eq + Hash,
33
0
    F: FnMut(&I::Item) -> V,
34
0
    I: Iterator,
35
{
36
0
    UniqueBy {
37
0
        iter,
38
0
        used: HashMap::new(),
39
0
        f,
40
0
    }
41
0
}
42
43
// count the number of new unique keys in iterable (`used` is the set already seen)
44
0
fn count_new_keys<I, K>(mut used: HashMap<K, ()>, iterable: I) -> usize
45
0
where
46
0
    I: IntoIterator<Item = K>,
47
0
    K: Hash + Eq,
48
{
49
0
    let iter = iterable.into_iter();
50
0
    let current_used = used.len();
51
0
    used.extend(iter.map(|key| (key, ())));
52
0
    used.len() - current_used
53
0
}
54
55
impl<I, V, F> Iterator for UniqueBy<I, V, F>
56
where
57
    I: Iterator,
58
    V: Eq + Hash,
59
    F: FnMut(&I::Item) -> V,
60
{
61
    type Item = I::Item;
62
63
0
    fn next(&mut self) -> Option<Self::Item> {
64
0
        let Self { iter, used, f } = self;
65
0
        iter.find(|v| used.insert(f(v), ()).is_none())
66
0
    }
67
68
    #[inline]
69
0
    fn size_hint(&self) -> (usize, Option<usize>) {
70
0
        let (low, hi) = self.iter.size_hint();
71
0
        ((low > 0 && self.used.is_empty()) as usize, hi)
72
0
    }
73
74
0
    fn count(self) -> usize {
75
0
        let mut key_f = self.f;
76
0
        count_new_keys(self.used, self.iter.map(move |elt| key_f(&elt)))
77
0
    }
78
}
79
80
impl<I, V, F> DoubleEndedIterator for UniqueBy<I, V, F>
81
where
82
    I: DoubleEndedIterator,
83
    V: Eq + Hash,
84
    F: FnMut(&I::Item) -> V,
85
{
86
0
    fn next_back(&mut self) -> Option<Self::Item> {
87
0
        let Self { iter, used, f } = self;
88
0
        iter.rfind(|v| used.insert(f(v), ()).is_none())
89
0
    }
90
}
91
92
impl<I, V, F> FusedIterator for UniqueBy<I, V, F>
93
where
94
    I: FusedIterator,
95
    V: Eq + Hash,
96
    F: FnMut(&I::Item) -> V,
97
{
98
}
99
100
impl<I> Iterator for Unique<I>
101
where
102
    I: Iterator,
103
    I::Item: Eq + Hash + Clone,
104
{
105
    type Item = I::Item;
106
107
0
    fn next(&mut self) -> Option<Self::Item> {
108
0
        let UniqueBy { iter, used, .. } = &mut self.iter;
109
0
        iter.find_map(|v| {
110
0
            if let Entry::Vacant(entry) = used.entry(v) {
111
0
                let elt = entry.key().clone();
112
0
                entry.insert(());
113
0
                return Some(elt);
114
0
            }
115
0
            None
116
0
        })
117
0
    }
118
119
    #[inline]
120
0
    fn size_hint(&self) -> (usize, Option<usize>) {
121
0
        let (low, hi) = self.iter.iter.size_hint();
122
0
        ((low > 0 && self.iter.used.is_empty()) as usize, hi)
123
0
    }
124
125
0
    fn count(self) -> usize {
126
0
        count_new_keys(self.iter.used, self.iter.iter)
127
0
    }
128
}
129
130
impl<I> DoubleEndedIterator for Unique<I>
131
where
132
    I: DoubleEndedIterator,
133
    I::Item: Eq + Hash + Clone,
134
{
135
0
    fn next_back(&mut self) -> Option<Self::Item> {
136
0
        let UniqueBy { iter, used, .. } = &mut self.iter;
137
0
        iter.rev().find_map(|v| {
138
0
            if let Entry::Vacant(entry) = used.entry(v) {
139
0
                let elt = entry.key().clone();
140
0
                entry.insert(());
141
0
                return Some(elt);
142
0
            }
143
0
            None
144
0
        })
145
0
    }
146
}
147
148
impl<I> FusedIterator for Unique<I>
149
where
150
    I: FusedIterator,
151
    I::Item: Eq + Hash + Clone,
152
{
153
}
154
155
/// An iterator adapter to filter out duplicate elements.
156
///
157
/// See [`.unique()`](crate::Itertools::unique) for more information.
158
#[derive(Clone)]
159
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
160
pub struct Unique<I>
161
where
162
    I: Iterator,
163
    I::Item: Eq + Hash + Clone,
164
{
165
    iter: UniqueBy<I, I::Item, ()>,
166
}
167
168
impl<I> fmt::Debug for Unique<I>
169
where
170
    I: Iterator + fmt::Debug,
171
    I::Item: Hash + Eq + fmt::Debug + Clone,
172
{
173
    debug_fmt_fields!(Unique, iter);
174
}
175
176
0
pub fn unique<I>(iter: I) -> Unique<I>
177
0
where
178
0
    I: Iterator,
179
0
    I::Item: Eq + Hash + Clone,
180
{
181
0
    Unique {
182
0
        iter: UniqueBy {
183
0
            iter,
184
0
            used: HashMap::new(),
185
0
            f: (),
186
0
        },
187
0
    }
188
0
}