1use std::collections::HashSet;
2use std::hash::Hash;
3use std::path::Path;
4
5pub trait IteratorExt: Iterator + Sized {
7 fn unique_by<F, K>(self, f: F) -> UniqueBy<Self, F, K>
8 where
9 F: Fn(&Self::Item) -> K,
10 K: Hash + Eq,
11 {
12 UniqueBy::new(self, f)
13 }
14}
15
16impl<I: Iterator> IteratorExt for I {}
17
18pub struct UniqueBy<I, F, K> {
19 iter: I,
20 set: HashSet<K>,
21 f: F,
22}
23
24impl<I, F, K> UniqueBy<I, F, K>
25where
26 I: Iterator,
27 F: Fn(&I::Item) -> K,
28 K: Hash + Eq,
29{
30 fn new(iter: I, f: F) -> Self {
31 Self {
32 iter,
33 f,
34 set: HashSet::new(),
35 }
36 }
37}
38
39#[allow(clippy::manual_find)]
40impl<I, F, K> Iterator for UniqueBy<I, F, K>
41where
42 I: Iterator,
43 F: Fn(&I::Item) -> K,
44 K: Hash + Eq,
45{
46 type Item = I::Item;
47
48 fn next(&mut self) -> Option<Self::Item> {
49 for item in &mut self.iter {
50 if self.set.insert((self.f)(&item)) {
51 return Some(item);
52 }
53 }
54 None
55 }
56}
57
58pub trait WalkParallelForEach {
59 fn for_each<F>(self, f: F)
60 where
61 F: Fn(Result<ignore::DirEntry, ignore::Error>) -> ignore::WalkState,
62 F: Send + Copy;
63}
64
65impl WalkParallelForEach for ignore::WalkParallel {
66 fn for_each<F>(self, f: F)
67 where
68 F: Fn(Result<ignore::DirEntry, ignore::Error>) -> ignore::WalkState,
69 F: Send + Copy,
70 {
71 self.run(|| Box::new(f))
72 }
73}
74
75pub trait WalkBuilderAddPaths {
76 fn add_paths<P, I>(&mut self, paths: I) -> &mut Self
77 where
78 P: AsRef<Path>,
79 I: IntoIterator<Item = P>;
80}
81
82impl WalkBuilderAddPaths for ignore::WalkBuilder {
83 fn add_paths<P, I>(&mut self, paths: I) -> &mut Self
84 where
85 P: AsRef<Path>,
86 I: IntoIterator<Item = P>,
87 {
88 for path in paths {
89 self.add(path);
90 }
91 self
92 }
93}