1use std::fs::{canonicalize, read_dir};
2use std::io::Error;
3use std::iter::FusedIterator;
4use std::path::{Path, PathBuf};
5
6pub struct RecursiveFolderIterator {
10 folder: Vec<PathBuf>,
11 file: Vec<PathBuf>,
12 filter_fn: fn(&Path) -> bool,
13}
14
15impl RecursiveFolderIterator {
16 pub fn new(folder: &Path, filter: fn(&Path) -> bool) -> Result<Self, Error> {
17 Ok(RecursiveFolderIterator {
18 folder: vec![folder.canonicalize()?],
19 file: Vec::new(),
20 filter_fn: filter,
21 })
22 }
23}
24
25impl Iterator for RecursiveFolderIterator {
26 type Item = PathBuf;
27
28 fn next(&mut self) -> Option<Self::Item> {
29 loop {
30 while let Some(file) = self.file.pop() {
31 if (self.filter_fn)(file.as_path()) {
32 return Some(file);
33 }
34 }
35
36 if let Some(folder) = self.folder.pop() {
37 if let Ok(fl) = read_dir(folder) {
38 for f in fl.flatten() {
39 let pth = match canonicalize(f.path()) {
40 Ok(x) => x,
41 Err(_) => continue,
42 };
43 if pth.is_dir() {
44 self.folder.push(pth);
45 } else if pth.is_file() {
46 self.file.push(pth);
47 }
48 }
49 };
50 } else {
51 break;
52 }
53 }
54
55 None
56 }
57}
58
59impl FusedIterator for RecursiveFolderIterator {}