litcheck_core/fs/
filesearch.rs1use std::path::Path;
2
3pub fn search_directory<P, F>(
10 dir: P,
11 recursive: bool,
12 mut predicate: F,
13) -> impl Iterator<Item = Result<walkdir::DirEntry, walkdir::Error>>
14where
15 P: AsRef<Path>,
16 F: Fn(&walkdir::DirEntry) -> bool,
17{
18 Searcher::new(dir.as_ref(), recursive, move |e| {
19 apply_search_filter(e, &mut predicate)
20 })
21}
22
23pub struct Searcher<P> {
24 walker: walkdir::FilterEntry<walkdir::IntoIter, P>,
25}
26impl<P> Searcher<P>
27where
28 P: FnMut(&walkdir::DirEntry) -> bool,
29{
30 fn new(path: &Path, recursive: bool, predicate: P) -> Self {
31 use walkdir::WalkDir;
32
33 let mut walker = WalkDir::new(path).follow_links(true);
34 if !recursive {
35 walker = walker.max_depth(1);
36 }
37 let walker = walker.into_iter().filter_entry(predicate);
38
39 Self { walker }
40 }
41}
42impl<P> Iterator for Searcher<P>
43where
44 P: FnMut(&walkdir::DirEntry) -> bool,
45{
46 type Item = Result<walkdir::DirEntry, walkdir::Error>;
47
48 #[inline]
49 fn next(&mut self) -> Option<Self::Item> {
50 #[allow(clippy::while_let_on_iterator)]
51 while let Some(entry) = self.walker.next() {
52 if let Ok(entry) = entry {
53 if entry.file_type().is_dir() {
54 continue;
55 }
56 return Some(Ok(entry));
57 } else {
58 return Some(entry);
59 }
60 }
61
62 None
63 }
64}
65
66#[inline]
67fn apply_search_filter<F>(entry: &walkdir::DirEntry, predicate: &mut F) -> bool
68where
69 F: FnMut(&walkdir::DirEntry) -> bool,
70{
71 let path = entry.path();
72 if path.is_dir() {
73 return true;
74 }
75 predicate(entry)
76}